diff --git a/4coder_buffer_types.h b/4coder_buffer_types.h new file mode 100644 index 00000000..07c11d98 --- /dev/null +++ b/4coder_buffer_types.h @@ -0,0 +1,78 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 23.02.2016 + * + * Types shared by custom and application + * + */ + +// TOP + +#ifndef FRED_BUFFER_TYPES_H +#define FRED_BUFFER_TYPES_H + +typedef struct Full_Cursor{ + int pos; + int line, character; + float unwrapped_x, unwrapped_y; + float wrapped_x, wrapped_y; +} Full_Cursor; + +typedef enum{ + buffer_seek_pos, + buffer_seek_wrapped_xy, + buffer_seek_unwrapped_xy, + buffer_seek_line_char +} Buffer_Seek_Type; + +typedef struct Buffer_Seek{ + Buffer_Seek_Type type; + union{ + struct { int pos; }; + struct { int round_down; float x, y; }; + struct { int line, character; }; + }; +} Buffer_Seek; + +static Buffer_Seek +seek_pos(int pos){ + Buffer_Seek result; + result.type = buffer_seek_pos; + result.pos = pos; + return(result); +} + +static Buffer_Seek +seek_wrapped_xy(float x, float y, int round_down){ + Buffer_Seek result; + result.type = buffer_seek_wrapped_xy; + result.x = x; + result.y = y; + result.round_down = round_down; + return(result); +} + +static Buffer_Seek +seek_unwrapped_xy(float x, float y, int round_down){ + Buffer_Seek result; + result.type = buffer_seek_unwrapped_xy; + result.x = x; + result.y = y; + result.round_down = round_down; + return(result); +} + +static Buffer_Seek +seek_line_char(int line, int character){ + Buffer_Seek result; + result.type = buffer_seek_line_char; + result.line = line; + result.character = character; + return(result); +} + +#endif + +// BOTTOM + diff --git a/4coder_custom.cpp b/4coder_custom.cpp index 3cd8b864..33080f27 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -89,8 +89,87 @@ CUSTOM_COMMAND_SIG(write_increment){ // is usually ready, but when a buffer has just been opened it is possible that the contents // haven't been filled yet. If the buffer is not ready trying to read or write it is invalid. // (See my_file_settings for comments on the exists field). + char text[] = "++"; + int size = sizeof(text) - 1; if (buffer.exists && buffer.ready){ - app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, "++", 2); + app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size); + } +} + +CUSTOM_COMMAND_SIG(write_decrement){ + Buffer_Summary buffer = app->get_active_buffer(cmd_context); + char text[] = "--"; + int size = sizeof(text) - 1; + if (buffer.exists && buffer.ready){ + app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size); + } +} + +CUSTOM_COMMAND_SIG(open_long_braces){ + File_View_Summary view; + Buffer_Summary buffer; + + view = app->get_active_view(cmd_context); + if (view.exists){ + buffer = app->get_active_buffer(cmd_context); + + char text[] = "{\n\n}"; + int size = sizeof(text) - 1; + int pos; + + if (buffer.exists && buffer.ready){ + pos = view.cursor.pos; + app->buffer_replace_range(cmd_context, &buffer, pos, pos, text, size); + app->view_set_cursor(cmd_context, &view, seek_pos(pos + 2), 1); + + push_parameter(app, cmd_context, par_range_start, pos); + push_parameter(app, cmd_context, par_range_end, pos + size); + push_parameter(app, cmd_context, par_clear_blank_lines, 0); + exec_command(cmd_context, cmdid_auto_tab_range); + } + } +} + +CUSTOM_COMMAND_SIG(ifdef_off){ + File_View_Summary view; + Buffer_Summary buffer; + + view = app->get_active_view(cmd_context); + if (view.exists){ + buffer = app->get_active_buffer(cmd_context); + + char text1[] = "#if 0\n"; + int size1 = sizeof(text1) - 1; + + char text2[] = "#endif\n"; + int size2 = sizeof(text2) - 1; + + int pos, c, m; + + if (buffer.exists && buffer.ready){ + c = view.cursor.pos; + m = view.mark.pos; + pos = (cbuffer_replace_range(cmd_context, &buffer, pos, pos, text1, size1); + + push_parameter(app, cmd_context, par_range_start, pos); + push_parameter(app, cmd_context, par_range_end, pos); + exec_command(cmd_context, cmdid_auto_tab_range); + + + app->refresh_view(cmd_context, &view); + c = view.cursor.pos; + m = view.mark.pos; + pos = (c>m)?(c):(m); + + + app->buffer_replace_range(cmd_context, &buffer, pos, pos, text2, size2); + + push_parameter(app, cmd_context, par_range_start, pos); + push_parameter(app, cmd_context, par_range_end, pos); + exec_command(cmd_context, cmdid_auto_tab_range); + } } } @@ -278,6 +357,9 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, ' ', MDFR_SHIFT, cmdid_write_character); bind(context, '=', MDFR_CTRL, write_increment); + bind(context, '-', MDFR_CTRL, write_decrement); + bind(context, '[', MDFR_CTRL, open_long_braces); + bind(context, 'i', MDFR_ALT, ifdef_off); end_map(context); @@ -333,7 +415,7 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, '!', MDFR_CTRL, cmdid_eol_nixify); bind(context, 'f', MDFR_CTRL, cmdid_search); - bind(context, 'r', MDFR_CTRL, cmdid_rsearch); + bind(context, 'r', MDFR_CTRL, cmdid_reverse_search); bind(context, 'g', MDFR_CTRL, cmdid_goto_line); bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer); diff --git a/4coder_custom.h b/4coder_custom.h index 338a4d0b..533ec527 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -1,4 +1,6 @@ +#include "4coder_buffer_types.h" + #define MDFR_NONE 0 #define MDFR_CTRL 1 #define MDFR_ALT 2 @@ -63,7 +65,7 @@ enum Command_ID{ cmdid_seek_alphanumeric_or_camel_left, cmdid_seek_alphanumeric_or_camel_right, cmdid_search, - cmdid_rsearch, + cmdid_reverse_search, cmdid_word_complete, cmdid_goto_line, cmdid_set_mark, @@ -124,6 +126,8 @@ enum Command_ID{ }; enum Param_ID{ + par_range_start, + par_range_end, par_name, par_lex_as_cpp_file, par_wrap_lines, @@ -133,6 +137,7 @@ enum Param_ID{ par_cli_command, par_cli_overlap_with_conflict, par_cli_always_bind_to_view, + par_clear_blank_lines, // never below this par_type_count }; @@ -216,10 +221,10 @@ struct Extra_Font{ int size; }; +// NOTE(allen): None of the members of *_Summary structs nor any of the +// data pointed to by the members should be modified, I would have made +// them all const... but that causes a lot problems for C++ reasons. struct Buffer_Summary{ - // NOTE(allen): None of these members nor any of the data pointed to - // by these members should be modified, I would have made them const... - // but that causes a lot problems for C++ reasons. int exists; int ready; int file_id; @@ -236,6 +241,15 @@ struct Buffer_Summary{ int map_id; }; +struct File_View_Summary{ + int exists; + int view_id; + int file_id; + + Full_Cursor cursor; + Full_Cursor mark; +}; + #ifndef FRED_STRING_STRUCT #define FRED_STRING_STRUCT struct String{ @@ -274,10 +288,21 @@ extern "C"{ #define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context) #define GET_BUFFER_BY_NAME(name) Buffer_Summary name(void *cmd_context, String filename) +#define REFRESH_BUFFER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer) #define BUFFER_SEEK_DELIMITER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, char delim, int *out) #define BUFFER_READ_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *out) #define BUFFER_REPLACE_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *str, int len) +// File view manipulation +#define GET_VIEW_MAX_INDEX_SIG(name) int name(void *cmd_context) +#define GET_VIEW_SIG(name) File_View_Summary name(void *cmd_context, int index) +#define GET_ACTIVE_VIEW_SIG(name) File_View_Summary name(void *cmd_context) + +#define REFRESH_VIEW_SIG(name) int name(void *cmd_context, File_View_Summary *view) +#define VIEW_SET_CURSOR_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek, int set_preferred_x) +#define VIEW_SET_MARK_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek) +#define VIEW_SET_FILE_SIG(name) int name(void *cmd_context, File_View_Summary *view, int file_id) + extern "C"{ // Command exectuion typedef EXECUTE_COMMAND_SIG(Exec_Command_Function); @@ -296,9 +321,20 @@ extern "C"{ typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function); typedef GET_BUFFER_BY_NAME(Get_Buffer_By_Name_Function); + typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function); typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function); typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function); typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); + + // View manipulation + typedef GET_VIEW_MAX_INDEX_SIG(Get_View_Max_Index_Function); + typedef GET_VIEW_SIG(Get_View_Function); + typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function); + + typedef REFRESH_VIEW_SIG(Refresh_View_Function); + typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function); + typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function); + typedef VIEW_SET_FILE_SIG(View_Set_File_Function); } struct Application_Links{ @@ -319,9 +355,20 @@ struct Application_Links{ Get_Active_Buffer_Function *get_active_buffer; Get_Buffer_By_Name_Function *get_buffer_by_name; + Refresh_Buffer_Function *refresh_buffer; Buffer_Seek_Delimiter_Function *buffer_seek_delimiter; Buffer_Read_Range_Function *buffer_read_range; Buffer_Replace_Range_Function *buffer_replace_range; + + // View manipulation + Get_View_Max_Index_Function *get_view_max_index; + Get_View_Function *get_view; + Get_Active_View_Function *get_active_view; + + Refresh_View_Function *refresh_view; + View_Set_Cursor_Function *view_set_cursor; + View_Set_Mark_Function *view_set_mark; + View_Set_File_Function *view_set_file; }; struct Custom_API{ diff --git a/4coder_helper.h b/4coder_helper.h index 90c65aa6..b2fece5c 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -92,61 +92,34 @@ end_map(Bind_Helper *helper){ helper->group = 0; } -struct Bind_Target{ - short code; - unsigned char modifiers; -}; - -inline Bind_Target -tkey(short code, unsigned char modifiers){ - Bind_Target target; - target.code = code; - target.modifiers = modifiers; - return target; -} - inline void -bind(Bind_Helper *helper, Bind_Target target, int cmdid){ +bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){ if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; if (!helper->error) ++helper->group->map_begin.bind_count; Binding_Unit unit; unit.type = unit_binding; unit.binding.command_id = cmdid; - unit.binding.code = target.code; - unit.binding.modifiers = target.modifiers; + unit.binding.code = code; + unit.binding.modifiers = modifiers; write_unit(helper, unit); } inline void -bind(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){ +bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){ if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; if (!helper->error) ++helper->group->map_begin.bind_count; Binding_Unit unit; unit.type = unit_callback; unit.callback.func = func; - unit.callback.code = target.code; - unit.callback.modifiers = target.modifiers; + unit.callback.code = code; + unit.callback.modifiers = modifiers; write_unit(helper, unit); } -inline void -bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){ - Bind_Target target; - target = tkey(code, modifiers); - bind(helper, target, cmdid); -} - -inline void -bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){ - Bind_Target target; - target = tkey(code, modifiers); - bind(helper, target, func); -} - inline void bind_vanilla_keys(Bind_Helper *helper, int cmdid){ bind(helper, 0, 0, cmdid); diff --git a/4ed.cpp b/4ed.cpp index 669af5ba..8d14992f 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -434,7 +434,7 @@ COMMAND_DECL(search){ view->isearch.pos = view->cursor.pos - 1; } -COMMAND_DECL(rsearch){ +COMMAND_DECL(reverse_search){ ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(fixed, view); @@ -1268,10 +1268,37 @@ COMMAND_DECL(auto_tab_range){ REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); - + + int r_start = 0, r_end = 0; + int start_set = 0, end_set = 0; + int clear_blank_lines = 1; + + Command_Parameter *end = param_stack_end(&command->part); + Command_Parameter *param = param_stack_first(&command->part, end); + for (; param < end; param = param_next(param, end)){ + int p = dynamic_to_int(¶m->param.param); + switch (p){ + case par_range_start: + start_set = 1; + r_start = dynamic_to_int(¶m->param.value); + break; + + case par_range_end: + end_set = 1; + r_end = dynamic_to_int(¶m->param.value); + break; + + case par_clear_blank_lines: + clear_blank_lines = dynamic_to_bool(¶m->param.value); + break; + } + } + if (file->state.token_stack.tokens && file->state.tokens_complete){ Range range = get_range(view->cursor.pos, view->mark); - view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, 1); + if (start_set) range.start = r_start; + if (end_set) range.end = r_end; + view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, clear_blank_lines); } } @@ -1282,9 +1309,22 @@ COMMAND_DECL(auto_tab_line_at_cursor){ USE_LAYOUT(layout); USE_MEM(mem); + int clear_blank_lines = 0; + + Command_Parameter *end = param_stack_end(&command->part); + Command_Parameter *param = param_stack_first(&command->part, end); + for (; param < end; param = param_next(param, end)){ + int p = dynamic_to_int(¶m->param.param); + switch (p){ + case par_clear_blank_lines: + clear_blank_lines = dynamic_to_bool(¶m->param.value); + break; + } + } + if (file->state.token_stack.tokens && file->state.tokens_complete){ i32 pos = view->cursor.pos; - view_auto_tab_tokens(system, mem, view, layout, pos, pos, 0); + view_auto_tab_tokens(system, mem, view, layout, pos, pos, clear_blank_lines); } } @@ -1695,7 +1735,6 @@ COMMAND_DECL(set_settings){ REQ_FILE_LOADING(file, view); USE_VARS(vars); USE_MEM(mem); - AllowLocal(mem); Command_Parameter *end = param_stack_end(&command->part); Command_Parameter *param = param_stack_first(&command->part, end); @@ -2026,6 +2065,17 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor buffer->map_id = file->settings.base_map_id; } +internal void +fill_view_summary(File_View_Summary *view, File_View *file_view, Live_Views *live_set, Working_Set *working_set){ + view->exists = 1; + view->view_id = (int)((char*)file_view - (char*)live_set->views) / live_set->stride; + if (file_view->file){ + view->file_id = (int)(file_view->file - working_set->files); + view->mark = view_compute_cursor_from_pos(file_view, file_view->mark); + view->cursor = file_view->cursor; + } +} + extern "C"{ EXECUTE_COMMAND_SIG(external_exec_command_keep_stack){ Command_Data *cmd = (Command_Data*)cmd_context; @@ -2079,29 +2129,22 @@ extern "C"{ GET_BUFFER_MAX_INDEX_SIG(external_get_buffer_max_index){ Command_Data *cmd = (Command_Data*)cmd_context; - Working_Set *working_set; - int max; - working_set = cmd->working_set; - max = working_set->file_index_count; + Working_Set *working_set = cmd->working_set; + int max = working_set->file_index_count; return(max); } GET_BUFFER_SIG(external_get_buffer){ Command_Data *cmd = (Command_Data*)cmd_context; Editing_File *file; - Working_Set *working_set; - int max; + Working_Set *working_set = cmd->working_set; + int max = working_set->file_index_count; Buffer_Summary buffer = {}; - working_set = cmd->working_set; - max = working_set->file_index_count; - if (index >= 0 && index < max){ file = working_set->files + index; if (!file->state.is_dummy){ -#if BUFFER_EXPERIMENT_SCALPEL <= 0 fill_buffer_summary(&buffer, file, working_set); -#endif } } @@ -2121,9 +2164,7 @@ extern "C"{ working_set = cmd->working_set; if (file && !file->state.is_dummy){ -#if BUFFER_EXPERIMENT_SCALPEL <= 0 fill_buffer_summary(&buffer, file, working_set); -#endif } } @@ -2141,15 +2182,20 @@ extern "C"{ if (table_find(&working_set->table, filename, &index)){ file = working_set->files + index; if (!file->state.is_dummy && file_is_ready(file)){ -#if BUFFER_EXPERIMENT_SCALPEL <= 0 fill_buffer_summary(&buffer, file, working_set); -#endif } } return(buffer); } + REFRESH_BUFFER_SIG(external_refresh_buffer){ + int result; + *buffer = external_get_buffer(cmd_context, buffer->file_id); + result = buffer->exists; + return(result); + } + BUFFER_SEEK_DELIMITER_SIG(external_buffer_seek_delimiter){ Command_Data *cmd = (Command_Data*)cmd_context; Editing_File *file; @@ -2237,6 +2283,135 @@ extern "C"{ return(result); } + + GET_VIEW_MAX_INDEX_SIG(external_get_view_max_index){ + Command_Data *cmd = (Command_Data*)cmd_context; + Live_Views *live_set = cmd->live_set; + int max = live_set->max; + return(max); + } + + GET_VIEW_SIG(external_get_view){ + Command_Data *cmd = (Command_Data*)cmd_context; + Live_Views *live_set = cmd->live_set; + int max = live_set->max; + View *vptr; + File_View *file_view; + File_View_Summary view = {}; + + if (index >= 0 && index < max){ + vptr = (View*)((char*)live_set->views + live_set->stride*index); + file_view = view_to_file_view(vptr); + if (file_view){ + fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set); + } + } + + return(view); + } + + GET_ACTIVE_VIEW_SIG(external_get_active_view){ + Command_Data *cmd = (Command_Data*)cmd_context; + File_View_Summary view = {}; + File_View *file_view; + + file_view = view_to_file_view(cmd->view); + if (file_view){ + fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set); + } + + return(view); + } + + REFRESH_VIEW_SIG(external_refresh_view){ + int result; + *view = external_get_view(cmd_context, view->view_id); + result = view->exists; + return(result); + } + + VIEW_SET_CURSOR_SIG(external_view_set_cursor){ + Command_Data *cmd = (Command_Data*)cmd_context; + Live_Views *live_set; + View *vptr; + File_View *file_view; + int result = 0; + + if (view->exists){ + live_set = cmd->live_set; + vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id); + file_view = view_to_file_view(vptr); + if (file_view){ + result = 1; + file_view->cursor = view_compute_cursor(file_view, seek); + if (set_preferred_x){ + file_view->preferred_x = view_get_cursor_x(file_view); + } + fill_view_summary(view, file_view, cmd->live_set, cmd->working_set); + } + } + + return(result); + } + + VIEW_SET_MARK_SIG(external_view_set_mark){ + Command_Data *cmd = (Command_Data*)cmd_context; + Live_Views *live_set; + View *vptr; + File_View *file_view; + Full_Cursor cursor; + int result = 0; + + if (view->exists){ + live_set = cmd->live_set; + vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id); + file_view = view_to_file_view(vptr); + if (file_view){ + result = 1; + if (seek.type != buffer_seek_pos){ + cursor = view_compute_cursor(file_view, seek); + file_view->mark = cursor.pos; + } + else{ + file_view->mark = seek.pos; + } + fill_view_summary(view, file_view, cmd->live_set, cmd->working_set); + } + } + + return(result); + } + + VIEW_SET_FILE_SIG(external_view_set_file){ + Command_Data *cmd = (Command_Data*)cmd_context; + Live_Views *live_set; + View *vptr; + File_View *file_view; + Editing_File *file; + Working_Set *working_set; + int max, result = 0; + + if (view->exists){ + live_set = cmd->live_set; + vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id); + file_view = view_to_file_view(vptr); + if (file_view){ + working_set = cmd->working_set; + max = working_set->file_index_count; + if (file_id >= 0 && file_id < max){ + file = working_set->files + file_id; + if (!file->state.is_dummy){ + view_set_file(cmd->system, file_view, file, cmd->vars->font_set, cmd->style, + cmd->vars->hooks[hook_open_file], cmd, &app_links); + } + } + + fill_view_summary(view, file_view, cmd->live_set, cmd->working_set); + } + } + + return(result); + } } inline void @@ -2250,18 +2425,24 @@ app_links_init(System_Functions *system){ app_links.directory_has_file = system->directory_has_file; app_links.directory_cd = system->directory_cd; - app_links.get_buffer_max_index = external_get_buffer_max_index; - app_links.get_buffer = external_get_buffer; - app_links.get_buffer_by_name = external_get_buffer_by_name; - app_links.get_buffer_max_index = external_get_buffer_max_index; app_links.get_buffer = external_get_buffer; app_links.get_active_buffer = external_get_active_buffer; app_links.get_buffer_by_name = external_get_buffer_by_name; + app_links.refresh_buffer = external_refresh_buffer; app_links.buffer_seek_delimiter = external_buffer_seek_delimiter; app_links.buffer_read_range = external_buffer_read_range; app_links.buffer_replace_range = external_buffer_replace_range; + + app_links.get_view_max_index = external_get_view_max_index; + app_links.get_view = external_get_view; + app_links.get_active_view = external_get_active_view; + + app_links.refresh_view = external_refresh_view; + app_links.view_set_cursor = external_view_set_cursor; + app_links.view_set_mark = external_view_set_mark; + app_links.view_set_file = external_view_set_file; } #if FRED_INTERNAL @@ -2338,9 +2519,9 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co map_add(commands, 'u', MDFR_CTRL, command_to_uppercase); map_add(commands, 'j', MDFR_CTRL, command_to_lowercase); map_add(commands, '~', MDFR_CTRL, command_clean_all_lines); - map_add(commands, 'f', MDFR_CTRL, command_search); - map_add(commands, 'r', MDFR_CTRL, command_rsearch); + map_add(commands, 'f', MDFR_CTRL, command_search); + map_add(commands, 'r', MDFR_CTRL, command_reverse_search); map_add(commands, 'g', MDFR_CTRL, command_goto_line); map_add(commands, '\n', MDFR_NONE, compose_write_auto_tab_line); @@ -2404,7 +2585,7 @@ setup_command_table(){ SET(seek_alphanumeric_or_camel_right); SET(seek_alphanumeric_or_camel_left); SET(search); - SET(rsearch); + SET(reverse_search); SET(word_complete); SET(goto_line); SET(set_mark); diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 10111d34..954cb63b 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -1207,7 +1207,6 @@ file_post_history(General_Memory *general, Editing_File *file, inline Full_Cursor view_compute_cursor_from_pos(File_View *view, i32 pos){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; Render_Font *font = get_font_info(view->font_set, style->font_id)->font; @@ -1219,16 +1218,11 @@ view_compute_cursor_from_pos(File_View *view, i32 pos){ max_width, (f32)view->font_height, font->advance_data); } return result; - -#else - return view->cursor; -#endif } inline Full_Cursor view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y, b32 round_down = 0){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; Render_Font *font = get_font_info(view->font_set, style->font_id)->font; @@ -1242,16 +1236,11 @@ view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y, } return result; - -#else - return view->cursor; -#endif } internal Full_Cursor view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y, b32 round_down = 0){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; Render_Font *font = get_font_info(view->font_set, style->font_id)->font; @@ -1265,15 +1254,10 @@ view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y, } return result; - -#else - return view->cursor; -#endif } internal Full_Cursor view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){ -#if BUFFER_EXPERIMENT_SCALPEL <= 3 Editing_File *file = view->file; Style *style = view->style; Render_Font *font = get_font_info(view->font_set, style->font_id)->font; @@ -1286,10 +1270,31 @@ view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){ } return result; +} + +inline Full_Cursor +view_compute_cursor(File_View *view, Buffer_Seek seek){ + Full_Cursor result = {}; -#else - return view->cursor; -#endif + switch(seek.type){ + case buffer_seek_pos: + result = view_compute_cursor_from_pos(view, seek.pos); + break; + + case buffer_seek_wrapped_xy: + result = view_compute_cursor_from_wrapped_xy(view, seek.x, seek.y); + break; + + case buffer_seek_unwrapped_xy: + result = view_compute_cursor_from_unwrapped_xy(view, seek.x, seek.y); + break; + + case buffer_seek_line_char: + result = view_compute_cursor_from_line_pos(view, seek.line, seek.character); + break; + } + + return result; } inline Full_Cursor @@ -2383,8 +2388,8 @@ view_clean_whitespace(System_Functions *system, Mem_Options *mem, File_View *vie for (i32 line_i = 0; line_i < line_count; ++line_i){ i32 start = file->state.buffer.line_starts[line_i]; i32 preferred_indentation; - bool32 all_whitespace = 0; - bool32 all_space = 0; + b32 all_whitespace = 0; + b32 all_space = 0; i32 hard_start = buffer_find_hard_start(&file->state.buffer, start, &all_whitespace, &all_space, &preferred_indentation, 4); @@ -3389,14 +3394,14 @@ kill_file(System_Functions *system, Exchange *exchange, internal void command_search(System_Functions*,Command_Data*,Command_Binding); internal void -command_rsearch(System_Functions*,Command_Data*,Command_Binding); +command_reverse_search(System_Functions*,Command_Data*,Command_Binding); internal HANDLE_COMMAND_SIG(handle_command_file_view){ File_View *file_view = (File_View*)(view); Editing_File *file = file_view->file; AllowLocal(file); - + switch (file_view->widget.type){ case FWIDG_NONE: case FWIDG_TIMELINES: @@ -3418,12 +3423,12 @@ HANDLE_COMMAND_SIG(handle_command_file_view){ if (result.made_a_change || binding.function == command_search || - binding.function == command_rsearch){ - bool32 step_forward = 0; - bool32 step_backward = 0; + binding.function == command_reverse_search){ + b32 step_forward = 0; + b32 step_backward = 0; if (binding.function == command_search) step_forward = 1; - if (binding.function == command_rsearch) step_backward = 1; + if (binding.function == command_reverse_search) step_backward = 1; i32 start_pos = file_view->isearch.pos; if (step_forward){ diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index 092a4764..8238a7b3 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -1,481 +1,423 @@ -/* - * Mr. 4th Dimention - Allen Webster - * Four Tech - * - * public domain -- no warranty is offered or implied; use this code at your own risk - * - * 23.10.2015 - * - * Items shared by gap buffer types - * - */ - -// TOP - -#ifndef inline_4tech -#define inline_4tech inline -#endif - -#ifndef internal_4tech -#define internal_4tech static -#endif - -#ifndef memset_4tech -#define memset_4tech memset -#endif - -#ifndef memzero_4tech -#define memzero_4tech(x) ((x) = {}) -#endif - -#ifndef memcpy_4tech -#define memcpy_4tech memcpy -#endif - -#ifndef memmove_4tech -#define memmove_4tech memmove -#endif - -#ifndef debug_4tech -#define debug_4tech(x) x -#endif - -#ifndef assert_4tech -#define assert_4tech assert -#endif - -#ifndef ceil_4tech -#define ceil_4tech CEIL32 -#endif - -#ifndef div_ceil_4tech -#define div_ceil_4tech DIVCEIL32 -#endif - -#ifndef cat_4tech -#define cat_4tech_(a,b) a##b -#define cat_4tech(a,b) cat_4tech_(a,b) -#endif - -#ifndef round_up_4tech -internal_4tech int -lroundup_(int x, int granularity){ - int original_x; - original_x = x; - x /= granularity; - x *= granularity; - if (x < original_x) x += granularity; - return x; -} -#define round_up_4tech(x,g) lroundup_(x,g) -#endif - -#ifndef round_pot_4tech -#define round_pot_4tech ROUNDPOT32 -#endif - -#define measure_character(a,c) ((a)[c]) - -typedef struct Buffer_Edit{ - int str_start, len; - int start, end; -} Buffer_Edit; - -typedef struct Buffer_Batch_State{ - int i; - int shift_total; -} Buffer_Batch_State; - -typedef enum{ - buffer_seek_pos, - buffer_seek_wrapped_xy, - buffer_seek_unwrapped_xy, - buffer_seek_line_char -} Buffer_Seek_Type; - -typedef struct Buffer_Seek{ - Buffer_Seek_Type type; - union{ - struct { int pos; }; - struct { int round_down; float x, y; }; - struct { int line, character; }; - }; -} Buffer_Seek; - -inline_4tech Buffer_Seek -seek_pos(int pos){ - Buffer_Seek result; - result.type = buffer_seek_pos; - result.pos = pos; - return(result); -} - -inline_4tech Buffer_Seek -seek_wrapped_xy(float x, float y, int round_down){ - Buffer_Seek result; - result.type = buffer_seek_wrapped_xy; - result.x = x; - result.y = y; - result.round_down = round_down; - return(result); -} - -inline_4tech Buffer_Seek -seek_unwrapped_xy(float x, float y, int round_down){ - Buffer_Seek result; - result.type = buffer_seek_unwrapped_xy; - result.x = x; - result.y = y; - result.round_down = round_down; - return(result); -} - -inline_4tech Buffer_Seek -seek_line_char(int line, int character){ - Buffer_Seek result; - result.type = buffer_seek_line_char; - result.line = line; - result.character = character; - return(result); -} - -typedef struct Full_Cursor{ - int pos; - int line, character; - float unwrapped_x, unwrapped_y; - float wrapped_x, wrapped_y; -} Full_Cursor; - -#define BRFlag_Special_Character (1 << 0) - -typedef struct Buffer_Render_Item{ - int index; - unsigned short glyphid; - unsigned short flags; - float x0, y0; - float x1, y1; -} Buffer_Render_Item; - -inline_4tech void -write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid, - float x, float y, float w, float h){ - item->index = index; - item->glyphid = glyphid; - item->x0 = x; - item->y0 = y; - item->x1 = x + w; - item->y1 = y + h; -} - -inline_4tech float -write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid, - float x, float y, float *advance_data, float h){ - float ch_width; - ch_width = measure_character(advance_data, (char)glyphid); - write_render_item(item, index, glyphid, x, y, ch_width, h); - return(ch_width); -} - -inline_4tech Full_Cursor -make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){ - Full_Cursor hint; - hint.pos = starts[line_index]; - hint.line = line_index + 1; - hint.character = 1; - hint.unwrapped_y = (float)(line_index * font_height); - hint.unwrapped_x = 0; - hint.wrapped_y = wrap_ys[line_index]; - hint.wrapped_x = 0; - return(hint); -} - -typedef struct Cursor_With_Index{ - int pos, index; -} Cursor_With_Index; - -inline_4tech void -write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){ - positions[*count].index = *count; - positions[*count].pos = pos; - ++*count; -} - -#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; } - -internal_4tech void -buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){ - int i, mid; - int pivot_pos; - - mid = start; - pivot_pos = positions[pivot].pos; - for (i = mid; i < pivot; ++i){ - if (positions[i].pos < pivot_pos){ - CursorSwap__(positions[mid], positions[i]); - ++mid; - } - } - CursorSwap__(positions[mid], positions[pivot]); - - if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1); - if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot); -} - -internal_4tech void -buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){ - int i, mid; - int pivot_index; - - mid = start; - pivot_index = positions[pivot].index; - for (i = mid; i < pivot; ++i){ - if (positions[i].index < pivot_index){ - CursorSwap__(positions[mid], positions[i]); - ++mid; - } - } - CursorSwap__(positions[mid], positions[pivot]); - - if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1); - if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot); -} - -#undef CursorSwap__ - -inline_4tech void -buffer_sort_cursors(Cursor_With_Index *positions, int count){ - assert_4tech(count > 0); - buffer_quick_sort_cursors(positions, 0, count-1); -} - -inline_4tech void -buffer_unsort_cursors(Cursor_With_Index *positions, int count){ - assert_4tech(count > 0); - buffer_quick_unsort_cursors(positions, 0, count-1); -} - -internal_4tech void -buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){ - Cursor_With_Index *position; - int shift_amount; - - shift_amount = (len - (end - start)); - - position = sorted_positions + count - 1; - for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount; - for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start; -} - -internal_4tech int -buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){ - Buffer_Edit *edit; - int i, result, start_point; - - result = 1; - start_point = 0; - - edit = sorted_edits; - for (i = 0; i < edit_count; ++i, ++edit){ - if (start_point > edit->start){ - result = 0; break; - } - start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end; - } - - return(result); -} - -internal_4tech int -buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){ - Buffer_Edit *edit; - int i, result; - int shift_total, shift_max; - - result = 0; - shift_total = 0; - shift_max = 0; - - edit = sorted_edits; - for (i = 0; i < edit_count; ++i, ++edit){ - shift_total += (edit->len - (edit->end - edit->start)); - if (shift_total > shift_max) shift_max = shift_total; - } - - return(shift_max); -} - -internal_4tech void -buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){ - Cursor_With_Index *position, *end_position; - Buffer_Edit *edit, *end_edit; - int start, end; - int shift_amount; - - position = sorted_positions; - end_position = sorted_positions + count; - - edit = sorted_edits; - end_edit = sorted_edits + edit_count; - - shift_amount = 0; - - for (; edit < end_edit && position < end_position; ++edit){ - start = edit->start; - end = edit->end; - - for (; position->pos < start && position < end_position; ++position){ - position->pos += shift_amount; - } - - for (; position->pos < end && position < end_position; ++position){ - position->pos = start + shift_amount; - } - - shift_amount += (edit->len - (end - start)); - } - - for (; position < end_position; ++position){ - position->pos += shift_amount; - } -} - -internal_4tech int -eol_convert_in(char *dest, char *src, int size){ - int i, j, k; - - i = 0; - k = 0; - j = 0; - - for (; j < size && src[j] != '\r'; ++j); - memcpy_4tech(dest, src, j); - - if (j < size){ - k = 1; - ++j; - for (i = j; i < size; ++i){ - if (src[i] == '\r'){ - memcpy_4tech(dest + j - k, src + j, i - j); - ++k; - j = i+1; - } - } - memcpy_4tech(dest + j - k, src + j, i - j); - j = i - k; - } - - return(j); -} - -internal_4tech int -eol_in_place_convert_in(char *data, int size){ - int i, j, k; - - i = 0; - k = 0; - j = 0; - - for (; j < size && data[j] != '\r'; ++j); - - if (j < size){ - k = 1; - ++j; - for (i = j; i < size; ++i){ - if (data[i] == '\r'){ - memmove_4tech(data + j - k, data + j, i - j); - ++k; - j = i+1; - } - } - memmove_4tech(data + j - k, data + j, i - j); - j = i - k; - } - - return(j); -} - -internal_4tech int -eol_convert_out(char *dest, int max, char *src, int size, int *size_out){ - int result; - int i, j; - - // TODO(allen): iterative memory check? - result = 1; - i = 0; - j = 0; - - for (; i < size; ++i, ++j){ - if (src[i] == '\n'){ - dest[j] = '\r'; - ++j; - dest[j] = '\n'; - } - else dest[j] = src[i]; - } - - *size_out = j; - return(result); -} - -internal_4tech int -eol_in_place_convert_out(char *data, int size, int max, int *size_out){ - int result; - int i; - - // TODO(allen): iterative memory check? - result = 1; - i = 0; - - for (; i < size; ++i){ - if (data[i] == '\n'){ - memmove_4tech(data + i + 1, data + i, size - i); - data[i] = '\r'; - ++i; - ++size; - } - } - - *size_out = size; - return(result); -} - -inline_4tech int -is_whitespace(char c){ - int result; - result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); - return(result); -} - -inline_4tech int -is_alphanumeric_true(char c){ - return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'); -} - -inline_4tech int -is_alphanumeric(char c){ - return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_'); -} - -inline_4tech int -is_upper(char c){ - return (c >= 'A' && c <= 'Z'); -} - -inline_4tech int -is_lower(char c){ - return (c >= 'a' && c <= 'z'); -} - -internal_4tech int -is_match(char *a, char *b, int len){ - int result; - - result = 1; - for (;len > 0; --len, ++a, ++b) - if (*a != *b) { result = 0; break; } - - return(result); -} - -// BOTTOM - +/* + * Mr. 4th Dimention - Allen Webster + * Four Tech + * + * public domain -- no warranty is offered or implied; use this code at your own risk + * + * 23.10.2015 + * + * Items shared by gap buffer types + * + */ + +// TOP + +#include "../4coder_buffer_types.h" + +#ifndef inline_4tech +#define inline_4tech inline +#endif + +#ifndef internal_4tech +#define internal_4tech static +#endif + +#ifndef memset_4tech +#define memset_4tech memset +#endif + +#ifndef memzero_4tech +#define memzero_4tech(x) ((x) = {}) +#endif + +#ifndef memcpy_4tech +#define memcpy_4tech memcpy +#endif + +#ifndef memmove_4tech +#define memmove_4tech memmove +#endif + +#ifndef debug_4tech +#define debug_4tech(x) x +#endif + +#ifndef assert_4tech +#define assert_4tech assert +#endif + +#ifndef ceil_4tech +#define ceil_4tech CEIL32 +#endif + +#ifndef div_ceil_4tech +#define div_ceil_4tech DIVCEIL32 +#endif + +#ifndef cat_4tech +#define cat_4tech_(a,b) a##b +#define cat_4tech(a,b) cat_4tech_(a,b) +#endif + +#ifndef round_up_4tech +internal_4tech int +lroundup_(int x, int granularity){ + int original_x; + original_x = x; + x /= granularity; + x *= granularity; + if (x < original_x) x += granularity; + return x; +} +#define round_up_4tech(x,g) lroundup_(x,g) +#endif + +#ifndef round_pot_4tech +#define round_pot_4tech ROUNDPOT32 +#endif + +#define measure_character(a,c) ((a)[c]) + +typedef struct Buffer_Edit{ + int str_start, len; + int start, end; +} Buffer_Edit; + +typedef struct Buffer_Batch_State{ + int i; + int shift_total; +} Buffer_Batch_State; + +#define BRFlag_Special_Character (1 << 0) + +typedef struct Buffer_Render_Item{ + int index; + unsigned short glyphid; + unsigned short flags; + float x0, y0; + float x1, y1; +} Buffer_Render_Item; + +inline_4tech void +write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid, + float x, float y, float w, float h){ + item->index = index; + item->glyphid = glyphid; + item->x0 = x; + item->y0 = y; + item->x1 = x + w; + item->y1 = y + h; +} + +inline_4tech float +write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid, + float x, float y, float *advance_data, float h){ + float ch_width; + ch_width = measure_character(advance_data, (char)glyphid); + write_render_item(item, index, glyphid, x, y, ch_width, h); + return(ch_width); +} + +inline_4tech Full_Cursor +make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){ + Full_Cursor hint; + hint.pos = starts[line_index]; + hint.line = line_index + 1; + hint.character = 1; + hint.unwrapped_y = (float)(line_index * font_height); + hint.unwrapped_x = 0; + hint.wrapped_y = wrap_ys[line_index]; + hint.wrapped_x = 0; + return(hint); +} + +typedef struct Cursor_With_Index{ + int pos, index; +} Cursor_With_Index; + +inline_4tech void +write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){ + positions[*count].index = *count; + positions[*count].pos = pos; + ++*count; +} + +#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; } + +internal_4tech void +buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){ + int i, mid; + int pivot_pos; + + mid = start; + pivot_pos = positions[pivot].pos; + for (i = mid; i < pivot; ++i){ + if (positions[i].pos < pivot_pos){ + CursorSwap__(positions[mid], positions[i]); + ++mid; + } + } + CursorSwap__(positions[mid], positions[pivot]); + + if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1); + if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot); +} + +internal_4tech void +buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){ + int i, mid; + int pivot_index; + + mid = start; + pivot_index = positions[pivot].index; + for (i = mid; i < pivot; ++i){ + if (positions[i].index < pivot_index){ + CursorSwap__(positions[mid], positions[i]); + ++mid; + } + } + CursorSwap__(positions[mid], positions[pivot]); + + if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1); + if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot); +} + +#undef CursorSwap__ + +inline_4tech void +buffer_sort_cursors(Cursor_With_Index *positions, int count){ + assert_4tech(count > 0); + buffer_quick_sort_cursors(positions, 0, count-1); +} + +inline_4tech void +buffer_unsort_cursors(Cursor_With_Index *positions, int count){ + assert_4tech(count > 0); + buffer_quick_unsort_cursors(positions, 0, count-1); +} + +internal_4tech void +buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){ + Cursor_With_Index *position; + int shift_amount; + + shift_amount = (len - (end - start)); + + position = sorted_positions + count - 1; + for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount; + for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start; +} + +internal_4tech int +buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){ + Buffer_Edit *edit; + int i, result, start_point; + + result = 1; + start_point = 0; + + edit = sorted_edits; + for (i = 0; i < edit_count; ++i, ++edit){ + if (start_point > edit->start){ + result = 0; break; + } + start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end; + } + + return(result); +} + +internal_4tech int +buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){ + Buffer_Edit *edit; + int i, result; + int shift_total, shift_max; + + result = 0; + shift_total = 0; + shift_max = 0; + + edit = sorted_edits; + for (i = 0; i < edit_count; ++i, ++edit){ + shift_total += (edit->len - (edit->end - edit->start)); + if (shift_total > shift_max) shift_max = shift_total; + } + + return(shift_max); +} + +internal_4tech void +buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){ + Cursor_With_Index *position, *end_position; + Buffer_Edit *edit, *end_edit; + int start, end; + int shift_amount; + + position = sorted_positions; + end_position = sorted_positions + count; + + edit = sorted_edits; + end_edit = sorted_edits + edit_count; + + shift_amount = 0; + + for (; edit < end_edit && position < end_position; ++edit){ + start = edit->start; + end = edit->end; + + for (; position->pos < start && position < end_position; ++position){ + position->pos += shift_amount; + } + + for (; position->pos < end && position < end_position; ++position){ + position->pos = start + shift_amount; + } + + shift_amount += (edit->len - (end - start)); + } + + for (; position < end_position; ++position){ + position->pos += shift_amount; + } +} + +internal_4tech int +eol_convert_in(char *dest, char *src, int size){ + int i, j, k; + + i = 0; + k = 0; + j = 0; + + for (; j < size && src[j] != '\r'; ++j); + memcpy_4tech(dest, src, j); + + if (j < size){ + k = 1; + ++j; + for (i = j; i < size; ++i){ + if (src[i] == '\r'){ + memcpy_4tech(dest + j - k, src + j, i - j); + ++k; + j = i+1; + } + } + memcpy_4tech(dest + j - k, src + j, i - j); + j = i - k; + } + + return(j); +} + +internal_4tech int +eol_in_place_convert_in(char *data, int size){ + int i, j, k; + + i = 0; + k = 0; + j = 0; + + for (; j < size && data[j] != '\r'; ++j); + + if (j < size){ + k = 1; + ++j; + for (i = j; i < size; ++i){ + if (data[i] == '\r'){ + memmove_4tech(data + j - k, data + j, i - j); + ++k; + j = i+1; + } + } + memmove_4tech(data + j - k, data + j, i - j); + j = i - k; + } + + return(j); +} + +internal_4tech int +eol_convert_out(char *dest, int max, char *src, int size, int *size_out){ + int result; + int i, j; + + // TODO(allen): iterative memory check? + result = 1; + i = 0; + j = 0; + + for (; i < size; ++i, ++j){ + if (src[i] == '\n'){ + dest[j] = '\r'; + ++j; + dest[j] = '\n'; + } + else dest[j] = src[i]; + } + + *size_out = j; + return(result); +} + +internal_4tech int +eol_in_place_convert_out(char *data, int size, int max, int *size_out){ + int result; + int i; + + // TODO(allen): iterative memory check? + result = 1; + i = 0; + + for (; i < size; ++i){ + if (data[i] == '\n'){ + memmove_4tech(data + i + 1, data + i, size - i); + data[i] = '\r'; + ++i; + ++size; + } + } + + *size_out = size; + return(result); +} + +inline_4tech int +is_whitespace(char c){ + int result; + result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); + return(result); +} + +inline_4tech int +is_alphanumeric_true(char c){ + return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'); +} + +inline_4tech int +is_alphanumeric(char c){ + return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_'); +} + +inline_4tech int +is_upper(char c){ + return (c >= 'A' && c <= 'Z'); +} + +inline_4tech int +is_lower(char c){ + return (c >= 'a' && c <= 'z'); +} + +internal_4tech int +is_match(char *a, char *b, int len){ + int result; + + result = 1; + for (;len > 0; --len, ++a, ++b) + if (*a != *b) { result = 0; break; } + + return(result); +} + +// BOTTOM +