Simplified and optimized implementation of string matching/scanning/listing operations by reducing to a chunked text linear scanning algorithim

master
Allen Webster 2019-06-16 16:38:22 -07:00
parent 27e12b8b0d
commit 316673af26
14 changed files with 793 additions and 583 deletions

View File

@ -1139,6 +1139,7 @@ STRUCT color_picker{
b32 *finished;
};
// TODO(allen): Remove these vvvvv ?
enum Found_String_Flag{
FoundString_Sensitive = 0x1,
FoundString_Insensitive = 0x2,
@ -1163,6 +1164,27 @@ STRUCT Found_String_List{
Found_String *last;
i32 count;
};
// TODO(allen): Remove these ^^^^^ ?
ENUM(u32, String_Match_Flag){
StringMatch_CaseSensitive = 1,
StringMatch_LeftSideSloppy = 2,
StringMatch_RightSideSloppy = 4,
StringMatch_Straddled = 8,
};
STRUCT String_Match{
String_Match *next;
Buffer_ID buffer;
String_Match_Flag flags;
u64 index;
};
STRUCT String_Match_List{
String_Match *first;
String_Match *last;
i32 count;
};
STRUCT Process_State {
b32 is_updating;

View File

@ -355,7 +355,7 @@ get_indentation_marks(Application_Links *app, Arena *arena, Buffer_ID buffer,
this_indent += tab_width;
}
}
}
}
}
}
if (this_indent < 0){
@ -438,7 +438,7 @@ get_indentation_marks(Application_Links *app, Arena *arena, Buffer_ID buffer,
{
if (!(token.flags & CPP_TFLAG_PP_BODY)){
if (indent.paren_nesting > 0){
--indent.paren_nesting;
--indent.paren_nesting;
}
}
}break;

View File

@ -479,59 +479,69 @@ CUSTOM_DOC("Scrolls the view down one view height and moves the cursor down one
}
internal void
seek_blank_line__generic(Application_Links *app, Scan_Direction direction, b32 skip_lead_whitespace){
seek_blank_line(Application_Links *app, Scan_Direction direction, Position_Within_Line position){
View_ID view = 0;
get_active_view(app, AccessProtected, &view);
Buffer_ID buffer_id = 0;
view_get_buffer(app, view, AccessProtected, &buffer_id);
Buffer_ID buffer = 0;
view_get_buffer(app, view, AccessProtected, &buffer);
i32 pos = 0;
view_get_cursor_pos(app, view, &pos);
i32 new_pos = get_pos_of_blank_line_grouped(app, buffer_id, direction, pos);
if (skip_lead_whitespace){
new_pos = get_pos_past_lead_whitespace(app, buffer_id, new_pos);
i32 new_pos = get_pos_of_blank_line_grouped(app, buffer, direction, pos);
switch (position){
case PositionWithinLine_SkipLeadingWhitespace:
{
new_pos = get_pos_past_lead_whitespace(app, buffer, new_pos);
}break;
case PositionWithinLine_End:
{
new_pos = get_line_side_pos_from_pos(app, buffer, new_pos, Side_Max);
}break;
}
view_set_cursor(app, view, seek_pos(new_pos), true);
no_mark_snap_to_cursor_if_shift(app, view);
}
internal void
seek_blank_line(Application_Links *app, Scan_Direction direction){
seek_blank_line__generic(app, direction, false);
}
internal void
seek_blank_line_skip_leading_whitespace(Application_Links *app, Scan_Direction direction){
seek_blank_line__generic(app, direction, true);
}
CUSTOM_COMMAND_SIG(move_up_to_blank_line)
CUSTOM_DOC("Seeks the cursor up to the next blank line.")
{
seek_blank_line(app, Scan_Backward);
seek_blank_line(app, Scan_Backward, PositionWithinLine_Start);
}
CUSTOM_COMMAND_SIG(move_down_to_blank_line)
CUSTOM_DOC("Seeks the cursor down to the next blank line.")
{
seek_blank_line(app, Scan_Forward);
seek_blank_line(app, Scan_Forward, PositionWithinLine_Start);
}
CUSTOM_COMMAND_SIG(move_up_to_blank_line_skip_whitespace)
CUSTOM_DOC("Seeks the cursor up to the next blank line and places it at the end of the line.")
{
seek_blank_line(app, Scan_Backward, PositionWithinLine_SkipLeadingWhitespace);
}
CUSTOM_COMMAND_SIG(move_down_to_blank_line_skip_whitespace)
CUSTOM_DOC("Seeks the cursor down to the next blank line and places it at the end of the line.")
{
seek_blank_line(app, Scan_Forward, PositionWithinLine_SkipLeadingWhitespace);
}
CUSTOM_COMMAND_SIG(move_up_to_blank_line_end)
CUSTOM_DOC("Seeks the cursor up to the next blank line and places it at the end of the line.")
{
seek_blank_line_skip_leading_whitespace(app, Scan_Backward);
seek_blank_line(app, Scan_Backward, PositionWithinLine_End);
}
CUSTOM_COMMAND_SIG(move_down_to_blank_line_end)
CUSTOM_DOC("Seeks the cursor down to the next blank line and places it at the end of the line.")
{
seek_blank_line_skip_leading_whitespace(app, Scan_Forward);
seek_blank_line(app, Scan_Forward, PositionWithinLine_End);
}
#define seek_whitespace_up move_up_to_blank_line
#define seek_whitespace_down move_down_to_blank_line
#define seek_whitespace_up_end_line move_up_to_blank_line_end
#define seek_whitespace_down_end_line move_down_to_blank_line_end
#define seek_whitespace_up_end_line move_up_to_blank_line_skip_whitespace
#define seek_whitespace_down_end_line move_down_to_blank_line_skip_whitespace
CUSTOM_COMMAND_SIG(move_left)
CUSTOM_DOC("Moves the cursor one character to the left.")
@ -1639,10 +1649,9 @@ CUSTOM_DOC("Create a copy of the line on which the cursor sits.")
i32 line = get_line_number_from_pos(app, buffer, pos);
Scratch_Block scratch(app);
String_Const_u8 s = push_buffer_line(app, scratch, buffer, line);
s = string_u8_pushf(scratch, "\n%.*s", string_expand(s));
pos = get_line_side_pos(app, buffer, line, Side_Max);
s = string_u8_pushf(scratch, "%.*s\n", string_expand(s));
pos = get_line_side_pos(app, buffer, line, Side_Min);
buffer_replace_range(app, buffer, make_range(pos), s);
view_set_cursor(app, view, seek_pos(pos + 1), true);
}
CUSTOM_COMMAND_SIG(delete_line)
@ -1702,7 +1711,7 @@ get_cpp_matching_file(Application_Links *app, Buffer_ID buffer, Buffer_ID *buffe
for (i32 i = 0; i < new_extensions_count; i += 1){
Temp_Memory temp = begin_temp(scratch);
String_Const_u8 new_extension = new_extensions[i];
String_Const_u8 new_file_name = string_u8_pushf(scratch, "%.*s.%.*s", string_expand(file_without_extension), string_expand(new_extension));
String_Const_u8 new_file_name = string_u8_pushf(scratch, "%.*s.%.*s", string_expand(file_without_extension), string_expand(new_extension));
if (open_file(app, buffer_out, new_file_name, false, true)){
result = true;
break;

View File

@ -774,6 +774,42 @@ typedef f32_Rect_Pair Rect_f32_Pair;
////////////////////////////////
struct i8_Array{
i8 *vals;
i32 coint;
};
struct i16_Array{
i16 *vals;
i32 coint;
};
struct i32_Array{
i32 *vals;
i32 coint;
};
struct i64_Array{
i64 *vals;
i32 coint;
};
struct u8_Array{
u8 *vals;
i32 count;
};
struct u16_Array{
u16 *vals;
i32 count;
};
struct u32_Array{
u32 *vals;
i32 count;
};
struct u64_Array{
u64 *vals;
i32 count;
};
////////////////////////////////
typedef i32 String_Fill_Terminate_Rule;
enum{
StringFill_NoTerminate = 0,

View File

@ -182,7 +182,7 @@ struct Application_Links;
#define DRAW_RENDER_LAYOUT_SIG(n) void n(Application_Links *app, View_ID view_id)
#define OPEN_COLOR_PICKER_SIG(n) void n(Application_Links *app, color_picker *picker)
#define ANIMATE_IN_N_MILLISECONDS_SIG(n) void n(Application_Links *app, u32 n)
#define FIND_ALL_IN_RANGE_INSENSITIVE_SIG(n) Found_String_List n(Application_Links *app, Buffer_ID buffer_id, i32 start, i32 end, String_Const_u8 key, Arena *arena)
#define FIND_ALL_MATCHES_BUFFER_RANGE_SIG(n) String_Match_List n(Application_Links *app, Arena *arena, Buffer_ID buffer, Range range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction)
#define GET_VIEW_VISIBLE_RANGE_SIG(n) Range n(Application_Links *app, View_ID view_id)
typedef GLOBAL_SET_SETTING_SIG(Global_Set_Setting_Function);
typedef GLOBAL_SET_MAPPING_SIG(Global_Set_Mapping_Function);
@ -367,7 +367,7 @@ typedef COMPUTE_RENDER_LAYOUT_SIG(Compute_Render_Layout_Function);
typedef DRAW_RENDER_LAYOUT_SIG(Draw_Render_Layout_Function);
typedef OPEN_COLOR_PICKER_SIG(Open_Color_Picker_Function);
typedef ANIMATE_IN_N_MILLISECONDS_SIG(Animate_In_N_Milliseconds_Function);
typedef FIND_ALL_IN_RANGE_INSENSITIVE_SIG(Find_All_In_Range_Insensitive_Function);
typedef FIND_ALL_MATCHES_BUFFER_RANGE_SIG(Find_All_Matches_Buffer_Range_Function);
typedef GET_VIEW_VISIBLE_RANGE_SIG(Get_View_Visible_Range_Function);
struct Application_Links{
#if defined(ALLOW_DEP_4CODER)
@ -554,7 +554,7 @@ Compute_Render_Layout_Function *compute_render_layout;
Draw_Render_Layout_Function *draw_render_layout;
Open_Color_Picker_Function *open_color_picker;
Animate_In_N_Milliseconds_Function *animate_in_n_milliseconds;
Find_All_In_Range_Insensitive_Function *find_all_in_range_insensitive;
Find_All_Matches_Buffer_Range_Function *find_all_matches_buffer_range;
Get_View_Visible_Range_Function *get_view_visible_range;
#else
Global_Set_Setting_Function *global_set_setting_;
@ -740,7 +740,7 @@ Compute_Render_Layout_Function *compute_render_layout_;
Draw_Render_Layout_Function *draw_render_layout_;
Open_Color_Picker_Function *open_color_picker_;
Animate_In_N_Milliseconds_Function *animate_in_n_milliseconds_;
Find_All_In_Range_Insensitive_Function *find_all_in_range_insensitive_;
Find_All_Matches_Buffer_Range_Function *find_all_matches_buffer_range_;
Get_View_Visible_Range_Function *get_view_visible_range_;
#endif
void *memory;
@ -934,7 +934,7 @@ app_links->compute_render_layout_ = Compute_Render_Layout;\
app_links->draw_render_layout_ = Draw_Render_Layout;\
app_links->open_color_picker_ = Open_Color_Picker;\
app_links->animate_in_n_milliseconds_ = Animate_In_N_Milliseconds;\
app_links->find_all_in_range_insensitive_ = Find_All_In_Range_Insensitive;\
app_links->find_all_matches_buffer_range_ = Find_All_Matches_Buffer_Range;\
app_links->get_view_visible_range_ = Get_View_Visible_Range;} while(false)
#if defined(ALLOW_DEP_4CODER)
static b32 global_set_setting(Application_Links *app, Global_Setting_ID setting, i32 value){return(app->global_set_setting(app, setting, value));}
@ -1120,7 +1120,7 @@ static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer
static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout(app, view_id));}
static void open_color_picker(Application_Links *app, color_picker *picker){(app->open_color_picker(app, picker));}
static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds(app, n));}
static Found_String_List find_all_in_range_insensitive(Application_Links *app, Buffer_ID buffer_id, i32 start, i32 end, String_Const_u8 key, Arena *arena){return(app->find_all_in_range_insensitive(app, buffer_id, start, end, key, arena));}
static String_Match_List find_all_matches_buffer_range(Application_Links *app, Arena *arena, Buffer_ID buffer, Range range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction){return(app->find_all_matches_buffer_range(app, arena, buffer, range, needle, predicate, direction));}
static Range get_view_visible_range(Application_Links *app, View_ID view_id){return(app->get_view_visible_range(app, view_id));}
#else
static b32 global_set_setting(Application_Links *app, Global_Setting_ID setting, i32 value){return(app->global_set_setting_(app, setting, value));}
@ -1306,6 +1306,6 @@ static b32 compute_render_layout(Application_Links *app, View_ID view_id, Buffer
static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout_(app, view_id));}
static void open_color_picker(Application_Links *app, color_picker *picker){(app->open_color_picker_(app, picker));}
static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds_(app, n));}
static Found_String_List find_all_in_range_insensitive(Application_Links *app, Buffer_ID buffer_id, i32 start, i32 end, String_Const_u8 key, Arena *arena){return(app->find_all_in_range_insensitive_(app, buffer_id, start, end, key, arena));}
static String_Match_List find_all_matches_buffer_range(Application_Links *app, Arena *arena, Buffer_ID buffer, Range range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction){return(app->find_all_matches_buffer_range_(app, arena, buffer, range, needle, predicate, direction));}
static Range get_view_visible_range(Application_Links *app, View_ID view_id){return(app->get_view_visible_range_(app, view_id));}
#endif

View File

@ -2,7 +2,7 @@
#define command_id(c) (fcoder_metacmd_ID_##c)
#define command_metadata(c) (&fcoder_metacmd_table[command_id(c)])
#define command_metadata_by_id(id) (&fcoder_metacmd_table[id])
#define command_one_past_last_id 234
#define command_one_past_last_id 236
#if defined(CUSTOM_COMMAND_SIG)
#define PROC_LINKS(x,y) x
#else
@ -57,6 +57,8 @@ CUSTOM_COMMAND_SIG(page_up);
CUSTOM_COMMAND_SIG(page_down);
CUSTOM_COMMAND_SIG(move_up_to_blank_line);
CUSTOM_COMMAND_SIG(move_down_to_blank_line);
CUSTOM_COMMAND_SIG(move_up_to_blank_line_skip_whitespace);
CUSTOM_COMMAND_SIG(move_down_to_blank_line_skip_whitespace);
CUSTOM_COMMAND_SIG(move_up_to_blank_line_end);
CUSTOM_COMMAND_SIG(move_down_to_blank_line_end);
CUSTOM_COMMAND_SIG(move_left);
@ -254,7 +256,7 @@ char *source_name;
int32_t source_name_len;
int32_t line_number;
};
static Command_Metadata fcoder_metacmd_table[234] = {
static Command_Metadata fcoder_metacmd_table[236] = {
{ PROC_LINKS(replace_all_occurrences, 0), "replace_all_occurrences", 23, "Queries the user for two strings, and replaces all occurrences of the first string with the second string in all open buffers.", 126, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 806 },
{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\4coder_seek.cpp", 27, 34 },
{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\4coder_seek.cpp", 27, 40 },
@ -301,76 +303,78 @@ static Command_Metadata fcoder_metacmd_table[234] = {
{ PROC_LINKS(move_down_textual, 0), "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 449 },
{ 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, 463 },
{ 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, 472 },
{ PROC_LINKS(move_up_to_blank_line, 0), "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 507 },
{ PROC_LINKS(move_down_to_blank_line, 0), "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 513 },
{ PROC_LINKS(move_up_to_blank_line_end, 0), "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 519 },
{ PROC_LINKS(move_down_to_blank_line_end, 0), "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 525 },
{ PROC_LINKS(move_left, 0), "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 536 },
{ PROC_LINKS(move_right, 0), "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 550 },
{ PROC_LINKS(move_right_whitespace_boundary, 0), "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 577 },
{ PROC_LINKS(move_left_whitespace_boundary, 0), "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 585 },
{ PROC_LINKS(move_right_token_boundary, 0), "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 593 },
{ PROC_LINKS(move_left_token_boundary, 0), "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 601 },
{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 609 },
{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 617 },
{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 625 },
{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 633 },
{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 641 },
{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 649 },
{ PROC_LINKS(select_all, 0), "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 670 },
{ 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, 686 },
{ 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, 706 },
{ 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, 726 },
{ PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 767 },
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 776 },
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 786 },
{ PROC_LINKS(hide_scrollbar, 0), "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 794 },
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 802 },
{ PROC_LINKS(hide_filebar, 0), "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 810 },
{ 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, 818 },
{ 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, 828 },
{ 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, 840 },
{ PROC_LINKS(increase_line_wrap, 0), "increase_line_wrap", 18, "Increases the current buffer's width for line wrapping.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 846 },
{ PROC_LINKS(decrease_line_wrap, 0), "decrease_line_wrap", 18, "Decrases the current buffer's width for line wrapping.", 54, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 858 },
{ PROC_LINKS(increase_face_size, 0), "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 870 },
{ PROC_LINKS(decrease_face_size, 0), "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 884 },
{ PROC_LINKS(mouse_wheel_change_face_size, 0), "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 898 },
{ 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, 915 },
{ 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, 927 },
{ 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, 937 },
{ PROC_LINKS(eol_dosify, 0), "eol_dosify", 10, "Puts the buffer in DOS line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 943 },
{ PROC_LINKS(eol_nixify, 0), "eol_nixify", 10, "Puts the buffer in NIX line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 953 },
{ PROC_LINKS(exit_4coder, 0), "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 963 },
{ PROC_LINKS(goto_line, 0), "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 971 },
{ PROC_LINKS(search, 0), "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1199 },
{ PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1205 },
{ PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1211 },
{ PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1226 },
{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for two strings, and replaces all occurences of the first string in the range between the cursor and the mark with the second string.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1241 },
{ 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, 1350 },
{ 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, 1373 },
{ 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, 1392 },
{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1436 },
{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1461 },
{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1501 },
{ 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, 1539 },
{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1582 },
{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1618 },
{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1624 },
{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1630 },
{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1648 },
{ 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, 1717 },
{ 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, 1755 },
{ 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, 1770 },
{ 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, 1785 },
{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1830 },
{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1840 },
{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1854 },
{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1918 },
{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1934 },
{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1952 },
{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 2031 },
{ 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, 2141 },
{ PROC_LINKS(move_up_to_blank_line, 0), "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 505 },
{ PROC_LINKS(move_down_to_blank_line, 0), "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 511 },
{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 517 },
{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 523 },
{ PROC_LINKS(move_up_to_blank_line_end, 0), "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 529 },
{ PROC_LINKS(move_down_to_blank_line_end, 0), "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 535 },
{ PROC_LINKS(move_left, 0), "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 546 },
{ PROC_LINKS(move_right, 0), "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 560 },
{ PROC_LINKS(move_right_whitespace_boundary, 0), "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 587 },
{ PROC_LINKS(move_left_whitespace_boundary, 0), "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 595 },
{ PROC_LINKS(move_right_token_boundary, 0), "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 603 },
{ PROC_LINKS(move_left_token_boundary, 0), "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 611 },
{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 619 },
{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 627 },
{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 635 },
{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 643 },
{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 651 },
{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 659 },
{ PROC_LINKS(select_all, 0), "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 680 },
{ 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, 696 },
{ 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, 716 },
{ 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, 736 },
{ PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 777 },
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 786 },
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 796 },
{ PROC_LINKS(hide_scrollbar, 0), "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 804 },
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 812 },
{ PROC_LINKS(hide_filebar, 0), "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 820 },
{ 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, 828 },
{ 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, 838 },
{ 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, 850 },
{ PROC_LINKS(increase_line_wrap, 0), "increase_line_wrap", 18, "Increases the current buffer's width for line wrapping.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 856 },
{ PROC_LINKS(decrease_line_wrap, 0), "decrease_line_wrap", 18, "Decrases the current buffer's width for line wrapping.", 54, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 868 },
{ PROC_LINKS(increase_face_size, 0), "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 880 },
{ PROC_LINKS(decrease_face_size, 0), "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 894 },
{ PROC_LINKS(mouse_wheel_change_face_size, 0), "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 908 },
{ 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, 925 },
{ 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, 937 },
{ 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, 947 },
{ PROC_LINKS(eol_dosify, 0), "eol_dosify", 10, "Puts the buffer in DOS line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 953 },
{ PROC_LINKS(eol_nixify, 0), "eol_nixify", 10, "Puts the buffer in NIX line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 963 },
{ PROC_LINKS(exit_4coder, 0), "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 973 },
{ PROC_LINKS(goto_line, 0), "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 981 },
{ PROC_LINKS(search, 0), "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1209 },
{ PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1215 },
{ PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1221 },
{ PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1236 },
{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for two strings, and replaces all occurences of the first string in the range between the cursor and the mark with the second string.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1251 },
{ 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, 1360 },
{ 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, 1383 },
{ 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, 1402 },
{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1446 },
{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1471 },
{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1511 },
{ 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, 1549 },
{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1592 },
{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1628 },
{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1634 },
{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1640 },
{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1657 },
{ 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, 1726 },
{ 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, 1764 },
{ 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, 1779 },
{ 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, 1794 },
{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1839 },
{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1849 },
{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1863 },
{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1927 },
{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1943 },
{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1961 },
{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 2040 },
{ 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, 2150 },
{ PROC_LINKS(lister__quit, 0), "lister__quit", 12, "A lister mode command that quits the list without executing any actions.", 72, "w:\\4ed\\code\\4coder_lists.cpp", 28, 8 },
{ PROC_LINKS(lister__activate, 0), "lister__activate", 16, "A lister mode command that activates the list's action on the highlighted item.", 79, "w:\\4ed\\code\\4coder_lists.cpp", 28, 16 },
{ PROC_LINKS(lister__write_character, 0), "lister__write_character", 23, "A lister mode command that dispatches to the lister's write character handler.", 78, "w:\\4ed\\code\\4coder_lists.cpp", 28, 32 },
@ -538,190 +542,192 @@ static int32_t fcoder_metacmd_ID_page_up = 44;
static int32_t fcoder_metacmd_ID_page_down = 45;
static int32_t fcoder_metacmd_ID_move_up_to_blank_line = 46;
static int32_t fcoder_metacmd_ID_move_down_to_blank_line = 47;
static int32_t fcoder_metacmd_ID_move_up_to_blank_line_end = 48;
static int32_t fcoder_metacmd_ID_move_down_to_blank_line_end = 49;
static int32_t fcoder_metacmd_ID_move_left = 50;
static int32_t fcoder_metacmd_ID_move_right = 51;
static int32_t fcoder_metacmd_ID_move_right_whitespace_boundary = 52;
static int32_t fcoder_metacmd_ID_move_left_whitespace_boundary = 53;
static int32_t fcoder_metacmd_ID_move_right_token_boundary = 54;
static int32_t fcoder_metacmd_ID_move_left_token_boundary = 55;
static int32_t fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 56;
static int32_t fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 57;
static int32_t fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 58;
static int32_t fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 59;
static int32_t fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 60;
static int32_t fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 61;
static int32_t fcoder_metacmd_ID_select_all = 62;
static int32_t fcoder_metacmd_ID_to_uppercase = 63;
static int32_t fcoder_metacmd_ID_to_lowercase = 64;
static int32_t fcoder_metacmd_ID_clean_all_lines = 65;
static int32_t fcoder_metacmd_ID_basic_change_active_panel = 66;
static int32_t fcoder_metacmd_ID_close_panel = 67;
static int32_t fcoder_metacmd_ID_show_scrollbar = 68;
static int32_t fcoder_metacmd_ID_hide_scrollbar = 69;
static int32_t fcoder_metacmd_ID_show_filebar = 70;
static int32_t fcoder_metacmd_ID_hide_filebar = 71;
static int32_t fcoder_metacmd_ID_toggle_filebar = 72;
static int32_t fcoder_metacmd_ID_toggle_line_wrap = 73;
static int32_t fcoder_metacmd_ID_toggle_fps_meter = 74;
static int32_t fcoder_metacmd_ID_increase_line_wrap = 75;
static int32_t fcoder_metacmd_ID_decrease_line_wrap = 76;
static int32_t fcoder_metacmd_ID_increase_face_size = 77;
static int32_t fcoder_metacmd_ID_decrease_face_size = 78;
static int32_t fcoder_metacmd_ID_mouse_wheel_change_face_size = 79;
static int32_t fcoder_metacmd_ID_toggle_virtual_whitespace = 80;
static int32_t fcoder_metacmd_ID_toggle_show_whitespace = 81;
static int32_t fcoder_metacmd_ID_toggle_line_numbers = 82;
static int32_t fcoder_metacmd_ID_eol_dosify = 83;
static int32_t fcoder_metacmd_ID_eol_nixify = 84;
static int32_t fcoder_metacmd_ID_exit_4coder = 85;
static int32_t fcoder_metacmd_ID_goto_line = 86;
static int32_t fcoder_metacmd_ID_search = 87;
static int32_t fcoder_metacmd_ID_reverse_search = 88;
static int32_t fcoder_metacmd_ID_search_identifier = 89;
static int32_t fcoder_metacmd_ID_reverse_search_identifier = 90;
static int32_t fcoder_metacmd_ID_replace_in_range = 91;
static int32_t fcoder_metacmd_ID_query_replace = 92;
static int32_t fcoder_metacmd_ID_query_replace_identifier = 93;
static int32_t fcoder_metacmd_ID_query_replace_selection = 94;
static int32_t fcoder_metacmd_ID_save_all_dirty_buffers = 95;
static int32_t fcoder_metacmd_ID_delete_file_query = 96;
static int32_t fcoder_metacmd_ID_save_to_query = 97;
static int32_t fcoder_metacmd_ID_rename_file_query = 98;
static int32_t fcoder_metacmd_ID_make_directory_query = 99;
static int32_t fcoder_metacmd_ID_move_line_up = 100;
static int32_t fcoder_metacmd_ID_move_line_down = 101;
static int32_t fcoder_metacmd_ID_duplicate_line = 102;
static int32_t fcoder_metacmd_ID_delete_line = 103;
static int32_t fcoder_metacmd_ID_open_file_in_quotes = 104;
static int32_t fcoder_metacmd_ID_open_matching_file_cpp = 105;
static int32_t fcoder_metacmd_ID_view_buffer_other_panel = 106;
static int32_t fcoder_metacmd_ID_swap_buffers_between_panels = 107;
static int32_t fcoder_metacmd_ID_kill_buffer = 108;
static int32_t fcoder_metacmd_ID_save = 109;
static int32_t fcoder_metacmd_ID_reopen = 110;
static int32_t fcoder_metacmd_ID_undo = 111;
static int32_t fcoder_metacmd_ID_redo = 112;
static int32_t fcoder_metacmd_ID_undo_all_buffers = 113;
static int32_t fcoder_metacmd_ID_redo_all_buffers = 114;
static int32_t fcoder_metacmd_ID_open_in_other = 115;
static int32_t fcoder_metacmd_ID_lister__quit = 116;
static int32_t fcoder_metacmd_ID_lister__activate = 117;
static int32_t fcoder_metacmd_ID_lister__write_character = 118;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field = 119;
static int32_t fcoder_metacmd_ID_lister__move_up = 120;
static int32_t fcoder_metacmd_ID_lister__move_down = 121;
static int32_t fcoder_metacmd_ID_lister__wheel_scroll = 122;
static int32_t fcoder_metacmd_ID_lister__mouse_press = 123;
static int32_t fcoder_metacmd_ID_lister__mouse_release = 124;
static int32_t fcoder_metacmd_ID_lister__repaint = 125;
static int32_t fcoder_metacmd_ID_lister__write_character__default = 126;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field__default = 127;
static int32_t fcoder_metacmd_ID_lister__move_up__default = 128;
static int32_t fcoder_metacmd_ID_lister__move_down__default = 129;
static int32_t fcoder_metacmd_ID_lister__write_character__file_path = 130;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field__file_path = 131;
static int32_t fcoder_metacmd_ID_lister__write_character__fixed_list = 132;
static int32_t fcoder_metacmd_ID_interactive_switch_buffer = 133;
static int32_t fcoder_metacmd_ID_interactive_kill_buffer = 134;
static int32_t fcoder_metacmd_ID_interactive_open_or_new = 135;
static int32_t fcoder_metacmd_ID_interactive_new = 136;
static int32_t fcoder_metacmd_ID_interactive_open = 137;
static int32_t fcoder_metacmd_ID_command_lister = 138;
static int32_t fcoder_metacmd_ID_auto_tab_whole_file = 139;
static int32_t fcoder_metacmd_ID_auto_tab_line_at_cursor = 140;
static int32_t fcoder_metacmd_ID_auto_tab_range = 141;
static int32_t fcoder_metacmd_ID_write_and_auto_tab = 142;
static int32_t fcoder_metacmd_ID_list_all_locations = 143;
static int32_t fcoder_metacmd_ID_list_all_substring_locations = 144;
static int32_t fcoder_metacmd_ID_list_all_locations_case_insensitive = 145;
static int32_t fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 146;
static int32_t fcoder_metacmd_ID_list_all_locations_of_identifier = 147;
static int32_t fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 148;
static int32_t fcoder_metacmd_ID_list_all_locations_of_selection = 149;
static int32_t fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 150;
static int32_t fcoder_metacmd_ID_list_all_locations_of_type_definition = 151;
static int32_t fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 152;
static int32_t fcoder_metacmd_ID_word_complete = 153;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_direct = 154;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_same_panel_direct = 155;
static int32_t fcoder_metacmd_ID_goto_next_jump_direct = 156;
static int32_t fcoder_metacmd_ID_goto_prev_jump_direct = 157;
static int32_t fcoder_metacmd_ID_goto_next_jump_no_skips_direct = 158;
static int32_t fcoder_metacmd_ID_goto_prev_jump_no_skips_direct = 159;
static int32_t fcoder_metacmd_ID_goto_first_jump_direct = 160;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_direct = 161;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_same_panel_direct = 162;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_sticky = 163;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_same_panel_sticky = 164;
static int32_t fcoder_metacmd_ID_goto_next_jump_sticky = 165;
static int32_t fcoder_metacmd_ID_goto_prev_jump_sticky = 166;
static int32_t fcoder_metacmd_ID_goto_next_jump_no_skips_sticky = 167;
static int32_t fcoder_metacmd_ID_goto_prev_jump_no_skips_sticky = 168;
static int32_t fcoder_metacmd_ID_goto_first_jump_sticky = 169;
static int32_t fcoder_metacmd_ID_goto_first_jump_same_panel_sticky = 170;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_sticky = 171;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_same_panel_sticky = 172;
static int32_t fcoder_metacmd_ID_view_jump_list_with_lister = 173;
static int32_t fcoder_metacmd_ID_copy = 174;
static int32_t fcoder_metacmd_ID_cut = 175;
static int32_t fcoder_metacmd_ID_paste = 176;
static int32_t fcoder_metacmd_ID_paste_next = 177;
static int32_t fcoder_metacmd_ID_paste_and_indent = 178;
static int32_t fcoder_metacmd_ID_paste_next_and_indent = 179;
static int32_t fcoder_metacmd_ID_execute_previous_cli = 180;
static int32_t fcoder_metacmd_ID_execute_any_cli = 181;
static int32_t fcoder_metacmd_ID_build_search = 182;
static int32_t fcoder_metacmd_ID_build_in_build_panel = 183;
static int32_t fcoder_metacmd_ID_close_build_panel = 184;
static int32_t fcoder_metacmd_ID_change_to_build_panel = 185;
static int32_t fcoder_metacmd_ID_close_all_code = 186;
static int32_t fcoder_metacmd_ID_open_all_code = 187;
static int32_t fcoder_metacmd_ID_open_all_code_recursive = 188;
static int32_t fcoder_metacmd_ID_load_project = 189;
static int32_t fcoder_metacmd_ID_project_fkey_command = 190;
static int32_t fcoder_metacmd_ID_project_go_to_root_directory = 191;
static int32_t fcoder_metacmd_ID_setup_new_project = 192;
static int32_t fcoder_metacmd_ID_setup_build_bat = 193;
static int32_t fcoder_metacmd_ID_setup_build_sh = 194;
static int32_t fcoder_metacmd_ID_setup_build_bat_and_sh = 195;
static int32_t fcoder_metacmd_ID_project_command_lister = 196;
static int32_t fcoder_metacmd_ID_list_all_functions_current_buffer = 197;
static int32_t fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 198;
static int32_t fcoder_metacmd_ID_list_all_functions_all_buffers = 199;
static int32_t fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 200;
static int32_t fcoder_metacmd_ID_select_surrounding_scope = 201;
static int32_t fcoder_metacmd_ID_select_next_scope_absolute = 202;
static int32_t fcoder_metacmd_ID_select_prev_scope_absolute = 203;
static int32_t fcoder_metacmd_ID_place_in_scope = 204;
static int32_t fcoder_metacmd_ID_delete_current_scope = 205;
static int32_t fcoder_metacmd_ID_scope_absorb_down = 206;
static int32_t fcoder_metacmd_ID_open_long_braces = 207;
static int32_t fcoder_metacmd_ID_open_long_braces_semicolon = 208;
static int32_t fcoder_metacmd_ID_open_long_braces_break = 209;
static int32_t fcoder_metacmd_ID_if0_off = 210;
static int32_t fcoder_metacmd_ID_write_todo = 211;
static int32_t fcoder_metacmd_ID_write_hack = 212;
static int32_t fcoder_metacmd_ID_write_note = 213;
static int32_t fcoder_metacmd_ID_write_block = 214;
static int32_t fcoder_metacmd_ID_write_zero_struct = 215;
static int32_t fcoder_metacmd_ID_comment_line = 216;
static int32_t fcoder_metacmd_ID_uncomment_line = 217;
static int32_t fcoder_metacmd_ID_comment_line_toggle = 218;
static int32_t fcoder_metacmd_ID_snippet_lister = 219;
static int32_t fcoder_metacmd_ID_set_bindings_choose = 220;
static int32_t fcoder_metacmd_ID_set_bindings_default = 221;
static int32_t fcoder_metacmd_ID_set_bindings_mac_default = 222;
static int32_t fcoder_metacmd_ID_miblo_increment_basic = 223;
static int32_t fcoder_metacmd_ID_miblo_decrement_basic = 224;
static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp = 225;
static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp = 226;
static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 227;
static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 228;
static int32_t fcoder_metacmd_ID_kill_rect = 229;
static int32_t fcoder_metacmd_ID_multi_line_edit = 230;
static int32_t fcoder_metacmd_ID_rename_parameter = 231;
static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 232;
static int32_t fcoder_metacmd_ID_write_explicit_enum_flags = 233;
static int32_t fcoder_metacmd_ID_move_up_to_blank_line_skip_whitespace = 48;
static int32_t fcoder_metacmd_ID_move_down_to_blank_line_skip_whitespace = 49;
static int32_t fcoder_metacmd_ID_move_up_to_blank_line_end = 50;
static int32_t fcoder_metacmd_ID_move_down_to_blank_line_end = 51;
static int32_t fcoder_metacmd_ID_move_left = 52;
static int32_t fcoder_metacmd_ID_move_right = 53;
static int32_t fcoder_metacmd_ID_move_right_whitespace_boundary = 54;
static int32_t fcoder_metacmd_ID_move_left_whitespace_boundary = 55;
static int32_t fcoder_metacmd_ID_move_right_token_boundary = 56;
static int32_t fcoder_metacmd_ID_move_left_token_boundary = 57;
static int32_t fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 58;
static int32_t fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 59;
static int32_t fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 60;
static int32_t fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 61;
static int32_t fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 62;
static int32_t fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 63;
static int32_t fcoder_metacmd_ID_select_all = 64;
static int32_t fcoder_metacmd_ID_to_uppercase = 65;
static int32_t fcoder_metacmd_ID_to_lowercase = 66;
static int32_t fcoder_metacmd_ID_clean_all_lines = 67;
static int32_t fcoder_metacmd_ID_basic_change_active_panel = 68;
static int32_t fcoder_metacmd_ID_close_panel = 69;
static int32_t fcoder_metacmd_ID_show_scrollbar = 70;
static int32_t fcoder_metacmd_ID_hide_scrollbar = 71;
static int32_t fcoder_metacmd_ID_show_filebar = 72;
static int32_t fcoder_metacmd_ID_hide_filebar = 73;
static int32_t fcoder_metacmd_ID_toggle_filebar = 74;
static int32_t fcoder_metacmd_ID_toggle_line_wrap = 75;
static int32_t fcoder_metacmd_ID_toggle_fps_meter = 76;
static int32_t fcoder_metacmd_ID_increase_line_wrap = 77;
static int32_t fcoder_metacmd_ID_decrease_line_wrap = 78;
static int32_t fcoder_metacmd_ID_increase_face_size = 79;
static int32_t fcoder_metacmd_ID_decrease_face_size = 80;
static int32_t fcoder_metacmd_ID_mouse_wheel_change_face_size = 81;
static int32_t fcoder_metacmd_ID_toggle_virtual_whitespace = 82;
static int32_t fcoder_metacmd_ID_toggle_show_whitespace = 83;
static int32_t fcoder_metacmd_ID_toggle_line_numbers = 84;
static int32_t fcoder_metacmd_ID_eol_dosify = 85;
static int32_t fcoder_metacmd_ID_eol_nixify = 86;
static int32_t fcoder_metacmd_ID_exit_4coder = 87;
static int32_t fcoder_metacmd_ID_goto_line = 88;
static int32_t fcoder_metacmd_ID_search = 89;
static int32_t fcoder_metacmd_ID_reverse_search = 90;
static int32_t fcoder_metacmd_ID_search_identifier = 91;
static int32_t fcoder_metacmd_ID_reverse_search_identifier = 92;
static int32_t fcoder_metacmd_ID_replace_in_range = 93;
static int32_t fcoder_metacmd_ID_query_replace = 94;
static int32_t fcoder_metacmd_ID_query_replace_identifier = 95;
static int32_t fcoder_metacmd_ID_query_replace_selection = 96;
static int32_t fcoder_metacmd_ID_save_all_dirty_buffers = 97;
static int32_t fcoder_metacmd_ID_delete_file_query = 98;
static int32_t fcoder_metacmd_ID_save_to_query = 99;
static int32_t fcoder_metacmd_ID_rename_file_query = 100;
static int32_t fcoder_metacmd_ID_make_directory_query = 101;
static int32_t fcoder_metacmd_ID_move_line_up = 102;
static int32_t fcoder_metacmd_ID_move_line_down = 103;
static int32_t fcoder_metacmd_ID_duplicate_line = 104;
static int32_t fcoder_metacmd_ID_delete_line = 105;
static int32_t fcoder_metacmd_ID_open_file_in_quotes = 106;
static int32_t fcoder_metacmd_ID_open_matching_file_cpp = 107;
static int32_t fcoder_metacmd_ID_view_buffer_other_panel = 108;
static int32_t fcoder_metacmd_ID_swap_buffers_between_panels = 109;
static int32_t fcoder_metacmd_ID_kill_buffer = 110;
static int32_t fcoder_metacmd_ID_save = 111;
static int32_t fcoder_metacmd_ID_reopen = 112;
static int32_t fcoder_metacmd_ID_undo = 113;
static int32_t fcoder_metacmd_ID_redo = 114;
static int32_t fcoder_metacmd_ID_undo_all_buffers = 115;
static int32_t fcoder_metacmd_ID_redo_all_buffers = 116;
static int32_t fcoder_metacmd_ID_open_in_other = 117;
static int32_t fcoder_metacmd_ID_lister__quit = 118;
static int32_t fcoder_metacmd_ID_lister__activate = 119;
static int32_t fcoder_metacmd_ID_lister__write_character = 120;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field = 121;
static int32_t fcoder_metacmd_ID_lister__move_up = 122;
static int32_t fcoder_metacmd_ID_lister__move_down = 123;
static int32_t fcoder_metacmd_ID_lister__wheel_scroll = 124;
static int32_t fcoder_metacmd_ID_lister__mouse_press = 125;
static int32_t fcoder_metacmd_ID_lister__mouse_release = 126;
static int32_t fcoder_metacmd_ID_lister__repaint = 127;
static int32_t fcoder_metacmd_ID_lister__write_character__default = 128;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field__default = 129;
static int32_t fcoder_metacmd_ID_lister__move_up__default = 130;
static int32_t fcoder_metacmd_ID_lister__move_down__default = 131;
static int32_t fcoder_metacmd_ID_lister__write_character__file_path = 132;
static int32_t fcoder_metacmd_ID_lister__backspace_text_field__file_path = 133;
static int32_t fcoder_metacmd_ID_lister__write_character__fixed_list = 134;
static int32_t fcoder_metacmd_ID_interactive_switch_buffer = 135;
static int32_t fcoder_metacmd_ID_interactive_kill_buffer = 136;
static int32_t fcoder_metacmd_ID_interactive_open_or_new = 137;
static int32_t fcoder_metacmd_ID_interactive_new = 138;
static int32_t fcoder_metacmd_ID_interactive_open = 139;
static int32_t fcoder_metacmd_ID_command_lister = 140;
static int32_t fcoder_metacmd_ID_auto_tab_whole_file = 141;
static int32_t fcoder_metacmd_ID_auto_tab_line_at_cursor = 142;
static int32_t fcoder_metacmd_ID_auto_tab_range = 143;
static int32_t fcoder_metacmd_ID_write_and_auto_tab = 144;
static int32_t fcoder_metacmd_ID_list_all_locations = 145;
static int32_t fcoder_metacmd_ID_list_all_substring_locations = 146;
static int32_t fcoder_metacmd_ID_list_all_locations_case_insensitive = 147;
static int32_t fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 148;
static int32_t fcoder_metacmd_ID_list_all_locations_of_identifier = 149;
static int32_t fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 150;
static int32_t fcoder_metacmd_ID_list_all_locations_of_selection = 151;
static int32_t fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 152;
static int32_t fcoder_metacmd_ID_list_all_locations_of_type_definition = 153;
static int32_t fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 154;
static int32_t fcoder_metacmd_ID_word_complete = 155;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_direct = 156;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_same_panel_direct = 157;
static int32_t fcoder_metacmd_ID_goto_next_jump_direct = 158;
static int32_t fcoder_metacmd_ID_goto_prev_jump_direct = 159;
static int32_t fcoder_metacmd_ID_goto_next_jump_no_skips_direct = 160;
static int32_t fcoder_metacmd_ID_goto_prev_jump_no_skips_direct = 161;
static int32_t fcoder_metacmd_ID_goto_first_jump_direct = 162;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_direct = 163;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_same_panel_direct = 164;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_sticky = 165;
static int32_t fcoder_metacmd_ID_goto_jump_at_cursor_same_panel_sticky = 166;
static int32_t fcoder_metacmd_ID_goto_next_jump_sticky = 167;
static int32_t fcoder_metacmd_ID_goto_prev_jump_sticky = 168;
static int32_t fcoder_metacmd_ID_goto_next_jump_no_skips_sticky = 169;
static int32_t fcoder_metacmd_ID_goto_prev_jump_no_skips_sticky = 170;
static int32_t fcoder_metacmd_ID_goto_first_jump_sticky = 171;
static int32_t fcoder_metacmd_ID_goto_first_jump_same_panel_sticky = 172;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_sticky = 173;
static int32_t fcoder_metacmd_ID_newline_or_goto_position_same_panel_sticky = 174;
static int32_t fcoder_metacmd_ID_view_jump_list_with_lister = 175;
static int32_t fcoder_metacmd_ID_copy = 176;
static int32_t fcoder_metacmd_ID_cut = 177;
static int32_t fcoder_metacmd_ID_paste = 178;
static int32_t fcoder_metacmd_ID_paste_next = 179;
static int32_t fcoder_metacmd_ID_paste_and_indent = 180;
static int32_t fcoder_metacmd_ID_paste_next_and_indent = 181;
static int32_t fcoder_metacmd_ID_execute_previous_cli = 182;
static int32_t fcoder_metacmd_ID_execute_any_cli = 183;
static int32_t fcoder_metacmd_ID_build_search = 184;
static int32_t fcoder_metacmd_ID_build_in_build_panel = 185;
static int32_t fcoder_metacmd_ID_close_build_panel = 186;
static int32_t fcoder_metacmd_ID_change_to_build_panel = 187;
static int32_t fcoder_metacmd_ID_close_all_code = 188;
static int32_t fcoder_metacmd_ID_open_all_code = 189;
static int32_t fcoder_metacmd_ID_open_all_code_recursive = 190;
static int32_t fcoder_metacmd_ID_load_project = 191;
static int32_t fcoder_metacmd_ID_project_fkey_command = 192;
static int32_t fcoder_metacmd_ID_project_go_to_root_directory = 193;
static int32_t fcoder_metacmd_ID_setup_new_project = 194;
static int32_t fcoder_metacmd_ID_setup_build_bat = 195;
static int32_t fcoder_metacmd_ID_setup_build_sh = 196;
static int32_t fcoder_metacmd_ID_setup_build_bat_and_sh = 197;
static int32_t fcoder_metacmd_ID_project_command_lister = 198;
static int32_t fcoder_metacmd_ID_list_all_functions_current_buffer = 199;
static int32_t fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 200;
static int32_t fcoder_metacmd_ID_list_all_functions_all_buffers = 201;
static int32_t fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 202;
static int32_t fcoder_metacmd_ID_select_surrounding_scope = 203;
static int32_t fcoder_metacmd_ID_select_next_scope_absolute = 204;
static int32_t fcoder_metacmd_ID_select_prev_scope_absolute = 205;
static int32_t fcoder_metacmd_ID_place_in_scope = 206;
static int32_t fcoder_metacmd_ID_delete_current_scope = 207;
static int32_t fcoder_metacmd_ID_scope_absorb_down = 208;
static int32_t fcoder_metacmd_ID_open_long_braces = 209;
static int32_t fcoder_metacmd_ID_open_long_braces_semicolon = 210;
static int32_t fcoder_metacmd_ID_open_long_braces_break = 211;
static int32_t fcoder_metacmd_ID_if0_off = 212;
static int32_t fcoder_metacmd_ID_write_todo = 213;
static int32_t fcoder_metacmd_ID_write_hack = 214;
static int32_t fcoder_metacmd_ID_write_note = 215;
static int32_t fcoder_metacmd_ID_write_block = 216;
static int32_t fcoder_metacmd_ID_write_zero_struct = 217;
static int32_t fcoder_metacmd_ID_comment_line = 218;
static int32_t fcoder_metacmd_ID_uncomment_line = 219;
static int32_t fcoder_metacmd_ID_comment_line_toggle = 220;
static int32_t fcoder_metacmd_ID_snippet_lister = 221;
static int32_t fcoder_metacmd_ID_set_bindings_choose = 222;
static int32_t fcoder_metacmd_ID_set_bindings_default = 223;
static int32_t fcoder_metacmd_ID_set_bindings_mac_default = 224;
static int32_t fcoder_metacmd_ID_miblo_increment_basic = 225;
static int32_t fcoder_metacmd_ID_miblo_decrement_basic = 226;
static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp = 227;
static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp = 228;
static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 229;
static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 230;
static int32_t fcoder_metacmd_ID_kill_rect = 231;
static int32_t fcoder_metacmd_ID_multi_line_edit = 232;
static int32_t fcoder_metacmd_ID_rename_parameter = 233;
static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 234;
static int32_t fcoder_metacmd_ID_write_explicit_enum_flags = 235;
#endif

View File

@ -75,11 +75,11 @@ bind(context, key_page_up, MDFR_CTRL|MDFR_SHIFT, goto_beginning_of_file);
bind(context, key_page_down, MDFR_CTRL|MDFR_SHIFT, goto_end_of_file);
bind(context, key_page_up, MDFR_SHIFT, page_up);
bind(context, key_page_down, MDFR_SHIFT, page_down);
bind(context, key_up, MDFR_CTRL, move_up_to_blank_line_end);
bind(context, key_up, MDFR_CTRL, move_up_to_blank_line_skip_whitespace);
bind(context, key_down, MDFR_CTRL, move_down_to_blank_line_end);
bind(context, key_left, MDFR_CTRL, move_left_whitespace_boundary);
bind(context, key_right, MDFR_CTRL, move_right_whitespace_boundary);
bind(context, key_up, MDFR_CTRL|MDFR_SHIFT, move_up_to_blank_line_end);
bind(context, key_up, MDFR_CTRL|MDFR_SHIFT, move_up_to_blank_line_skip_whitespace);
bind(context, key_down, MDFR_CTRL|MDFR_SHIFT, move_down_to_blank_line_end);
bind(context, key_left, MDFR_CTRL|MDFR_SHIFT, move_left_whitespace_boundary);
bind(context, key_right, MDFR_CTRL|MDFR_SHIFT, move_right_whitespace_boundary);
@ -261,11 +261,11 @@ bind(context, key_page_up, MDFR_CTRL|MDFR_SHIFT, goto_beginning_of_file);
bind(context, key_page_down, MDFR_CTRL|MDFR_SHIFT, goto_end_of_file);
bind(context, key_page_up, MDFR_SHIFT, page_up);
bind(context, key_page_down, MDFR_SHIFT, page_down);
bind(context, key_up, MDFR_CMND, move_up_to_blank_line_end);
bind(context, key_up, MDFR_CMND, move_up_to_blank_line_skip_whitespace);
bind(context, key_down, MDFR_CMND, move_down_to_blank_line_end);
bind(context, key_left, MDFR_CMND, move_left_whitespace_boundary);
bind(context, key_right, MDFR_CMND, move_right_whitespace_boundary);
bind(context, key_up, MDFR_CMND|MDFR_SHIFT, move_up_to_blank_line_end);
bind(context, key_up, MDFR_CMND|MDFR_SHIFT, move_up_to_blank_line_skip_whitespace);
bind(context, key_down, MDFR_CMND|MDFR_SHIFT, move_down_to_blank_line_end);
bind(context, key_left, MDFR_CMND|MDFR_SHIFT, move_left_whitespace_boundary);
bind(context, key_right, MDFR_CMND|MDFR_SHIFT, move_right_whitespace_boundary);
@ -477,11 +477,11 @@ static Meta_Key_Bind fcoder_binds_for_default_mapid_file[78] = {
{0, 55306, 9, "goto_end_of_file", 16, LINK_PROCS(goto_end_of_file)},
{0, 55305, 8, "page_up", 7, LINK_PROCS(page_up)},
{0, 55306, 8, "page_down", 9, LINK_PROCS(page_down)},
{0, 55297, 1, "move_up_to_blank_line_end", 25, LINK_PROCS(move_up_to_blank_line_end)},
{0, 55297, 1, "move_up_to_blank_line_skip_whitespace", 37, LINK_PROCS(move_up_to_blank_line_skip_whitespace)},
{0, 55298, 1, "move_down_to_blank_line_end", 27, LINK_PROCS(move_down_to_blank_line_end)},
{0, 55299, 1, "move_left_whitespace_boundary", 29, LINK_PROCS(move_left_whitespace_boundary)},
{0, 55300, 1, "move_right_whitespace_boundary", 30, LINK_PROCS(move_right_whitespace_boundary)},
{0, 55297, 9, "move_up_to_blank_line_end", 25, LINK_PROCS(move_up_to_blank_line_end)},
{0, 55297, 9, "move_up_to_blank_line_skip_whitespace", 37, LINK_PROCS(move_up_to_blank_line_skip_whitespace)},
{0, 55298, 9, "move_down_to_blank_line_end", 27, LINK_PROCS(move_down_to_blank_line_end)},
{0, 55299, 9, "move_left_whitespace_boundary", 29, LINK_PROCS(move_left_whitespace_boundary)},
{0, 55300, 9, "move_right_whitespace_boundary", 30, LINK_PROCS(move_right_whitespace_boundary)},
@ -666,11 +666,11 @@ static Meta_Key_Bind fcoder_binds_for_mac_default_mapid_file[77] = {
{0, 55306, 9, "goto_end_of_file", 16, LINK_PROCS(goto_end_of_file)},
{0, 55305, 8, "page_up", 7, LINK_PROCS(page_up)},
{0, 55306, 8, "page_down", 9, LINK_PROCS(page_down)},
{0, 55297, 4, "move_up_to_blank_line_end", 25, LINK_PROCS(move_up_to_blank_line_end)},
{0, 55297, 4, "move_up_to_blank_line_skip_whitespace", 37, LINK_PROCS(move_up_to_blank_line_skip_whitespace)},
{0, 55298, 4, "move_down_to_blank_line_end", 27, LINK_PROCS(move_down_to_blank_line_end)},
{0, 55299, 4, "move_left_whitespace_boundary", 29, LINK_PROCS(move_left_whitespace_boundary)},
{0, 55300, 4, "move_right_whitespace_boundary", 30, LINK_PROCS(move_right_whitespace_boundary)},
{0, 55297, 12, "move_up_to_blank_line_end", 25, LINK_PROCS(move_up_to_blank_line_end)},
{0, 55297, 12, "move_up_to_blank_line_skip_whitespace", 37, LINK_PROCS(move_up_to_blank_line_skip_whitespace)},
{0, 55298, 12, "move_down_to_blank_line_end", 27, LINK_PROCS(move_down_to_blank_line_end)},
{0, 55299, 12, "move_left_whitespace_boundary", 29, LINK_PROCS(move_left_whitespace_boundary)},
{0, 55300, 12, "move_right_whitespace_boundary", 30, LINK_PROCS(move_right_whitespace_boundary)},

View File

@ -638,9 +638,9 @@ scan(Application_Links *app, Boundary_Function_List funcs, Buffer_ID buffer, Sca
}
else{
result = -1;
for (Boundary_Function_Node *node = funcs.first;
node != 0;
node = node->next){
for (Boundary_Function_Node *node = funcs.first;
node != 0;
node = node->next){
i32 pos = scan(app, node->func, buffer, direction, start_pos);
result = Max(result, pos);
}

View File

@ -33,6 +33,15 @@ struct File_Name_Data{
////////////////////////////////
typedef i32 Position_Within_Line;
enum{
PositionWithinLine_Start,
PositionWithinLine_SkipLeadingWhitespace,
PositionWithinLine_End,
};
////////////////////////////////
typedef b8 Character_Predicate_Function(u8 c);
global Character_Predicate character_predicate_alpha = { {

View File

@ -263,7 +263,7 @@ Buffers should not be killed or created durring a buffer loop.
DOC_SEE(Access_Flag)
DOC_SEE(get_buffer_first)
*/{
Models *models = (Models*)app->cmd_context;
Models *models = (Models*)app->cmd_context;
Working_Set *working_set = &models->working_set;
Editing_File *file = working_set_get_active_file(working_set, buffer_id);
file = file_get_next(working_set, file);
@ -461,93 +461,38 @@ Buffer_Seek_String(Application_Links *app, Buffer_ID buffer, String_Const_u8 nee
if (api_check_buffer(file)){
if (needle.size == 0){
*pos_out = start_pos;
result = true;
*case_sensitive_out = true;
}
else{
Scratch_Block scratch(app);
Gap_Buffer *gap_buffer = &file->state.buffer;
i32 size = buffer_size(gap_buffer);
if (size >= (imem)needle.size){
u8 first_character = character_to_upper(needle.str[0]);
i32 last_point = size - (i32)(needle.size) + 1;
String_Const_u8 chunks_space[2];
Cursor chunks_cursor = make_cursor(chunks_space, sizeof(chunks_space));
String_Const_u8_Array chunks = buffer_get_chunks(&chunks_cursor, gap_buffer, BufferGetChunk_Basic);
start_pos = clamp(-1, start_pos, last_point + 1);
Buffer_Chunk_Position pos = buffer_get_chunk_position(chunks, size, start_pos);
if (direction == Scan_Forward){
for (; pos.chunk_index < chunks.count; pos.chunk_index += 1, pos.chunk_pos = 0){
for (;;){
pos.real_pos += 1;
if (pos.real_pos > last_point){
goto done_forward;
}
pos.chunk_pos += 1;
if (pos.chunk_pos >= chunks.vals[pos.chunk_index].size){
break;
}
// TODO(allen): "point skip array" for speedup
u8 v = chunks.vals[pos.chunk_index].str[pos.chunk_pos];
if (character_to_upper(v) == first_character){
if (chunked_match(chunks, needle, pos.chunk_index, pos.chunk_pos, case_sensitive_out)){
*pos_out = pos.real_pos;
result = true;
goto done_forward;
}
}
}
}
done_forward:;
if (!result){
*pos_out = size;
}
}
else{
for (;;){
for (;;){
pos.real_pos -= 1;
if (pos.real_pos < 0){
goto done_backward;
}
pos.chunk_pos -= 1;
if (pos.chunk_pos < 0){
break;
}
// TODO(allen): "point skip array" for speedup
u8 v = chunks.vals[pos.chunk_index].str[pos.chunk_pos];
if (character_to_upper(v) == first_character){
if (chunked_match(chunks, needle, pos.chunk_index, pos.chunk_pos, case_sensitive_out)){
*pos_out = pos.real_pos;
result = true;
goto done_forward;
}
}
}
pos.chunk_index -= 1;
if (pos.chunk_index >= 0){
pos.chunk_pos = (i32)chunks.vals[pos.chunk_index].size - 1;
}
else{
break;
}
}
done_backward:;
if (!result){
*pos_out = 0;
}
}
String_Const_u8 space[3];
Cursor cursor = make_cursor(space, sizeof(space));
String_Const_u8_Array chunks = buffer_get_chunks(&cursor, gap_buffer);
Range range = {};
if (direction == Scan_Forward){
range = make_range(start_pos, size);
}
else{
*pos_out = 0;
range = make_range(0, start_pos);
}
chunks = buffer_chunks_clamp(chunks, range);
u64_Array jump_table = string_compute_needle_jump_table(scratch, needle, direction);
Character_Predicate dummy = {};
String_Match_List list = find_all_matches(scratch, 1,
chunks, needle, jump_table, &dummy, direction,
range.min, 0);
if (list.count == 1){
result = true;
*pos_out = (i32)list.first->index;
*case_sensitive_out = (HasFlag(list.first->flags, StringMatch_CaseSensitive));
}
}
}
return(result);
}
#define character_predicate_check_character(p, c) (((p).b[(c)/8] & (1 << ((c)%8))) != 0)
API_EXPORT b32
Buffer_Seek_Character_Class(Application_Links *app, Buffer_ID buffer_id, Character_Predicate *predicate, Scan_Direction direction, i32 start_pos, i32 *pos_out){
Models *models = (Models*)app->cmd_context;
@ -1197,7 +1142,7 @@ DOC_SEE(Buffer_Save_Flag)
b32 skip_save = false;
if (!(flags & BufferSave_IgnoreDirtyFlag)){
if (file->state.dirty == DirtyState_UpToDate){
skip_save = true;
skip_save = true;
}
}
@ -1565,7 +1510,7 @@ View_Get_Preferred_X(Application_Links *app, View_ID view_id, f32 *preferred_x_o
b32 result = false;
if (api_check_view(view)){
*preferred_x_out = view->preferred_x;
result = true;
result = true;
}
return(result);
}
@ -4363,208 +4308,31 @@ Animate_In_N_Milliseconds(Application_Links *app, u32 n)
}
}
// NOTE(casey): Find_All_In_Range_Insensitive is the only routine supplied, because anyone who would prefer case-sensitive can
// check afterward.
// TODO(casey): Allen, this routine is very intricate and needs to be tested thoroughly before mainlining. I've only done cursory testing on it and have probably missed bugs that only occur in highly segmented buffers.
// TODO(casey): I think this routine could potentially be simplified by making it into something that always works with a partial match list, where the partial matches have 0 characters matched, and they just get moved forward as they go. This would solve the duplicate code problem the routine currently has where it does the same thing in its two halves, but slightly differently.
API_EXPORT Found_String_List
Find_All_In_Range_Insensitive(Application_Links *app, Buffer_ID buffer_id, i32 start, i32 end, String_Const_u8 key, Arena *arena)
API_EXPORT String_Match_List
Find_All_Matches_Buffer_Range(Application_Links *app, Arena *arena, Buffer_ID buffer, Range range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction)
{
Found_String_List result = {};
Found_String *first_partial = 0;
Found_String *first_free = 0;
Models *models = (Models*)app->cmd_context;
Editing_File *file = imp_get_file(models, buffer_id);
if((file != 0) && key.size)
{
i32 total_size = buffer_size(&file->state.buffer);
u32 clean_edegs = FoundString_CleanEdges;
if (0 <= start && start <= end && end <= total_size)
{
Gap_Buffer *gap = &file->state.buffer;
Gap_Buffer_Stream stream = {};
i32 i = start;
if (buffer_stringify_loop(&stream, gap, i, end))
{
b32 still_looping = 0;
do
{
i32 size = stream.end - i;
char *data = stream.data + i;
// NOTE(casey): Check all partial matches
Found_String **partial = &first_partial;
while(*partial)
{
Found_String *check = *partial;
i32 trailing_char_at = ((check->location.start + (i32)key.size) - check->location.end);
i32 remaining = trailing_char_at;
b32 valid = true;
b32 full = true;
if(remaining > size)
{
full = false;
remaining = size;
}
for(i32 test = 0;
test < remaining;
++test)
{
char a = key.str[test];
char b = data[test];
if(a != b)
{
check->flags &= ~FoundString_Sensitive;
}
if(character_to_lower(a) != character_to_lower(b))
{
valid = false;
break;
}
}
check->location.end += remaining;
if(valid)
{
// NOTE(casey): Although technically "full matches" are full, we haven't yet checked the trailing edge for tokenization,
// so we need to shunt to partial in the cases where we _can't_ check the overhanging character.
full = full && (trailing_char_at < size);
if(full)
{
if(character_is_alpha_numeric(data[trailing_char_at]))
{
check->flags &= ~FoundString_CleanEdges;
}
// NOTE(casey): This is a full match now, so we can move it to the result list
*partial = check->next;
check->next = 0;
result.last = (result.last ? result.last->next : result.first) = check;
++result.count;
}
else
{
// NOTE(casey): This is still a partial match, so we just look at the next one
partial = &check->next;
}
}
else
{
// NOTE(casey): This is no longer a potential match, eliminate it.
*partial = check->next;
check->next = first_free;
first_free = check;
}
}
// NOTE(casey): Check for new matches
// TODO(casey): We could definitely do way more efficient string matching here
for(i32 at = 0;
at < size;
++at)
{
i32 remaining = size - at;
b32 full = false;
if(remaining >= key.size)
{
full = true;
remaining = (i32)key.size;
}
u32 exact_matched = FoundString_Sensitive;
b32 lower_matched = true;
for(i32 test = 0;
test < remaining;
++test)
{
char a = key.str[test];
char b = data[at + test];
if(a != b)
{
exact_matched = 0;
}
if(character_to_lower(a) != character_to_lower(b))
{
lower_matched = false;
break;
}
}
if(lower_matched)
{
Found_String *found = first_free;
if(found)
{
first_free = found->next;
}
else
{
found = push_array(arena, Found_String, 1);
}
if(found)
{
found->next = 0;
found->buffer_id = buffer_id;
found->flags = FoundString_Insensitive | exact_matched | clean_edegs;
found->string_id = 0;
found->location.start = i + at;
found->location.end = found->location.start + remaining;
// NOTE(casey): Although technically "full matches" are full, we haven't yet checked the trailing edge for tokenization,
// so we need to shunt to partial in the cases where we _can't_ check the overhanging character.
i32 trailing_char_at = (at + (i32)key.size);
full = full && (trailing_char_at < size);
if(full)
{
if(character_is_alpha_numeric(data[trailing_char_at]))
{
found->flags &= ~FoundString_CleanEdges;
}
result.last = (result.last ? result.last->next : result.first) = found;
++result.count;
}
else
{
found->flags |= FoundString_Straddled;
*partial = (*partial ? (*partial)->next : first_partial) = found;
}
}
else
{
// TODO(casey): Allen, this is a non-fatal error that produces bad results - eg., there's not enough
// memory to actually store all the locations found. Hopefully this will never happen once this can
// be fed through a growable arena - right now it happens all the time, because the partition is too f'ing tiny.
}
}
if(character_is_alpha(data[at]))
{
clean_edegs = 0;
}
else
{
clean_edegs = FoundString_CleanEdges;
}
}
i = stream.end;
still_looping = buffer_stringify_next(&stream);
} while(still_looping);
Editing_File *file = imp_get_file(models, buffer);
String_Match_List list = {};
if (api_check_buffer(file)){
if (needle.size > 0){
String_Const_u8 space[3];
Cursor cursor = make_cursor(space, sizeof(space));
String_Const_u8_Array chunks = buffer_get_chunks(&cursor, &file->state.buffer);
chunks = buffer_chunks_clamp(chunks, range);
if (chunks.count > 0){
u64_Array jump_table = string_compute_needle_jump_table(arena, needle, direction);
Character_Predicate dummy = {};
if (predicate == 0){
predicate = &dummy;
}
list = find_all_matches(arena, max_i32,
chunks, needle, jump_table, predicate, direction,
range.min, buffer);
}
}
}
return(result);
return(list);
}
API_EXPORT Range

View File

@ -80,6 +80,7 @@ struct Mem_Options{
#include "4ed_render_format.cpp"
#include "4ed_command.cpp"
#include "4ed_buffer.cpp"
#include "4ed_string_matching.cpp"
#include "4ed_history.cpp"
#include "4ed_file_lex.cpp"
#include "4ed_file.cpp"

View File

@ -535,6 +535,27 @@ buffer_get_chunks(Cursor *cursor, Gap_Buffer *buffer){
return(buffer_get_chunks(cursor, buffer, BufferGetChunk_Basic));
}
internal String_Const_u8_Array
buffer_chunks_clamp(String_Const_u8_Array chunks, Range range){
i32 real_position = 0;
for (i32 i = 0; i < chunks.count; i += 1){
Range chunk_range = make_range(real_position, real_position + (i32)chunks.strings[i].size);
Range clamped_range = make_range(clamp(range.min, chunk_range.min, range.max),
clamp(range.min, chunk_range.max, range.max));
chunks.strings[i].str += clamped_range.min - chunk_range.min;
chunks.strings[i].size = range_size(clamped_range);
real_position += range_size(chunk_range);
}
for (; chunks.count > 0 && chunks.strings[0].size == 0;){
chunks.strings += 1;
chunks.count -= 1;
}
for (; chunks.count > 0 && chunks.strings[chunks.count - 1].size == 0;){
chunks.count -= 1;
}
return(chunks);
}
internal void
buffer_stringify(Gap_Buffer *buffer, i32 start, i32 end, char *out){
Gap_Buffer_Stream stream = {};

338
4ed_string_matching.cpp Normal file
View File

@ -0,0 +1,338 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 16.06.2019
*
* Routines for string matching within chunked streams.
*
*/
// TOP
internal u64_Array
string_compute_prefix_table(Arena *arena, String_Const_u8 string, Scan_Direction direction){
u64_Array array = {};
array.count = (i32)(string.size);
array.vals = push_array(arena, u64, array.count);
u8 *str = string.str;
if (direction == Scan_Backward){
str = string.str + string.size - 1;
}
array.vals[0] = 0;
for (u64 i = 1; i < string.size; i += 1){
u64 previous_longest_prefix = array.vals[i - 1];
for (;;){
u8 *a = str + previous_longest_prefix;
u8 *b = str + i;
if (direction == Scan_Backward){
a = str - previous_longest_prefix;
b = str - i;
}
if (character_to_upper(*a) == character_to_upper(*b)){
array.vals[i] = previous_longest_prefix + 1;
break;
}
if (previous_longest_prefix == 0){
array.vals[i] = 0;
break;
}
previous_longest_prefix = array.vals[previous_longest_prefix - 1];
}
}
return(array);
}
internal u64_Array
string_compute_needle_jump_table(Arena *arena, u64_Array longest_prefixes){
u64_Array array = {};
array.count = longest_prefixes.count + 1;
array.vals = push_array(arena, u64, array.count);
array.vals[0] = 0;
for (u64 i = 1; i < array.count; i += 1){
array.vals[i] = i - longest_prefixes.vals[i - 1];
}
return(array);
}
internal u64_Array
string_compute_needle_jump_table(Arena *arena, String_Const_u8 needle, Scan_Direction direction){
u64_Array prefix_table = string_compute_prefix_table(arena, needle, direction);
return(string_compute_needle_jump_table(arena, prefix_table));
}
internal void
string_match_list_push(Arena *arena, String_Match_List *list,
u64 index, String_Match_Flag flags, Buffer_ID buffer){
String_Match *match = push_array(arena, String_Match, 1);
sll_queue_push(list->first, list->last, match);
list->count += 1;
match->buffer = buffer;
match->flags = flags;
match->index = index;
}
#define character_predicate_check_character(p, c) (((p).b[(c)/8] & (1 << ((c)%8))) != 0)
internal String_Match_List
find_all_matches_forward(Arena *arena, i32 maximum_output_count,
String_Const_u8_Array chunks, String_Const_u8 needle,
u64_Array jump_table, Character_Predicate *predicate,
u64 base_index, Buffer_ID buffer){
String_Match_List list = {};
if (chunks.count > 0){
u64 i = 0;
u64 j = 0;
b8 current_l = false;
i64 last_insensitive = -1;
i64 last_boundary = -1;
i32 chunk_index = 0;
i64 chunk_pos = 0;
String_Const_u8 chunk = chunks.strings[chunk_index];
i32 jump_back_code = 0;
if (false){
iterate_forward:
i += 1;
chunk_pos += 1;
if (chunk_pos >= (i64)chunk.size){
last_boundary = i;
chunk_pos = 0;
chunk_index += 1;
if (chunk_index < chunks.count){
chunk = chunks.strings[chunk_index];
}
}
switch (jump_back_code){
case 0:
{
goto jump_back_0;
}break;
case 1:
{
goto jump_back_1;
}break;
}
}
for (;chunk_index < chunks.count;){
u8 c = chunk.str[chunk_pos];
u64 n = i - j;
u8 needle_c = needle.str[n];
if (character_to_upper(c) == character_to_upper(needle_c)){
if (c != needle_c){
last_insensitive = i;
}
jump_back_code = 0;
goto iterate_forward;
jump_back_0:
if (n + 1 == needle.size){
String_Match_Flag flags = {};
if (!(last_insensitive >= 0 &&
j <= (u64)last_insensitive &&
(u64)last_insensitive < j + needle.size)){
AddFlag(flags, StringMatch_CaseSensitive);
}
if (!(last_boundary >= 0 &&
j <= (u64)last_boundary &&
(u64)last_boundary < j + needle.size)){
AddFlag(flags, StringMatch_Straddled);
}
if (chunk_index < chunks.count){
u8 next_c = chunk.str[chunk_pos];
if (character_predicate_check_character(*predicate, next_c)){
AddFlag(flags, StringMatch_RightSideSloppy);
}
}
if (current_l){
AddFlag(flags, StringMatch_LeftSideSloppy);
}
string_match_list_push(arena, &list, base_index + j, flags, buffer);
if (list.count >= maximum_output_count){
break;
}
u64 jump = jump_table.vals[n + 1];
current_l = character_predicate_check_character(*predicate, needle.str[jump - 1]);
j += jump;
}
}
else{
u64 jump = jump_table.vals[n];
if (jump == 0){
current_l = character_predicate_check_character(*predicate, c);
jump_back_code = 1;
goto iterate_forward;
jump_back_1:
j += 1;
}
else{
u8 prev_c = needle.str[jump - 1];
current_l = character_predicate_check_character(*predicate, prev_c);
j += jump;
}
}
}
}
return(list);
}
internal String_Match_List
find_all_matches_backward(Arena *arena, i32 maximum_output_count,
String_Const_u8_Array chunks, String_Const_u8 needle,
u64_Array jump_table, Character_Predicate *predicate,
u64 base_index, Buffer_ID buffer){
String_Match_List list = {};
if (chunks.count > 0){
i64 size = 0;
for (i32 i = 0; i < chunks.count; i += 1){
size += chunks.strings[i].size;
}
i64 i = size - 1;
i64 j = size - 1;
b8 current_r = false;
i64 last_insensitive = size;
i64 last_boundary = size;
i32 chunk_index = chunks.count - 1;
String_Const_u8 chunk = chunks.strings[chunk_index];
i64 chunk_pos = chunk.size - 1;
i32 jump_back_code = 0;
if (false){
iterate_backward:
i -= 1;
chunk_pos -= 1;
if (chunk_pos < 0){
last_boundary = i;
chunk_index -= 1;
if (chunk_index >= 0){
chunk = chunks.strings[chunk_index];
chunk_pos = chunk.size - 1;
}
}
switch (jump_back_code){
case 0:
{
goto jump_back_0;
}break;
case 1:
{
goto jump_back_1;
}break;
}
}
for (;chunk_index >= 0;){
u8 c = chunk.str[chunk_pos];
u64 n = j - i;
u8 needle_c = needle.str[needle.size - 1 - n];
if (character_to_upper(c) == character_to_upper(needle_c)){
if (c != needle_c){
last_insensitive = i;
}
jump_back_code = 0;
goto iterate_backward;
jump_back_0:
if (n + 1 == needle.size){
String_Match_Flag flags = {};
if (!(last_insensitive < size &&
j >= last_insensitive &&
last_insensitive > j - (i64)needle.size)){
AddFlag(flags, StringMatch_CaseSensitive);
}
if (!(last_boundary < size &&
j >= last_boundary &&
last_boundary > j - (i64)needle.size)){
AddFlag(flags, StringMatch_Straddled);
}
if (chunk_index >= 0){
u8 next_c = chunk.str[chunk_pos];
if (character_predicate_check_character(*predicate, next_c)){
AddFlag(flags, StringMatch_LeftSideSloppy);
}
}
if (current_r){
AddFlag(flags, StringMatch_RightSideSloppy);
}
string_match_list_push(arena, &list,
base_index + (j - (needle.size - 1)), flags, buffer);
if (list.count >= maximum_output_count){
break;
}
u64 jump = jump_table.vals[n + 1];
u64 m = needle.size - jump;
u8 needle_m = needle.str[m];
current_r = character_predicate_check_character(*predicate, needle_m);
j -= jump;
}
}
else{
u64 jump = jump_table.vals[n];
if (jump == 0){
current_r = character_predicate_check_character(*predicate, c);
jump_back_code = 1;
goto iterate_backward;
jump_back_1:
j -= 1;
}
else{
u64 m = needle.size - jump;
u8 needle_m = needle.str[m];
current_r = character_predicate_check_character(*predicate, needle_m);
j -= jump;
}
}
}
}
return(list);
}
internal String_Match_List
find_all_matches(Arena *arena, i32 maximum_output_count,
String_Const_u8_Array chunks, String_Const_u8 needle,
u64_Array jump_table, Character_Predicate *predicate,
Scan_Direction direction,
u64 base_index, Buffer_ID buffer){
String_Match_List list = {};
switch (direction){
case Scan_Forward:
{
list = find_all_matches_forward(arena, maximum_output_count,
chunks, needle, jump_table, predicate,
base_index, buffer);
}break;
case Scan_Backward:
{
list = find_all_matches_backward(arena, maximum_output_count,
chunks, needle, jump_table, predicate,
base_index, buffer);
}break;
}
return(list);
}
// BOTTOM

View File

@ -531,11 +531,11 @@ generate_remapping_code_and_data(Arena *arena){
bind(arena, mappings, key_page_up, MDFR_SHIFT, page_up);
bind(arena, mappings, key_page_down, MDFR_SHIFT, page_down);
bind(arena, mappings, key_up, MDFR_CTRL, move_up_to_blank_line_end);
bind(arena, mappings, key_up, MDFR_CTRL, move_up_to_blank_line_skip_whitespace);
bind(arena, mappings, key_down, MDFR_CTRL, move_down_to_blank_line_end);
bind(arena, mappings, key_left, MDFR_CTRL, move_left_whitespace_boundary);
bind(arena, mappings, key_right, MDFR_CTRL, move_right_whitespace_boundary);
bind(arena, mappings, key_up, MDFR_CTRL|MDFR_SHIFT, move_up_to_blank_line_end);
bind(arena, mappings, key_up, MDFR_CTRL|MDFR_SHIFT, move_up_to_blank_line_skip_whitespace);
bind(arena, mappings, key_down, MDFR_CTRL|MDFR_SHIFT, move_down_to_blank_line_end);
bind(arena, mappings, key_left, MDFR_CTRL|MDFR_SHIFT, move_left_whitespace_boundary);
bind(arena, mappings, key_right, MDFR_CTRL|MDFR_SHIFT, move_right_whitespace_boundary);
@ -760,11 +760,11 @@ generate_remapping_code_and_data(Arena *arena){
bind(arena, mappings, key_page_up, MDFR_SHIFT, page_up);
bind(arena, mappings, key_page_down, MDFR_SHIFT, page_down);
bind(arena, mappings, key_up, MDFR_CMND, move_up_to_blank_line_end);
bind(arena, mappings, key_up, MDFR_CMND, move_up_to_blank_line_skip_whitespace);
bind(arena, mappings, key_down, MDFR_CMND, move_down_to_blank_line_end);
bind(arena, mappings, key_left, MDFR_CMND, move_left_whitespace_boundary);
bind(arena, mappings, key_right, MDFR_CMND, move_right_whitespace_boundary);
bind(arena, mappings, key_up, MDFR_CMND|MDFR_SHIFT, move_up_to_blank_line_end);
bind(arena, mappings, key_up, MDFR_CMND|MDFR_SHIFT, move_up_to_blank_line_skip_whitespace);
bind(arena, mappings, key_down, MDFR_CMND|MDFR_SHIFT, move_down_to_blank_line_end);
bind(arena, mappings, key_left, MDFR_CMND|MDFR_SHIFT, move_left_whitespace_boundary);
bind(arena, mappings, key_right, MDFR_CMND|MDFR_SHIFT, move_right_whitespace_boundary);