gap buffer editing

master
Allen Webster 2015-10-28 18:59:39 -04:00
parent d3913c0c7a
commit 7c2d26463e
8 changed files with 336 additions and 164 deletions

View File

@ -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
View File

@ -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(&param->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){

View File

@ -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, &current_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, &current_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){

View File

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

View File

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

View File

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

View File

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

View File

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