gap buffer editing
This commit is contained in:
parent
d3913c0c7a
commit
7c2d26463e
|
@ -2,7 +2,7 @@
|
|||
* Example use of customization API
|
||||
*/
|
||||
|
||||
// NOTE(allen): NEW THINGS TO LOOK FOR:
|
||||
// NOTE(allen|a3.1): NEW THINGS TO LOOK FOR:
|
||||
// mapid_user_custom - define maps other than the built in global and file maps
|
||||
//
|
||||
// inherit_map - override bindings or add new bindings in a new map with another
|
||||
|
@ -52,7 +52,7 @@
|
|||
|
||||
#define literal(s) s, (sizeof(s)-1)
|
||||
|
||||
// NOTE(allen): All of your custom ids should be >= mapid_user_custom.
|
||||
// NOTE(allen|a3.1): All of your custom ids should be >= mapid_user_custom.
|
||||
// I recommend enumerating your own map ids as shown here.
|
||||
enum My_Maps{
|
||||
my_code_map = mapid_user_custom,
|
||||
|
@ -63,30 +63,6 @@ HOOK_SIG(my_start){
|
|||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_my_files){
|
||||
// NOTE(allen): The command cmdid_interactive_open has is now able to
|
||||
// open a file specified on the parameter stack. If the file does not
|
||||
// exist cmdid_interactive_open behaves as usual.
|
||||
push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
|
||||
char my_file[256];
|
||||
int my_file_len;
|
||||
|
||||
my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1;
|
||||
for (int i = 0; i < my_file_len; ++i){
|
||||
my_file[i] = ("w:/4ed/data/test/basic.txt")[i];
|
||||
}
|
||||
|
||||
// NOTE(allen): null terminators are not needed for strings.
|
||||
push_parameter(cmd_context, par_name, my_file, my_file_len);
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
}
|
||||
|
||||
char *get_extension(const char *filename, int len, int *extension_len){
|
||||
char *c = (char*)(filename + len - 1);
|
||||
char *end = c;
|
||||
|
@ -112,7 +88,7 @@ HOOK_SIG(my_file_settings){
|
|||
|
||||
int treat_as_code = 0;
|
||||
|
||||
// NOTE(allen): This checks buffer.file_name just in case get_active_buffer returns back
|
||||
// NOTE(allen|a3.1): This checks buffer.file_name just in case get_active_buffer returns back
|
||||
// a null buffer (where every member is 0).
|
||||
if (buffer.file_name && buffer.size < (16 << 20)){
|
||||
int extension_len;
|
||||
|
@ -134,12 +110,41 @@ CUSTOM_COMMAND_SIG(open_in_other){
|
|||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(open_my_files){
|
||||
// NOTE(allen|a3.1): The command cmdid_interactive_open can now open
|
||||
// a file specified on the parameter stack. If the file does not
|
||||
// exist cmdid_interactive_open behaves as usual.
|
||||
push_parameter(cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
|
||||
char my_file[256];
|
||||
int my_file_len;
|
||||
|
||||
my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1;
|
||||
for (int i = 0; i < my_file_len; ++i){
|
||||
my_file[i] = ("w:/4ed/data/test/basic.txt")[i];
|
||||
}
|
||||
|
||||
// NOTE(allen|3.1): null terminators are not needed for strings.
|
||||
push_parameter(cmd_context, par_name, my_file, my_file_len);
|
||||
exec_command(cmd_context, cmdid_interactive_open);
|
||||
|
||||
exec_command(cmd_context, cmdid_change_active_panel);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
||||
exec_command(cmd_context, cmdid_write_character);
|
||||
exec_command(cmd_context, cmdid_auto_tab_line_at_cursor);
|
||||
}
|
||||
|
||||
extern "C" GET_BINDING_DATA(get_bindings){
|
||||
Bind_Helper context_actual = begin_bind_helper(data, size);
|
||||
Bind_Helper *context = &context_actual;
|
||||
|
||||
// NOTE(allen): Right now hooks have no loyalties to maps, all hooks are
|
||||
// global and once set they always apply.
|
||||
// NOTE(allen|a3.1): Right now hooks have no loyalties to maps, all hooks are
|
||||
// global and once set they always apply, regardless of what map is active.
|
||||
set_hook(context, hook_start, my_start);
|
||||
set_hook(context, hook_open_file, my_file_settings);
|
||||
|
||||
|
@ -156,7 +161,8 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
|
||||
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
|
||||
bind_me(context, 'o', MDFR_ALT, open_in_other);
|
||||
// NOTE(allen): Go look at open_my_files, that's the only point of this being here.
|
||||
// NOTE(allen|a3.1): Go look at open_my_files, that's the only point of this being here,
|
||||
// it won't actually be useful for you.
|
||||
bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
|
||||
|
||||
end_map(context);
|
||||
|
@ -164,26 +170,36 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
|
||||
begin_map(context, my_code_map);
|
||||
|
||||
// NOTE(allen): Set this map (my_code_map == mapid_user_custom) to
|
||||
// NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to
|
||||
// inherit from mapid_file. When searching if a key is bound
|
||||
// in this map, if it is not found here it will then search mapid_file.
|
||||
//
|
||||
// If this is not set, it defaults to mapid_global.
|
||||
inherit_map(context, mapid_file);
|
||||
|
||||
// NOTE(allen): This demonstrates that children can override parent's bindings.
|
||||
|
||||
// NOTE(allen|a3.1): Children can override parent's bindings.
|
||||
bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
|
||||
bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
|
||||
|
||||
// NOTE(allen): Not currently functional
|
||||
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab);
|
||||
// NOTE(allen|a3.1.1): Specific keys can override vanilla keys,
|
||||
// and write character writes whichever character corresponds
|
||||
// to the key that triggered the command.
|
||||
bind_me(context, '\n', MDFR_NONE, write_and_auto_tab);
|
||||
bind_me(context, '}', MDFR_NONE, write_and_auto_tab);
|
||||
bind_me(context, ')', MDFR_NONE, write_and_auto_tab);
|
||||
bind_me(context, ']', MDFR_NONE, write_and_auto_tab);
|
||||
bind_me(context, ';', MDFR_NONE, write_and_auto_tab);
|
||||
|
||||
bind(context, '\t', MDFR_NONE, cmdid_auto_tab_line_at_cursor);
|
||||
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range);
|
||||
bind(context, '\t', MDFR_CTRL | MDFR_SHIFT, cmdid_write_character);
|
||||
|
||||
end_map(context);
|
||||
|
||||
|
||||
|
||||
begin_map(context, mapid_file);
|
||||
|
||||
// NOTE(allen): Binding this essentially binds all key combos that
|
||||
// NOTE(allen|a3.1): Binding this essentially binds all key combos that
|
||||
// would normally insert a character into a buffer.
|
||||
// Or apply this rule (which always works): if the code for the key
|
||||
// is not in the codes struct, it is a vanilla key.
|
||||
|
@ -228,7 +244,7 @@ extern "C" GET_BINDING_DATA(get_bindings){
|
|||
bind(context, '?', MDFR_CTRL, cmdid_toggle_show_whitespace);
|
||||
|
||||
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
|
||||
// NOTE(allen): These now only set the mode of the file for writing to disk
|
||||
// NOTE(allen|a3.1.1): These now only set the mode of the file for writing to disk
|
||||
// they do no longer effect the internal representation.
|
||||
bind(context, '1', MDFR_CTRL, cmdid_eol_dosify);
|
||||
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
|
||||
|
|
90
4ed.cpp
90
4ed.cpp
|
@ -354,55 +354,23 @@ COMMAND_DECL(seek_alphanumeric_left){
|
|||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_or_camel_right){
|
||||
#if 0
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
char *data = file->buffer.data;
|
||||
|
||||
i32 an_pos, camel_pos;
|
||||
an_pos = seek_alphanumeric_right(
|
||||
(u8*)file->buffer.data, file->buffer.size, view->cursor.pos);
|
||||
|
||||
u8 curr_char;
|
||||
u8 prev_char = data[view->cursor.pos + 1];
|
||||
for (camel_pos = view->cursor.pos + 2; camel_pos < an_pos; ++camel_pos){
|
||||
curr_char = data[camel_pos];
|
||||
if (char_is_upper(curr_char) && char_is_lower(prev_char)){
|
||||
break;
|
||||
}
|
||||
prev_char = curr_char;
|
||||
}
|
||||
|
||||
view_cursor_move(view, camel_pos);
|
||||
#endif
|
||||
|
||||
i32 an_pos = buffer_seek_alphanumeric_right(&file->buffer, view->cursor.pos);
|
||||
i32 pos = buffer_seek_alphanumeric_or_camel_right(&file->buffer, view->cursor.pos, an_pos);
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
||||
COMMAND_DECL(seek_alphanumeric_or_camel_left){
|
||||
#if 0
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
||||
u8 *data = (u8*)file->buffer.data;
|
||||
|
||||
i32 an_pos, camel_pos;
|
||||
an_pos = buffer_seek_alphanumeric_left(
|
||||
data, view->cursor.pos);
|
||||
|
||||
char curr_char;
|
||||
char prev_char = data[view->cursor.pos];
|
||||
for (camel_pos = view->cursor.pos - 1; camel_pos > an_pos; --camel_pos){
|
||||
curr_char = data[camel_pos];
|
||||
if (char_is_upper(curr_char) && char_is_lower(prev_char)){
|
||||
break;
|
||||
}
|
||||
prev_char = curr_char;
|
||||
}
|
||||
|
||||
view_cursor_move(view, camel_pos);
|
||||
#endif
|
||||
i32 an_pos = buffer_seek_alphanumeric_left(&file->buffer, view->cursor.pos);
|
||||
i32 pos = buffer_seek_alphanumeric_or_camel_left(&file->buffer, view->cursor.pos, an_pos);
|
||||
view_cursor_move(view, pos);
|
||||
}
|
||||
|
||||
COMMAND_DECL(search){
|
||||
|
@ -458,13 +426,11 @@ COMMAND_DECL(copy){
|
|||
|
||||
Range range = get_range(view->cursor.pos, view->mark);
|
||||
if (range.start < range.end){
|
||||
u8 *data = (u8*)file->buffer.data;
|
||||
clipboard_copy(&mem->general, working_set, data, range);
|
||||
clipboard_copy(&mem->general, working_set, range, file);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(cut){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -474,17 +440,15 @@ COMMAND_DECL(cut){
|
|||
|
||||
Range range = get_range(view->cursor.pos, view->mark);
|
||||
if (range.start < range.end){
|
||||
u8 *data = (u8*)file->buffer.data;
|
||||
|
||||
i32 next_cursor_pos = range.start;
|
||||
clipboard_copy(&mem->general, working_set, data, range);
|
||||
|
||||
clipboard_copy(&mem->general, working_set, range, file);
|
||||
view_replace_range(mem, view, layout, range.start, range.end, 0, 0, next_cursor_pos);
|
||||
|
||||
view->mark = range.start;
|
||||
view_measure_wraps(&mem->general, view);
|
||||
view_cursor_move(view, next_cursor_pos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(paste){
|
||||
|
@ -561,7 +525,6 @@ COMMAND_DECL(paste_next){
|
|||
}
|
||||
|
||||
COMMAND_DECL(delete_chunk){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
|
@ -576,7 +539,6 @@ COMMAND_DECL(delete_chunk){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
view->mark = range.start;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(timeline_scrub){
|
||||
|
@ -1246,15 +1208,15 @@ COMMAND_DECL(move_right){
|
|||
}
|
||||
|
||||
COMMAND_DECL(delete){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
USE_LAYOUT(layout);
|
||||
USE_MEM(mem);
|
||||
|
||||
|
||||
i32 size = buffer_size(&file->buffer);
|
||||
i32 cursor_pos = view->cursor.pos;
|
||||
if (file->buffer.size > 0 && cursor_pos < file->buffer.size){
|
||||
if (0 < size && cursor_pos < size){
|
||||
i32 start, end;
|
||||
start = cursor_pos;
|
||||
end = cursor_pos+1;
|
||||
|
@ -1267,22 +1229,20 @@ COMMAND_DECL(delete){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
if (view->mark >= end) view->mark -= shift;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(backspace){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
ProfileMomentFunction();
|
||||
REQ_FILE_VIEW(view);
|
||||
REQ_FILE(file, view);
|
||||
USE_LAYOUT(layout);
|
||||
USE_MEM(mem);
|
||||
|
||||
i32 size = buffer_size(&file->buffer);
|
||||
i32 cursor_pos = view->cursor.pos;
|
||||
if (cursor_pos > 0 && cursor_pos <= (i32)file->buffer.size){
|
||||
if (cursor_pos > 0 && cursor_pos <= size){
|
||||
i32 start, end;
|
||||
end = cursor_pos;
|
||||
|
||||
start = cursor_pos-1;
|
||||
|
||||
i32 shift = (end - start);
|
||||
|
@ -1293,7 +1253,6 @@ COMMAND_DECL(backspace){
|
|||
view_cursor_move(view, next_cursor_pos);
|
||||
if (view->mark >= end) view->mark -= shift;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COMMAND_DECL(move_up){
|
||||
|
@ -1531,13 +1490,12 @@ COMMAND_DECL(set_settings){
|
|||
case par_key_mapid:
|
||||
{
|
||||
int v = dynamic_to_int(¶m->param.value);
|
||||
Command_Map *map = 0;
|
||||
if (v == mapid_global) map = &vars->map_top;
|
||||
else if (v == mapid_file) map = &vars->map_file;
|
||||
if (v == mapid_global) file->base_map_id = mapid_global;
|
||||
else if (v == mapid_file) file->base_map_id = mapid_file;
|
||||
else if (v >= mapid_user_custom){
|
||||
int index = app_get_map_index(vars, v);
|
||||
if (index < vars->user_map_count) map = vars->user_maps + index;
|
||||
else map = 0;
|
||||
if (index < vars->user_map_count) file->base_map_id = v;
|
||||
else file->base_map_id = mapid_file;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
@ -1685,8 +1643,8 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
|
|||
map_add(commands, codes->page_up, MDFR_NONE, command_page_up);
|
||||
map_add(commands, codes->page_down, MDFR_NONE, command_page_down);
|
||||
|
||||
map_add(commands, codes->right, MDFR_CTRL, command_seek_whitespace_right);
|
||||
map_add(commands, codes->left, MDFR_CTRL, command_seek_whitespace_left);
|
||||
map_add(commands, codes->right, MDFR_CTRL, command_seek_alphanumeric_or_camel_right);
|
||||
map_add(commands, codes->left, MDFR_CTRL, command_seek_alphanumeric_or_camel_left);
|
||||
map_add(commands, codes->up, MDFR_CTRL, command_seek_whitespace_up);
|
||||
map_add(commands, codes->down, MDFR_CTRL, command_seek_whitespace_down);
|
||||
|
||||
|
@ -2568,9 +2526,7 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
if (!view_->is_active) continue;
|
||||
File_View *view = view_to_file_view(view_);
|
||||
if (!view) continue;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
view_measure_wraps(&vars->mem.general, view);
|
||||
#endif
|
||||
view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos);
|
||||
}
|
||||
app_result.redraw = 1;
|
||||
|
@ -3099,15 +3055,13 @@ app_step(Thread_Context *thread, Key_Codes *codes,
|
|||
// NOTE(allen): send style change messages if the style has changed
|
||||
if (vars->style.font_changed){
|
||||
vars->style.font_changed = 0;
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
|
||||
Editing_File *file = vars->working_set.files;
|
||||
for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){
|
||||
if (file->buffer.data && !file->is_dummy){
|
||||
file_measure_widths(&vars->mem.general, file, vars->style.font);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Panel *panel = panels;
|
||||
for (i32 panel_i = vars->layout.panel_count; panel_i > 0; --panel_i, ++panel){
|
||||
|
|
|
@ -1664,14 +1664,10 @@ file_grow_as_needed(General_Memory *general, Editing_File *file, i32 additional_
|
|||
if (target_size >= file->buffer.max){
|
||||
i32 request_size = LargeRoundUp(target_size*2, Kbytes(256));
|
||||
char *new_data = (char*)
|
||||
general_memory_reallocate(general, file->buffer.data, size, request_size, BUBBLE_BUFFER);
|
||||
if (new_data){
|
||||
file->buffer.data = new_data;
|
||||
file->buffer.max = request_size;
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
}
|
||||
general_memory_allocate(general, request_size, BUBBLE_BUFFER);
|
||||
TentativeAssert(new_data);
|
||||
void *old_data = buffer_relocate(&file->buffer, new_data, request_size);
|
||||
general_memory_free(general, old_data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2427,10 +2423,10 @@ view_do_single_edit(Mem_Options *mem, File_View *view, Editing_File *file,
|
|||
i32 str_len = spec.step.edit.len;
|
||||
|
||||
i32 shift_amount = 0;
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount))
|
||||
file_grow_as_needed(general, file, shift_amount);
|
||||
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
// NOTE(allen): fixing stuff afterwards
|
||||
if (file->tokens_exist)
|
||||
file_relex_parallel(mem, file, start, end, shift_amount);
|
||||
|
@ -2844,11 +2840,12 @@ working_set_lookup_file(Working_Set *working_set, String string){
|
|||
}
|
||||
|
||||
internal void
|
||||
clipboard_copy(General_Memory *general, Working_Set *working, u8 *data, Range range){
|
||||
i32 size = range.end - range.start;
|
||||
String *dest = working_set_next_clipboard_string(general, working, size);
|
||||
copy(dest, make_string((char*)data + range.start, size));
|
||||
system_post_clipboard(*dest);
|
||||
clipboard_copy(General_Memory *general, Working_Set *working, Range range, Editing_File *file){
|
||||
i32 size = range.end - range.start;
|
||||
String *dest = working_set_next_clipboard_string(general, working, size);
|
||||
buffer_stringify(&file->buffer, range.start, range.end, dest->str);
|
||||
dest->size = size;
|
||||
system_post_clipboard(*dest);
|
||||
}
|
||||
|
||||
internal Edit_Spec
|
||||
|
@ -2856,6 +2853,7 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
|
|||
Buffer_Edit *edits, char *str_base, i32 str_size,
|
||||
Buffer_Edit *inverse_array, char *inv_str, i32 inv_max,
|
||||
i32 edit_count){
|
||||
#if BUFFER_EXPERIMENT_SCALPEL
|
||||
General_Memory *general = &mem->general;
|
||||
|
||||
i32 inv_str_pos = 0;
|
||||
|
@ -2878,7 +2876,9 @@ view_compute_whitespace_edit(Mem_Options *mem, Editing_File *file,
|
|||
spec.step.special_type = 1;
|
||||
spec.step.child_count = edit_count;
|
||||
spec.step.inverse_child_count = edit_count;
|
||||
|
||||
#else
|
||||
Edit_Spec spec = {};
|
||||
#endif
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
@ -2964,47 +2964,92 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout,
|
|||
i32 *indent_marks = push_array(part, i32, indent_mark_count);
|
||||
{
|
||||
i32 current_indent = 0;
|
||||
i32 line;
|
||||
for (line = line_start - 1; line >= 0; --line){
|
||||
i32 token_i;
|
||||
Cpp_Token *token, *self_token;
|
||||
|
||||
{
|
||||
i32 start_pos = file->buffer.line_starts[line_start];
|
||||
Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos);
|
||||
token_i = result.token_index;
|
||||
if (result.in_whitespace) token_i += 1;
|
||||
self_token = tokens.tokens + token_i;
|
||||
}
|
||||
|
||||
i32 line = line_start - 1;
|
||||
for (; line >= 0; --line){
|
||||
i32 start = file->buffer.line_starts[line];
|
||||
b32 all_whitespace = 0;
|
||||
b32 all_space = 0;
|
||||
buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4);
|
||||
if (!all_whitespace) break;
|
||||
}
|
||||
|
||||
if (line < 0) line = 0;
|
||||
i32 start_pos = file->buffer.line_starts[line];
|
||||
Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos);
|
||||
i32 start_token;
|
||||
if (result.in_whitespace) start_token = result.token_index + 1;
|
||||
else start_token = result.token_index;
|
||||
|
||||
if (line < 0){
|
||||
token_i = 0;
|
||||
token = tokens.tokens + token_i;
|
||||
}
|
||||
else{
|
||||
i32 start_pos = file->buffer.line_starts[line];
|
||||
Cpp_Get_Token_Result result = cpp_get_token(&tokens, start_pos);
|
||||
token_i = result.token_index;
|
||||
if (result.in_whitespace) token_i += 1;
|
||||
token = tokens.tokens + token_i;
|
||||
|
||||
if (token->start < start_pos){
|
||||
line = buffer_get_line_index(&file->buffer, token->start);
|
||||
i32 start = file->buffer.line_starts[line];
|
||||
b32 all_whitespace = 0;
|
||||
b32 all_space = 0;
|
||||
buffer_find_hard_start(&file->buffer, start, &all_whitespace, &all_space, ¤t_indent, 4);
|
||||
Assert(!all_whitespace);
|
||||
}
|
||||
}
|
||||
|
||||
indent_marks -= line_start;
|
||||
i32 line_i = line_start;
|
||||
i32 next_line_start = file->buffer.line_starts[line_i];
|
||||
Cpp_Token *token = tokens.tokens + start_token;
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACKET_OPEN: current_indent += 4; break;
|
||||
case CPP_TOKEN_PARENTHESE_OPEN: current_indent += 4; break;
|
||||
case CPP_TOKEN_BRACE_OPEN: current_indent += 4; break;
|
||||
}
|
||||
|
||||
Cpp_Token *prev_token = token;
|
||||
++token;
|
||||
for (i32 token_i = start_token + 1; line_i < line_end; ++token_i, ++token){
|
||||
for (; line_i < line_end; ++token_i, ++token){
|
||||
for (; token->start >= next_line_start && line_i < line_end;){
|
||||
i32 this_line_start = next_line_start;
|
||||
next_line_start = file->buffer.line_starts[line_i+1];
|
||||
i32 this_indent = current_indent;
|
||||
if (token->start < next_line_start){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACKET_CLOSE: this_indent -= 4; break;
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE: this_indent -= 4; break;
|
||||
case CPP_TOKEN_BRACE_CLOSE: this_indent -= 4; break;
|
||||
}
|
||||
i32 this_indent;
|
||||
if (prev_token && prev_token->type == CPP_TOKEN_COMMENT &&
|
||||
prev_token->start <= this_line_start && prev_token->start + prev_token->size > this_line_start){
|
||||
this_indent = -1;
|
||||
}
|
||||
else{
|
||||
this_indent = current_indent;
|
||||
if (token->start < next_line_start){
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACKET_CLOSE: this_indent -= 4; break;
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE: this_indent -= 4; break;
|
||||
case CPP_TOKEN_BRACE_CLOSE: this_indent -= 4; break;
|
||||
case CPP_TOKEN_BRACE_OPEN: break;
|
||||
default:
|
||||
if (current_indent > 0 && prev_token){
|
||||
switch (prev_token->type){
|
||||
case CPP_TOKEN_BRACKET_OPEN: case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
case CPP_TOKEN_BRACE_OPEN: case CPP_TOKEN_BRACE_CLOSE:
|
||||
case CPP_TOKEN_SEMICOLON: case CPP_TOKEN_COLON: break;
|
||||
default: this_indent += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this_indent < 0) this_indent = 0;
|
||||
}
|
||||
if (this_indent < 0) this_indent = 0;
|
||||
indent_marks[line_i] = this_indent;
|
||||
++line_i;
|
||||
}
|
||||
|
||||
switch (token->type){
|
||||
case CPP_TOKEN_BRACKET_OPEN: current_indent += 4; break;
|
||||
case CPP_TOKEN_BRACKET_CLOSE: current_indent -= 4; break;
|
||||
|
@ -3013,6 +3058,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout,
|
|||
case CPP_TOKEN_BRACE_OPEN: current_indent += 4; break;
|
||||
case CPP_TOKEN_BRACE_CLOSE: current_indent -= 4; break;
|
||||
}
|
||||
prev_token = token;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3032,6 +3078,7 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout,
|
|||
|
||||
correct_indentation = indent_marks[line_i];
|
||||
if (all_whitespace && empty_blank_lines) correct_indentation = 0;
|
||||
if (correct_indentation == -1) correct_indentation = preferred_indentation;
|
||||
|
||||
if ((all_whitespace && hard_start > start) || !all_space || correct_indentation != preferred_indentation){
|
||||
Buffer_Edit new_edit;
|
||||
|
@ -3653,7 +3700,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act
|
|||
u32 mark_color = style->main.mark_color;
|
||||
Buffer_Render_Item *item = items;
|
||||
i32 prev_ind = -1;
|
||||
u32 highlight_color = 0;
|
||||
u32 highlight_color = 0; AllowLocal(highlight_color);
|
||||
for (i32 i = 0; i < count; ++i, ++item){
|
||||
i32 ind = item->index;
|
||||
if (tokens_use && ind != prev_ind){
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
inline_4tech void
|
||||
buffer_stringify(Buffer_Type *buffer, int start, int end, char *out){
|
||||
for (Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||
for (Buffer_Stringify_Type loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
memcpy_4tech(out, loop.data, loop.size);
|
||||
|
@ -133,7 +133,7 @@ buffer_seek_whitespace_up(Buffer_Type *buffer, int pos){
|
|||
buffer_backify_next(&loop)){
|
||||
end = loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (;pos > end; --pos){
|
||||
for (;pos >= end && pos > 0; --pos){
|
||||
if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_up_mid;
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ buffer_seek_whitespace_up_mid:
|
|||
buffer_backify_next(&loop)){
|
||||
end = loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; pos > end; --pos){
|
||||
for (; pos >= end && pos > 0; --pos){
|
||||
if (data[pos] == '\n'){
|
||||
if (no_hard) goto buffer_seek_whitespace_up_end;
|
||||
else no_hard = 1;
|
||||
|
@ -293,6 +293,76 @@ buffer_seek_alphanumeric_left(Buffer_Type *buffer, int pos){
|
|||
return(pos);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_seek_alphanumeric_or_camel_right(Buffer_Type *buffer, int pos, int an_pos){
|
||||
Buffer_Stringify_Type loop;
|
||||
char *data;
|
||||
int end, size;
|
||||
char ch, prev_ch;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
assert_4tech(pos < an_pos);
|
||||
assert_4tech(an_pos < size);
|
||||
|
||||
++pos;
|
||||
if (pos < an_pos){
|
||||
loop = buffer_stringify_loop(buffer, pos, an_pos, size);
|
||||
if (buffer_stringify_good(&loop)){
|
||||
prev_ch = loop.data[0];
|
||||
++pos;
|
||||
|
||||
for (;buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
end = loop.size + loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; pos < end; ++pos){
|
||||
ch = data[pos];
|
||||
if (is_upper(ch) && is_lower(prev_ch)) goto buffer_seek_alphanumeric_or_camel_right_end;
|
||||
prev_ch = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
pos = an_pos;
|
||||
}
|
||||
|
||||
buffer_seek_alphanumeric_or_camel_right_end:
|
||||
return(pos);
|
||||
}
|
||||
|
||||
internal_4tech int
|
||||
buffer_seek_alphanumeric_or_camel_left(Buffer_Type *buffer, int pos, int an_pos){
|
||||
Buffer_Backify_Type loop;
|
||||
char *data;
|
||||
int end, size;
|
||||
char ch, prev_ch;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
assert_4tech(an_pos < pos);
|
||||
assert_4tech(0 <= an_pos);
|
||||
|
||||
loop = buffer_backify_loop(buffer, pos, an_pos, size);
|
||||
if (buffer_backify_good(&loop)){
|
||||
prev_ch = loop.data[0];
|
||||
--pos;
|
||||
|
||||
for (;buffer_backify_good(&loop);
|
||||
buffer_backify_next(&loop)){
|
||||
end = loop.absolute_pos;
|
||||
data = loop.data - loop.absolute_pos;
|
||||
for (; pos >= end && pos > 0; --pos){
|
||||
ch = data[pos];
|
||||
if (is_upper(ch) && is_lower(prev_ch)) goto buffer_seek_alphanumeric_or_camel_left_end;
|
||||
prev_ch = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer_seek_alphanumeric_or_camel_left_end:
|
||||
return(pos);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
int i;
|
||||
int count;
|
||||
|
|
|
@ -24,18 +24,23 @@ typedef struct{
|
|||
int widths_max;
|
||||
} Gap_Buffer;
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Gap_Buffer *buffer){
|
||||
int size;
|
||||
size = buffer->size1 + buffer->size2;
|
||||
return(size);
|
||||
}
|
||||
|
||||
inline_4tech void
|
||||
buffer_initialize(Gap_Buffer *buffer, char *data, int size){
|
||||
int osize1, size1, size2;
|
||||
|
||||
assert_4tech(buffer->max >= size);
|
||||
|
||||
size2 = size >> 1;
|
||||
size1 = osize1 = size - size2;
|
||||
|
||||
if (size1 > 0){
|
||||
size1 = eol_convert_in(buffer->data, data, size1);
|
||||
|
||||
if (size2 > 0){
|
||||
size2 = eol_convert_in(buffer->data + size1, data + osize1, size2);
|
||||
}
|
||||
|
@ -47,11 +52,23 @@ buffer_initialize(Gap_Buffer *buffer, char *data, int size){
|
|||
memmove_4tech(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Gap_Buffer *buffer){
|
||||
int size;
|
||||
size = buffer->size1 + buffer->size2;
|
||||
return(size);
|
||||
internal_4tech void*
|
||||
buffer_relocate(Gap_Buffer *buffer, char *new_data, int new_max){
|
||||
void *result;
|
||||
int new_gap_size;
|
||||
|
||||
assert_4tech(new_max >= buffer_size(buffer));
|
||||
|
||||
result = buffer->data;
|
||||
new_gap_size = new_max - buffer_size(buffer);
|
||||
memcpy_4tech(new_data, buffer->data, buffer->size1);
|
||||
memcpy_4tech(new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2);
|
||||
|
||||
buffer->data = new_data;
|
||||
buffer->gap_size = new_gap_size;
|
||||
buffer->max = new_max;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
|
@ -149,6 +166,7 @@ buffer_backify_loop(Gap_Buffer *buffer, int start, int end, int page_size){
|
|||
Gap_Buffer_Backify_Loop result;
|
||||
int chunk2_start;
|
||||
|
||||
++start;
|
||||
if (0 <= end && end < start && start <= buffer->size1 + buffer->size2){
|
||||
chunk2_start = buffer->size1 + buffer->gap_size;
|
||||
|
||||
|
@ -237,14 +255,49 @@ buffer_backify_next(Gap_Buffer_Backify_Loop *loop){
|
|||
loop->data = loop->base + loop->pos;
|
||||
}
|
||||
|
||||
inline_4tech void
|
||||
buffer_stringify(Gap_Buffer *buffer, int start, int end, char *out){
|
||||
for (Gap_Buffer_Stringify_Loop loop = buffer_stringify_loop(buffer, start, end, end - start);
|
||||
buffer_stringify_good(&loop);
|
||||
buffer_stringify_next(&loop)){
|
||||
memcpy_4tech(out, loop.data, loop.size);
|
||||
out += loop.size;
|
||||
internal_4tech int
|
||||
buffer_replace_range(Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||
char *data;
|
||||
int result;
|
||||
int size;
|
||||
int move_size;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
assert_4tech(0 <= start);
|
||||
assert_4tech(start <= end);
|
||||
assert_4tech(end <= size);
|
||||
|
||||
*shift_amount = (len - (end - start));
|
||||
if (*shift_amount + size <= buffer->max){
|
||||
data = buffer->data;
|
||||
if (end < buffer->size1){
|
||||
move_size = buffer->size1 - end;
|
||||
memmove_4tech(data + buffer->size1 + buffer->gap_size - move_size, data + end, move_size);
|
||||
buffer->size1 -= move_size;
|
||||
buffer->size2 += move_size;
|
||||
}
|
||||
if (start > buffer->size1){
|
||||
move_size = start - buffer->size1;
|
||||
memmove_4tech(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size);
|
||||
buffer->size1 += move_size;
|
||||
buffer->size2 -= move_size;
|
||||
}
|
||||
|
||||
memcpy_4tech(data + start, str, len);
|
||||
buffer->size2 = size - end;
|
||||
buffer->size1 = start + len;
|
||||
buffer->gap_size -= *shift_amount;
|
||||
|
||||
assert_4tech(buffer->size1 + buffer->size2 == size + *shift_amount);
|
||||
assert_4tech(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else{
|
||||
result = *shift_amount + size;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -24,15 +24,29 @@ typedef struct{
|
|||
int widths_max;
|
||||
} Buffer;
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Buffer *buffer){
|
||||
return buffer->size;
|
||||
}
|
||||
|
||||
internal_4tech void
|
||||
buffer_initialize(Buffer *buffer, char *data, int size){
|
||||
assert_4tech(size <= buffer->max);
|
||||
buffer->size = eol_convert_in(buffer->data, data, size);
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
buffer_size(Buffer *buffer){
|
||||
return buffer->size;
|
||||
internal_4tech void*
|
||||
buffer_relocate(Buffer *buffer, char *new_data, int new_max){
|
||||
void *result;
|
||||
|
||||
assert_4tech(new_max >= buffer->size);
|
||||
|
||||
result = buffer->data;
|
||||
memcpy_4tech(new_data, buffer->data, buffer->size);
|
||||
buffer->data = new_data;
|
||||
buffer->max = new_max;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
|
@ -88,6 +102,8 @@ typedef struct{
|
|||
inline_4tech Buffer_Backify_Loop
|
||||
buffer_backify_loop(Buffer *buffer, int start, int end, int page_size){
|
||||
Buffer_Backify_Loop result;
|
||||
|
||||
++start;
|
||||
if (0 <= end && end < start && start <= buffer->size){
|
||||
result.buffer = buffer;
|
||||
result.end = buffer->data + end;
|
||||
|
@ -128,9 +144,15 @@ internal_4tech int
|
|||
buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int *shift_amount){
|
||||
char *data;
|
||||
int result;
|
||||
int size;
|
||||
|
||||
size = buffer_size(buffer);
|
||||
assert_4tech(0 <= start);
|
||||
assert_4tech(start <= end);
|
||||
assert_4tech(end <= size);
|
||||
|
||||
*shift_amount = (len - (end - start));
|
||||
if (*shift_amount + buffer->size + 1 <= buffer->max){
|
||||
if (*shift_amount + size <= buffer->max){
|
||||
data = (char*)buffer->data;
|
||||
memmove_4tech(data + end + *shift_amount, data + end, buffer->size - end);
|
||||
buffer->size += *shift_amount;
|
||||
|
@ -140,7 +162,7 @@ buffer_replace_range(Buffer *buffer, int start, int end, char *str, int len, int
|
|||
result = 0;
|
||||
}
|
||||
else{
|
||||
result = *shift_amount + buffer->size + 1;
|
||||
result = *shift_amount + size;
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
|
|
@ -383,5 +383,15 @@ is_alphanumeric_true(char c){
|
|||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_upper(char c){
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
inline_4tech int
|
||||
is_lower(char c){
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define FPS 30
|
||||
#define FRAME_TIME (1000000 / FPS)
|
||||
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 1
|
||||
#define BUFFER_EXPERIMENT_SCALPEL 0
|
||||
|
||||
#include "4ed_meta.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue