From aaec0cc3c88bef64e4567a96efa6826c6e996523 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 2 Sep 2019 11:59:36 -0700 Subject: [PATCH] Character positioning by line relative layout iteration --- 4coder_API/4coder_types.h | 191 +- 4coder_api_transition_30_31.cpp | 644 ------- 4coder_api_transition_30_31.h | 134 -- 4coder_api_transition_30_31_helpers.cpp | 1101 ----------- 4coder_auto_indent.cpp | 44 +- 4coder_base_commands.cpp | 203 +- 4coder_base_types.cpp | 172 +- 4coder_buffer_seek_constructors.cpp | 44 +- 4coder_default_hooks.cpp | 150 +- 4coder_default_include.cpp | 16 - 4coder_experiments.cpp | 219 +-- 4coder_generated/app_functions.h | 231 ++- 4coder_generated/command_metadata.h | 272 ++- 4coder_helper.cpp | 115 +- 4coder_jump_sticky.cpp | 20 +- 4coder_jump_sticky.h | 2 +- 4coder_jumping.cpp | 4 +- 4coder_lib/4coder_heap.cpp | 2 +- 4coder_lists.cpp | 6 +- 4coder_log_parser.cpp | 2 +- 4coder_scope_commands.cpp | 102 +- 4coder_search.cpp | 8 +- 4coder_seek.cpp | 9 +- 4coder_table.cpp | 58 +- 4coder_ui_helper.cpp | 108 +- 4ed.cpp | 168 +- 4ed_allocator_models.cpp | 28 + 4ed_api_implementation.cpp | 1562 +++++---------- 4ed_app_models.h | 2 +- 4ed_app_target.cpp | 4 +- 4ed_buffer.cpp | 2326 +++++++---------------- 4ed_buffer.h | 238 +-- 4ed_code_wrap.cpp | 941 --------- 4ed_code_wrap.h | 77 - 4ed_edit.cpp | 160 +- 4ed_edit.h | 11 - 4ed_file.cpp | 526 ++--- 4ed_file.h | 42 +- 4ed_file_lex.cpp | 73 +- 4ed_font_interface.h | 1 + 4ed_font_set.cpp | 2 + 4ed_history.cpp | 60 +- 4ed_history.h | 13 +- 4ed_string_matching.cpp | 56 +- 4ed_system.h | 2 +- 4ed_text_layout.cpp | 119 +- 4ed_text_layout.h | 37 +- 4ed_translation.cpp | 25 + 4ed_translation.h | 1 - 4ed_view.cpp | 682 +++---- 4ed_view.h | 34 +- 4ed_view_ui.cpp | 180 -- 4ed_working_set.cpp | 6 +- meta/4ed_build.cpp | 9 +- old_string_api.h | 245 --- platform_win32/win32_4ed_functions.cpp | 14 +- 56 files changed, 3033 insertions(+), 8468 deletions(-) delete mode 100644 4coder_api_transition_30_31.cpp delete mode 100644 4coder_api_transition_30_31.h delete mode 100644 4coder_api_transition_30_31_helpers.cpp create mode 100644 4ed_allocator_models.cpp delete mode 100644 4ed_code_wrap.cpp delete mode 100644 4ed_code_wrap.h delete mode 100644 4ed_view_ui.cpp delete mode 100644 old_string_api.h diff --git a/4coder_API/4coder_types.h b/4coder_API/4coder_types.h index f3bb82a4..276e1f9e 100644 --- a/4coder_API/4coder_types.h +++ b/4coder_API/4coder_types.h @@ -41,6 +41,16 @@ STRUCT Buffer_Point{ Vec2 pixel_shift; }; +STRUCT Line_Shift_Vertical{ + i64 line; + f32 y_delta; +}; + +STRUCT Line_Shift_Character{ + i64 line; + i64 character_delta; +}; + ENUM(u32, Child_Process_Set_Target_Flags){ ChildProcessSet_FailIfBufferAlreadyAttachedToAProcess = 1, ChildProcessSet_FailIfProcessAlreadyAttachedToABuffer = 2, @@ -469,143 +479,56 @@ STRUCT Buffer_Identifier{ Buffer_ID id; }; -/* DOC(Describes the various coordinate locations associated with the view's scroll position within it's buffer.) */ -STRUCT GUI_Scroll_Vars{ - UNION{ - STRUCT{ - /* DOC(The current actual x position of the view scroll.) */ - f32 scroll_x; - /* DOC(The current actual y position of the view scroll.) */ - f32 scroll_y; - }; - /* DOC(TODO) */ - Vec2 scroll_p; - }; - UNION{ - STRUCT{ - /* DOC(The target x position to which the view is moving. If scroll_x is not the same value, then it is still sliding to the target by the smooth scroll rule.) */ - i32 target_x; - /* DOC(The target y position to which the view is moving. If scroll_y is not the same value, then it is still sliding to the target by the smooth scroll rule.) */ - i32 target_y; - }; - /* DOC(TODO) */ - Vec2_i32 target_p; - }; +STRUCT Buffer_Scroll{ + Buffer_Point position; + Buffer_Point target; +}; + +STRUCT Basic_Scroll{ + Vec2_f32 position; + Vec2_f32 target; }; -/* DOC(The Buffer_Seek_Type is is used in a Buffer_Seek to identify which coordinates are suppose to be used for the seek.) -DOC_SEE(Buffer_Seek) -DOC_SEE(4coder_Buffer_Positioning_System) -*/ ENUM(i32, Buffer_Seek_Type){ - /* DOC(This value indicates absolute byte index positioning - where positions are measured as the number of bytes from the start of the file.) */ buffer_seek_pos, - /* DOC(This value indicates apparent character index positioning - where positions are measured as the number of apparent characters from the starts of the file.) */ - buffer_seek_character_pos, - /* DOC(This value indicates xy positioning with wrapped lines where the x and y values are in pixels.) */ - buffer_seek_wrapped_xy, - /* DOC(This value indicates xy positioning with unwrapped lines where the x and y values are in pixels.) */ - buffer_seek_unwrapped_xy, - /* DOC(This value indicates line-character positioning. - These coordinates are 1 based to match standard line numbering.) */ - buffer_seek_line_char + buffer_seek_line_col, }; -/* DOC(Buffer_Seek describes the destination of a seek operation. There are helpers for concisely creating Buffer_Seek structs. They can be found in 4coder_buffer_types.h.) -DOC_SEE(Buffer_Seek_Type) -DOC_SEE(4coder_Buffer_Positioning_System) */ STRUCT Buffer_Seek{ - /* DOC(The type field determines the coordinate system of the seek operation.) */ Buffer_Seek_Type type; UNION{ - STRUCT { - /* DOC(The pos field specified the pos when the seek is in absolute position.) */ + STRUCT{ i64 pos; }; - STRUCT { - /* DOC(For xy coordinate seeks, rounding down means that any x in the box of the character lands on that character. For instance when clicking rounding down is the user's expected behavior. Not rounding down means that the right hand portion of the character's box, which is closer to the next character, will land on that next character. The unrounded behavior is the expected behavior when moving vertically and keeping the preferred x.) */ - b32 round_down; - /* DOC(The x coordinate for xy type seeks.) */ - f32 x; - /* DOC(The y coordinate for xy type seeks.) */ - f32 y; - }; - STRUCT { - /* DOC(The line number of a line-character type seek.) */ + STRUCT{ i64 line; - /* DOC(The character number of a line-character type seek.) */ - i64 character; + i64 col; }; }; }; -/* DOC(Full_Cursor describes the position of a cursor in every buffer coordinate system supported by 4coder. This cursor type requires that the buffer is associated with a view to give the x/y values meaning.) -DOC_SEE(4coder_Buffer_Positioning_System) */ -STRUCT Full_Cursor{ - /* DOC(This field contains the cursor's position in absolute byte index positioning.) */ +STRUCT Buffer_Cursor{ i64 pos; - /* DOC(This field contains the cursor's position in apparent character index positioning.) */ - i64 character_pos; - /* DOC(This field contains the number of the line where the cursor is located. This field is one based.) */ i64 line; - /* DOC(This field contains the number of the character from the beginninf of the line where the cursor is located. This field is one based.) */ - i64 character; - /* DOC(This field contains the number of the line where the cursor is located, taking the line wrapping into account. This field is one based.) */ - i64 wrap_line; - union{ - struct{ - /* DOC(This field contains the x position measured with unwrapped lines.) */ - f32 unwrapped_x; - /* DOC(This field contains the y position measured with unwrapped lines.) */ - f32 unwrapped_y; - }; - /* DOC(TODO) */ - Vec2 unwrapped_p; - }; - union{ - struct{ - /* DOC(This field contains the x position measured with wrapped lines.) */ - f32 wrapped_x; - /* DOC(This field contains the y position measured with wrapped lines.) */ - f32 wrapped_y; - }; - /* DOC(TODO) */ - Vec2 wrapped_p; - }; + i64 col; }; -/* DOC(Partial_Cursor describes the position of a cursor in all of the coordinate systems that a invariant to the View. In other words the coordinate systems available here can be used on a buffer that is not currently associated with a View.) -DOC_SEE(4coder_Buffer_Positioning_System) */ -STRUCT Partial_Cursor{ - /* DOC(This field contains the cursor's position in absolute byte index positioning.) */ - i32 pos; - /* DOC(This field contains the cursor's position in apparent character index positioning.) */ - i32 character_pos; - /* DOC(This field contains the number of the character from the beginninf of the line - where the cursor is located. This field is one based.) */ - i32 line; - /* DOC(This field contains the number of the column where the cursor is located. This field is one based.) */ - i32 character; -}; - -STRUCT Range_Partial_Cursor{ +STRUCT Range_Cursor{ struct{ - Partial_Cursor min; - Partial_Cursor max; + Buffer_Cursor min; + Buffer_Cursor max; }; struct{ - Partial_Cursor begin; - Partial_Cursor end; + Buffer_Cursor begin; + Buffer_Cursor end; }; struct{ - Partial_Cursor start; - Partial_Cursor end; + Buffer_Cursor start; + Buffer_Cursor end; }; struct{ - Partial_Cursor first; - Partial_Cursor one_past_last; + Buffer_Cursor first; + Buffer_Cursor one_past_last; }; }; @@ -651,12 +574,6 @@ static Managed_Scope ManagedScope_NULL = 0; static Managed_Variable_ID ManagedVariableIndex_ERROR = -1; static Managed_Object ManagedObject_NULL = 0; -STRUCT Text_Layout_Coordinates{ - Vec2_f32 on_screen_p0; - Vec2_f32 in_buffer_p0; - Vec2_f32 dim; -}; - /* DOC(A multi-member identifier for a marker visual. A marker visual is attached to a marker object (Marker_Object), it is freed when the marker object is freed or when it is specifically destroyed. Multiple marker visuals can be placed on a single marker object.) DOC_SEE(Marker_Visual_Type) DOC_SEE(Marker_Visual_Symbolic_Color) @@ -843,34 +760,14 @@ STRUCT Face_Metrics{ f32 typical_character_width; }; -/* DOC(Buffer_Edit describes a range of a buffer and string to replace that range. A Buffer_Edit has to be paired with a string that contains the actual -text that will be replaced into the buffer.) */ -STRUCT Buffer_Edit{ - /* DOC(The str_start field specifies the first character in the accompanying string that corresponds with this edit.) */ - i32 str_start; - /* DOC(The len field specifies the length of the string being written into the buffer.) */ - i32 len; - /* DOC(The start field specifies the start of the range in the buffer to replace in absolute position.) */ - i32 start; - /* DOC(The end field specifies one past the end of the range in the buffer to replace in absolute position.) */ - i32 end; +STRUCT Edit{ + String_Const_u8 text; + Interval_i64 range; }; -/* -DOC(This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient for a few functions that return a batch edit to the user.) -DOC_SEE(Buffer_Edit) -DOC_SEE(buffer_batch_edit) -*/ -STRUCT Buffer_Batch_Edit{ - /* DOC(The pointer to the edit string buffer.) */ - char *str; - /* DOC(The length of the edit string buffer.) */ - i32 str_len; - - /* DOC(The array of edits to be applied.) */ - Buffer_Edit *edits; - /* DOC(The number of edits in the array.) */ - i32 edit_count; +STRUCT Batch_Edit{ + Batch_Edit *next; + Edit edit; }; ENUM(i32, Record_Kind){ @@ -1022,8 +919,9 @@ TYPEDEF_FUNC i32 Hook_Function(struct Application_Links *app); TYPEDEF_FUNC i32 Open_File_Hook_Function(struct Application_Links *app, Buffer_ID buffer_id); #define OPEN_FILE_HOOK_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id) -TYPEDEF_FUNC i32 File_Edit_Range_Function(struct Application_Links *app, Buffer_ID buffer_id, Range range, String_Const_u8 text); -#define FILE_EDIT_RANGE_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id, Range range, String_Const_u8 text) +TYPEDEF_FUNC i32 File_Edit_Range_Function(struct Application_Links *app, Buffer_ID buffer_id, + Interval_i64 range, String_Const_u8 text); +#define FILE_EDIT_RANGE_SIG(name) i32 name(struct Application_Links *app, Buffer_ID buffer_id, Interval_i64 range, String_Const_u8 text) TYPEDEF_FUNC i32 File_Edit_Finished_Function(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count); #define FILE_EDIT_FINISHED_SIG(name) i32 name(struct Application_Links *app, Buffer_ID *buffer_ids, i32 buffer_id_count) @@ -1034,9 +932,8 @@ TYPEDEF_FUNC i32 File_Externally_Modified_Function(struct Application_Links *app TYPEDEF_FUNC void Input_Filter_Function(Mouse_State *mouse); #define INPUT_FILTER_SIG(name) void name(Mouse_State *mouse) -TYPEDEF_FUNC i32 Scroll_Rule_Function(float target_x, float target_y, float *scroll_x, float *scroll_y, i32 view_id, i32 is_new_target, float dt); -#define SCROLL_RULE_SIG(name) \ -i32 name(float target_x, float target_y, float *scroll_x, float *scroll_y, i32 view_id, i32 is_new_target, float dt) +TYPEDEF_FUNC Vec2_f32 Delta_Rule_Function(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt); +#define DELTA_RULE_SIG(name) Vec2_f32 name(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt) STRUCT Color_Table{ argb_color *vals; diff --git a/4coder_api_transition_30_31.cpp b/4coder_api_transition_30_31.cpp deleted file mode 100644 index 6e3595cf..00000000 --- a/4coder_api_transition_30_31.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Helpers for the API transition from 4.0.30 to 4.0.31 - * - * In order to keep your layer on the old API you don't have to do anything, this provides wrappers - * idential to the 4.0.30 API. - * In order to transition your entire layer over to the 4.0.31 API define 'REMOVE_TRANSITION_HELPER_31' and fix errors. - * Or you can do it step by step by removing a few wrappers at a time. - * This transition helper will be removed in a future version so it is recommended to get off sooner or laster. - * - * Tips on transitioning: -* -* Wrather than just try to inline this code everywhere, you can simplify things quite a lot by storing references -* to buffers and views and Buffer_ID and View_ID instead of Buffer_Summary and View_Summary. - * Just get the summaries when you need information in those structures. - * - * You will make your code simpler if you stick to String as much as possible, but whenever you want to you can switch - * to any string type you have to String by calling make_string(char_ptr, length) or make_string_slowly(null_terminated_c_str). - * To pull the char ptr and length out of a String named "string": string.str and str.size. - * If you need a null terminated string from a String use get_null_terminated in 4coder_helper.cpp - * - */ - -// TOP - -#if !defined(REMOVE_TRANSITION_HELPER_31) - -typedef b32 bool32; - -static b32 -get_buffer_summary(Application_Links *app, Buffer_ID buffer, Access_Flag access, Buffer_Summary *summary){ - b32 result = false; - if (buffer_exists(app, buffer)){ - Scratch_Block scratch(app); - Access_Flag buffer_access_flags = buffer_get_access_flags(app, buffer); - if ((buffer_access_flags & ~access) == 0){ - result = true; - summary->exists = true; - summary->ready = buffer_ready(app, buffer); - summary->buffer_id = buffer; - summary->size = (i32)buffer_get_size(app, buffer); - summary->line_count = (i32)buffer_get_line_count(app, buffer); - - String_Const_u8 file_name_get = push_buffer_file_name(app, scratch, buffer); - block_copy(summary->file_name, file_name_get.str, file_name_get.size); - summary->file_name_len = (i32)file_name_get.size; - - String_Const_u8 buffer_name_get = push_buffer_unique_name(app, scratch, buffer); - block_copy(summary->buffer_name, buffer_name_get.str, buffer_name_get.size); - summary->buffer_name_len = (i32)buffer_name_get.size; - - summary->dirty = buffer_get_dirty_state(app, buffer); - buffer_get_setting(app, buffer, BufferSetting_Lex, &summary->is_lexed); - summary->tokens_are_ready = buffer_tokens_are_ready(app, buffer); - buffer_get_setting(app, buffer, BufferSetting_MapID, &summary->map_id); - buffer_get_setting(app, buffer, BufferSetting_WrapLine, &summary->unwrapped_lines); - summary->unwrapped_lines = !summary->unwrapped_lines; - summary->lock_flags = buffer_access_flags; - } - } - return(result); -} - -static b32 -get_view_summary(Application_Links *app, View_ID view_id, Access_Flag access, View_Summary *view){ - b32 result = false; - if (view_exists(app, view_id)){ - Buffer_ID buffer = view_get_buffer(app, view_id, access); - if (buffer != 0){ - result = true; - - Face_ID face_id = get_face_id(app, buffer); - Face_Metrics metrics = get_face_metrics(app, face_id); - - view->exists = true; - view->view_id = view_id; - view->line_height = metrics.line_height; - buffer_get_setting(app, buffer, BufferSetting_WrapLine, &view->unwrapped_lines); - view->unwrapped_lines = !view->unwrapped_lines; - view_get_setting(app, view_id, ViewSetting_ShowWhitespace, &view->show_whitespace); - view->buffer_id = buffer; - i64 pos = view_get_mark_pos(app, view_id); - view->mark = view_compute_cursor(app, view_id, seek_pos(pos)); - pos = view_get_cursor_pos(app, view_id); - view->cursor = view_compute_cursor(app, view_id, seek_pos(pos)); - view->preferred_x = view_get_preferred_x(app, view_id); - Rect_f32 screen_rect = view_get_screen_rect(app, view_id); - view->view_region = screen_rect; - view->render_region = Rf32(0.f, 0.f, rect_width(screen_rect), rect_height(screen_rect)); - view->scroll_vars = view_get_scroll_vars(app, view_id); - } - } - return(result); -} - -static b32 -clipboard_post(Application_Links *app, i32 clipboard_id, char *str, i32 len){ - return(clipboard_post(app, clipboard_id, SCu8(str, len))); -} - -static i32 -clipboard_index(Application_Links *app, i32 clipboard_id, i32 item_index, char *out, i32 len){ - Scratch_Block scratch(app); - String_Const_u8 string = push_clipboard_index(app, scratch, clipboard_id, item_index); - block_copy(out, string.str, clamp_top((i32)string.size, len)); - return((i32)string.size); -} - -static Buffer_Summary -get_buffer_first(Application_Links *app, Access_Flag access){ - Buffer_Summary buffer = {}; - Buffer_ID buffer_id = get_buffer_next(app, 0, access); - if (buffer_id != 0){ - get_buffer_summary(app, buffer_id, access, &buffer); - } - return(buffer); -} - -static void -get_buffer_next(Application_Links *app, Buffer_Summary *buffer, Access_Flag access){ - if (buffer != 0 && buffer->exists){ - Buffer_ID buffer_id = get_buffer_next(app, buffer->buffer_id, access); - if (buffer_id != 0){ - get_buffer_summary(app, buffer_id, access, buffer); - } - else{ - block_zero_struct(buffer); - } - } -} - -static Buffer_Summary -get_buffer(Application_Links *app, Buffer_ID buffer_id, Access_Flag access){ - Buffer_Summary buffer = {}; - get_buffer_summary(app, buffer_id, access, &buffer); - return(buffer); -} - -static Buffer_Summary -get_buffer_by_name(Application_Links *app, char *name, i32 len, Access_Flag access){ - Buffer_Summary buffer = {}; - Buffer_ID id = get_buffer_by_name(app, SCu8(name, len), access); - if (id != 0){ - get_buffer_summary(app, id, access, &buffer); - } - return(buffer); -} - -static Buffer_Summary -get_buffer_by_file_name(Application_Links *app, char *name, i32 len, Access_Flag access){ - Buffer_Summary buffer = {}; - Buffer_ID id = get_buffer_by_file_name(app, SCu8(name, len), access); - if (id != 0){ - get_buffer_summary(app, id, access, &buffer); - } - return(buffer); -} - -static b32 -buffer_read_range(Application_Links *app, Buffer_Summary *buffer, i32 start, i32 one_past_last, char *out){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_read_range(app, buffer->buffer_id, Ii64(start, one_past_last), out); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_replace_range(Application_Links *app, Buffer_Summary *buffer, i32 start, i32 one_past_last, char *str, i32 len){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_replace_range(app, buffer->buffer_id, Ii64(start, one_past_last), SCu8(str, len)); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_compute_cursor(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - *cursor_out = buffer_compute_cursor(app, buffer->buffer_id, seek); - result = (cursor_out->line > 0); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_batch_edit(Application_Links *app, Buffer_Summary *buffer, char *str, i32 str_len, Buffer_Edit *edits, i32 edit_count, i32 type){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_batch_edit(app, buffer->buffer_id, str, edits, edit_count); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_get_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, i32 *value_out){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_get_setting(app, buffer->buffer_id, setting, value_out); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_set_setting(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, i32 value){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_set_setting(app, buffer->buffer_id, setting, value); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static i32 -buffer_token_count(Application_Links *app, Buffer_Summary *buffer){ - i32 count = 0; - if (buffer != 0 && buffer->exists){ - count = buffer_get_token_array(app, buffer->buffer_id).count; - } - return(count); -} - -static b32 -buffer_read_tokens(Application_Links *app, Buffer_ID buffer, i32 start_token, i32 end_token, Cpp_Token *tokens_out){ - b32 result = false; - if (buffer != 0){ - Cpp_Token_Array array = buffer_get_token_array(app, buffer); - if (0 <= start_token && start_token <= end_token && end_token < array.count){ - result = true; - block_copy_dynamic_array(tokens_out, array.tokens + start_token, end_token - start_token); - } - } - return(result); -} - -static b32 -buffer_read_tokens(Application_Links *app, Buffer_Summary *buffer, i32 start_token, i32 end_token, Cpp_Token *tokens_out){ - Buffer_ID buffer_id = (buffer==0?0:buffer->buffer_id); - b32 result = buffer_read_tokens(app, buffer_id, start_token, end_token, tokens_out); - get_buffer_summary(app, buffer_id, AccessAll, buffer); - return(result); -} - -static b32 -buffer_get_token_range(Application_Links *app, Buffer_Summary *buffer, Cpp_Token **first_token_out, Cpp_Token **one_past_last_token_out){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - Cpp_Token_Array array = buffer_get_token_array(app, buffer->buffer_id); - result = true; - if (first_token_out != 0){ - *first_token_out = array.tokens; - } - if (one_past_last_token_out != 0){ - *one_past_last_token_out = array.tokens + array.count; - } - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_get_token_index(Application_Links *app, Buffer_Summary *buffer, i32 pos, Cpp_Get_Token_Result *get_result){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - Cpp_Token_Array array = buffer_get_token_array(app, buffer->buffer_id); - result = true; - *get_result = cpp_get_token(array, pos); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static b32 -buffer_send_end_signal(Application_Links *app, Buffer_Summary *buffer){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_send_end_signal(app, buffer->buffer_id); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static Buffer_Summary -create_buffer(Application_Links *app, char *filename, i32 filename_len, Buffer_Create_Flag flags){ - Buffer_Summary buffer = {}; - Buffer_ID buffer_id = create_buffer(app, SCu8(filename, filename_len), flags); - if (buffer_id != 0){ - get_buffer_summary(app, buffer_id, AccessAll, &buffer); - } - return(buffer); -} - -static b32 -save_buffer(Application_Links *app, Buffer_Summary *buffer, char *file_name, i32 file_name_len, u32 flags){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_save(app, buffer->buffer_id, SCu8(file_name, file_name_len), flags); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static Buffer_Kill_Result -kill_buffer(Application_Links *app, Buffer_Identifier buffer, Buffer_Kill_Flag flags){ - Buffer_Kill_Result result = 0; - if (buffer.id != 0){ - result = buffer_kill(app, buffer.id, flags); - } - else if (buffer.name != 0){ - Buffer_ID id = get_buffer_by_name(app, SCu8(buffer.name, buffer.name_len), AccessAll); - if (id != 0){ - result = buffer_kill(app, id, flags); - } - } - return(result); -} - -static Buffer_Reopen_Result -reopen_buffer(Application_Links *app, Buffer_Summary *buffer, Buffer_Reopen_Flag flags){ - Buffer_Reopen_Result result = 0; - if (buffer != 0 && buffer->exists){ - result = buffer_reopen(app, buffer->buffer_id, flags); - } - return(result); -} - -static View_Summary -get_view_first(Application_Links *app, Access_Flag access){ - View_Summary view = {}; - View_ID view_id = get_view_next(app, 0, access); - if (view_id != 0){ - get_view_summary(app, view_id, access, &view); - } - return(view); -} - -static void -get_view_next(Application_Links *app, View_Summary *view, Access_Flag access){ - if (view != 0 && view->exists){ - View_ID view_id = get_view_next(app, view->view_id, access); - if (view_id != 0){ - get_view_summary(app, view_id, access, view); - } - else{ - block_zero_struct(view); - } - } -} - -static View_Summary -get_view(Application_Links *app, View_ID view_id, Access_Flag access){ - View_Summary view = {}; - get_view_summary(app, view_id, access, &view); - return(view); -} - -static View_Summary -get_active_view_DEP(Application_Links *app, Access_Flag access){ - View_Summary view = {}; - View_ID id = get_active_view(app, access); - if (id != 0){ - get_view_summary(app, id, access, &view); - } - return(view); -} - -static View_Summary -open_view(Application_Links *app, View_Summary *view_location, View_Split_Position position){ - View_Summary view = {}; - if (view_location != 0 && view_location->exists){ - Panel_ID panel_id = view_get_panel(app, view_location->view_id); - if (panel_id != 0){ - b32 vertical = (position == ViewSplit_Left || position == ViewSplit_Right); - if (panel_split(app, panel_id, vertical?PanelSplit_LeftAndRight:PanelSplit_TopAndBottom)){ - Panel_Child child = (position == ViewSplit_Left || position == ViewSplit_Top)?PanelChild_Min:PanelChild_Max; - Panel_ID new_panel_id = panel_get_child(app, panel_id, child); - if (new_panel_id != 0){ - View_ID new_view_id = panel_get_view(app, new_panel_id); - if (new_view_id != 0){ - get_view_summary(app, new_view_id, AccessAll, &view); - get_view_summary(app, view_location->view_id, AccessAll, view_location); - } - } - } - } - } - return(view); -} - -static b32 -close_view(Application_Links *app, View_Summary *view){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_close(app, view->view_id); - } - return(result); -} - -static b32 -set_active_view(Application_Links *app, View_Summary *view){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_active(app, view->view_id); - } - return(result); -} - -static b32 -view_get_setting(Application_Links *app, View_Summary *view, View_Setting_ID setting, i32 *value_out){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_get_setting(app, view->view_id, setting, value_out); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_setting(Application_Links *app, View_Summary *view, View_Setting_ID setting, i32 value){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_setting(app, view->view_id, setting, value); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_compute_cursor_DEP(Application_Links *app, View_Summary *view, Buffer_Seek seek, Full_Cursor *cursor_out){ - b32 result = false; - if (view != 0 && view->exists){ - *cursor_out = view_compute_cursor(app, view->view_id, seek); - result = (cursor_out->line > 0); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_cursor(Application_Links *app, View_Summary *view, Buffer_Seek seek, b32 set_preferred_x){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_cursor(app, view->view_id, seek, set_preferred_x); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_scroll(Application_Links *app, View_Summary *view, GUI_Scroll_Vars scroll){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_scroll(app, view->view_id, scroll); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_mark(Application_Links *app, View_Summary *view, Buffer_Seek seek){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_mark(app, view->view_id, seek); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_buffer(Application_Links *app, View_Summary *view, Buffer_ID buffer_id, Set_Buffer_Flag flags){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_set_buffer(app, view->view_id, buffer_id, flags); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_post_fade(Application_Links *app, View_Summary *view, float seconds, i32 start, i32 end, int_color color){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_post_fade(app, view->view_id, seconds, Ii64(start, end), color); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_begin_ui_mode(Application_Links *app, View_Summary *view){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_begin_ui_mode(app, view->view_id); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_end_ui_mode(Application_Links *app, View_Summary *view){ - b32 result = false; - if (view != 0 && view->exists){ - result = view_end_ui_mode(app, view->view_id); - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_highlight(Application_Links *app, View_ID view_id, i32 start, i32 end, b32 turn_on){ - // NOTE(allen): this feature is completely removed, transition to using highlighted markers instead - return(false); -} - -static b32 -buffer_set_face(Application_Links *app, Buffer_Summary *buffer, Face_ID id){ - b32 result = false; - if (buffer != 0 && buffer->exists){ - result = buffer_set_face(app, buffer->buffer_id, id); - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); - } - return(result); -} - -static Face_ID -get_face_id(Application_Links *app, Buffer_Summary *buffer){ - Face_ID result = 0; - if (buffer != 0 && buffer->exists){ - result = get_face_id(app, buffer->buffer_id); - } - else{ - result = get_face_id(app, 0); - } - return(result); -} - -static void -print_message(Application_Links *app, char *str, i32 len){ - print_message(app, SCu8(str, len)); -} - -#if 0 -static void -create_theme(Application_Links *app, Theme *theme, char *name, i32 len){ - create_theme(app, theme, make_string(name, len)); -} - -static void -change_theme(Application_Links *app, char *name, i32 len){ - change_theme(app, make_string(name, len)); -} -#endif - -static i32 -directory_get_hot(Application_Links *app, char *out, i32 capacity){ - Scratch_Block scratch(app); - String_Const_u8 string = push_hot_directory(app, scratch); - block_copy(out, string.str, clamp_top((i32)string.size, capacity)); - return((i32)string.size); -} - -static b32 -directory_set_hot(Application_Links *app, char *str, i32 len){ - return(set_hot_directory(app, SCu8(str, len))); -} - -static b32 -file_exists(Application_Links *app, char *file_name, i32 len){ - File_Attributes attributes = get_file_attributes(app, SCu8(file_name, len)); - return(attributes.last_write_time > 0); -} - -static b32 -directory_cd(Application_Links *app, char *dir, i32 *len, i32 capacity, char *rel_path, i32 rel_len){ - String_Const_u8 directory = SCu8(dir, *len); - String_Const_u8 relative_path = SCu8(rel_path, rel_len); - - Scratch_Block scratch(app); - String_Const_u8 new_directory = {}; - b32 result = false; - if (relative_path.size > 0){ - if (string_match(relative_path, string_u8_litexpr("."))){ - new_directory = directory; - result = true; - } - else if (string_match(relative_path, string_u8_litexpr(".."))){ - directory = string_remove_last_folder(directory); - if (file_exists(app, (char*)directory.str, (i32)directory.size)){ - new_directory = directory; - result = true; - } - } - else{ - new_directory = push_u8_stringf(scratch, "%.*s/%.*s", - string_expand(directory), - string_expand(relative_path)); - if (file_exists(app, (char*)new_directory.str, (i32)new_directory.size)){ - result = true; - } - } - } - - if (result){ - i32 new_len = clamp_top((i32)new_directory.size, capacity); - block_copy(dir, new_directory.str, new_len); - *len = new_len; - } - - return(result); -} - -static i32 -get_4ed_path(Application_Links *app, char *out, i32 capacity){ - Scratch_Block scratch(app); - String_Const_u8 string = push_4ed_path(app, scratch); - block_copy(out, string.str, clamp_top((i32)string.size, capacity)); - return((i32)string.size); -} - -static void -set_window_title(Application_Links *app, char *title){ - String_Const_u8 title_string = SCu8(title); - set_window_title(app, title_string); -} - -static Process_State -get_process_state(Application_Links *app, Buffer_ID buffer){ - Process_State state = {}; - Child_Process_ID child_process = buffer_get_attached_child_process(app, buffer); - if (child_process != 0){ - state = child_process_get_state(app, child_process); - } - return(state); -} - -#endif - -// BOTTOM - diff --git a/4coder_api_transition_30_31.h b/4coder_api_transition_30_31.h deleted file mode 100644 index e05f4af1..00000000 --- a/4coder_api_transition_30_31.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Helpers for the API transition from 4.0.30 to 4.0.31 - * - * In order to keep your layer on the old API you don't have to do anything, this provides wrappers - * idential to the 4.0.30 API. - * In order to transition your entire layer over to the 4.0.31 API define 'REMOVE_TRANSITION_HELPER_31' and fix errors. - * Or you can do it step by step by removing a few wrappers at a time. - * This transition helper will be removed in a future version so it is recommended to get off sooner or laster. - * - * Tips on transitioning: - * - * Wrather than just try to inline this code everywhere, you can simplify things quite a lot by storing references - * to buffers and views and Buffer_ID and View_ID instead of Buffer_Summary and View_Summary. - * Just get the summaries when you need information in those structures. - * - * You will make your code simpler if you stick to String as much as possible, but whenever you want to you can switch - * to any string type you have to String by calling make_string(char_ptr, length) or make_string_slowly(null_terminated_c_str). - * To pull the char ptr and length out of a String named "string": string.str and str.size. - * If you need a null terminated string from a String use get_null_terminated in 4coder_helper.cpp - * - */ - -// TOP - -#if !defined(REMOVE_TRANSITION_HELPER_31) - -#define BatchEdit_PreserveTokens 0 -#define BatchEdit_Normal 0 - -/* DOC(Buffer_Summary acts as a handle to a buffer and describes the state of the buffer.) -DOC_SEE(Access_Flag) -DOC_SEE(Dirty_State) */ -STRUCT Buffer_Summary{ - /* DOC(This field indicates whether the Buffer_Summary describes a buffer that is open in 4coder. When this field is false the summary is referred to as a "null summary".) */ - b32 exists; - /* DOC(If this is not a null summary, this field indicates whether the buffer has finished loading.) */ - b32 ready; - /* DOC(If this is not a null summary this field is the id of the associated buffer. If this is a null summary then buffer_id is 0.) */ - Buffer_ID buffer_id; - /* DOC(If this is not a null summary, this field contains flags describing the protection status of the buffer.) */ - Access_Flag lock_flags; - - /* DOC(If this is not a null summary, this field specifies the number of bytes in the buffer.) */ - i32 size; - /* DOC(If this is not a null summary, this field specifies the number of lines in the buffer.) */ - i32 line_count; - - /* DOC(If this is not a null summary, this field specifies the file name associated to this buffer.) */ - char file_name[256]; - /* DOC(This field specifies the length of the file_name string.) */ - i32 file_name_len; - - /* DOC(If this is not a null summary, this field specifies the name of the buffer.) */ - char buffer_name[256]; - /* DOC(This field specifies the length of the buffer_name string.) */ - i32 buffer_name_len; - - /* DOC(This field indicates the dirty state of the buffer.) */ - Dirty_State dirty; - - /* DOC(If this is not a null summary, this field indicates whether the buffer is set to lex tokens.) */ - b32 is_lexed; - /* DOC(If this is not a null summary, this field indicates whether the buffer has up to date tokens available. If this field is false, it may simply mean the tokens are still being generated in a background task and will be available later. If that is the case, is_lexed will be true to indicate that the buffer is trying to get it's tokens up to date.) */ - b32 tokens_are_ready; - /* DOC(If this is not a null summary, this field specifies the id of the command map for this buffer.) */ - i32 map_id; - /* DOC(If this is not a null summary, this field indicates whether the buffer 'prefers' wrapped lines.) */ - b32 unwrapped_lines; -}; - -/* DOC(View_Summary acts as a handle to a view and describes the state of the view.) -DOC_SEE(Access_Flag) -DOC_SEE(Full_Cursor) -DOC_SEE(GUI_Scroll_Vars) */ -STRUCT View_Summary{ - /* DOC(This field indicates whether the View_Summary describes a view that is open in 4coder. When this field is false the summary is referred to as a "null summary". ) */ - b32 exists; - /* DOC(This field is the id of the associated view. If this is a null summary then view_id is 0. ) */ - i32 view_id; - /* DOC(Then this is the id of the buffer this view currently sees.) */ - i32 buffer_id; - /* DOC(This field contains flags describing the protection status of the view.) */ - Access_Flag lock_flags; - - /* DOC(This describes the position of the cursor.) */ - Full_Cursor cursor; - /* DOC(This describes the position of the mark.) */ - Full_Cursor mark; - /* DOC(This is the x position that is maintained in vertical navigation.) */ - f32 preferred_x; - /* DOC(This specifies the height of a line rendered in the view.) */ - f32 line_height; - /* DOC(This indicates that the view is set to render with unwrapped lines.) */ - b32 unwrapped_lines; - /* DOC(This indicates that the view is set to highlight white space.) */ - b32 show_whitespace; - - /* DOC(This describes the screen position in which this view is displayed.) */ - Rect_f32 view_region; - /* DOC(TODO) */ - Rect_f32 render_region; - /* DOC(This describes the scrolling position inside the view.) */ - GUI_Scroll_Vars scroll_vars; -}; - -/* DOC(A Seek_Boundary_Flag field specifies a set of "boundary" types used in seeks for the beginning or end of different types of words.) */ -typedef u32 Seek_Boundary_Flag; -enum{ - BoundaryWhitespace = 0x1, - BoundaryToken = 0x2, - BoundaryAlphanumeric = 0x4, - BoundaryCamelCase = 0x8 -}; - -// NOTE(allen|4.0.31): Stream_Tokens has been deprecated in favor of the Token_Iterator. -// For examples of usage: 4coder_function_list.cpp 4coder_scope_commands.cpp -// If you want to keep your code working easily uncomment the typedef for Stream_Tokens. -struct Stream_Tokens_DEP{ - Application_Links *app; - Buffer_ID buffer_id; - - Cpp_Token *base_tokens; - Cpp_Token *tokens; - i32 start; - i32 end; - i32 count; - i32 token_count; -}; -//typedef Stream_Tokens_DEP Stream_Tokens; - -#endif - -// BOTTOM - diff --git a/4coder_api_transition_30_31_helpers.cpp b/4coder_api_transition_30_31_helpers.cpp deleted file mode 100644 index e60d21d1..00000000 --- a/4coder_api_transition_30_31_helpers.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Helpers for the API transition from 4.0.30 to 4.0.31 - * - * In order to keep your layer on the old API you don't have to do anything, this provides wrappers - * idential to the 4.0.30 API. - * In order to transition your entire layer over to the 4.0.31 API define 'REMOVE_TRANSITION_HELPER_31' and fix errors. - * Or you can do it step by step by removing a few wrappers at a time. - * This transition helper will be removed in a future version so it is recommended to get off sooner or laster. - * - * Tips on transitioning: -* -* Wrather than just try to inline this code everywhere, you can simplify things quite a lot by storing references -* to buffers and views and Buffer_ID and View_ID instead of Buffer_Summary and View_Summary. - * Just get the summaries when you need information in those structures. - * - * You will make your code simpler if you stick to String as much as possible, but whenever you want to you can switch - * to any string type you have to String by calling make_string(char_ptr, length) or make_string_slowly(null_terminated_c_str). - * To pull the char ptr and length out of a String named "string": string.str and str.size. - * If you need a null terminated string from a String use get_null_terminated in 4coder_helper.cpp - * - */ - -// TOP - -#if !defined(REMOVE_TRANSITION_HELPER_31) - -static b32 -exec_system_command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer_id, - char *path, int32_t path_len, char *command, i32 command_len, Command_Line_Interface_Flag flags){ - return(exec_system_command(app, (view == 0)?0:view->view_id, buffer_id, - SCu8(path, path_len), SCu8(command, command_len), flags)); - -#if 0 - b32 result = false; - - String_Const_u8 path_string = SCu8((u8*)path, path_len); - String_Const_u8 command_string = SCu8((u8*)command, command_len); - Child_Process_ID child_process_id = 0; - if (create_child_process(app, path_string, command_string, &child_process_id)){ - result = true; - - Buffer_ID buffer_attach_id = 0; - if (buffer_id.name != 0 && buffer_id.name_len > 0){ - String_Const_u8 buffer_name = SCu8((u8*)buffer_id.name, buffer_id.name_len); - if (!get_buffer_by_name(app, buffer_name, AccessAll, &buffer_attach_id)){ - if (create_buffer(app, buffer_name, BufferCreate_AlwaysNew|BufferCreate_NeverAttachToFile, &buffer_attach_id)){ - buffer_set_setting(app, buffer_attach_id, BufferSetting_ReadOnly, true); - buffer_set_setting(app, buffer_attach_id, BufferSetting_Unimportant, true); - } - } - } - else if (buffer_id.id != 0){ - buffer_attach_id = buffer_id.id; - } - - if (buffer_attach_id != 0){ - Child_Process_Set_Target_Flags set_buffer_flags = 0; - if (!HasFlag(flags, CLI_OverlapWithConflict)){ - set_buffer_flags |= ChildProcessSet_FailIfBufferAlreadyAttachedToAProcess; - } - if (HasFlag(flags, CLI_CursorAtEnd)){ - set_buffer_flags |= ChildProcessSet_CursorAtEnd; - } - - if (child_process_set_target_buffer(app, child_process_id, buffer_attach_id, set_buffer_flags)){ - Buffer_Summary buffer = {}; - get_buffer_summary(app, buffer_attach_id, AccessAll, &buffer); - buffer_replace_range(app, buffer_attach_id, make_range(0, buffer.size), string_u8_litexpr("")); - if (HasFlag(flags, CLI_SendEndSignal)){ - buffer_send_end_signal(app, buffer_attach_id); - } - if (view != 0){ - view_set_buffer(app, view->view_id, buffer_attach_id, 0); - get_view_summary(app, view->view_id, AccessAll, view); - } - } - } - } - - return(result); -#endif -} - -static b32 -exec_system_command(Application_Links *app, View_ID view, Buffer_Identifier buffer_id, - char *path, int32_t path_len, char *command, i32 command_len, Command_Line_Interface_Flag flags){ - View_Summary view_summary = {}; - get_view_summary(app, view, AccessAll, &view_summary); - return(exec_system_command(app, &view_summary, buffer_id, path, path_len, command, command_len, flags)); -} - -static char -buffer_get_char(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:buffer_get_char(app, buffer->buffer_id, pos)); -} - -static i32 -buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, i32 line){ - return(buffer==0?0:(i32)get_line_start_pos(app, buffer->buffer_id, line)); -} - -static i32 -buffer_get_line_end(Application_Links *app, Buffer_Summary *buffer, i32 line){ - return(buffer==0?0:(i32)get_line_end_pos(app, buffer->buffer_id, line)); -} - -static Cpp_Token* -get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, i32 line){ - return(buffer==0?0:get_first_token_from_line(app, buffer->buffer_id, tokens, line)); -} - -static b32 -read_line(Application_Links *app, Arena *arena, Buffer_Summary *buffer, i32 line, String *str, - Partial_Cursor *start_out, Partial_Cursor *one_past_last_out){ - String_Const_u8 string = {}; - Range_Partial_Cursor out = {}; - b32 result = (buffer != 0 && is_valid_line(app, buffer->buffer_id, line)); - if (result){ - out = get_line_range(app, buffer->buffer_id, line); - string = push_buffer_range(app, arena, buffer->buffer_id, make_range_from_cursors(out)); - } - *start_out = out.start; - *one_past_last_out = out.one_past_last; - *str = string_old_from_new(string); - return(result); -} - -static b32 -read_line(Application_Links *app, Arena *arena, Buffer_Summary *buffer, i32 line, String *str){ - String_Const_u8 string = {}; - b32 result = (buffer != 0 && is_valid_line(app, buffer->buffer_id, line)); - if (result){ - Range_Partial_Cursor range = get_line_range(app, buffer->buffer_id, line); - string = push_buffer_range(app, arena, buffer->buffer_id, make_range_from_cursors(range)); - } - *str = string_old_from_new(string); - return(result); -} - - -static b32 -init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer, i32 pos, char *data, u32 size){ - return(buffer==0?0:init_stream_chunk(chunk, app, buffer->buffer_id, pos, data, size)); -} - -static b32 -init_stream_tokens(Stream_Tokens_DEP *stream, Application_Links *app, Buffer_Summary *buffer, i32 pos, Cpp_Token *data, i32 count){ - b32 result = false; - - if (buffer != 0){ - i32 token_count = buffer_token_count(app, buffer); - if (buffer_tokens_are_ready(app, buffer->buffer_id) && - 0 <= pos && pos < token_count && count > 0){ - stream->app = app; - stream->buffer_id = buffer->buffer_id; - stream->base_tokens = data; - stream->count = count; - stream->start = round_down_i32(pos, count); - stream->end = round_up_i32(pos, count); - stream->token_count = token_count; - - stream->start = clamp_bot(0, stream->start); - stream->end = clamp_top(stream->end, stream->token_count); - - buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); - stream->tokens = stream->base_tokens - stream->start; - result = true; - } - } - - return(result); -} - -static Stream_Tokens_DEP -begin_temp_stream_token(Stream_Tokens_DEP *stream){ - return(*stream); -} - -static void -end_temp_stream_token(Stream_Tokens_DEP *stream, Stream_Tokens_DEP temp){ - if (stream->start != temp.start || stream->end != temp.end){ - Application_Links *app = stream->app; - buffer_read_tokens(app, temp.buffer_id, temp.start, temp.end, temp.base_tokens); - stream->tokens = stream->base_tokens - temp.start; - stream->start = temp.start; - stream->end = temp.end; - } -} - -static b32 -forward_stream_tokens(Stream_Tokens_DEP *stream){ - Application_Links *app = stream->app; - Buffer_ID buffer_id = stream->buffer_id; - b32 result = false; - if (stream->end < stream->token_count){ - stream->start = stream->end; - stream->end += stream->count; - if (stream->end > stream->token_count){ - stream->end = stream->token_count; - } - if (stream->start < stream->end){ - buffer_read_tokens(app, buffer_id, stream->start, stream->end, stream->base_tokens); - stream->tokens = stream->base_tokens - stream->start; - result = true; - } - } - return(result); -} - -static b32 -backward_stream_tokens(Stream_Tokens_DEP *stream){ - Application_Links *app = stream->app; - Buffer_ID buffer_id = stream->buffer_id; - b32 result = false; - if (stream->start > 0){ - stream->end = stream->start; - stream->start -= stream->count; - if (0 > stream->start){ - stream->start = 0; - } - if (stream->start < stream->end){ - buffer_read_tokens(app, buffer_id, stream->start, stream->end, stream->base_tokens); - stream->tokens = stream->base_tokens - stream->start; - result = true; - } - } - return(result); -} - -static String -token_get_lexeme(Application_Links *app, Arena *arena, Buffer_Summary *buffer, Cpp_Token *token){ - String result = {}; - if (buffer != 0 && token != 0){ - result = string_old_from_new(push_token_lexeme(app, arena, buffer->buffer_id, *token)); - } - return(result); -} - -static String -get_token_or_word_under_pos(Application_Links *app, Buffer_Summary *buffer, i32 pos, char *space, i32 capacity){ - String result = {}; - if (buffer != 0){ - Scratch_Block scratch(app); - String_Const_u8 string = push_token_or_word_under_pos(app, scratch, buffer->buffer_id, pos); - i32 size = (i32)string.size; - size = clamp_top(size, capacity); - block_copy(space, string.str, size); - result = make_string_cap(space, size, capacity); - } - return(result); -} - -static i32 -seek_line_end(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)get_line_end_pos_from_pos(app, buffer->buffer_id, pos)); -} - -static i32 -seek_line_beginning(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)get_line_start_pos_from_pos(app, buffer->buffer_id, pos)); -} - -static void -move_past_lead_whitespace(Application_Links *app, View_Summary *view, Buffer_Summary *buffer){ - move_past_lead_whitespace(app, view!=0?0:view->view_id, buffer!=0?0:buffer->buffer_id); -} - -static i32 -buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)get_pos_of_blank_line(app, buffer->buffer_id, Scan_Backward, pos)); -} - -static i32 -buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)get_pos_of_blank_line(app, buffer->buffer_id, Scan_Forward, pos)); -} - -static i32 -buffer_seek_whitespace_right(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_non_whitespace, buffer->buffer_id, Scan_Forward, pos)); -} - -static i32 -buffer_seek_whitespace_left(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_non_whitespace, buffer->buffer_id, Scan_Backward, pos)); -} - -static i32 -buffer_seek_alphanumeric_right(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric, buffer->buffer_id, Scan_Forward, pos)); -} - -static i32 -buffer_seek_alphanumeric_left(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric, buffer->buffer_id, Scan_Backward, pos)); -} - -static i32 -buffer_seek_alphanumeric_or_underscore_right(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric_underscore, buffer->buffer_id, - Scan_Forward, pos)); -} - -static i32 -buffer_seek_alphanumeric_or_underscore_left(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric_underscore, buffer->buffer_id, - Scan_Backward, pos)); -} - -static i32 -buffer_seek_alphanumeric_or_camel_right(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric_camel, buffer->buffer_id, - Scan_Forward, pos)); -} - -static i32 -buffer_seek_alphanumeric_or_camel_left(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)scan(app, boundary_alpha_numeric_camel, buffer->buffer_id, - Scan_Backward, pos)); -} - -static i32 -buffer_seek_alpha_numeric_end(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ - return(buffer!=0?0:(i32)scan(app, boundary_alpha_numeric_unicode, - buffer->buffer_id, - Scan_Forward, pos)); -} - -static Cpp_Token_Array -buffer_get_all_tokens(Application_Links *app, Arena *arena, Buffer_ID buffer_id){ - Cpp_Token_Array array = {}; - if (buffer_exists(app, buffer_id)){ - b32 is_lexed = false; - if (buffer_get_setting(app, buffer_id, BufferSetting_Lex, &is_lexed)){ - if (is_lexed){ - array.count = buffer_get_token_array(app, buffer_id).count; - array.max_count = array.count; - array.tokens = push_array(arena, Cpp_Token, array.count); - buffer_read_tokens(app, buffer_id, 0, array.count, array.tokens); - } - } - } - return(array); -} - -static Cpp_Token_Array -buffer_get_all_tokens(Application_Links *app, Arena *arena, Buffer_Summary *buffer){ - Cpp_Token_Array result = {}; - if (buffer != 0){ - result = buffer_get_all_tokens(app, arena, buffer->buffer_id); - } - return(result); -} - -void -buffer_seek_delimiter_forward(Application_Links *app, Buffer_ID buffer, i32 pos, char delim, i32 *result){ - Character_Predicate predicate = character_predicate_from_character((u8)delim); - String_Match m = buffer_seek_character_class(app, buffer, &predicate, Scan_Forward, pos); - *result = (i32)m.range.min; -} - -void -buffer_seek_delimiter_backward(Application_Links *app, Buffer_ID buffer, i32 pos, char delim, i32 *result){ - Character_Predicate predicate = character_predicate_from_character((u8)delim); - String_Match m = buffer_seek_character_class(app, buffer, &predicate, Scan_Backward, pos); - *result = (i32)m.range.min; -} - -static void -buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer, i32 pos, char delim, i32 *result){ - if (buffer != 0){ - buffer_seek_delimiter_forward(app, buffer->buffer_id, pos, delim, result); - } -} - -static void -buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer, i32 pos, char delim, i32 *result){ - if (buffer != 0){ - buffer_seek_delimiter_backward(app, buffer->buffer_id, pos, delim, result); - } -} - -static void -buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 end, char *str, i32 size, i32 *result){ - if (buffer != 0){ - i64 result_i64 = 0; - buffer_seek_string_forward(app, buffer->buffer_id, pos, end, SCu8(str, size), &result_i64); - *result = (i32)result_i64; - } -} - -static void -buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 end, char *str, i32 size, i32 *result){ - if (buffer != 0){ - i64 result_i64 = 0; - buffer_seek_string_backward(app, buffer->buffer_id, pos, end, SCu8(str, size), &result_i64); - *result = (i32)result_i64; - } -} - -static void -buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 end, char *str, i32 size, i32 *result){ - if (buffer != 0){ - i64 result_i64 = 0; - buffer_seek_string_insensitive_forward(app, buffer->buffer_id, pos, end, SCu8(str, size), &result_i64); - *result = (i32)result_i64; - } -} - -static void -buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 end, char *str, i32 size, i32 *result){ - if (buffer != 0){ - i64 result_i64 = 0; - buffer_seek_string_insensitive_backward(app, buffer->buffer_id, pos, end, SCu8(str, size), &result_i64); - *result = (i32)result_i64; - } -} - -static void -buffer_seek_string(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 end, i32 min, char *str, i32 size, i32 *result, Buffer_Seek_String_Flags flags){ - if (buffer != 0){ - i64 result_i64 = 0; - buffer_seek_string(app, buffer->buffer_id, pos, end, min, SCu8(str, size), &result_i64, flags); - *result = (i32)result_i64; - } -} - -static b32 -buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, i32 line){ - return(buffer==0?0:line_is_valid_and_blank(app, buffer->buffer_id, line)); -} - -static String -read_identifier_at_pos(Application_Links *app, Buffer_Summary *buffer, i32 pos, char *space, i32 max, Range *range_out){ - String result = {}; - if (buffer != 0){ - Scratch_Block scratch(app); - Range_i64 range = enclose_pos_alpha_numeric_underscore(app, buffer->buffer_id, pos); - String_Const_u8 string = push_buffer_range(app, scratch, buffer->buffer_id, range); - if (range_out != 0){ - *range_out = Ii32((i32)range.min, (i32)range.max);; - } - i32 size = (i32)string.size; - size = clamp_top(size, max); - block_copy(space, string.str, size); - result = make_string_cap(space, size, max); - } - return(result); -} - -internal Boundary_Function_List -boundary_list_from_old_flags(Arena *arena, Seek_Boundary_Flag flags){ - Boundary_Function_List list = {}; - if (HasFlag(flags, BoundaryWhitespace)){ - push_boundary(arena, &list, boundary_non_whitespace); - } - if (HasFlag(flags, BoundaryToken)){ - push_boundary(arena, &list, boundary_token); - } - if (HasFlag(flags, BoundaryAlphanumeric)){ - push_boundary(arena, &list, boundary_alpha_numeric); - } - if (HasFlag(flags, BoundaryCamelCase)){ - push_boundary(arena, &list, boundary_alpha_numeric_camel); - } - return(list); -} - -static i32 -buffer_boundary_seek(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, i32 dir, Seek_Boundary_Flag flags){ - i32 result = 0; - if (buffer != 0){ - Scratch_Block scratch(app); - result = (i32)scan(app, boundary_list_from_old_flags(scratch, flags), buffer->buffer_id, dir, start_pos); - } - return(result); -} - -static void -query_replace_base(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, i32 pos, String r, String w){ - query_replace_base(app, view==0?0:view->view_id, buffer==0?0:buffer->buffer_id, pos, - string_new_u8_from_old(r), - string_new_u8_from_old(w)); -} - -static Statement_Parser -make_statement_parser(Application_Links *app, Buffer_Summary *buffer, i32 token_index){ - Statement_Parser parser = {}; - if (buffer != 0){ - parser = make_statement_parser(app, buffer->buffer_id, token_index); - } - return(parser); -} - -static b32 -find_whole_statement_down(Application_Links *app, Buffer_Summary *buffer, i32 pos, i32 *start_out, i32 *end_out){ - Range_i64 r = {}; - b32 result = (buffer==0?false:find_whole_statement_down(app, buffer->buffer_id, pos, &r.min, &r.max)); - *start_out = (i32)r.min; - *end_out = (i32)r.max; - return(result); -} - -static b32 -find_scope_top(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, u32 flags, i32 *end_pos_out){ - i64 r = 0; - b32 result = (buffer==0?false:find_scope_top(app, buffer->buffer_id, start_pos, flags, &r)); - *end_pos_out = (i32)r; - return(result); -} - -static b32 -find_scope_bottom(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, u32 flags, i32 *end_pos_out){ - i64 r = 0; - b32 result = (buffer==0?false:find_scope_bottom(app, buffer->buffer_id, start_pos, flags, &r)); - *end_pos_out = (i32)r; - return(result); -} - -static b32 -find_scope_range(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, Range *range_out, u32 flags){ - Range_i64 r = {}; - b32 result = (buffer==0?false:find_scope_range(app, buffer->buffer_id, start_pos, &r, flags)); - *range_out = Ii32((i32)r.min, (i32)r.max); - return(result); -} - -static b32 -find_next_scope(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, u32 flags, i32 *end_pos_out){ - i64 r = 0; - b32 result = (buffer==0?false:find_next_scope(app, buffer->buffer_id, start_pos, flags, &r)); - *end_pos_out = (i32)r; - return(result); -} - -static b32 -find_prev_scope(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, u32 flags, i32 *end_pos_out){ - i64 r = 0; - b32 result = (buffer==0?false:find_prev_scope(app, buffer->buffer_id, start_pos, flags, &r)); - *end_pos_out = (i32)r; - return(result); -} - -struct Hard_Start_Result{ - i32 char_pos; - i32 indent_pos; - i32 all_whitespace; - i32 all_space; -}; - -static Hard_Start_Result -buffer_find_hard_start(Application_Links *app, Buffer_Summary *buffer, i32 line_start, i32 tab_width){ - Hard_Start_Result result = {}; - if (buffer != 0){ - Indent_Info info = get_indent_info_line_start(app, buffer->buffer_id, line_start, tab_width); - result.char_pos = (i32)info.first_char_pos; - result.indent_pos = info.indent_pos; - result.all_whitespace = info.is_blank; - result.all_space = info.all_space; - } - return(result); -} - -static Indent_Anchor_Position -find_anchor_token(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, i32 line_start, i32 tab_width){ - Indent_Anchor_Position result = {}; - if (buffer != 0){ - result = find_anchor_token(app, buffer->buffer_id, tokens, line_start, tab_width); - } - return(result); -} - -static i32 -buffer_get_line_number(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:(i32)get_line_number_from_pos(app, buffer->buffer_id, pos)); -} - -static void -get_indent_lines_minimum(Application_Links *app, Buffer_Summary *buffer, i32 start_pos, i32 end_pos, i32 *line_start_out, i32 *line_end_out){ - if (buffer != 0){ - Range_i64 r = {}; - get_indent_lines_minimum(app, buffer->buffer_id, start_pos, end_pos, &r.min, &r.max); - *line_start_out = (i32)r.min; - *line_end_out = (i32)r.max; - } -} - -static void -get_indent_lines_whole_tokens(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, i32 start_pos, i32 end_pos, i32 *line_start_out, i32 *line_end_out){ - if (buffer != 0){ - Range_i64 r = {}; - get_indent_lines_whole_tokens(app, buffer->buffer_id, tokens, start_pos, end_pos, &r.min, &r.max); - *line_start_out = (i32)r.min; - *line_end_out = (i32)r.max; - } -} - -static b32 -buffer_auto_indent(Application_Links *app, Arena *arena, Buffer_Summary *buffer, i32 start, i32 end, i32 tab_width, Auto_Indent_Flag flags){ - return(buffer==0?0:buffer_auto_indent(app, buffer->buffer_id, start, end, tab_width, flags)); -} - -static b32 -buffer_auto_indent(Application_Links *app, Buffer_Summary *buffer, i32 start, i32 end, i32 tab_width, Auto_Indent_Flag flags){ - return(buffer==0?0:buffer_auto_indent(app, buffer->buffer_id, start, end, tab_width, flags)); -} - -static Get_Positions_Results -get_function_positions(Application_Links *app, Buffer_Summary *buffer, i32 first_token_index, Function_Positions *positions_array, i32 positions_max){ - Get_Positions_Results result = {}; - if (buffer != 0){ - result = get_function_positions(app, buffer->buffer_id, first_token_index, positions_array, positions_max); - } - return(result); -} - -static void -list_all_functions(Application_Links *app, Buffer_Summary *optional_target_buffer){ - if (optional_target_buffer != 0){ - list_all_functions(app, optional_target_buffer->buffer_id); - } -} - -static i32 -get_start_of_line_at_cursor(Application_Links *app, View_Summary *view, Buffer_Summary *buffer){ - return((i32)get_start_of_line_at_cursor(app, view==0?0:view->view_id, buffer==0?0:buffer->buffer_id)); -} - -static b32 -c_line_comment_starts_at_position(Application_Links *app, Buffer_Summary *buffer, i32 pos){ - return(buffer==0?0:c_line_comment_starts_at_position(app, buffer->buffer_id, pos)); -} - -static void -write_string(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, String string){ - write_string(app, view==0?0:view->view_id, buffer==0?0:buffer->buffer_id, string_new_u8_from_old(string)); -} - -static b32 -open_file(Application_Links *app, Buffer_Summary *buffer_out, char *filename, i32 filename_len, b32 background, b32 never_new){ - b32 result = false; - Buffer_ID id_out = 0; - result = open_file(app, &id_out, SCu8(filename, filename_len), background, never_new); - if (result && buffer_out != 0){ - get_buffer_summary(app, id_out, AccessAll, buffer_out); - } - return(result); -} - -static b32 -get_cpp_matching_file(Application_Links *app, Buffer_Summary buffer, Buffer_Summary *buffer_out){ - b32 result = false; - if (buffer.exists){ - Buffer_ID id_out = 0; - result = get_cpp_matching_file(app, buffer.buffer_id, &id_out); - if (result && buffer_out != 0){ - get_buffer_summary(app, id_out, AccessAll, buffer_out); - } - } - return(result); -} - -static b32 -get_jump_buffer(Application_Links *app, Buffer_Summary *buffer, Name_Line_Column_Location *location){ - Buffer_ID id = 0; - b32 result = get_jump_buffer(app, &id, location); - if (result){ - get_buffer_summary(app, id, AccessAll, buffer); - } - return(result); -} - -static b32 -get_jump_buffer(Application_Links *app, Buffer_Summary *buffer, ID_Pos_Jump_Location *location, Access_Flag access){ - Buffer_ID id = 0; - b32 result = get_jump_buffer(app, &id, location, access); - if (result){ - get_buffer_summary(app, id, AccessAll, buffer); - } - return(result); -} - -static b32 -get_jump_buffer(Application_Links *app, Buffer_Summary *buffer, ID_Pos_Jump_Location *location){ - Buffer_ID id = 0; - b32 result = get_jump_buffer(app, &id, location); - if (result){ - get_buffer_summary(app, id, AccessAll, buffer); - } - return(result); -} - -static void -switch_to_existing_view(Application_Links *app, View_Summary *view, Buffer_Summary *buffer){ - View_ID result = switch_to_existing_view(app, view==0?0:view->view_id, buffer==0?0:buffer->buffer_id); - if (view != 0 && result != 0){ - get_view_summary(app, result, AccessAll, view); - } -} - -static void -set_view_to_location(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, Buffer_Seek seek){ - set_view_to_location(app, view==0?0:view->view_id, buffer==0?0:buffer->buffer_id, seek); -} - -static void -jump_to_location(Application_Links *app, View_Summary *view, Buffer_ID buffer, Name_Line_Column_Location location){ - jump_to_location(app, view==0?0:view->view_id, buffer, location); -} - -static void -jump_to_location(Application_Links *app, View_Summary *view, Buffer_ID buffer, ID_Pos_Jump_Location location){ - jump_to_location(app, view==0?0:view->view_id, buffer, location); -} - -static Buffer_Summary -buffer_identifier_to_buffer_summary(Application_Links *app, Buffer_Identifier identifier, Access_Flag access){ - Buffer_Summary buffer = {}; - if (identifier.id != 0){ - buffer = get_buffer(app, identifier.id, access); - } - else{ - buffer = get_buffer_by_name(app, identifier.name, identifier.name_len, access); - if (!buffer.exists){ - buffer = get_buffer_by_file_name(app, identifier.name, identifier.name_len, access); - } - } - return(buffer); -} - -static void -refresh_buffer(Application_Links *app, Buffer_Summary *buffer){ - get_buffer_summary(app, buffer->buffer_id, AccessAll, buffer); -} - -static Sticky_Jump_Array -parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_Summary buffer){ - return(parse_buffer_to_jump_array(app, arena, buffer.buffer_id)); -} - -static Face_Description -get_buffer_face_description(Application_Links *app, Buffer_Summary *buffer){ - Face_Description result = {}; - if (buffer != 0){ - result = get_buffer_face_description(app, buffer->buffer_id); - } - return(result); -} - -static void -execute_standard_build(Application_Links *app, View_Summary *view, Buffer_ID active_buffer){ - standard_search_and_build(app, view==0?0:view->view_id, active_buffer); -} - -static b32 -post_buffer_range_to_clipboard(Application_Links *app, i32 clipboard_index, Buffer_Summary *buffer, i32 first, i32 one_past_last){ - return(clipboard_post_buffer_range(app, clipboard_index, buffer==0?0:buffer->buffer_id, Ii64(first, one_past_last))); -} - -static void -view_set_vertical_focus(Application_Links *app, View_Summary *view, i32 y_top, i32 y_bot){ - view_set_vertical_focus(app, view==0?0:view->view_id, (f32)y_top, (f32)y_bot); -} - -#if 0 -static b32 -advance_cursor_in_jump_view(Application_Links *app, View_Summary *view, i32 skip_repeats, i32 skip_sub_error, i32 direction, Name_Line_Column_Location *location_out){ - return(advance_cursor_in_jump_view(app, view==0?0:view->view_id, skip_repeats, skip_sub_error, direction, location_out)); -} -#endif - -static Parsed_Jump -seek_next_jump_in_view(Application_Links *app, Arena *arena, View_Summary *view, i32 skip_sub_errors, i32 direction, i32 *line_out){ - i64 r = 0; - Parsed_Jump result = (seek_next_jump_in_view(app, arena, view==0?0:view->view_id, skip_sub_errors, direction, &r)); - *line_out = (i32)r; - return(result); -} - -static void -goto_next_filtered_jump(Application_Links *app, Marker_List *list, View_Summary *jump_view, i32 list_index, i32 direction, b32 skip_repeats, b32 skip_sub_errors){ - goto_next_filtered_jump(app, list, jump_view==0?0:jump_view->view_id, list_index, direction, skip_repeats, skip_sub_errors); -} - -static void -goto_jump_in_order(Application_Links *app, Marker_List *list, View_Summary *jump_view, ID_Pos_Jump_Location location){ - goto_jump_in_order(app, list, jump_view==0?0:jump_view->view_id, location); -} - -static void -open_jump_lister(Application_Links *app, Heap *heap, View_Summary *ui_view, Buffer_ID list_buffer_id, Jump_Lister_Activation_Rule activation_rule, View_Summary *optional_target_view){ - open_jump_lister(app, heap, ui_view==0?0:ui_view->view_id, list_buffer_id, activation_rule, optional_target_view==0?0:optional_target_view->view_id); -} - -static void -view_set_to_region(Application_Links *app, View_Summary *view, i32 major_pos, i32 minor_pos, f32 normalized_threshold){ - view_set_to_region(app, view==0?0:view->view_id, major_pos, minor_pos, normalized_threshold); -} - -static i32 -character_pos_to_pos(Application_Links *app, View_Summary *view, i32 character_pos){ - return((i32)character_pos_to_pos_view(app, view==0?0:view->view_id, character_pos)); -} - -static b32 -view_open_file(Application_Links *app, View_Summary *view, char *filename, i32 filename_len, b32 never_new){ - return(view_open_file(app, view==0?0:view->view_id, SCu8(filename, filename_len), never_new)); -} - -static f32 -get_page_jump(Application_Links *app, View_Summary *view){ - return(get_page_jump(app, view==0?0:view->view_id)); -} - -static void -get_view_prev(Application_Links *app, View_Summary *view, Access_Flag access){ - View_ID new_id = get_view_prev(app, view->view_id, access); - get_view_summary(app, new_id, access, view); -} - -static void -get_next_view_looped_all_panels(Application_Links *app, View_Summary *view, Access_Flag access){ - View_ID new_id = get_next_view_looped_all_panels(app, view==0?0:view->view_id, access); - get_view_summary(app, new_id, access, view); -} - -static void -get_prev_view_looped_all_panels(Application_Links *app, View_Summary *view, Access_Flag access){ - View_ID new_id = get_prev_view_looped_all_panels(app, view->view_id, access); - get_view_summary(app, new_id, access, view); -} - -static void -refresh_view(Application_Links *app, View_Summary *view){ - *view = get_view(app, view->view_id, AccessAll); -} - -static String -get_string_in_view_range(Application_Links *app, Arena *arena, View_Summary *view){ - return(string_old_from_new(push_view_range_string(app, arena, view==0?0:view->view_id))); -} - -static b32 -view_set_split(Application_Links *app, View_Summary *view, View_Split_Kind kind, f32 t){ - b32 result = view_set_split(app, view==0?0:view->view_id, kind, t); - if (result && view != 0){ - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_split_proportion(Application_Links *app, View_Summary *view, f32 t){ - b32 result = view_set_split_proportion(app, view==0?0:view->view_id, t); - if (result && view != 0){ - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static b32 -view_set_split_pixel_size(Application_Links *app, View_Summary *view, i32 t){ - b32 result = view_set_split_pixel_size(app, view==0?0:view->view_id, t); - if (result && view != 0){ - get_view_summary(app, view->view_id, AccessAll, view); - } - return(result); -} - -static View_Summary -open_footer_panel(Application_Links *app, View_Summary *view){ - View_ID new_id = open_footer_panel(app, view==0?0:view->view_id); - View_Summary result = {}; - get_view_summary(app, new_id, AccessAll, &result); - return(result); -} - -static void -new_view_settings(Application_Links *app, View_Summary *view){ - new_view_settings(app, view==0?0:view->view_id); -} - -static void -view_set_passive(Application_Links *app, View_Summary *view, b32 value){ - view_set_passive(app, view==0?0:view->view_id, value); -} - -static b32 -view_get_is_passive(Application_Links *app, View_Summary *view){ - return(view != 0 && view_get_is_passive(app, view->view_id)); -} - -static void -get_next_view_looped_primary_panels(Application_Links *app, View_Summary *view_start, Access_Flag access){ - View_ID new_id = get_next_view_looped_primary_panels(app, view_start->view_id, access); - get_view_summary(app, new_id, AccessAll, view_start); -} - -static void -get_prev_view_looped_primary_panels(Application_Links *app, View_Summary *view_start, Access_Flag access){ - View_ID new_id = get_prev_view_looped_primary_panels(app, view_start->view_id, access); - get_view_summary(app, new_id, AccessAll, view_start); -} - -static Buffer_ID -create_or_switch_to_buffer_by_name(Application_Links *app, char *name, i32 name_length, View_Summary default_target_view){ - return(create_or_switch_to_buffer_and_clear_by_name(app, SCu8(name, name_length), default_target_view.view_id)); -} - -static b32 -backspace_utf8(String *str){ - b32 result = false; - uint8_t *s = (uint8_t*)str->str; - if (str->size > 0){ - u32 i = str->size-1; - for (; i > 0; --i){ - if (s[i] <= 0x7F || s[i] >= 0xC0){ - break; - } - } - str->size = i; - result = true; - } - return(result); -} - -static void -change_mapping(Application_Links *app, String mapping){ - change_mapping(app, string_new_u8_from_old(mapping)); -} - -static void -query_replace_parameter(Application_Links *app, String replace_str, i32 start_pos, b32 add_replace_query_bar){ - query_replace_parameter(app, SCu8(string_new_from_old(replace_str)), start_pos, add_replace_query_bar); -} - -static String -hot_directory_push(Application_Links *app, Arena *arena){ - return(string_old_from_new(push_hot_directory(app, arena))); -} - -static void -append_int_to_str_left_pad(String *str, i32 x, i32 minimum_width, char pad_char){ - i32 length = int_to_str_size(x); - i32 left_over = minimum_width - length; - if (left_over > 0){ - append_padding(str, pad_char, str->size + left_over); - } - append_int_to_str(str, x); -} - -static void -condense_whitespace(String *a){ - *a = skip_chop_whitespace(*a); - int size = a->size; - a->size = 0; - int i = 0; - for (;i < size;){ - if (char_is_whitespace(a->str[i])){ - a->str[a->size++] = ' '; - for (;(i < size) && char_is_whitespace(a->str[i]);){ - ++i; - } - } - else{ - a->str[a->size++] = a->str[i++]; - } - } -} - -static void -insert_string__no_buffering(Buffer_Insertion *insertion, String string){ - insert_string__no_buffering(insertion, string_new_u8_from_old(string)); -} - -static void -insert_string(Buffer_Insertion *insertion, String string){ - insert_string(insertion, string_new_u8_from_old(string)); -} - -static void -save_all_dirty_buffers_with_postfix(Application_Links *app, String postfix){ - save_all_dirty_buffers_with_postfix(app, string_new_u8_from_old(postfix)); -} - -static void -delete_file_base(Application_Links *app, String file_name, Buffer_ID buffer_id){ - delete_file_base(app, string_new_u8_from_old(file_name), buffer_id); -} - -static b32 -ms_style_verify(String line, i32 left_paren_pos, i32 right_paren_pos){ - return(ms_style_verify(string_new_u8_from_old(line), left_paren_pos, right_paren_pos)); -} - -static i32 -try_skip_rust_arrow(String line){ - return((i32)(try_skip_rust_arrow(string_new_u8_from_old(line)))); -} - -static b32 -check_is_note(String line, i32 colon_pos){ - return(check_is_note(string_new_u8_from_old(line), colon_pos)); -} - -static void -close_all_files_with_extension(Application_Links *app, CString_Array extension_array){ - Scratch_Block scratch(app); - String_Const_u8_Array array = {}; - array.count = extension_array.count; - array.strings = push_array(scratch, String_Const_u8, array.count); - for (i32 i = 0; i < array.count; i += 1){ - array.strings[i] = SCu8(extension_array.strings[i]); - } - close_all_files_with_extension(app, array); -} - -static void -open_all_files_in_directory_pattern_match(Application_Links *app, - String dir, - Project_File_Pattern_Array whitelist, - Project_File_Pattern_Array blacklist, - u32 flags){ - open_all_files_in_directory_pattern_match(app, string_new_u8_from_old(dir), whitelist, blacklist, flags); -} - -static String_Const_u8 -scratch_read(Application_Links *app, Arena *arena, Buffer_ID buffer, umem start, umem end){ - return(push_buffer_range(app, arena, buffer, Ii64(start, end))); -} - -static String_Const_u8 -scratch_read(Application_Links *app, Arena *arena, Buffer_ID buffer, Range range){ - return(push_buffer_range(app, arena, buffer, Ii64(range.min, range.max))); -} - -static String_Const_u8 -scratch_read(Application_Links *app, Arena *arena, Buffer_ID buffer, Range_u64 range){ - return(push_buffer_range(app, arena, buffer, Ii64(range.min, range.max))); -} - -static String_Const_u8 -scratch_read(Application_Links *app, Arena *arena, Buffer_ID buffer, Cpp_Token token){ - return(push_token_lexeme(app, arena, buffer, token)); -} - -static String_Const_u8 -scratch_read_line(Application_Links *app, Arena *arena, Buffer_ID buffer, i32 line){ - return(push_buffer_line(app, arena, buffer, line)); -} - -static String_Const_u8 -token_get_lexeme(Application_Links *app, Arena *arena, Buffer_ID buffer, Cpp_Token token){ - return(push_token_lexeme(app, arena, buffer, token)); -} - -static String_Const_u8 -get_token_lexeme(Application_Links *app, Arena *arena, Buffer_ID buffer, Cpp_Token token){ - return(push_token_lexeme(app, arena, buffer, token)); -} - -static String_Const_u8 -read_entire_buffer(Application_Links *app, Buffer_ID buffer_id, Arena *scratch){ - return(push_whole_buffer(app, scratch, buffer_id)); -} - -static String_Const_u8 -buffer_read_string(Application_Links *app, Buffer_ID buffer, Range range, void *dest){ - Scratch_Block scratch(app); - String_Const_u8 result = push_buffer_range(app, scratch, buffer, Ii64(range.min, range.max)); - block_copy(dest, result.str, result.size); - result.str = (u8*)dest; - return(result); -} - -static b32 -token_match(Application_Links *app, Buffer_ID buffer, Cpp_Token token, String b){ - return(token_lexeme_string_match(app, buffer, token, string_new_u8_from_old(b))); -} - -static i32 -view_get_line_number(Application_Links *app, View_ID view, i32 pos){ - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - return((i32)cursor.line); -} - -static void -current_view_boundary_seek_set_pos(Application_Links *app, Scan_Direction direction, u32 flags){ - Scratch_Block scratch(app); - current_view_scan_move(app, direction, boundary_list_from_old_flags(scratch, flags)); -} - -static Buffer_Kill_Result -kill_buffer(Application_Links *app, Buffer_Identifier identifier, View_ID gui_view_id, Buffer_Kill_Flag flags){ - return(try_buffer_kill(app, buffer_identifier_to_id(app, identifier), gui_view_id, flags)); -} - -#endif - -// BOTTOM - diff --git a/4coder_auto_indent.cpp b/4coder_auto_indent.cpp index 733e824e..269e31c4 100644 --- a/4coder_auto_indent.cpp +++ b/4coder_auto_indent.cpp @@ -4,17 +4,14 @@ // TOP -internal Buffer_Batch_Edit +internal Batch_Edit* make_batch_from_indent_marks(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 first_line, i64 one_past_last_line, i64 *indent_marks, Indent_Options opts){ i64 *shifted_indent_marks = indent_marks - first_line; - i64 edit_count = 0; - i64 edit_max = one_past_last_line - first_line; - Buffer_Edit *edits = push_array(arena, Buffer_Edit, edit_max); - - List_String_Const_u8 list = {}; + Batch_Edit *batch_first = 0; + Batch_Edit *batch_last = 0; for (i64 line_number = first_line; line_number < one_past_last_line; @@ -32,50 +29,37 @@ make_batch_from_indent_marks(Application_Links *app, Arena *arena, Buffer_ID buf if (correct_indentation != hard_start.indent_pos){ umem str_size = 0; - char *str = 0; + u8 *str = 0; if (opts.use_tabs){ i64 tab_count = correct_indentation/opts.tab_width; i64 indent = tab_count*opts.tab_width; i64 space_count = correct_indentation - indent; str_size = tab_count + space_count; - str = push_array(arena, char, str_size); + str = push_array(arena, u8, str_size); block_fill_u8(str, tab_count, '\t'); block_fill_u8(str + tab_count, space_count, ' '); } else{ str_size = correct_indentation; - str = push_array(arena, char, str_size); + str = push_array(arena, u8, str_size); block_fill_u8(str, str_size, ' '); } - i64 str_position = list.total_size; - string_list_push(arena, &list, SCu8(str, str_size)); - - edits[edit_count].str_start = (i32)str_position; - edits[edit_count].len = (i32)str_size; - edits[edit_count].start = (i32)line_start_pos; - edits[edit_count].end = (i32)hard_start.first_char_pos; - edit_count += 1; + Batch_Edit *batch = push_array(arena, Batch_Edit, 1); + sll_queue_push(batch_first, batch_last, batch); + batch->edit.text = SCu8(str, str_size); + batch->edit.range = Ii64(line_start_pos, hard_start.first_char_pos); } - - Assert(edit_count <= edit_max); } - String_Const_u8 contiguous_text = string_list_flatten(arena, list); - - Buffer_Batch_Edit result = {}; - result.str = (char*)contiguous_text.str; - result.str_len = (i32)contiguous_text.size; - result.edits = edits; - result.edit_count = (i32)edit_count; - return(result); + return(batch_first); } internal void set_line_indents(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 first_line, i64 one_past_last_line, i64 *indent_marks, Indent_Options opts){ - Buffer_Batch_Edit batch = make_batch_from_indent_marks(app, arena, buffer, first_line, one_past_last_line, indent_marks, opts); - if (batch.edit_count > 0){ - buffer_batch_edit(app, buffer, batch.str, batch.edits, batch.edit_count); + Batch_Edit *batch = make_batch_from_indent_marks(app, arena, buffer, first_line, one_past_last_line, indent_marks, opts); + if (batch != 0){ + buffer_batch_edit(app, buffer, batch); } } diff --git a/4coder_base_commands.cpp b/4coder_base_commands.cpp index c847b425..0eb942b2 100644 --- a/4coder_base_commands.cpp +++ b/4coder_base_commands.cpp @@ -11,17 +11,10 @@ write_character_parameter(Application_Links *app, u8 *character, u32 length){ View_ID view = get_active_view(app, AccessOpen); if_view_has_highlighted_range_delete_range(app, view); - Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + pos = view_get_character_legal_pos_from_pos(app, view, pos); - // NOTE(allen): setup markers to figure out the new position of cursor after the insert - Marker next_cursor_marker = {}; - // TODO(allen): should be using character_pos_to_pos_buffer here! - next_cursor_marker.pos = (i32)character_pos_to_pos_view(app, view, cursor.character_pos); - next_cursor_marker.lean_right = true; - Managed_Object handle = alloc_buffer_markers_on_buffer(app, buffer, 1, 0); - managed_object_store_data(app, handle, 0, 1, &next_cursor_marker); + Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); // NOTE(allen): consecutive inserts merge logic History_Record_Index first_index = buffer_history_get_current_state_index(app, buffer); @@ -55,10 +48,8 @@ write_character_parameter(Application_Links *app, u8 *character, u32 length){ } // NOTE(allen): finish updating the cursor - managed_object_load_data(app, handle, 0, 1, &next_cursor_marker); - managed_object_free(app, handle); if (edit_success){ - view_set_cursor(app, view, seek_pos(next_cursor_marker.pos), true); + view_set_cursor(app, view, seek_pos(pos + length), true); } } } @@ -88,9 +79,9 @@ CUSTOM_DOC("Deletes the character to the right of the cursor.") i64 start = view_get_cursor_pos(app, view); i64 buffer_size = buffer_get_size(app, buffer); if (0 <= start && start < buffer_size){ - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(start)); - cursor = view_compute_cursor(app, view, seek_character_pos(cursor.character_pos + 1)); - i64 end = cursor.pos; + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(start)); + i64 character = view_relative_character_from_pos(app, view, cursor.line, cursor.pos); + i64 end = view_pos_from_relative_character(app, view, cursor.line, character + 1); buffer_replace_range(app, buffer, Ii64(start, end), string_u8_empty); } } @@ -105,9 +96,9 @@ CUSTOM_DOC("Deletes the character to the left of the cursor.") i64 end = view_get_cursor_pos(app, view); i64 buffer_size = buffer_get_size(app, buffer); if (0 < end && end <= buffer_size){ - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(end)); - cursor = view_compute_cursor(app, view, seek_character_pos(cursor.character_pos - 1)); - i64 start = cursor.pos; + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(end)); + i64 character = view_relative_character_from_pos(app, view, cursor.line, cursor.pos); + i64 start = view_pos_from_relative_character(app, view, cursor.line, character - 1); if (buffer_replace_range(app, buffer, Ii64(start, end), string_u8_empty)){ view_set_cursor(app, view, seek_pos(start), true); } @@ -207,52 +198,37 @@ CUSTOM_COMMAND_SIG(center_view) CUSTOM_DOC("Centers the view vertically on the line on which the cursor sits.") { View_ID view = get_active_view(app, AccessProtected); - Rect_f32 region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); - - f32 h = (f32)(rect_height(region)); - f32 y = get_view_y(app, view); - y = y - h*.5f; - scroll.target_y = (i32)(y + .5f); - view_set_scroll(app, view, scroll); + i64 pos = view_get_cursor_pos(app, view); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + f32 view_height = rect_height(region); + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + scroll.target.line_number = cursor.line; + scroll.target.pixel_shift.y = -view_height*0.5f; + view_set_buffer_scroll(app, view, scroll); } CUSTOM_COMMAND_SIG(left_adjust_view) CUSTOM_DOC("Sets the left size of the view near the x position of the cursor.") { View_ID view = get_active_view(app, AccessProtected); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); - f32 x = clamp_bot(0.f, get_view_x(app, view) - 30.f); - scroll.target_x = (i32)(x + .5f); - view_set_scroll(app, view, scroll); -} - -static b32 -view_space_from_screen_space_checked(Vec2_f32 p, Rect_f32 file_region, Vec2 scroll_p, Vec2 *p_out){ - b32 result = false; - if (rect_contains_point(file_region, p)){ - *p_out = view_space_from_screen_space(p, file_region.p0, scroll_p); - result = true; - } - else{ - *p_out = V2(0.f, 0.f); - } - return(result); + i64 pos = view_get_cursor_pos(app, view); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos); + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + scroll.target.pixel_shift.x = clamp_bot(0.f, p.x - 30.f); + view_set_buffer_scroll(app, view, scroll); } CUSTOM_COMMAND_SIG(click_set_cursor_and_mark) CUSTOM_DOC("Sets the cursor position and mark to the mouse position.") { View_ID view = get_active_view(app, AccessProtected); - Rect_f32 region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); - Mouse_State mouse = get_mouse_state(app); - Vec2 p = {}; - if (view_space_from_screen_space_checked(V2(mouse.p), region, scroll_vars.scroll_p, &p)){ - Full_Cursor cursor = view_compute_cursor(app, view, seek_wrapped_xy(p.x, p.y, true)); - view_set_cursor(app, view, seek_pos(cursor.pos), true); - view_set_mark(app, view, seek_pos(cursor.pos)); + if (!view_is_in_ui_mode(app, view)){ + Mouse_State mouse = get_mouse_state(app); + i64 pos = view_pos_from_xy(app, view, V2(mouse.p)); + view_set_cursor(app, view, seek_pos(pos), true); + view_set_mark(app, view, seek_pos(pos)); } } @@ -260,44 +236,38 @@ CUSTOM_COMMAND_SIG(click_set_cursor) CUSTOM_DOC("Sets the cursor position to the mouse position.") { View_ID view = get_active_view(app, AccessProtected); - Rect_f32 region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); - Mouse_State mouse = get_mouse_state(app); - Vec2 p = {}; - if (view_space_from_screen_space_checked(V2(mouse.p), region, scroll_vars.scroll_p, &p)){ - view_set_cursor(app, view, seek_wrapped_xy(p.x, p.y, true), true); + if (!view_is_in_ui_mode(app, view)){ + Mouse_State mouse = get_mouse_state(app); + i64 pos = view_pos_from_xy(app, view, V2(mouse.p)); + view_set_cursor(app, view, seek_pos(pos), true); + no_mark_snap_to_cursor(app, view); } - no_mark_snap_to_cursor(app, view); } CUSTOM_COMMAND_SIG(click_set_cursor_if_lbutton) CUSTOM_DOC("If the mouse left button is pressed, sets the cursor position to the mouse position.") { View_ID view = get_active_view(app, AccessProtected); - Mouse_State mouse = get_mouse_state(app); - if (mouse.l){ - Rect_f32 region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); - Vec2 p = {}; - if (view_space_from_screen_space_checked(V2(mouse.p), region, scroll_vars.scroll_p, &p)){ - view_set_cursor(app, view, seek_wrapped_xy(p.x, p.y, true), true); + if (!view_is_in_ui_mode(app, view)){ + Mouse_State mouse = get_mouse_state(app); + if (mouse.l){ + i64 pos = view_pos_from_xy(app, view, V2(mouse.p)); + view_set_cursor(app, view, seek_pos(pos), true); } + no_mark_snap_to_cursor(app, view); } - no_mark_snap_to_cursor(app, view); } CUSTOM_COMMAND_SIG(click_set_mark) CUSTOM_DOC("Sets the mark position to the mouse position.") { View_ID view = get_active_view(app, AccessProtected); - Rect_f32 region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); - Mouse_State mouse = get_mouse_state(app); - Vec2 p = {}; - if (view_space_from_screen_space_checked(V2(mouse.p), region, scroll_vars.scroll_p, &p)){ - view_set_mark(app, view, seek_wrapped_xy(p.x, p.y, true)); + if (!view_is_in_ui_mode(app, view)){ + Mouse_State mouse = get_mouse_state(app); + i64 pos = view_pos_from_xy(app, view, V2(mouse.p)); + view_set_mark(app, view, seek_pos(pos)); + no_mark_snap_to_cursor(app, view); } - no_mark_snap_to_cursor(app, view); } CUSTOM_COMMAND_SIG(mouse_wheel_scroll) @@ -306,9 +276,16 @@ CUSTOM_DOC("Reads the scroll wheel value from the mouse state and scrolls accord View_ID view = get_active_view(app, AccessProtected); Mouse_State mouse = get_mouse_state(app); if (mouse.wheel != 0){ - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); - scroll.target_y += mouse.wheel; - view_set_scroll(app, view, scroll); + if (view_is_in_ui_mode(app, view)){ + Basic_Scroll scroll = view_get_basic_scroll(app, view); + scroll.target.y += mouse.wheel; + view_set_basic_scroll(app, view, scroll); + } + else{ + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + scroll.target = view_move_buffer_point(app, view, scroll.target, V2f32(0.f, (f32)mouse.wheel)); + view_set_buffer_scroll(app, view, scroll); + } } } @@ -316,24 +293,12 @@ CUSTOM_DOC("Reads the scroll wheel value from the mouse state and scrolls accord internal void move_vertical_pixels(Application_Links *app, View_ID view, f32 pixels){ - f32 new_y = get_view_y(app, view) + pixels; - f32 x = view_get_preferred_x(app, view); - - view_set_cursor(app, view, seek_wrapped_xy(x, new_y, false), false); - f32 actual_new_y = get_view_y(app, view); - if (actual_new_y < new_y){ - Rect_f32 file_region = view_get_buffer_region(app, view); - f32 height = rect_height(file_region); - f32 full_scroll_y = actual_new_y - height*0.5f; - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); - if (scroll_vars.target_y < full_scroll_y){ - GUI_Scroll_Vars new_scroll_vars = scroll_vars; - new_scroll_vars.target_y += (i32)pixels; - new_scroll_vars.target_y = clamp_top(new_scroll_vars.target_y, (i32)full_scroll_y); - view_set_scroll(app, view, new_scroll_vars); - } - } - + i64 pos = view_get_cursor_pos(app, view); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos); + p.y += pixels; + i64 new_pos = view_pos_at_relative_xy(app, view, cursor.line, p); + view_set_cursor(app, view, seek_pos(new_pos), false); no_mark_snap_to_cursor_if_shift(app, view); } @@ -396,9 +361,9 @@ CUSTOM_DOC("Moves down to the next line of actual text, regardless of line wrapp { View_ID view = get_active_view(app, AccessOpen); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); i64 next_line = cursor.line + 1; - view_set_cursor(app, view, seek_line_char(next_line, 1), true); + view_set_cursor(app, view, seek_line_col(next_line, 1), true); } CUSTOM_COMMAND_SIG(page_up) @@ -484,9 +449,10 @@ CUSTOM_DOC("Moves the cursor one character to the left.") { View_ID view = get_active_view(app, AccessProtected); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - i64 new_pos = clamp_bot(0, cursor.character_pos - 1); - view_set_cursor(app, view, seek_character_pos(new_pos), true); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + i64 character = view_relative_character_from_pos(app, view, cursor.line, pos); + i64 new_pos = view_pos_from_relative_character(app, view, cursor.line, character - 1); + view_set_cursor(app, view, seek_pos(new_pos), true); no_mark_snap_to_cursor_if_shift(app, view); } @@ -495,9 +461,10 @@ CUSTOM_DOC("Moves the cursor one character to the right.") { View_ID view = get_active_view(app, AccessProtected); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - i64 new_pos = cursor.character_pos + 1; - view_set_cursor(app, view, seek_character_pos(new_pos), 1); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + i64 character = view_relative_character_from_pos(app, view, cursor.line, pos); + i64 new_pos = view_pos_from_relative_character(app, view, cursor.line, character + 1); + view_set_cursor(app, view, seek_pos(new_pos), true); no_mark_snap_to_cursor_if_shift(app, view); } @@ -649,11 +616,9 @@ CUSTOM_DOC("Removes trailing whitespace from all lines in the current buffer.") View_ID view = get_active_view(app, AccessOpen); Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); - i32 line_count = (i32)buffer_get_line_count(app, buffer); - Scratch_Block scratch(app); - Buffer_Edit *edits = push_array(scratch, Buffer_Edit, line_count); - Buffer_Edit *edit = edits; + Batch_Edit *batch_first = 0; + Batch_Edit *batch_last = 0; String_Const_u8 text = push_whole_buffer(app, scratch, buffer); @@ -662,11 +627,10 @@ CUSTOM_DOC("Removes trailing whitespace from all lines in the current buffer.") u8 v = string_get_character(text, i); if (v == '\n' || i + 1 == text.size){ if (whitespace_start < i){ - edit->str_start = 0; - edit->len = 0; - edit->start = (i32)whitespace_start; - edit->end = (i32)i; - ++edit; + Batch_Edit *batch = push_array(scratch, Batch_Edit, 1); + sll_queue_push(batch_first, batch_last, batch); + batch->edit.text = SCu8(); + batch->edit.range = Ii64(whitespace_start, i); } whitespace_start = i + 1; } @@ -675,8 +639,7 @@ CUSTOM_DOC("Removes trailing whitespace from all lines in the current buffer.") } } - i32 edit_count = (i32)(edit - edits); - buffer_batch_edit(app, buffer, 0, edits, edit_count); + buffer_batch_edit(app, buffer, batch_first); } //////////////////////////////// @@ -870,7 +833,7 @@ CUSTOM_DOC("Queries the user for a number, and jumps the cursor to the correspon if (query_user_number(app, &bar)){ i32 line_number = (i32)string_to_integer(bar.string, 10); View_ID view = get_active_view(app, AccessProtected); - view_set_cursor(app, view, seek_line_char(line_number, 0), true); + view_set_cursor(app, view, seek_line_col(line_number, 0), true); } } @@ -1647,7 +1610,9 @@ CUSTOM_DOC("Set the other non-active panel to view the buffer that the active pa change_active_panel(app); View_ID view2 = get_active_view(app, AccessAll); - if (view1 != view2){ + if (view1 != view2 && + !view_is_in_ui_mode(app, view1) && + !view_is_in_ui_mode(app, view2)){ Buffer_ID buffer1 = view_get_buffer(app, view1, AccessAll); Buffer_ID buffer2 = view_get_buffer(app, view2, AccessAll); if (buffer1 != buffer2){ @@ -1657,17 +1622,17 @@ CUSTOM_DOC("Set the other non-active panel to view the buffer that the active pa else{ i64 p1 = view_get_cursor_pos(app, view1); i64 m1 = view_get_mark_pos(app, view1); - GUI_Scroll_Vars sc1 = view_get_scroll_vars(app, view1); + Buffer_Scroll sc1 = view_get_buffer_scroll(app, view1); i64 p2 = view_get_cursor_pos(app, view2); i64 m2 = view_get_mark_pos(app, view2); - GUI_Scroll_Vars sc2 = view_get_scroll_vars(app, view2); + Buffer_Scroll sc2 = view_get_buffer_scroll(app, view2); view_set_cursor(app, view1, seek_pos(p2), true); view_set_mark (app, view1, seek_pos(m2)); - view_set_scroll(app, view1, sc2); + view_set_buffer_scroll(app, view1, sc2); view_set_cursor(app, view2, seek_pos(p1), true); view_set_mark (app, view2, seek_pos(m1)); - view_set_scroll(app, view2, sc1); + view_set_buffer_scroll(app, view2, sc1); } } } diff --git a/4coder_base_types.cpp b/4coder_base_types.cpp index d60b45b0..004e626f 100644 --- a/4coder_base_types.cpp +++ b/4coder_base_types.cpp @@ -274,6 +274,7 @@ block_fill_u64(void *a, umem size, u64 val){ #define block_zero_struct(p) block_zero((p), sizeof(*(p))) #define block_zero_array(a) block_zero((a), sizeof(a)) +#define block_zero_dynamic_array(p,c) block_zero((p), sizeof(*(p))*(c)) #define block_copy_struct(d,s) block_copy((d), (s), sizeof(*(d))) #define block_copy_array(d,s) block_copy((d), (s), sizeof(d)) @@ -1428,6 +1429,40 @@ operator!=(Vec4_f32 a, Vec4_f32 b){ //////////////////////////////// +static b32 +near_zero(f32 p, f32 epsilon){ + return(-epsilon <= p && p <= epsilon); +} +static b32 +near_zero(Vec2_f32 p, f32 epsilon){ + return(-epsilon <= p.x && p.x <= epsilon && + -epsilon <= p.y && p.y <= epsilon); +} +static b32 +near_zero(Vec3_f32 p, f32 epsilon){ + return(-epsilon <= p.x && p.x <= epsilon && + -epsilon <= p.y && p.y <= epsilon && + -epsilon <= p.z && p.z <= epsilon); +} +static b32 +near_zero(Vec4_f32 p, f32 epsilon){ + return(-epsilon <= p.x && p.x <= epsilon && + -epsilon <= p.y && p.y <= epsilon && + -epsilon <= p.z && p.z <= epsilon && + -epsilon <= p.w && p.w <= epsilon); +} + +static b32 +near_zero(f32 p){ return(near_zero(p, epsilon_f32)); } +static b32 +near_zero(Vec2_f32 p){ return(near_zero(p, epsilon_f32)); } +static b32 +near_zero(Vec3_f32 p){ return(near_zero(p, epsilon_f32)); } +static b32 +near_zero(Vec4_f32 p){ return(near_zero(p, epsilon_f32)); } + +//////////////////////////////// + static b32 operator==(Rect_i32 a, Rect_i32 b){ return(a.p0 == b.p0 && a.p1 == b.p1); @@ -1718,6 +1753,23 @@ range_overlap(Interval_f32 a, Interval_f32 b){ return(a.min < b.max && b.min < a.max); } +internal b32 +range_contains_inclusive(Interval_i32 a, i32 p){ + return(a.min <= p && p <= a.max); +} +internal b32 +range_contains_inclusive(Interval_i64 a, i64 p){ + return(a.min <= p && p <= a.max); +} +internal b32 +range_contains_inclusive(Interval_u64 a, u64 p){ + return(a.min <= p && p <= a.max); +} +internal b32 +range_inclusive_contains(Interval_f32 a, f32 p){ + return(a.min <= p && p <= a.max); +} + internal b32 range_contains(Interval_i32 a, i32 p){ return(a.min <= p && p < a.max); @@ -1760,6 +1812,31 @@ range_size(Interval_f32 a){ return(size); } +internal i32 +range_size_inclusive(Interval_i32 a){ + i32 size = a.max - a.min + 1; + size = clamp_bot(0, size); + return(size); +} +internal i64 +range_size_inclusive(Interval_i64 a){ + i64 size = a.max - a.min + 1; + size = clamp_bot(0, size); + return(size); +} +internal u64 +range_size_inclusive(Interval_u64 a){ + u64 size = a.max - a.min + 1; + size = clamp_bot(0, size); + return(size); +} +internal f32 +range_size_inclusive(Interval_f32 a){ + f32 size = a.max - a.min + 1; + size = clamp_bot(0, size); + return(size); +} + internal Interval_i32 rectify(Interval_i32 a){ return(Ii32(a.min, a.max)); @@ -1892,39 +1969,39 @@ range_distance(Interval_f32 a, Interval_f32 b){ //////////////////////////////// internal i32 -replace_range_compute_shift(i32 replace_length, i32 insert_length){ +replace_range_shift(i32 replace_length, i32 insert_length){ return(insert_length - replace_length); } internal i32 -replace_range_compute_shift(i32 start, i32 end, i32 insert_length){ +replace_range_shift(i32 start, i32 end, i32 insert_length){ return(insert_length - (end - start)); } internal i32 -replace_range_compute_shift(Interval_i32 range, i32 insert_length){ +replace_range_shift(Interval_i32 range, i32 insert_length){ return(insert_length - (range.end - range.start)); } internal i64 -replace_range_compute_shift(i64 replace_length, i64 insert_length){ +replace_range_shift(i64 replace_length, i64 insert_length){ return(insert_length - replace_length); } internal i64 -replace_range_compute_shift(i64 start, i64 end, i64 insert_length){ +replace_range_shift(i64 start, i64 end, i64 insert_length){ return(insert_length - (end - start)); } internal i64 -replace_range_compute_shift(Interval_i64 range, i64 insert_length){ +replace_range_shift(Interval_i64 range, i64 insert_length){ return(insert_length - (range.end - range.start)); } internal i64 -replace_range_compute_shift(u64 replace_length, u64 insert_length){ +replace_range_shift(u64 replace_length, u64 insert_length){ return((i64)insert_length - replace_length); } internal i64 -replace_range_compute_shift(i64 start, i64 end, u64 insert_length){ +replace_range_shift(i64 start, i64 end, u64 insert_length){ return((i64)insert_length - (end - start)); } internal i64 -replace_range_compute_shift(Interval_i64 range, u64 insert_length){ +replace_range_shift(Interval_i64 range, u64 insert_length){ return((i64)insert_length - (range.end - range.start)); } @@ -1991,6 +2068,9 @@ Rf32_xy_wh(Vec2_f32 p0, Vec2_f32 d){ #define i32R_xy_wh #define f32R_xy_wh +global_const Rect_f32 Rf32_infinity = {-max_f32, -max_f32, max_f32, max_f32}; +global_const Rect_f32 Rf32_negative_infinity = { max_f32, max_f32, -max_f32, -max_f32}; + internal b32 rect_equals(Rect_i32 a, Rect_i32 b){ return(a.x0 == b.x0 && a.y0 == b.y0 && a.x1 == b.x1 && a.y1 == b.y1); @@ -2053,6 +2133,15 @@ rect_height(Rect_f32 r){ return(r.y1 - r.y0); } +internal Vec2_i32 +rect_center(Rect_i32 r){ + return((r.p0 + r.p1)/2); +} +internal Vec2_f32 +rect_center(Rect_f32 r){ + return((r.p0 + r.p1)*0.5f); +} + internal Interval_i32 rect_range_x(Rect_i32 r){ return(Ii32(r.x0, r.x1)); @@ -2082,16 +2171,14 @@ rect_overlap(Rect_f32 a, Rect_f32 b){ } internal Vec2_i32 -rect_center(Rect_i32 r){ +rect_half_dim(Rect_i32 r){ return(rect_dim(r)/2); } internal Vec2_f32 -rect_center(Rect_f32 r){ - return(rect_dim(r)/2); +rect_half_dim(Rect_f32 r){ + return(rect_dim(r)*0.5f); } -#define center_of rect_center - internal Rect_i32 rect_intersect(Rect_i32 a, Rect_i32 b){ a.x0 = Max(a.x0, b.x0); @@ -2221,7 +2308,9 @@ base_allocate(Base_Allocator *allocator, umem size){ } static void base_free(Base_Allocator *allocator, void *ptr){ - allocator->free(allocator->user_data, ptr); + if (ptr != 0){ + allocator->free(allocator->user_data, ptr); + } } //////////////////////////////// @@ -5355,6 +5444,59 @@ string_wildcard_match_insensitive(List_String_Const_u8 list, String_Const_u8 str return(string_wildcard_match(list, string, StringMatch_CaseInsensitive)); } +static void +string_list_reverse(List_String_Const_char *list){ + Node_String_Const_char *first = 0; + Node_String_Const_char *last = list->first; + for (Node_String_Const_char *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + sll_stack_push(first, node); + } + list->first = first; + list->last = last; +} +static void +string_list_reverse(List_String_Const_u8 *list){ + Node_String_Const_u8 *first = 0; + Node_String_Const_u8 *last = list->first; + for (Node_String_Const_u8 *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + sll_stack_push(first, node); + } + list->first = first; + list->last = last; +} +static void +string_list_reverse(List_String_Const_u16 *list){ + Node_String_Const_u16 *first = 0; + Node_String_Const_u16 *last = list->first; + for (Node_String_Const_u16 *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + sll_stack_push(first, node); + } + list->first = first; + list->last = last; +} +static void +string_list_reverse(List_String_Const_u32 *list){ + Node_String_Const_u32 *first = 0; + Node_String_Const_u32 *last = list->first; + for (Node_String_Const_u32 *node = list->first, *next = 0; + node != 0; + node = next){ + next = node->next; + sll_stack_push(first, node); + } + list->first = first; + list->last = last; +} + //////////////////////////////// global_const u8 utf8_class[32] = { diff --git a/4coder_buffer_seek_constructors.cpp b/4coder_buffer_seek_constructors.cpp index 3b79b34a..3bf3357a 100644 --- a/4coder_buffer_seek_constructors.cpp +++ b/4coder_buffer_seek_constructors.cpp @@ -13,49 +13,11 @@ seek_pos(i64 pos){ } static Buffer_Seek -seek_character_pos(i64 pos){ +seek_line_col(i64 line, i64 col){ Buffer_Seek result; - result.type = buffer_seek_character_pos; - result.pos = pos; - return(result); -} - -static Buffer_Seek -seek_wrapped_xy(f32 x, f32 y, b32 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(f32 x, f32 y, b32 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_xy(f32 x, f32 y, b32 round_down, b32 unwrapped){ - Buffer_Seek result; - result.type = unwrapped?buffer_seek_unwrapped_xy:buffer_seek_wrapped_xy; - result.x = x; - result.y = y; - result.round_down = round_down; - return(result); -} - -static Buffer_Seek -seek_line_char(i64 line, i64 character){ - Buffer_Seek result; - result.type = buffer_seek_line_char; + result.type = buffer_seek_line_col; result.line = line; - result.character = character; + result.col = col; return(result); } diff --git a/4coder_default_hooks.cpp b/4coder_default_hooks.cpp index ad96f318..1c2b8235 100644 --- a/4coder_default_hooks.cpp +++ b/4coder_default_hooks.cpp @@ -13,7 +13,7 @@ CUSTOM_COMMAND_SIG(set_bindings_choose); CUSTOM_COMMAND_SIG(set_bindings_default); CUSTOM_COMMAND_SIG(set_bindings_mac_default); -static Named_Mapping named_maps_values[] = { +global Named_Mapping named_maps_values[] = { {string_u8_litexpr("mac-default") , set_bindings_mac_default }, {string_u8_litexpr("choose") , set_bindings_choose }, {string_u8_litexpr("default") , set_bindings_default }, @@ -119,7 +119,7 @@ struct Highlight_Record{ int_color color; }; -static void +internal void sort_highlight_record(Highlight_Record *records, i32 first, i32 one_past_last){ if (first + 1 < one_past_last){ i32 pivot_index = one_past_last - 1; @@ -140,7 +140,7 @@ sort_highlight_record(Highlight_Record *records, i32 first, i32 one_past_last){ } } -static Range_i64_Array +internal Range_i64_Array get_enclosure_ranges(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 pos, u32 flags){ Range_i64_Array array = {}; i32 max = 100; @@ -168,7 +168,7 @@ enum{ RangeHighlightKind_CharacterHighlight, }; -static void +internal void draw_enclosures(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID buffer, i64 pos, u32 flags, Range_Highlight_Kind kind, int_color *back_colors, int_color *fore_colors, i32 color_count){ @@ -327,27 +327,7 @@ GET_VIEW_BUFFER_REGION_SIG(default_view_buffer_region){ return(sub_region); } -static Buffer_Point -buffer_position_from_scroll_position(Application_Links *app, View_ID view_id, Vec2 scroll){ - Full_Cursor cursor = view_compute_cursor(app, view_id, seek_wrapped_xy(0.f, scroll.y, false)); - cursor = view_compute_cursor(app, view_id, seek_line_char(cursor.line, 1)); - Buffer_Point result = {}; - result.line_number = cursor.line; - result.pixel_shift.x = scroll.x; - result.pixel_shift.y = scroll.y - cursor.wrapped_y; - return(result); -} - -static i64 -abs_position_from_buffer_point(Application_Links *app, View_ID view_id, Buffer_Point buffer_point){ - Full_Cursor cursor = view_compute_cursor(app, view_id, seek_line_char(buffer_point.line_number, 0)); - Buffer_Seek seek = seek_wrapped_xy(buffer_point.pixel_shift.x, - buffer_point.pixel_shift.y + cursor.wrapped_y, false); - cursor = view_compute_cursor(app, view_id, seek); - return(cursor.pos); -} - -static void +internal void default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View_ID view_id, Rect_f32 view_inner_rect){ Buffer_ID buffer = view_get_buffer(app, view_id, AccessAll); @@ -362,11 +342,10 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View V2(view_inner_rect.p0 + sub_region.p1)); buffer_rect = rect_intersect(buffer_rect, view_inner_rect); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view_id); - - Buffer_Point buffer_point = buffer_position_from_scroll_position(app, view_id, scroll.scroll_p); - Text_Layout_ID text_layout_id = compute_render_layout(app, view_id, buffer, buffer_rect.p0, rect_dim(buffer_rect), buffer_point, max_i32); - Range_i64 on_screen_range = text_layout_get_on_screen_range(app, text_layout_id); + Buffer_Scroll scroll = view_get_buffer_scroll(app, view_id); + Buffer_Point buffer_point = scroll.position; + Text_Layout_ID text_layout_id = text_layout_create(app, buffer, buffer_rect, buffer_point); + Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); View_ID active_view = get_active_view(app, AccessAll); b32 is_active_view = (active_view == view_id); @@ -376,7 +355,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View // NOTE(allen): Scan for TODOs and NOTEs { Temp_Memory temp = begin_temp(scratch); - String_Const_u8 tail = push_buffer_range(app, scratch, buffer, on_screen_range); + String_Const_u8 tail = push_buffer_range(app, scratch, buffer, visible_range); Highlight_Record *record_first = 0; Highlight_Record *record_last = 0; @@ -388,7 +367,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View Highlight_Record *record = push_array(scratch, Highlight_Record, 1); sll_queue_push(record_first, record_last, record); record_count += 1; - record->range.first = on_screen_range.first + index; + record->range.first = visible_range.first + index; record->range.one_past_last = record->range.first + 4; record->color = Stag_Text_Cycle_2; tail = string_skip(tail, 3); @@ -398,7 +377,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View Highlight_Record *record = push_array(scratch, Highlight_Record, 1); sll_queue_push(record_first, record_last, record); record_count += 1; - record->range.first = on_screen_range.first + index; + record->range.first = visible_range.first + index; record->range.one_past_last = record->range.first + 4; record->color = Stag_Text_Cycle_1; tail = string_skip(tail, 3); @@ -537,7 +516,7 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View } draw_clip_push(app, buffer_rect); - draw_render_layout(app, view_id); + draw_text_layout(app, text_layout_id); text_layout_free(app, text_layout_id); draw_clip_pop(app); @@ -622,12 +601,12 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View Temp_Memory temp = begin_temp(scratch); i64 cursor_position = view_get_cursor_pos(app, view_id); - Full_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(cursor_position)); + Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(cursor_position)); Fancy_String_List list = {}; String_Const_u8 unique_name = push_buffer_unique_name(app, scratch, buffer); push_fancy_string(scratch, &list, base_color, unique_name); - push_fancy_stringf(scratch, &list, base_color, " - Row: %3.lld Col: %3.lld -", cursor.line, cursor.character); + push_fancy_stringf(scratch, &list, base_color, " - Row: %3.lld Col: %3.lld -", cursor.line, cursor.col); b32 is_dos_mode = false; if (buffer_get_setting(app, buffer, BufferSetting_Eol, &is_dos_mode)){ @@ -715,18 +694,16 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View Fancy_Color line_color = fancy_id(Stag_Line_Numbers_Text); - Full_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(on_screen_range.first)); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view_id); - for (;cursor.pos <= on_screen_range.one_past_last;){ - Vec2 p = panel_space_from_view_space(cursor.wrapped_p, scroll_vars.scroll_p); - p.y += left_margin.y0; - p.x = left_margin.x0; + Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(visible_range.first)); + for (;cursor.pos <= visible_range.one_past_last;){ + Rect_f32 line_rect = text_layout_line_on_screen(app, text_layout_id, cursor.line); + Vec2_f32 p = V2f32(left_margin.x1, line_rect.y0); Temp_Memory temp = begin_temp(scratch); Fancy_String *line_string = push_fancy_stringf(scratch, line_color, "%*lld", line_count_digit_count, cursor.line); draw_fancy_string(app, face_id, line_string, p, Stag_Margin_Active, 0); end_temp(temp); i64 next_line = cursor.line + 1; - cursor = view_compute_cursor(app, view_id, seek_line_char(next_line, 1)); + cursor = view_compute_cursor(app, view_id, seek_line_col(next_line, 1)); if (cursor.line < next_line){ break; } @@ -736,12 +713,12 @@ default_buffer_render_caller(Application_Links *app, Frame_Info frame_info, View } } -static void +internal void default_ui_render_caller(Application_Links *app, View_ID view_id, Rect_f32 rect_f32, Face_ID face_id){ UI_Data *ui_data = 0; Arena *ui_arena = 0; if (view_get_ui_data(app, view_id, ViewGetUIFlag_KeepDataAsIs, &ui_data, &ui_arena)){ - GUI_Scroll_Vars ui_scroll = view_get_scroll_vars(app, view_id); + Basic_Scroll scroll = view_get_basic_scroll(app, view_id); for (UI_Item *item = ui_data->list.first; item != 0; @@ -751,8 +728,8 @@ default_ui_render_caller(Application_Links *app, View_ID view_id, Rect_f32 rect_ switch (item->coordinates){ case UICoordinates_ViewSpace: { - item_rect.p0 -= ui_scroll.scroll_p; - item_rect.p1 -= ui_scroll.scroll_p; + item_rect.p0 -= scroll.position; + item_rect.p1 -= scroll.position; }break; case UICoordinates_PanelSpace: {}break; @@ -778,20 +755,20 @@ default_ui_render_caller(Application_Links *app, View_ID view_id, Rect_f32 rect_ } } } -static void +internal void default_ui_render_caller(Application_Links *app, View_ID view_id, Rect_f32 rect_f32){ Buffer_ID buffer = view_get_buffer(app, view_id, AccessAll); Face_ID face_id = get_face_id(app, buffer); default_ui_render_caller(app, view_id, rect_f32, face_id); } -static void +internal void default_ui_render_caller(Application_Links *app, View_ID view_id, Face_ID face_id){ Rect_f32 rect = view_get_screen_rect(app, view_id); rect.p1 -= rect.p0; rect.p0 = V2(0.f,0.f); default_ui_render_caller(app, view_id, rect, face_id); } -static void +internal void default_ui_render_caller(Application_Links *app, View_ID view){ Rect_f32 rect = view_get_screen_rect(app, view); rect.p1 -= rect.p0; @@ -801,7 +778,7 @@ default_ui_render_caller(Application_Links *app, View_ID view){ default_ui_render_caller(app, view, rect, face_id); } -static void +internal void default_render_view(Application_Links *app, Frame_Info frame_info, View_ID view, b32 is_active){ Rect_f32 view_rect = view_get_screen_rect(app, view); Rect_f32 inner = rect_inner(view_rect, 3); @@ -1244,57 +1221,54 @@ INPUT_FILTER_SIG(default_suppress_mouse_filter){ // 4coder scrolling behavior. // -Vec2 scroll_velocity_[16] = {}; -Vec2 *scroll_velocity = scroll_velocity_ - 1; +Vec2_f32 scroll_velocity_[16] = {}; +Vec2_f32 *scroll_velocity = scroll_velocity_ - 1; -static i32 -smooth_camera_step(f32 target, f32 *current, f32 *vel, f32 S, f32 T){ - i32 result = 0; - f32 curr = *current; - f32 v = *vel; - if (curr != target){ - if (curr > target - .1f && curr < target + .1f){ - curr = target; - v = 1.f; +struct Smooth_Step{ + f32 p; + f32 v; +}; + +internal Smooth_Step +smooth_camera_step(f32 target, f32 v, f32 S, f32 T){ + Smooth_Step step = {}; + step.v = v; + if (step.p != target){ + if (step.p > target - .1f && step.p < target + .1f){ + step.p = target; + step.v = 1.f; } else{ - f32 L = curr + T*(target - curr); - - i32 sign = (target > curr) - (target < curr); - f32 V = curr + sign*v; - - if (sign > 0) curr = (LV)?(L):(V); - - if (curr == V){ - v *= S; + f32 L = step.p + T*(target - step.p); + i32 sign = (target > step.p) - (target < step.p); + f32 V = step.p + sign*step.v; + if (sign > 0){ + step.p = (LV)?(L):(V); + } + if (step.p == V){ + step.v *= S; } } - - *current = curr; - *vel = v; - result = 1; } - return(result); + return(step); } -SCROLL_RULE_SIG(smooth_scroll_rule){ - Vec2 *velocity = scroll_velocity + view_id; - i32 result = 0; +DELTA_RULE_SIG(smooth_scroll_rule){ + Vec2_f32 *velocity = scroll_velocity + view_id; if (velocity->x == 0.f){ velocity->x = 1.f; velocity->y = 1.f; } - if (smooth_camera_step(target_y, scroll_y, &velocity->y, 80.f, 1.f/2.f)){ - result = 1; - } - if (smooth_camera_step(target_x, scroll_x, &velocity->x, 80.f, 1.f/2.f)){ - result = 1; - } - return(result); + Smooth_Step step_x = smooth_camera_step(pending_delta.x, velocity->x, 80.f, 1.f/2.f); + Smooth_Step step_y = smooth_camera_step(pending_delta.y, velocity->y, 80.f, 1.f/2.f); + *velocity = V2f32(step_x.v, step_y.v); + return(V2f32(step_x.p, step_y.p)); } -static void +internal void set_all_default_hooks(Bind_Helper *context){ set_hook(context, hook_exit, default_exit); set_hook(context, hook_buffer_viewer_update, default_view_adjust); diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 667b58c3..97e5f035 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -7,16 +7,6 @@ #if !defined(FCODER_DEFAULT_INCLUDE_CPP) #define FCODER_DEFAULT_INCLUDE_CPP -// NOTE(allen): Defines before 4coder_default_include.cpp: -// REMOVE_TRANSITION_HELPER_31 -> does not include the transition helpers for the API changes in 4.0.31 -// REMOVE_OLD_STRING -> does not include the old 4coder_string.h library. -// NOTE: You can only remove "old string" if you first remove the transition helper. - -#if 0 -#define REMOVE_TRANSITION_HELPER_31 -#define REMOVE_OLD_STRING -#endif - #include "4coder_API/4coder_custom.h" #include "4coder_generated/command_metadata.h" @@ -34,8 +24,6 @@ #include "4coder_table.h" #include "4coder_string_match.h" -#include "4coder_api_transition_30_31.h" - #include "4coder_helper.h" #include "4coder_insertion.h" #include "4coder_fancy.h" @@ -61,8 +49,6 @@ #include "4coder_string_match.cpp" #include "4coder_buffer_seek_constructors.cpp" -#include "4coder_api_transition_30_31.cpp" - #include "4coder_default_framework_variables.cpp" #include "4coder_helper.cpp" #include "4coder_seek.cpp" @@ -91,8 +77,6 @@ #include "4coder_default_hooks.cpp" #include "4coder_remapping_commands.cpp" -#include "4coder_api_transition_30_31_helpers.cpp" - #endif // BOTTOM diff --git a/4coder_experiments.cpp b/4coder_experiments.cpp index b4598c8a..a7ec3e93 100644 --- a/4coder_experiments.cpp +++ b/4coder_experiments.cpp @@ -12,205 +12,6 @@ #include -static float -get_line_y(Application_Links *app, View_ID view, i32 line){ - Full_Cursor cursor = view_compute_cursor(app, view, seek_line_char(line, 1)); - return(cursor.wrapped_y); -} - -static Rect_i32 -get_line_x_rect(Application_Links *app, View_ID view){ - i64 cursor_pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(cursor_pos)); - i64 mark_pos = view_get_mark_pos(app, view); - Full_Cursor mark = view_compute_cursor(app, view, seek_pos(mark_pos)); - - Rect_i32 rect = {}; - rect.x0 = (i32)mark.wrapped_x; - rect.x1 = (i32)cursor.wrapped_x; - rect.y0 = (i32)mark.line; - rect.y1 = (i32)cursor.line; - - if (rect.y0 > rect.y1){ - Swap(i32, rect.y0, rect.y1); - } - if (rect.x0 > rect.x1){ - Swap(i32, rect.x0, rect.x1); - } - - return(rect); -} - -CUSTOM_COMMAND_SIG(kill_rect) -CUSTOM_DOC("Delete characters in a rectangular region. Range testing is done by unwrapped-xy coordinates.") -{ - View_ID view = get_active_view(app, AccessOpen); - Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); - - i32_Rect rect = get_line_x_rect(app, view); - - for (i32 line = rect.y1; line >= rect.y0; --line){ - f32 y = get_line_y(app, view, line); - Full_Cursor cursor = view_compute_cursor(app, view, seek_wrapped_xy((f32)rect.x0, y, 0)); - if (cursor.line > 0){ - i64 start = cursor.pos; - cursor = view_compute_cursor(app, view, seek_wrapped_xy((f32)rect.x1, y, 0)); - if (cursor.line > 0){ - i64 end = cursor.pos; - buffer_replace_range(app, buffer, Ii64(start, end), string_u8_empty); - } - } - } -} - -static void -pad_buffer_line(Application_Links *app, Buffer_ID buffer, i64 line, char padchar, i64 target){ - Partial_Cursor start = buffer_compute_cursor(app, buffer, seek_line_char(line, 1)); - if (start.line == line){ - Partial_Cursor end = buffer_compute_cursor(app, buffer, seek_line_char(line, 65536)); - if (end.line == line){ - if (end.character - 1 < target){ - Scratch_Block scratch(app); - i64 size = target - (end.character - 1); - char *str = push_array(scratch, char, size); - block_fill_u8(str, size, ' '); - buffer_replace_range(app, buffer, Ii64(end.pos), SCu8(str, size)); - } - } - } -} - -/* -NOTE(allen): Things I learned from this experiment. - -First of all the batch edits aren't too bad, but I think -there could be a single system that I run that through that -knows how to build the batch edit from slightly higher level -information. For instance the idea in point 2. - -Secondly I definitely believe I need some sort of "mini-buffer" -concept where a view sends commands so that things like -pasting still work. Then the contents of the "mini-buffer" -can be used to complete the edits at all cursor points. -This doesn't answer all questions, because somehow backspace -still wants to work for multi-lines even when the "mini-buffer" -is emtpy. Such a system would also make it possible to send -paste commands and cursor navigation to interactive bars. - -Thirdly any system like this will probably not want to -operate through the co-routine system, because that makes -sending these commands to the "mini-buffer" much more -difficult. - -Fourthly I desperately need some way to do multi-highlighting -multi-cursor showing but it is unclear to me how to do that -conveniently. Since this won't exist inside a coroutine -what does such an API even look like??? It's clear to me now -that I may need to start pushing for the view routine before -I am even able to support the GUI. Because that will set up the -system to allow me to think about the problem in more ways. - -Finally I have decided not to pursue this direction any more, -it just seems like the wrong way to do it, so I'll stop without -doing multi-cursor for now. -*/ - -struct Buffer_Rect{ - i64 char0; - i64 line0; - i64 char1; - i64 line1; -}; - -CUSTOM_COMMAND_SIG(multi_line_edit) -CUSTOM_DOC("Begin multi-line mode. In multi-line mode characters are inserted at every line between the mark and cursor. All characters are inserted at the same character offset into the line. This mode uses line_char coordinates.") -{ - View_ID view = get_active_view(app, AccessOpen); - Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); - - i64 cursor_pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(cursor_pos)); - i64 mark_pos = view_get_mark_pos(app, view); - Full_Cursor mark = view_compute_cursor(app, view, seek_pos(mark_pos)); - Buffer_Rect rect = {}; - rect.char0 = mark.character; - rect.line0 = mark.line; - rect.char1 = cursor.character; - rect.line1 = cursor.line; - if (rect.line0 > rect.line1){ - Swap(i64, rect.line0, rect.line1); - } - if (rect.char0 > rect.char1){ - Swap(i64, rect.char0, rect.char1); - } - - i64 start_line = cursor.line; - i64 pos = cursor.character - 1; - - for (i64 i = rect.line0; i <= rect.line1; ++i){ - pad_buffer_line(app, buffer, i, ' ', pos); - } - - i64 line_count = rect.line1 - rect.line0 + 1; - - for (;;){ - User_Input in = get_user_input(app, EventOnAnyKey, EventOnEsc|EventOnMouseLeftButton|EventOnMouseRightButton); - if (in.abort) break; - - if (in.key.character && key_is_unmodified(&in.key)){ - char str = (char)in.key.character; - - Scratch_Block scratch(app); - Buffer_Edit *edits = push_array(scratch, Buffer_Edit, line_count); - Buffer_Edit *edit = edits; - - for (i64 i = rect.line0; i <= rect.line1; ++i){ - Partial_Cursor partial_cursor = buffer_compute_cursor(app, buffer, seek_line_char(i, pos + 1)); - if (partial_cursor.line > 0){ - edit->str_start = 0; - edit->len = 1; - edit->start = partial_cursor.pos; - edit->end = partial_cursor.pos; - ++edit; - } - } - - i32 edit_count = (int)(edit - edits); - buffer_batch_edit(app, buffer, &str, edits, edit_count); - - ++pos; - - view_set_cursor(app, view, seek_line_char(start_line, pos + 1), true); - } - else if (in.key.keycode == key_back){ - if (pos > 0){ - Scratch_Block scratch(app); - Buffer_Edit *edits = push_array(scratch, Buffer_Edit, line_count); - Buffer_Edit *edit = edits; - - for (i64 i = rect.line0; i <= rect.line1; ++i){ - Partial_Cursor partial_cursor = buffer_compute_cursor(app, buffer, seek_line_char(i, pos + 1)); - if (partial_cursor.line > 0){ - edit->str_start = 0; - edit->len = 0; - edit->start = partial_cursor.pos - 1; - edit->end = partial_cursor.pos; - ++edit; - } - } - - i32 edit_count = (int)(edit - edits); - buffer_batch_edit(app, buffer, 0, edits, edit_count); - - --pos; - } - } - else{ - break; - } - } -} - // NOTE(allen): An experimental mutli-pasting thing CUSTOM_COMMAND_SIG(multi_paste){ @@ -260,9 +61,11 @@ multi_paste_range(Application_Links *app, View_ID view, Range_i64 range, i32 pas if (paste_count >= 1){ Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); if (buffer != 0){ - i32 total_size = 0; + i64 total_size = 0; for (i32 paste_index = 0; paste_index < paste_count; ++paste_index){ - total_size += 1 + clipboard_index(app, 0, paste_index, 0, 0); + Scratch_Block scratch(app); + String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); + total_size += string.size + 1; } total_size -= 1; @@ -386,6 +189,8 @@ CUSTOM_COMMAND_SIG(multi_paste_interactive_quick){ CUSTOM_COMMAND_SIG(rename_parameter) CUSTOM_DOC("If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.") { + NotImplemented; +#if 0 View_ID view = get_active_view(app, AccessOpen); Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); i64 cursor_pos = view_get_cursor_pos(app, view); @@ -396,7 +201,6 @@ CUSTOM_DOC("If the cursor is found to be on the name of a function parameter in Cpp_Get_Token_Result result = {}; if (get_token_from_pos(app, buffer, cursor_pos, &result)){ if (!result.in_whitespace_after_token){ -#if 0 static const i32 stream_space_size = 512; Cpp_Token stream_space[stream_space_size]; Stream_Tokens_DEP stream = {}; @@ -517,11 +321,11 @@ CUSTOM_DOC("If the cursor is found to be on the name of a function parameter in } } } -#endif } } end_temp(temp); +#endif } typedef u32 Write_Explicit_Enum_Values_Mode; @@ -532,6 +336,8 @@ enum{ static void write_explicit_enum_values_parameters(Application_Links *app, Write_Explicit_Enum_Values_Mode mode){ + NotImplemented; +#if 0 View_ID view = get_active_view(app, AccessOpen); Buffer_ID buffer = view_get_buffer(app, view, AccessOpen); @@ -543,7 +349,6 @@ write_explicit_enum_values_parameters(Application_Links *app, Write_Explicit_Enu Cpp_Get_Token_Result result = {}; if (get_token_from_pos(app, buffer, pos, &result)){ if (!result.in_whitespace_after_token){ -#if 0 Cpp_Token stream_space[32]; Stream_Tokens_DEP stream = {}; @@ -683,11 +488,11 @@ write_explicit_enum_values_parameters(Application_Links *app, Write_Explicit_Enu } } } -#endif } } end_temp(temp); +#endif } CUSTOM_COMMAND_SIG(write_explicit_enum_values) @@ -742,8 +547,8 @@ get_bindings(void *data, i32 size){ // begin_map to clear everything that was in the map and // bind new things instead. begin_map(context, mapid_file); - bind(context, key_back, MDFR_ALT|MDFR_CTRL, kill_rect); - bind(context, ' ', MDFR_ALT|MDFR_CTRL, multi_line_edit); + //bind(context, key_back, MDFR_ALT|MDFR_CTRL, kill_rect); + //bind(context, ' ', MDFR_ALT|MDFR_CTRL, multi_line_edit); bind(context, key_page_up, MDFR_ALT, miblo_increment_time_stamp); bind(context, key_page_down, MDFR_ALT, miblo_decrement_time_stamp); diff --git a/4coder_generated/app_functions.h b/4coder_generated/app_functions.h index 8755487f..4c3aafe9 100644 --- a/4coder_generated/app_functions.h +++ b/4coder_generated/app_functions.h @@ -19,10 +19,21 @@ struct Application_Links; #define GET_BUFFER_BY_FILE_NAME_SIG(n) Buffer_ID n(Application_Links *app, String_Const_u8 file_name, Access_Flag access) #define BUFFER_READ_RANGE_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, char *out) #define BUFFER_REPLACE_RANGE_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string) -#define BUFFER_BATCH_EDIT_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, char *str, Buffer_Edit *edits, i32 edit_count) +#define BUFFER_BATCH_EDIT_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id, Batch_Edit *batch) #define BUFFER_SEEK_STRING_SIG(n) String_Match n(Application_Links *app, Buffer_ID buffer, String_Const_u8 needle, Scan_Direction direction, i64 start_pos) #define BUFFER_SEEK_CHARACTER_CLASS_SIG(n) String_Match n(Application_Links *app, Buffer_ID buffer, Character_Predicate *predicate, Scan_Direction direction, i64 start_pos) -#define BUFFER_COMPUTE_CURSOR_SIG(n) Partial_Cursor n(Application_Links *app, Buffer_ID buffer_id, Buffer_Seek seek) +#define BUFFER_LINE_Y_DIFFERENCE_SIG(n) f32 n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line_a, i64 line_b) +#define BUFFER_LINE_SHIFT_Y_SIG(n) Line_Shift_Vertical n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line, f32 y_shift) +#define BUFFER_POS_AT_RELATIVE_XY_SIG(n) i64 n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy) +#define BUFFER_RELATIVE_XY_OF_POS_SIG(n) Vec2_f32 n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) +#define BUFFER_RELATIVE_CHARACTER_FROM_POS_SIG(n) i64 n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) +#define BUFFER_POS_FROM_RELATIVE_CHARACTER_SIG(n) i64 n(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 relative_character) +#define VIEW_LINE_Y_DIFFERENCE_SIG(n) f32 n(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b) +#define VIEW_LINE_SHIFT_Y_SIG(n) Line_Shift_Vertical n(Application_Links *app, View_ID view_id, i64 line, f32 y_shift) +#define VIEW_POS_AT_RELATIVE_XY_SIG(n) i64 n(Application_Links *app, View_ID view_id, i64 base_line, Vec2_f32 relative_xy) +#define VIEW_RELATIVE_XY_OF_POS_SIG(n) Vec2_f32 n(Application_Links *app, View_ID view_id, i64 base_line, i64 pos) +#define VIEW_RELATIVE_CHARACTER_FROM_POS_SIG(n) i64 n(Application_Links *app, View_ID view_id, i64 base_line, i64 pos) +#define VIEW_POS_FROM_RELATIVE_CHARACTER_SIG(n) i64 n(Application_Links *app, View_ID view_id, i64 base_line, i64 character) #define BUFFER_EXISTS_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id) #define BUFFER_READY_SIG(n) b32 n(Application_Links *app, Buffer_ID buffer_id) #define BUFFER_GET_ACCESS_FLAGS_SIG(n) Access_Flag n(Application_Links *app, Buffer_ID buffer_id) @@ -68,14 +79,16 @@ struct Application_Links; #define PANEL_GET_MARGIN_SIG(n) Rect_i32 n(Application_Links *app, Panel_ID panel_id) #define VIEW_CLOSE_SIG(n) b32 n(Application_Links *app, View_ID view_id) #define VIEW_GET_BUFFER_REGION_SIG(n) Rect_f32 n(Application_Links *app, View_ID view_id) -#define VIEW_GET_SCROLL_VARS_SIG(n) GUI_Scroll_Vars n(Application_Links *app, View_ID view_id) +#define VIEW_GET_BUFFER_SCROLL_SIG(n) Buffer_Scroll n(Application_Links *app, View_ID view_id) +#define VIEW_GET_BASIC_SCROLL_SIG(n) Basic_Scroll n(Application_Links *app, View_ID view_id) #define VIEW_SET_ACTIVE_SIG(n) b32 n(Application_Links *app, View_ID view_id) #define VIEW_GET_SETTING_SIG(n) b32 n(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 *value_out) #define VIEW_SET_SETTING_SIG(n) b32 n(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 value) #define VIEW_GET_MANAGED_SCOPE_SIG(n) Managed_Scope n(Application_Links *app, View_ID view_id) -#define VIEW_COMPUTE_CURSOR_SIG(n) Full_Cursor n(Application_Links *app, View_ID view_id, Buffer_Seek seek) +#define BUFFER_COMPUTE_CURSOR_SIG(n) Buffer_Cursor n(Application_Links *app, Buffer_ID buffer, Buffer_Seek seek) #define VIEW_SET_CURSOR_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_Seek seek, b32 set_preferred_x) -#define VIEW_SET_SCROLL_SIG(n) b32 n(Application_Links *app, View_ID view_id, GUI_Scroll_Vars scroll) +#define VIEW_SET_BUFFER_SCROLL_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_Scroll scroll) +#define VIEW_SET_BASIC_SCROLL_SIG(n) b32 n(Application_Links *app, View_ID view_id, Basic_Scroll scroll) #define VIEW_SET_MARK_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_Seek seek) #define VIEW_SET_BUFFER_SIG(n) b32 n(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags) #define VIEW_POST_FADE_SIG(n) b32 n(Application_Links *app, View_ID view_id, f32 seconds, Range_i64 range, int_color color) @@ -159,21 +172,17 @@ struct Application_Links; #define DRAW_CLIP_POP_SIG(n) f32_Rect n(Application_Links *app) #define DRAW_COORDINATE_CENTER_PUSH_SIG(n) void n(Application_Links *app, Vec2 point) #define DRAW_COORDINATE_CENTER_POP_SIG(n) Vec2 n(Application_Links *app) +#define TEXT_LAYOUT_CREATE_SIG(n) Text_Layout_ID n(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point) #define TEXT_LAYOUT_GET_BUFFER_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out) -#define TEXT_LAYOUT_BUFFER_POINT_TO_LAYOUT_POINT_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out) -#define TEXT_LAYOUT_LAYOUT_POINT_TO_BUFFER_POINT_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out) -#define TEXT_LAYOUT_GET_ON_SCREEN_RANGE_SIG(n) Range_i64 n(Application_Links *app, Text_Layout_ID text_layout_id) -#define TEXT_LAYOUT_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID text_layout_id) +#define TEXT_LAYOUT_GET_VISIBLE_RANGE_SIG(n) Interval_i64 n(Application_Links *app, Text_Layout_ID text_layout_id) #define TEXT_LAYOUT_LINE_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID layout_id, i64 line_number) #define TEXT_LAYOUT_CHARACTER_ON_SCREEN_SIG(n) Rect_f32 n(Application_Links *app, Text_Layout_ID layout_id, i64 pos) -#define PAINT_TEXT_COLOR_SIG(n) void n(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color) +#define PAINT_TEXT_COLOR_SIG(n) void n(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range, int_color color) #define TEXT_LAYOUT_FREE_SIG(n) b32 n(Application_Links *app, Text_Layout_ID text_layout_id) -#define COMPUTE_RENDER_LAYOUT_SIG(n) Text_Layout_ID n(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last) -#define DRAW_RENDER_LAYOUT_SIG(n) void n(Application_Links *app, View_ID view_id) +#define DRAW_TEXT_LAYOUT_SIG(n) void n(Application_Links *app, Text_Layout_ID layout_id) #define OPEN_COLOR_PICKER_SIG(n) void n(Application_Links *app, Color_Picker *picker) #define ANIMATE_IN_N_MILLISECONDS_SIG(n) void n(Application_Links *app, u32 n) #define BUFFER_FIND_ALL_MATCHES_SIG(n) String_Match_List n(Application_Links *app, Arena *arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction) -#define GET_VIEW_VISIBLE_RANGE_SIG(n) Range n(Application_Links *app, View_ID view_id) typedef GLOBAL_SET_SETTING_SIG(Global_Set_Setting_Function); typedef GLOBAL_SET_MAPPING_SIG(Global_Set_Mapping_Function); typedef GLOBAL_GET_SCREEN_RECTANGLE_SIG(Global_Get_Screen_Rectangle_Function); @@ -197,7 +206,18 @@ typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); typedef BUFFER_BATCH_EDIT_SIG(Buffer_Batch_Edit_Function); typedef BUFFER_SEEK_STRING_SIG(Buffer_Seek_String_Function); typedef BUFFER_SEEK_CHARACTER_CLASS_SIG(Buffer_Seek_Character_Class_Function); -typedef BUFFER_COMPUTE_CURSOR_SIG(Buffer_Compute_Cursor_Function); +typedef BUFFER_LINE_Y_DIFFERENCE_SIG(Buffer_Line_Y_Difference_Function); +typedef BUFFER_LINE_SHIFT_Y_SIG(Buffer_Line_Shift_Y_Function); +typedef BUFFER_POS_AT_RELATIVE_XY_SIG(Buffer_Pos_At_Relative_XY_Function); +typedef BUFFER_RELATIVE_XY_OF_POS_SIG(Buffer_Relative_XY_Of_Pos_Function); +typedef BUFFER_RELATIVE_CHARACTER_FROM_POS_SIG(Buffer_Relative_Character_From_Pos_Function); +typedef BUFFER_POS_FROM_RELATIVE_CHARACTER_SIG(Buffer_Pos_From_Relative_Character_Function); +typedef VIEW_LINE_Y_DIFFERENCE_SIG(View_Line_Y_Difference_Function); +typedef VIEW_LINE_SHIFT_Y_SIG(View_Line_Shift_Y_Function); +typedef VIEW_POS_AT_RELATIVE_XY_SIG(View_Pos_At_Relative_XY_Function); +typedef VIEW_RELATIVE_XY_OF_POS_SIG(View_Relative_XY_Of_Pos_Function); +typedef VIEW_RELATIVE_CHARACTER_FROM_POS_SIG(View_Relative_Character_From_Pos_Function); +typedef VIEW_POS_FROM_RELATIVE_CHARACTER_SIG(View_Pos_From_Relative_Character_Function); typedef BUFFER_EXISTS_SIG(Buffer_Exists_Function); typedef BUFFER_READY_SIG(Buffer_Ready_Function); typedef BUFFER_GET_ACCESS_FLAGS_SIG(Buffer_Get_Access_Flags_Function); @@ -243,14 +263,16 @@ typedef PANEL_GET_MAX_SIG(Panel_Get_Max_Function); typedef PANEL_GET_MARGIN_SIG(Panel_Get_Margin_Function); typedef VIEW_CLOSE_SIG(View_Close_Function); typedef VIEW_GET_BUFFER_REGION_SIG(View_Get_Buffer_Region_Function); -typedef VIEW_GET_SCROLL_VARS_SIG(View_Get_Scroll_Vars_Function); +typedef VIEW_GET_BUFFER_SCROLL_SIG(View_Get_Buffer_Scroll_Function); +typedef VIEW_GET_BASIC_SCROLL_SIG(View_Get_Basic_Scroll_Function); typedef VIEW_SET_ACTIVE_SIG(View_Set_Active_Function); typedef VIEW_GET_SETTING_SIG(View_Get_Setting_Function); typedef VIEW_SET_SETTING_SIG(View_Set_Setting_Function); typedef VIEW_GET_MANAGED_SCOPE_SIG(View_Get_Managed_Scope_Function); -typedef VIEW_COMPUTE_CURSOR_SIG(View_Compute_Cursor_Function); +typedef BUFFER_COMPUTE_CURSOR_SIG(Buffer_Compute_Cursor_Function); typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function); -typedef VIEW_SET_SCROLL_SIG(View_Set_Scroll_Function); +typedef VIEW_SET_BUFFER_SCROLL_SIG(View_Set_Buffer_Scroll_Function); +typedef VIEW_SET_BASIC_SCROLL_SIG(View_Set_Basic_Scroll_Function); typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function); typedef VIEW_SET_BUFFER_SIG(View_Set_Buffer_Function); typedef VIEW_POST_FADE_SIG(View_Post_Fade_Function); @@ -334,21 +356,17 @@ typedef DRAW_CLIP_PUSH_SIG(Draw_Clip_Push_Function); typedef DRAW_CLIP_POP_SIG(Draw_Clip_Pop_Function); typedef DRAW_COORDINATE_CENTER_PUSH_SIG(Draw_Coordinate_Center_Push_Function); typedef DRAW_COORDINATE_CENTER_POP_SIG(Draw_Coordinate_Center_Pop_Function); +typedef TEXT_LAYOUT_CREATE_SIG(Text_Layout_Create_Function); typedef TEXT_LAYOUT_GET_BUFFER_SIG(Text_Layout_Get_Buffer_Function); -typedef TEXT_LAYOUT_BUFFER_POINT_TO_LAYOUT_POINT_SIG(Text_Layout_Buffer_Point_To_Layout_Point_Function); -typedef TEXT_LAYOUT_LAYOUT_POINT_TO_BUFFER_POINT_SIG(Text_Layout_Layout_Point_To_Buffer_Point_Function); -typedef TEXT_LAYOUT_GET_ON_SCREEN_RANGE_SIG(Text_Layout_Get_On_Screen_Range_Function); -typedef TEXT_LAYOUT_ON_SCREEN_SIG(Text_Layout_On_Screen_Function); +typedef TEXT_LAYOUT_GET_VISIBLE_RANGE_SIG(Text_Layout_Get_Visible_Range_Function); typedef TEXT_LAYOUT_LINE_ON_SCREEN_SIG(Text_Layout_Line_On_Screen_Function); typedef TEXT_LAYOUT_CHARACTER_ON_SCREEN_SIG(Text_Layout_Character_On_Screen_Function); typedef PAINT_TEXT_COLOR_SIG(Paint_Text_Color_Function); typedef TEXT_LAYOUT_FREE_SIG(Text_Layout_Free_Function); -typedef COMPUTE_RENDER_LAYOUT_SIG(Compute_Render_Layout_Function); -typedef DRAW_RENDER_LAYOUT_SIG(Draw_Render_Layout_Function); +typedef DRAW_TEXT_LAYOUT_SIG(Draw_Text_Layout_Function); typedef OPEN_COLOR_PICKER_SIG(Open_Color_Picker_Function); typedef ANIMATE_IN_N_MILLISECONDS_SIG(Animate_In_N_Milliseconds_Function); typedef BUFFER_FIND_ALL_MATCHES_SIG(Buffer_Find_All_Matches_Function); -typedef GET_VIEW_VISIBLE_RANGE_SIG(Get_View_Visible_Range_Function); struct Application_Links{ #if defined(ALLOW_DEP_4CODER) Global_Set_Setting_Function *global_set_setting; @@ -374,7 +392,18 @@ Buffer_Replace_Range_Function *buffer_replace_range; Buffer_Batch_Edit_Function *buffer_batch_edit; Buffer_Seek_String_Function *buffer_seek_string; Buffer_Seek_Character_Class_Function *buffer_seek_character_class; -Buffer_Compute_Cursor_Function *buffer_compute_cursor; +Buffer_Line_Y_Difference_Function *buffer_line_y_difference; +Buffer_Line_Shift_Y_Function *buffer_line_shift_y; +Buffer_Pos_At_Relative_XY_Function *buffer_pos_at_relative_xy; +Buffer_Relative_XY_Of_Pos_Function *buffer_relative_xy_of_pos; +Buffer_Relative_Character_From_Pos_Function *buffer_relative_character_from_pos; +Buffer_Pos_From_Relative_Character_Function *buffer_pos_from_relative_character; +View_Line_Y_Difference_Function *view_line_y_difference; +View_Line_Shift_Y_Function *view_line_shift_y; +View_Pos_At_Relative_XY_Function *view_pos_at_relative_xy; +View_Relative_XY_Of_Pos_Function *view_relative_xy_of_pos; +View_Relative_Character_From_Pos_Function *view_relative_character_from_pos; +View_Pos_From_Relative_Character_Function *view_pos_from_relative_character; Buffer_Exists_Function *buffer_exists; Buffer_Ready_Function *buffer_ready; Buffer_Get_Access_Flags_Function *buffer_get_access_flags; @@ -420,14 +449,16 @@ Panel_Get_Max_Function *panel_get_max; Panel_Get_Margin_Function *panel_get_margin; View_Close_Function *view_close; View_Get_Buffer_Region_Function *view_get_buffer_region; -View_Get_Scroll_Vars_Function *view_get_scroll_vars; +View_Get_Buffer_Scroll_Function *view_get_buffer_scroll; +View_Get_Basic_Scroll_Function *view_get_basic_scroll; View_Set_Active_Function *view_set_active; View_Get_Setting_Function *view_get_setting; View_Set_Setting_Function *view_set_setting; View_Get_Managed_Scope_Function *view_get_managed_scope; -View_Compute_Cursor_Function *view_compute_cursor; +Buffer_Compute_Cursor_Function *buffer_compute_cursor; View_Set_Cursor_Function *view_set_cursor; -View_Set_Scroll_Function *view_set_scroll; +View_Set_Buffer_Scroll_Function *view_set_buffer_scroll; +View_Set_Basic_Scroll_Function *view_set_basic_scroll; View_Set_Mark_Function *view_set_mark; View_Set_Buffer_Function *view_set_buffer; View_Post_Fade_Function *view_post_fade; @@ -511,21 +542,17 @@ Draw_Clip_Push_Function *draw_clip_push; Draw_Clip_Pop_Function *draw_clip_pop; Draw_Coordinate_Center_Push_Function *draw_coordinate_center_push; Draw_Coordinate_Center_Pop_Function *draw_coordinate_center_pop; +Text_Layout_Create_Function *text_layout_create; Text_Layout_Get_Buffer_Function *text_layout_get_buffer; -Text_Layout_Buffer_Point_To_Layout_Point_Function *text_layout_buffer_point_to_layout_point; -Text_Layout_Layout_Point_To_Buffer_Point_Function *text_layout_layout_point_to_buffer_point; -Text_Layout_Get_On_Screen_Range_Function *text_layout_get_on_screen_range; -Text_Layout_On_Screen_Function *text_layout_on_screen; +Text_Layout_Get_Visible_Range_Function *text_layout_get_visible_range; Text_Layout_Line_On_Screen_Function *text_layout_line_on_screen; Text_Layout_Character_On_Screen_Function *text_layout_character_on_screen; Paint_Text_Color_Function *paint_text_color; Text_Layout_Free_Function *text_layout_free; -Compute_Render_Layout_Function *compute_render_layout; -Draw_Render_Layout_Function *draw_render_layout; +Draw_Text_Layout_Function *draw_text_layout; Open_Color_Picker_Function *open_color_picker; Animate_In_N_Milliseconds_Function *animate_in_n_milliseconds; Buffer_Find_All_Matches_Function *buffer_find_all_matches; -Get_View_Visible_Range_Function *get_view_visible_range; #else Global_Set_Setting_Function *global_set_setting_; Global_Set_Mapping_Function *global_set_mapping_; @@ -550,7 +577,18 @@ Buffer_Replace_Range_Function *buffer_replace_range_; Buffer_Batch_Edit_Function *buffer_batch_edit_; Buffer_Seek_String_Function *buffer_seek_string_; Buffer_Seek_Character_Class_Function *buffer_seek_character_class_; -Buffer_Compute_Cursor_Function *buffer_compute_cursor_; +Buffer_Line_Y_Difference_Function *buffer_line_y_difference_; +Buffer_Line_Shift_Y_Function *buffer_line_shift_y_; +Buffer_Pos_At_Relative_XY_Function *buffer_pos_at_relative_xy_; +Buffer_Relative_XY_Of_Pos_Function *buffer_relative_xy_of_pos_; +Buffer_Relative_Character_From_Pos_Function *buffer_relative_character_from_pos_; +Buffer_Pos_From_Relative_Character_Function *buffer_pos_from_relative_character_; +View_Line_Y_Difference_Function *view_line_y_difference_; +View_Line_Shift_Y_Function *view_line_shift_y_; +View_Pos_At_Relative_XY_Function *view_pos_at_relative_xy_; +View_Relative_XY_Of_Pos_Function *view_relative_xy_of_pos_; +View_Relative_Character_From_Pos_Function *view_relative_character_from_pos_; +View_Pos_From_Relative_Character_Function *view_pos_from_relative_character_; Buffer_Exists_Function *buffer_exists_; Buffer_Ready_Function *buffer_ready_; Buffer_Get_Access_Flags_Function *buffer_get_access_flags_; @@ -596,14 +634,16 @@ Panel_Get_Max_Function *panel_get_max_; Panel_Get_Margin_Function *panel_get_margin_; View_Close_Function *view_close_; View_Get_Buffer_Region_Function *view_get_buffer_region_; -View_Get_Scroll_Vars_Function *view_get_scroll_vars_; +View_Get_Buffer_Scroll_Function *view_get_buffer_scroll_; +View_Get_Basic_Scroll_Function *view_get_basic_scroll_; View_Set_Active_Function *view_set_active_; View_Get_Setting_Function *view_get_setting_; View_Set_Setting_Function *view_set_setting_; View_Get_Managed_Scope_Function *view_get_managed_scope_; -View_Compute_Cursor_Function *view_compute_cursor_; +Buffer_Compute_Cursor_Function *buffer_compute_cursor_; View_Set_Cursor_Function *view_set_cursor_; -View_Set_Scroll_Function *view_set_scroll_; +View_Set_Buffer_Scroll_Function *view_set_buffer_scroll_; +View_Set_Basic_Scroll_Function *view_set_basic_scroll_; View_Set_Mark_Function *view_set_mark_; View_Set_Buffer_Function *view_set_buffer_; View_Post_Fade_Function *view_post_fade_; @@ -687,21 +727,17 @@ Draw_Clip_Push_Function *draw_clip_push_; Draw_Clip_Pop_Function *draw_clip_pop_; Draw_Coordinate_Center_Push_Function *draw_coordinate_center_push_; Draw_Coordinate_Center_Pop_Function *draw_coordinate_center_pop_; +Text_Layout_Create_Function *text_layout_create_; Text_Layout_Get_Buffer_Function *text_layout_get_buffer_; -Text_Layout_Buffer_Point_To_Layout_Point_Function *text_layout_buffer_point_to_layout_point_; -Text_Layout_Layout_Point_To_Buffer_Point_Function *text_layout_layout_point_to_buffer_point_; -Text_Layout_Get_On_Screen_Range_Function *text_layout_get_on_screen_range_; -Text_Layout_On_Screen_Function *text_layout_on_screen_; +Text_Layout_Get_Visible_Range_Function *text_layout_get_visible_range_; Text_Layout_Line_On_Screen_Function *text_layout_line_on_screen_; Text_Layout_Character_On_Screen_Function *text_layout_character_on_screen_; Paint_Text_Color_Function *paint_text_color_; Text_Layout_Free_Function *text_layout_free_; -Compute_Render_Layout_Function *compute_render_layout_; -Draw_Render_Layout_Function *draw_render_layout_; +Draw_Text_Layout_Function *draw_text_layout_; Open_Color_Picker_Function *open_color_picker_; Animate_In_N_Milliseconds_Function *animate_in_n_milliseconds_; Buffer_Find_All_Matches_Function *buffer_find_all_matches_; -Get_View_Visible_Range_Function *get_view_visible_range_; #endif void *memory; int32_t memory_size; @@ -734,7 +770,18 @@ app_links->buffer_replace_range_ = Buffer_Replace_Range;\ app_links->buffer_batch_edit_ = Buffer_Batch_Edit;\ app_links->buffer_seek_string_ = Buffer_Seek_String;\ app_links->buffer_seek_character_class_ = Buffer_Seek_Character_Class;\ -app_links->buffer_compute_cursor_ = Buffer_Compute_Cursor;\ +app_links->buffer_line_y_difference_ = Buffer_Line_Y_Difference;\ +app_links->buffer_line_shift_y_ = Buffer_Line_Shift_Y;\ +app_links->buffer_pos_at_relative_xy_ = Buffer_Pos_At_Relative_XY;\ +app_links->buffer_relative_xy_of_pos_ = Buffer_Relative_XY_Of_Pos;\ +app_links->buffer_relative_character_from_pos_ = Buffer_Relative_Character_From_Pos;\ +app_links->buffer_pos_from_relative_character_ = Buffer_Pos_From_Relative_Character;\ +app_links->view_line_y_difference_ = View_Line_Y_Difference;\ +app_links->view_line_shift_y_ = View_Line_Shift_Y;\ +app_links->view_pos_at_relative_xy_ = View_Pos_At_Relative_XY;\ +app_links->view_relative_xy_of_pos_ = View_Relative_XY_Of_Pos;\ +app_links->view_relative_character_from_pos_ = View_Relative_Character_From_Pos;\ +app_links->view_pos_from_relative_character_ = View_Pos_From_Relative_Character;\ app_links->buffer_exists_ = Buffer_Exists;\ app_links->buffer_ready_ = Buffer_Ready;\ app_links->buffer_get_access_flags_ = Buffer_Get_Access_Flags;\ @@ -780,14 +827,16 @@ app_links->panel_get_max_ = Panel_Get_Max;\ app_links->panel_get_margin_ = Panel_Get_Margin;\ app_links->view_close_ = View_Close;\ app_links->view_get_buffer_region_ = View_Get_Buffer_Region;\ -app_links->view_get_scroll_vars_ = View_Get_Scroll_Vars;\ +app_links->view_get_buffer_scroll_ = View_Get_Buffer_Scroll;\ +app_links->view_get_basic_scroll_ = View_Get_Basic_Scroll;\ app_links->view_set_active_ = View_Set_Active;\ app_links->view_get_setting_ = View_Get_Setting;\ app_links->view_set_setting_ = View_Set_Setting;\ app_links->view_get_managed_scope_ = View_Get_Managed_Scope;\ -app_links->view_compute_cursor_ = View_Compute_Cursor;\ +app_links->buffer_compute_cursor_ = Buffer_Compute_Cursor;\ app_links->view_set_cursor_ = View_Set_Cursor;\ -app_links->view_set_scroll_ = View_Set_Scroll;\ +app_links->view_set_buffer_scroll_ = View_Set_Buffer_Scroll;\ +app_links->view_set_basic_scroll_ = View_Set_Basic_Scroll;\ app_links->view_set_mark_ = View_Set_Mark;\ app_links->view_set_buffer_ = View_Set_Buffer;\ app_links->view_post_fade_ = View_Post_Fade;\ @@ -871,21 +920,17 @@ app_links->draw_clip_push_ = Draw_Clip_Push;\ app_links->draw_clip_pop_ = Draw_Clip_Pop;\ app_links->draw_coordinate_center_push_ = Draw_Coordinate_Center_Push;\ app_links->draw_coordinate_center_pop_ = Draw_Coordinate_Center_Pop;\ +app_links->text_layout_create_ = Text_Layout_Create;\ app_links->text_layout_get_buffer_ = Text_Layout_Get_Buffer;\ -app_links->text_layout_buffer_point_to_layout_point_ = Text_Layout_Buffer_Point_To_Layout_Point;\ -app_links->text_layout_layout_point_to_buffer_point_ = Text_Layout_Layout_Point_To_Buffer_Point;\ -app_links->text_layout_get_on_screen_range_ = Text_Layout_Get_On_Screen_Range;\ -app_links->text_layout_on_screen_ = Text_Layout_On_Screen;\ +app_links->text_layout_get_visible_range_ = Text_Layout_Get_Visible_Range;\ app_links->text_layout_line_on_screen_ = Text_Layout_Line_On_Screen;\ app_links->text_layout_character_on_screen_ = Text_Layout_Character_On_Screen;\ app_links->paint_text_color_ = Paint_Text_Color;\ app_links->text_layout_free_ = Text_Layout_Free;\ -app_links->compute_render_layout_ = Compute_Render_Layout;\ -app_links->draw_render_layout_ = Draw_Render_Layout;\ +app_links->draw_text_layout_ = Draw_Text_Layout;\ app_links->open_color_picker_ = Open_Color_Picker;\ app_links->animate_in_n_milliseconds_ = Animate_In_N_Milliseconds;\ -app_links->buffer_find_all_matches_ = Buffer_Find_All_Matches;\ -app_links->get_view_visible_range_ = Get_View_Visible_Range;} while(false) +app_links->buffer_find_all_matches_ = Buffer_Find_All_Matches;} while(false) #if defined(ALLOW_DEP_4CODER) static b32 global_set_setting(Application_Links *app, Global_Setting_ID setting, i32 value){return(app->global_set_setting(app, setting, value));} static b32 global_set_mapping(Application_Links *app, void *data, i32 size){return(app->global_set_mapping(app, data, size));} @@ -907,10 +952,21 @@ static Buffer_ID get_buffer_by_name(Application_Links *app, String_Const_u8 name static Buffer_ID get_buffer_by_file_name(Application_Links *app, String_Const_u8 file_name, Access_Flag access){return(app->get_buffer_by_file_name(app, file_name, access));} static b32 buffer_read_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, char *out){return(app->buffer_read_range(app, buffer_id, range, out));} static b32 buffer_replace_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string){return(app->buffer_replace_range(app, buffer_id, range, string));} -static b32 buffer_batch_edit(Application_Links *app, Buffer_ID buffer_id, char *str, Buffer_Edit *edits, i32 edit_count){return(app->buffer_batch_edit(app, buffer_id, str, edits, edit_count));} +static b32 buffer_batch_edit(Application_Links *app, Buffer_ID buffer_id, Batch_Edit *batch){return(app->buffer_batch_edit(app, buffer_id, batch));} static String_Match buffer_seek_string(Application_Links *app, Buffer_ID buffer, String_Const_u8 needle, Scan_Direction direction, i64 start_pos){return(app->buffer_seek_string(app, buffer, needle, direction, start_pos));} static String_Match buffer_seek_character_class(Application_Links *app, Buffer_ID buffer, Character_Predicate *predicate, Scan_Direction direction, i64 start_pos){return(app->buffer_seek_character_class(app, buffer, predicate, direction, start_pos));} -static Partial_Cursor buffer_compute_cursor(Application_Links *app, Buffer_ID buffer_id, Buffer_Seek seek){return(app->buffer_compute_cursor(app, buffer_id, seek));} +static f32 buffer_line_y_difference(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line_a, i64 line_b){return(app->buffer_line_y_difference(app, buffer_id, width, face_id, line_a, line_b));} +static Line_Shift_Vertical buffer_line_shift_y(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line, f32 y_shift){return(app->buffer_line_shift_y(app, buffer_id, width, face_id, line, y_shift));} +static i64 buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy){return(app->buffer_pos_at_relative_xy(app, buffer_id, width, face_id, base_line, relative_xy));} +static Vec2_f32 buffer_relative_xy_of_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){return(app->buffer_relative_xy_of_pos(app, buffer_id, width, face_id, base_line, pos));} +static i64 buffer_relative_character_from_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){return(app->buffer_relative_character_from_pos(app, buffer_id, width, face_id, base_line, pos));} +static i64 buffer_pos_from_relative_character(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 relative_character){return(app->buffer_pos_from_relative_character(app, buffer_id, width, face_id, base_line, relative_character));} +static f32 view_line_y_difference(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b){return(app->view_line_y_difference(app, view_id, line_a, line_b));} +static Line_Shift_Vertical view_line_shift_y(Application_Links *app, View_ID view_id, i64 line, f32 y_shift){return(app->view_line_shift_y(app, view_id, line, y_shift));} +static i64 view_pos_at_relative_xy(Application_Links *app, View_ID view_id, i64 base_line, Vec2_f32 relative_xy){return(app->view_pos_at_relative_xy(app, view_id, base_line, relative_xy));} +static Vec2_f32 view_relative_xy_of_pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){return(app->view_relative_xy_of_pos(app, view_id, base_line, pos));} +static i64 view_relative_character_from_pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){return(app->view_relative_character_from_pos(app, view_id, base_line, pos));} +static i64 view_pos_from_relative_character(Application_Links *app, View_ID view_id, i64 base_line, i64 character){return(app->view_pos_from_relative_character(app, view_id, base_line, character));} static b32 buffer_exists(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_exists(app, buffer_id));} static b32 buffer_ready(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_ready(app, buffer_id));} static Access_Flag buffer_get_access_flags(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_get_access_flags(app, buffer_id));} @@ -956,14 +1012,16 @@ static Panel_ID panel_get_max(Application_Links *app, Panel_ID panel_id){return( static Rect_i32 panel_get_margin(Application_Links *app, Panel_ID panel_id){return(app->panel_get_margin(app, panel_id));} static b32 view_close(Application_Links *app, View_ID view_id){return(app->view_close(app, view_id));} static Rect_f32 view_get_buffer_region(Application_Links *app, View_ID view_id){return(app->view_get_buffer_region(app, view_id));} -static GUI_Scroll_Vars view_get_scroll_vars(Application_Links *app, View_ID view_id){return(app->view_get_scroll_vars(app, view_id));} +static Buffer_Scroll view_get_buffer_scroll(Application_Links *app, View_ID view_id){return(app->view_get_buffer_scroll(app, view_id));} +static Basic_Scroll view_get_basic_scroll(Application_Links *app, View_ID view_id){return(app->view_get_basic_scroll(app, view_id));} static b32 view_set_active(Application_Links *app, View_ID view_id){return(app->view_set_active(app, view_id));} static b32 view_get_setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 *value_out){return(app->view_get_setting(app, view_id, setting, value_out));} static b32 view_set_setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 value){return(app->view_set_setting(app, view_id, setting, value));} static Managed_Scope view_get_managed_scope(Application_Links *app, View_ID view_id){return(app->view_get_managed_scope(app, view_id));} -static Full_Cursor view_compute_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek){return(app->view_compute_cursor(app, view_id, seek));} +static Buffer_Cursor buffer_compute_cursor(Application_Links *app, Buffer_ID buffer, Buffer_Seek seek){return(app->buffer_compute_cursor(app, buffer, seek));} static b32 view_set_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek, b32 set_preferred_x){return(app->view_set_cursor(app, view_id, seek, set_preferred_x));} -static b32 view_set_scroll(Application_Links *app, View_ID view_id, GUI_Scroll_Vars scroll){return(app->view_set_scroll(app, view_id, scroll));} +static b32 view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll){return(app->view_set_buffer_scroll(app, view_id, scroll));} +static b32 view_set_basic_scroll(Application_Links *app, View_ID view_id, Basic_Scroll scroll){return(app->view_set_basic_scroll(app, view_id, scroll));} static b32 view_set_mark(Application_Links *app, View_ID view_id, Buffer_Seek seek){return(app->view_set_mark(app, view_id, seek));} static b32 view_set_buffer(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags){return(app->view_set_buffer(app, view_id, buffer_id, flags));} static b32 view_post_fade(Application_Links *app, View_ID view_id, f32 seconds, Range_i64 range, int_color color){return(app->view_post_fade(app, view_id, seconds, range, color));} @@ -1047,21 +1105,17 @@ static void draw_clip_push(Application_Links *app, Rect_f32 clip_box){(app->draw static f32_Rect draw_clip_pop(Application_Links *app){return(app->draw_clip_pop(app));} static void draw_coordinate_center_push(Application_Links *app, Vec2 point){(app->draw_coordinate_center_push(app, point));} static Vec2 draw_coordinate_center_pop(Application_Links *app){return(app->draw_coordinate_center_pop(app));} +static Text_Layout_ID text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point){return(app->text_layout_create(app, buffer_id, rect, buffer_point));} static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){return(app->text_layout_get_buffer(app, text_layout_id, buffer_id_out));} -static b32 text_layout_buffer_point_to_layout_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out){return(app->text_layout_buffer_point_to_layout_point(app, text_layout_id, buffer_relative_p, p_out));} -static b32 text_layout_layout_point_to_buffer_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out){return(app->text_layout_layout_point_to_buffer_point(app, text_layout_id, layout_relative_p, p_out));} -static Range_i64 text_layout_get_on_screen_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_on_screen_range(app, text_layout_id));} -static Rect_f32 text_layout_on_screen(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_on_screen(app, text_layout_id));} +static Interval_i64 text_layout_get_visible_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_visible_range(app, text_layout_id));} static Rect_f32 text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){return(app->text_layout_line_on_screen(app, layout_id, line_number));} static Rect_f32 text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){return(app->text_layout_character_on_screen(app, layout_id, pos));} -static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){(app->paint_text_color(app, layout_id, range, color));} +static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range, int_color color){(app->paint_text_color(app, layout_id, range, color));} static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free(app, text_layout_id));} -static Text_Layout_ID compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last){return(app->compute_render_layout(app, view_id, buffer_id, screen_p, layout_dim, buffer_point, one_past_last));} -static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout(app, view_id));} +static void draw_text_layout(Application_Links *app, Text_Layout_ID layout_id){(app->draw_text_layout(app, layout_id));} static void open_color_picker(Application_Links *app, Color_Picker *picker){(app->open_color_picker(app, picker));} static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds(app, n));} static String_Match_List buffer_find_all_matches(Application_Links *app, Arena *arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction){return(app->buffer_find_all_matches(app, arena, buffer, string_id, range, needle, predicate, direction));} -static Range get_view_visible_range(Application_Links *app, View_ID view_id){return(app->get_view_visible_range(app, view_id));} #else static b32 global_set_setting(Application_Links *app, Global_Setting_ID setting, i32 value){return(app->global_set_setting_(app, setting, value));} static b32 global_set_mapping(Application_Links *app, void *data, i32 size){return(app->global_set_mapping_(app, data, size));} @@ -1083,10 +1137,21 @@ static Buffer_ID get_buffer_by_name(Application_Links *app, String_Const_u8 name static Buffer_ID get_buffer_by_file_name(Application_Links *app, String_Const_u8 file_name, Access_Flag access){return(app->get_buffer_by_file_name_(app, file_name, access));} static b32 buffer_read_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, char *out){return(app->buffer_read_range_(app, buffer_id, range, out));} static b32 buffer_replace_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string){return(app->buffer_replace_range_(app, buffer_id, range, string));} -static b32 buffer_batch_edit(Application_Links *app, Buffer_ID buffer_id, char *str, Buffer_Edit *edits, i32 edit_count){return(app->buffer_batch_edit_(app, buffer_id, str, edits, edit_count));} +static b32 buffer_batch_edit(Application_Links *app, Buffer_ID buffer_id, Batch_Edit *batch){return(app->buffer_batch_edit_(app, buffer_id, batch));} static String_Match buffer_seek_string(Application_Links *app, Buffer_ID buffer, String_Const_u8 needle, Scan_Direction direction, i64 start_pos){return(app->buffer_seek_string_(app, buffer, needle, direction, start_pos));} static String_Match buffer_seek_character_class(Application_Links *app, Buffer_ID buffer, Character_Predicate *predicate, Scan_Direction direction, i64 start_pos){return(app->buffer_seek_character_class_(app, buffer, predicate, direction, start_pos));} -static Partial_Cursor buffer_compute_cursor(Application_Links *app, Buffer_ID buffer_id, Buffer_Seek seek){return(app->buffer_compute_cursor_(app, buffer_id, seek));} +static f32 buffer_line_y_difference(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line_a, i64 line_b){return(app->buffer_line_y_difference_(app, buffer_id, width, face_id, line_a, line_b));} +static Line_Shift_Vertical buffer_line_shift_y(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line, f32 y_shift){return(app->buffer_line_shift_y_(app, buffer_id, width, face_id, line, y_shift));} +static i64 buffer_pos_at_relative_xy(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy){return(app->buffer_pos_at_relative_xy_(app, buffer_id, width, face_id, base_line, relative_xy));} +static Vec2_f32 buffer_relative_xy_of_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){return(app->buffer_relative_xy_of_pos_(app, buffer_id, width, face_id, base_line, pos));} +static i64 buffer_relative_character_from_pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos){return(app->buffer_relative_character_from_pos_(app, buffer_id, width, face_id, base_line, pos));} +static i64 buffer_pos_from_relative_character(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 relative_character){return(app->buffer_pos_from_relative_character_(app, buffer_id, width, face_id, base_line, relative_character));} +static f32 view_line_y_difference(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b){return(app->view_line_y_difference_(app, view_id, line_a, line_b));} +static Line_Shift_Vertical view_line_shift_y(Application_Links *app, View_ID view_id, i64 line, f32 y_shift){return(app->view_line_shift_y_(app, view_id, line, y_shift));} +static i64 view_pos_at_relative_xy(Application_Links *app, View_ID view_id, i64 base_line, Vec2_f32 relative_xy){return(app->view_pos_at_relative_xy_(app, view_id, base_line, relative_xy));} +static Vec2_f32 view_relative_xy_of_pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){return(app->view_relative_xy_of_pos_(app, view_id, base_line, pos));} +static i64 view_relative_character_from_pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){return(app->view_relative_character_from_pos_(app, view_id, base_line, pos));} +static i64 view_pos_from_relative_character(Application_Links *app, View_ID view_id, i64 base_line, i64 character){return(app->view_pos_from_relative_character_(app, view_id, base_line, character));} static b32 buffer_exists(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_exists_(app, buffer_id));} static b32 buffer_ready(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_ready_(app, buffer_id));} static Access_Flag buffer_get_access_flags(Application_Links *app, Buffer_ID buffer_id){return(app->buffer_get_access_flags_(app, buffer_id));} @@ -1132,14 +1197,16 @@ static Panel_ID panel_get_max(Application_Links *app, Panel_ID panel_id){return( static Rect_i32 panel_get_margin(Application_Links *app, Panel_ID panel_id){return(app->panel_get_margin_(app, panel_id));} static b32 view_close(Application_Links *app, View_ID view_id){return(app->view_close_(app, view_id));} static Rect_f32 view_get_buffer_region(Application_Links *app, View_ID view_id){return(app->view_get_buffer_region_(app, view_id));} -static GUI_Scroll_Vars view_get_scroll_vars(Application_Links *app, View_ID view_id){return(app->view_get_scroll_vars_(app, view_id));} +static Buffer_Scroll view_get_buffer_scroll(Application_Links *app, View_ID view_id){return(app->view_get_buffer_scroll_(app, view_id));} +static Basic_Scroll view_get_basic_scroll(Application_Links *app, View_ID view_id){return(app->view_get_basic_scroll_(app, view_id));} static b32 view_set_active(Application_Links *app, View_ID view_id){return(app->view_set_active_(app, view_id));} static b32 view_get_setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 *value_out){return(app->view_get_setting_(app, view_id, setting, value_out));} static b32 view_set_setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 value){return(app->view_set_setting_(app, view_id, setting, value));} static Managed_Scope view_get_managed_scope(Application_Links *app, View_ID view_id){return(app->view_get_managed_scope_(app, view_id));} -static Full_Cursor view_compute_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek){return(app->view_compute_cursor_(app, view_id, seek));} +static Buffer_Cursor buffer_compute_cursor(Application_Links *app, Buffer_ID buffer, Buffer_Seek seek){return(app->buffer_compute_cursor_(app, buffer, seek));} static b32 view_set_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek, b32 set_preferred_x){return(app->view_set_cursor_(app, view_id, seek, set_preferred_x));} -static b32 view_set_scroll(Application_Links *app, View_ID view_id, GUI_Scroll_Vars scroll){return(app->view_set_scroll_(app, view_id, scroll));} +static b32 view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll){return(app->view_set_buffer_scroll_(app, view_id, scroll));} +static b32 view_set_basic_scroll(Application_Links *app, View_ID view_id, Basic_Scroll scroll){return(app->view_set_basic_scroll_(app, view_id, scroll));} static b32 view_set_mark(Application_Links *app, View_ID view_id, Buffer_Seek seek){return(app->view_set_mark_(app, view_id, seek));} static b32 view_set_buffer(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags){return(app->view_set_buffer_(app, view_id, buffer_id, flags));} static b32 view_post_fade(Application_Links *app, View_ID view_id, f32 seconds, Range_i64 range, int_color color){return(app->view_post_fade_(app, view_id, seconds, range, color));} @@ -1223,19 +1290,15 @@ static void draw_clip_push(Application_Links *app, Rect_f32 clip_box){(app->draw static f32_Rect draw_clip_pop(Application_Links *app){return(app->draw_clip_pop_(app));} static void draw_coordinate_center_push(Application_Links *app, Vec2 point){(app->draw_coordinate_center_push_(app, point));} static Vec2 draw_coordinate_center_pop(Application_Links *app){return(app->draw_coordinate_center_pop_(app));} +static Text_Layout_ID text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point){return(app->text_layout_create_(app, buffer_id, rect, buffer_point));} static b32 text_layout_get_buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){return(app->text_layout_get_buffer_(app, text_layout_id, buffer_id_out));} -static b32 text_layout_buffer_point_to_layout_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out){return(app->text_layout_buffer_point_to_layout_point_(app, text_layout_id, buffer_relative_p, p_out));} -static b32 text_layout_layout_point_to_buffer_point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out){return(app->text_layout_layout_point_to_buffer_point_(app, text_layout_id, layout_relative_p, p_out));} -static Range_i64 text_layout_get_on_screen_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_on_screen_range_(app, text_layout_id));} -static Rect_f32 text_layout_on_screen(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_on_screen_(app, text_layout_id));} +static Interval_i64 text_layout_get_visible_range(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_get_visible_range_(app, text_layout_id));} static Rect_f32 text_layout_line_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){return(app->text_layout_line_on_screen_(app, layout_id, line_number));} static Rect_f32 text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){return(app->text_layout_character_on_screen_(app, layout_id, pos));} -static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){(app->paint_text_color_(app, layout_id, range, color));} +static void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range, int_color color){(app->paint_text_color_(app, layout_id, range, color));} static b32 text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){return(app->text_layout_free_(app, text_layout_id));} -static Text_Layout_ID compute_render_layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last){return(app->compute_render_layout_(app, view_id, buffer_id, screen_p, layout_dim, buffer_point, one_past_last));} -static void draw_render_layout(Application_Links *app, View_ID view_id){(app->draw_render_layout_(app, view_id));} +static void draw_text_layout(Application_Links *app, Text_Layout_ID layout_id){(app->draw_text_layout_(app, layout_id));} static void open_color_picker(Application_Links *app, Color_Picker *picker){(app->open_color_picker_(app, picker));} static void animate_in_n_milliseconds(Application_Links *app, u32 n){(app->animate_in_n_milliseconds_(app, n));} static String_Match_List buffer_find_all_matches(Application_Links *app, Arena *arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate *predicate, Scan_Direction direction){return(app->buffer_find_all_matches_(app, arena, buffer, string_id, range, needle, predicate, direction));} -static Range get_view_visible_range(Application_Links *app, View_ID view_id){return(app->get_view_visible_range_(app, view_id));} #endif diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index 79a85a0a..f3237304 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -2,7 +2,7 @@ #define command_id(c) (fcoder_metacmd_ID_##c) #define command_metadata(c) (&fcoder_metacmd_table[command_id(c)]) #define command_metadata_by_id(id) (&fcoder_metacmd_table[id]) -#define command_one_past_last_id 235 +#define command_one_past_last_id 233 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -240,8 +240,6 @@ CUSTOM_COMMAND_SIG(miblo_increment_time_stamp); CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp); CUSTOM_COMMAND_SIG(miblo_increment_time_stamp_minute); CUSTOM_COMMAND_SIG(miblo_decrement_time_stamp_minute); -CUSTOM_COMMAND_SIG(kill_rect); -CUSTOM_COMMAND_SIG(multi_line_edit); CUSTOM_COMMAND_SIG(rename_parameter); CUSTOM_COMMAND_SIG(write_explicit_enum_values); #endif @@ -255,14 +253,14 @@ char *source_name; int32_t source_name_len; int32_t line_number; }; -static Command_Metadata fcoder_metacmd_table[235] = { -{ PROC_LINKS(write_explicit_enum_flags, 0), "write_explicit_enum_flags", 25, "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in to give each a unique power of 2 value, starting from 1. Existing values are overwritten.", 194, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 699 }, -{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\4coder_seek.cpp", 27, 28 }, -{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\4coder_seek.cpp", 27, 34 }, -{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\4coder_seek.cpp", 27, 40 }, -{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\4coder_seek.cpp", 27, 46 }, -{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\4coder_seek.cpp", 27, 52 }, -{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\4coder_seek.cpp", 27, 60 }, +static Command_Metadata fcoder_metacmd_table[233] = { +{ PROC_LINKS(write_explicit_enum_flags, 0), "write_explicit_enum_flags", 25, "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in to give each a unique power of 2 value, starting from 1. Existing values are overwritten.", 194, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 504 }, +{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\4coder_seek.cpp", 27, 29 }, +{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\4coder_seek.cpp", 27, 35 }, +{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\4coder_seek.cpp", 27, 41 }, +{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\4coder_seek.cpp", 27, 47 }, +{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\4coder_seek.cpp", 27, 53 }, +{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\4coder_seek.cpp", 27, 61 }, { PROC_LINKS(change_active_panel, 0), "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 201 }, { PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 211 }, { PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 221 }, @@ -277,105 +275,105 @@ static Command_Metadata fcoder_metacmd_table[235] = { { PROC_LINKS(toggle_paren_matching_helper, 0), "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 334 }, { PROC_LINKS(toggle_fullscreen, 0), "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 340 }, { PROC_LINKS(remap_interactive, 0), "remap_interactive", 17, "Switch to a named key binding map.", 34, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 348 }, -{ PROC_LINKS(write_character, 0), "write_character", 15, "Inserts whatever character was used to trigger this command.", 60, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 66 }, -{ PROC_LINKS(write_underscore, 0), "write_underscore", 16, "Inserts an underscore.", 22, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 75 }, -{ PROC_LINKS(delete_char, 0), "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 82 }, -{ PROC_LINKS(backspace_char, 0), "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 99 }, -{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 118 }, -{ PROC_LINKS(cursor_mark_swap, 0), "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 127 }, -{ PROC_LINKS(delete_range, 0), "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 137 }, -{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 157 }, -{ PROC_LINKS(delete_alpha_numeric_boundary, 0), "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 165 }, -{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 185 }, -{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 193 }, -{ PROC_LINKS(center_view, 0), "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 206 }, -{ PROC_LINKS(left_adjust_view, 0), "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 221 }, -{ PROC_LINKS(click_set_cursor_and_mark, 0), "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 244 }, -{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 259 }, -{ PROC_LINKS(click_set_cursor_if_lbutton, 0), "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 273 }, -{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 289 }, -{ PROC_LINKS(mouse_wheel_scroll, 0), "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 303 }, -{ PROC_LINKS(move_up, 0), "move_up", 7, "Moves the cursor up one line.", 29, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 370 }, -{ PROC_LINKS(move_down, 0), "move_down", 9, "Moves the cursor down one line.", 31, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 376 }, -{ PROC_LINKS(move_up_10, 0), "move_up_10", 10, "Moves the cursor up ten lines.", 30, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 382 }, -{ PROC_LINKS(move_down_10, 0), "move_down_10", 12, "Moves the cursor down ten lines.", 32, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 388 }, -{ PROC_LINKS(move_down_textual, 0), "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 394 }, -{ PROC_LINKS(page_up, 0), "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 404 }, -{ PROC_LINKS(page_down, 0), "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 412 }, -{ PROC_LINKS(move_up_to_blank_line, 0), "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 441 }, -{ PROC_LINKS(move_down_to_blank_line, 0), "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 447 }, -{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 453 }, -{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 459 }, -{ PROC_LINKS(move_up_to_blank_line_end, 0), "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 465 }, -{ PROC_LINKS(move_down_to_blank_line_end, 0), "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 471 }, -{ PROC_LINKS(move_left, 0), "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 482 }, -{ PROC_LINKS(move_right, 0), "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 493 }, -{ PROC_LINKS(move_right_whitespace_boundary, 0), "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 514 }, -{ PROC_LINKS(move_left_whitespace_boundary, 0), "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 522 }, -{ PROC_LINKS(move_right_token_boundary, 0), "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 530 }, -{ PROC_LINKS(move_left_token_boundary, 0), "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 538 }, -{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 546 }, -{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 554 }, -{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 562 }, -{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 570 }, -{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 578 }, -{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 586 }, -{ PROC_LINKS(select_all, 0), "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 607 }, -{ PROC_LINKS(to_uppercase, 0), "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 620 }, -{ PROC_LINKS(to_lowercase, 0), "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 633 }, -{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 646 }, -{ PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 684 }, -{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 692 }, -{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 701 }, -{ PROC_LINKS(hide_scrollbar, 0), "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 708 }, -{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 715 }, -{ PROC_LINKS(hide_filebar, 0), "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 722 }, -{ PROC_LINKS(toggle_filebar, 0), "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 729 }, -{ PROC_LINKS(toggle_line_wrap, 0), "toggle_line_wrap", 16, "Toggles the current buffer's line wrapping status.", 50, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 738 }, -{ PROC_LINKS(toggle_fps_meter, 0), "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 748 }, -{ PROC_LINKS(increase_line_wrap, 0), "increase_line_wrap", 18, "Increases the current buffer's width for line wrapping.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 754 }, -{ PROC_LINKS(decrease_line_wrap, 0), "decrease_line_wrap", 18, "Decrases the current buffer's width for line wrapping.", 54, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 764 }, -{ PROC_LINKS(increase_face_size, 0), "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 774 }, -{ PROC_LINKS(decrease_face_size, 0), "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 785 }, -{ PROC_LINKS(mouse_wheel_change_face_size, 0), "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 796 }, -{ PROC_LINKS(toggle_virtual_whitespace, 0), "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 813 }, -{ PROC_LINKS(toggle_show_whitespace, 0), "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 823 }, -{ PROC_LINKS(toggle_line_numbers, 0), "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 832 }, -{ PROC_LINKS(eol_dosify, 0), "eol_dosify", 10, "Puts the buffer in DOS line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 838 }, -{ PROC_LINKS(eol_nixify, 0), "eol_nixify", 10, "Puts the buffer in NIX line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 846 }, -{ PROC_LINKS(exit_4coder, 0), "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 854 }, -{ PROC_LINKS(goto_line, 0), "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 862 }, -{ PROC_LINKS(search, 0), "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1073 }, -{ PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1079 }, -{ PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1085 }, -{ PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1096 }, -{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1147 }, -{ PROC_LINKS(replace_in_buffer, 0), "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1156 }, -{ PROC_LINKS(replace_in_all_buffers, 0), "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1165 }, -{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1253 }, -{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1273 }, -{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1289 }, -{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1324 }, -{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1349 }, -{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1387 }, -{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1422 }, -{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1462 }, -{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1495 }, -{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1501 }, -{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1507 }, -{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1521 }, -{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1586 }, -{ PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1618 }, -{ PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1631 }, -{ PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1643 }, -{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1677 }, -{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1685 }, -{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1697 }, -{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1755 }, -{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1768 }, -{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1782 }, -{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1856 }, -{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1959 }, +{ PROC_LINKS(write_character, 0), "write_character", 15, "Inserts whatever character was used to trigger this command.", 60, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 57 }, +{ PROC_LINKS(write_underscore, 0), "write_underscore", 16, "Inserts an underscore.", 22, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 66 }, +{ PROC_LINKS(delete_char, 0), "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 73 }, +{ PROC_LINKS(backspace_char, 0), "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 90 }, +{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 109 }, +{ PROC_LINKS(cursor_mark_swap, 0), "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 118 }, +{ PROC_LINKS(delete_range, 0), "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 128 }, +{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 148 }, +{ PROC_LINKS(delete_alpha_numeric_boundary, 0), "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 156 }, +{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 176 }, +{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 184 }, +{ PROC_LINKS(center_view, 0), "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 197 }, +{ PROC_LINKS(left_adjust_view, 0), "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 211 }, +{ PROC_LINKS(click_set_cursor_and_mark, 0), "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 223 }, +{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 235 }, +{ PROC_LINKS(click_set_cursor_if_lbutton, 0), "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 247 }, +{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 261 }, +{ PROC_LINKS(mouse_wheel_scroll, 0), "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 273 }, +{ PROC_LINKS(move_up, 0), "move_up", 7, "Moves the cursor up one line.", 29, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 335 }, +{ PROC_LINKS(move_down, 0), "move_down", 9, "Moves the cursor down one line.", 31, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 341 }, +{ PROC_LINKS(move_up_10, 0), "move_up_10", 10, "Moves the cursor up ten lines.", 30, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 347 }, +{ PROC_LINKS(move_down_10, 0), "move_down_10", 12, "Moves the cursor down ten lines.", 32, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 353 }, +{ PROC_LINKS(move_down_textual, 0), "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 359 }, +{ PROC_LINKS(page_up, 0), "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 369 }, +{ PROC_LINKS(page_down, 0), "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 377 }, +{ PROC_LINKS(move_up_to_blank_line, 0), "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 406 }, +{ PROC_LINKS(move_down_to_blank_line, 0), "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 412 }, +{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 418 }, +{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 424 }, +{ PROC_LINKS(move_up_to_blank_line_end, 0), "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 430 }, +{ PROC_LINKS(move_down_to_blank_line_end, 0), "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 436 }, +{ PROC_LINKS(move_left, 0), "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 447 }, +{ PROC_LINKS(move_right, 0), "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 459 }, +{ PROC_LINKS(move_right_whitespace_boundary, 0), "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 481 }, +{ PROC_LINKS(move_left_whitespace_boundary, 0), "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 489 }, +{ PROC_LINKS(move_right_token_boundary, 0), "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 497 }, +{ PROC_LINKS(move_left_token_boundary, 0), "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 505 }, +{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 513 }, +{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 521 }, +{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 529 }, +{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 537 }, +{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 545 }, +{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 553 }, +{ PROC_LINKS(select_all, 0), "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 574 }, +{ PROC_LINKS(to_uppercase, 0), "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 587 }, +{ PROC_LINKS(to_lowercase, 0), "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 600 }, +{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 613 }, +{ PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 647 }, +{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 655 }, +{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 664 }, +{ PROC_LINKS(hide_scrollbar, 0), "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 671 }, +{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 678 }, +{ PROC_LINKS(hide_filebar, 0), "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 685 }, +{ PROC_LINKS(toggle_filebar, 0), "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 692 }, +{ PROC_LINKS(toggle_line_wrap, 0), "toggle_line_wrap", 16, "Toggles the current buffer's line wrapping status.", 50, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 701 }, +{ PROC_LINKS(toggle_fps_meter, 0), "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 711 }, +{ PROC_LINKS(increase_line_wrap, 0), "increase_line_wrap", 18, "Increases the current buffer's width for line wrapping.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 717 }, +{ PROC_LINKS(decrease_line_wrap, 0), "decrease_line_wrap", 18, "Decrases the current buffer's width for line wrapping.", 54, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 727 }, +{ PROC_LINKS(increase_face_size, 0), "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 737 }, +{ PROC_LINKS(decrease_face_size, 0), "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 748 }, +{ PROC_LINKS(mouse_wheel_change_face_size, 0), "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 759 }, +{ PROC_LINKS(toggle_virtual_whitespace, 0), "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 776 }, +{ PROC_LINKS(toggle_show_whitespace, 0), "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 786 }, +{ PROC_LINKS(toggle_line_numbers, 0), "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 795 }, +{ PROC_LINKS(eol_dosify, 0), "eol_dosify", 10, "Puts the buffer in DOS line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 801 }, +{ PROC_LINKS(eol_nixify, 0), "eol_nixify", 10, "Puts the buffer in NIX line ending mode.", 40, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 809 }, +{ PROC_LINKS(exit_4coder, 0), "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 817 }, +{ PROC_LINKS(goto_line, 0), "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 825 }, +{ PROC_LINKS(search, 0), "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1036 }, +{ PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1042 }, +{ PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1048 }, +{ PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1059 }, +{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1110 }, +{ PROC_LINKS(replace_in_buffer, 0), "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1119 }, +{ PROC_LINKS(replace_in_all_buffers, 0), "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1128 }, +{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1216 }, +{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1236 }, +{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1252 }, +{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1287 }, +{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1312 }, +{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1350 }, +{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1385 }, +{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1425 }, +{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1458 }, +{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1464 }, +{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1470 }, +{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1484 }, +{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1549 }, +{ PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1581 }, +{ PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1594 }, +{ PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1606 }, +{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1642 }, +{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1650 }, +{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1662 }, +{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1720 }, +{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1733 }, +{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1747 }, +{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1821 }, +{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\4coder_base_commands.cpp", 36, 1924 }, { PROC_LINKS(lister__quit, 0), "lister__quit", 12, "A lister mode command that quits the list without executing any actions.", 72, "w:\\4ed\\code\\4coder_lists.cpp", 28, 8 }, { PROC_LINKS(lister__activate, 0), "lister__activate", 16, "A lister mode command that activates the list's action on the highlighted item.", 79, "w:\\4ed\\code\\4coder_lists.cpp", 28, 15 }, { PROC_LINKS(lister__write_character, 0), "lister__write_character", 23, "A lister mode command that dispatches to the lister's write character handler.", 78, "w:\\4ed\\code\\4coder_lists.cpp", 28, 30 }, @@ -399,21 +397,21 @@ static Command_Metadata fcoder_metacmd_table[235] = { { PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\4coder_lists.cpp", 28, 854 }, { PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\4coder_lists.cpp", 28, 887 }, { PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\4coder_lists.cpp", 28, 969 }, -{ PROC_LINKS(auto_tab_whole_file, 0), "auto_tab_whole_file", 19, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 546 }, -{ PROC_LINKS(auto_tab_line_at_cursor, 0), "auto_tab_line_at_cursor", 23, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 555 }, -{ PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 565 }, -{ PROC_LINKS(write_and_auto_tab, 0), "write_and_auto_tab", 18, "Inserts a character and auto-indents the line on which the cursor sits.", 71, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 575 }, -{ PROC_LINKS(list_all_locations, 0), "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\4coder_search.cpp", 29, 164 }, -{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\4coder_search.cpp", 29, 170 }, -{ PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\4coder_search.cpp", 29, 176 }, -{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\4coder_search.cpp", 29, 182 }, -{ PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 188 }, -{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 194 }, -{ PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 200 }, -{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 206 }, -{ PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "w:\\4ed\\code\\4coder_search.cpp", 29, 212 }, -{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "w:\\4ed\\code\\4coder_search.cpp", 29, 220 }, -{ PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\4coder_search.cpp", 29, 374 }, +{ PROC_LINKS(auto_tab_whole_file, 0), "auto_tab_whole_file", 19, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 530 }, +{ PROC_LINKS(auto_tab_line_at_cursor, 0), "auto_tab_line_at_cursor", 23, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 539 }, +{ PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 549 }, +{ PROC_LINKS(write_and_auto_tab, 0), "write_and_auto_tab", 18, "Inserts a character and auto-indents the line on which the cursor sits.", 71, "w:\\4ed\\code\\4coder_auto_indent.cpp", 34, 559 }, +{ PROC_LINKS(list_all_locations, 0), "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\4coder_search.cpp", 29, 166 }, +{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\4coder_search.cpp", 29, 172 }, +{ PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\4coder_search.cpp", 29, 178 }, +{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\4coder_search.cpp", 29, 184 }, +{ PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 190 }, +{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 196 }, +{ PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\4coder_search.cpp", 29, 202 }, +{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\4coder_search.cpp", 29, 208 }, +{ PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "w:\\4ed\\code\\4coder_search.cpp", 29, 214 }, +{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "w:\\4ed\\code\\4coder_search.cpp", 29, 222 }, +{ PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\4coder_search.cpp", 29, 376 }, { PROC_LINKS(goto_jump_at_cursor, 0), "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "w:\\4ed\\code\\4coder_jump_sticky.cpp", 34, 352 }, { PROC_LINKS(goto_jump_at_cursor_same_panel, 0), "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "w:\\4ed\\code\\4coder_jump_sticky.cpp", 34, 379 }, { PROC_LINKS(goto_next_jump, 0), "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "w:\\4ed\\code\\4coder_jump_sticky.cpp", 34, 468 }, @@ -459,12 +457,12 @@ static Command_Metadata fcoder_metacmd_table[235] = { { PROC_LINKS(list_all_functions_current_buffer_lister, 0), "list_all_functions_current_buffer_lister", 40, "Creates a lister of locations that look like function definitions and declarations in the buffer.", 97, "w:\\4ed\\code\\4coder_function_list.cpp", 36, 276 }, { PROC_LINKS(list_all_functions_all_buffers, 0), "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "w:\\4ed\\code\\4coder_function_list.cpp", 36, 288 }, { PROC_LINKS(list_all_functions_all_buffers_lister, 0), "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "w:\\4ed\\code\\4coder_function_list.cpp", 36, 294 }, -{ PROC_LINKS(select_surrounding_scope, 0), "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 337 }, -{ PROC_LINKS(select_next_scope_absolute, 0), "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 352 }, -{ PROC_LINKS(select_prev_scope_absolute, 0), "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 371 }, -{ PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 445 }, -{ PROC_LINKS(delete_current_scope, 0), "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 451 }, -{ PROC_LINKS(scope_absorb_down, 0), "scope_absorb_down", 17, "If a scope is currently selected, and a statement or block statement is present below the current scope, the statement is moved into the scope.", 143, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 670 }, +{ PROC_LINKS(select_surrounding_scope, 0), "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 341 }, +{ PROC_LINKS(select_next_scope_absolute, 0), "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 356 }, +{ PROC_LINKS(select_prev_scope_absolute, 0), "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 375 }, +{ PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 449 }, +{ PROC_LINKS(delete_current_scope, 0), "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 455 }, +{ PROC_LINKS(scope_absorb_down, 0), "scope_absorb_down", 17, "If a scope is currently selected, and a statement or block statement is present below the current scope, the statement is moved into the scope.", 143, "w:\\4ed\\code\\4coder_scope_commands.cpp", 37, 672 }, { PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 46 }, { PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 54 }, { PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\4coder_combined_write_commands.cpp", 46, 62 }, @@ -487,10 +485,8 @@ static Command_Metadata fcoder_metacmd_table[235] = { { PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\4coder_miblo_numbers.cpp", 36, 237 }, { PROC_LINKS(miblo_increment_time_stamp_minute, 0), "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\4coder_miblo_numbers.cpp", 36, 243 }, { PROC_LINKS(miblo_decrement_time_stamp_minute, 0), "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\4coder_miblo_numbers.cpp", 36, 249 }, -{ PROC_LINKS(kill_rect, 0), "kill_rect", 9, "Delete characters in a rectangular region. Range testing is done by unwrapped-xy coordinates.", 93, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 44 }, -{ PROC_LINKS(multi_line_edit, 0), "multi_line_edit", 15, "Begin multi-line mode. In multi-line mode characters are inserted at every line between the mark and cursor. All characters are inserted at the same character offset into the line. This mode uses line_char coordinates.", 221, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 125 }, -{ PROC_LINKS(rename_parameter, 0), "rename_parameter", 16, "If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.", 200, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 386 }, -{ PROC_LINKS(write_explicit_enum_values, 0), "write_explicit_enum_values", 26, "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in sequentially starting from zero. Existing values are overwritten.", 170, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 693 }, +{ PROC_LINKS(rename_parameter, 0), "rename_parameter", 16, "If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.", 200, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 189 }, +{ PROC_LINKS(write_explicit_enum_values, 0), "write_explicit_enum_values", 26, "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in sequentially starting from zero. Existing values are overwritten.", 170, "w:\\4ed\\code\\4coder_experiments.cpp", 34, 498 }, }; static int32_t fcoder_metacmd_ID_write_explicit_enum_flags = 0; static int32_t fcoder_metacmd_ID_seek_beginning_of_textual_line = 1; @@ -723,8 +719,6 @@ static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp = 227; static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp = 228; static int32_t fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 229; static int32_t fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 230; -static int32_t fcoder_metacmd_ID_kill_rect = 231; -static int32_t fcoder_metacmd_ID_multi_line_edit = 232; -static int32_t fcoder_metacmd_ID_rename_parameter = 233; -static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 234; +static int32_t fcoder_metacmd_ID_rename_parameter = 231; +static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 232; #endif diff --git a/4coder_helper.cpp b/4coder_helper.cpp index 942d9a64..c0df2432 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -117,7 +117,7 @@ set_hook(Bind_Helper *helper, i32 hook_id, Hook_Function *func){ } internal void -set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){ +set_scroll_rule(Bind_Helper *helper, Delta_Rule_Function *func){ Binding_Unit unit = {}; unit.type = unit_hook; unit.hook.hook_id = special_hook_scroll_rule; @@ -290,7 +290,7 @@ get_key_code(char *buffer){ internal Buffer_Seek seek_location(ID_Line_Column_Jump_Location location){ - return(seek_line_char(location.line, location.column)); + return(seek_line_col(location.line, location.column)); } internal Buffer_Seek @@ -300,7 +300,7 @@ seek_location(ID_Pos_Jump_Location location){ internal Buffer_Seek seek_location(Name_Line_Column_Location location){ - return(seek_line_char(location.line, location.column)); + return(seek_line_col(location.line, location.column)); } internal Buffer_Seek @@ -408,6 +408,46 @@ buffer_seek_character_class_change_0_1(Application_Links *app, Buffer_ID buffer, //////////////////////////////// +internal Buffer_Cursor +view_compute_cursor(Application_Links *app, View_ID view, Buffer_Seek seek){ + return(buffer_compute_cursor(app, view_get_buffer(app, view, AccessAll), seek)); +} + +internal i64 +view_pos_from_xy(Application_Links *app, View_ID view, Vec2_f32 p){ + Buffer_ID buffer = view_get_buffer(app, view, AccessProtected); + Rect_f32 region = view_get_buffer_region(app, view); + f32 width = rect_width(region); + Face_ID face_id = get_face_id(app, buffer); + Buffer_Scroll scroll_vars = view_get_buffer_scroll(app, view); + i64 line = scroll_vars.position.line_number; + p = (p - region.p0) + scroll_vars.position.pixel_shift; + return(buffer_pos_at_relative_xy(app, buffer, width, face_id, line, p)); +} + +internal Buffer_Point +view_move_buffer_point(Application_Links *app, View_ID view, Buffer_Point buffer_point, Vec2_f32 delta){ + delta += buffer_point.pixel_shift; + Line_Shift_Vertical shift = view_line_shift_y(app, view, buffer_point.line_number, delta.y); + buffer_point.line_number = shift.line; + buffer_point.pixel_shift = V2f32(delta.x, delta.y - shift.y_delta); + return(buffer_point); +} + +internal void +view_zero_scroll(Application_Links *app, View_ID view){ + if (view_is_in_ui_mode(app, view)){ + Basic_Scroll scroll = {}; + view_set_basic_scroll(app, view, scroll); + } + else{ + Buffer_Scroll scroll = {}; + view_set_buffer_scroll(app, view, scroll); + } +} + +//////////////////////////////// + internal Range_i64 buffer_range(Application_Links *app, Buffer_ID buffer){ Range_i64 range = {}; @@ -439,20 +479,6 @@ set_view_range(Application_Links *app, View_ID view, Range_i64 range){ } } -internal f32 -get_view_y(Application_Links *app, View_ID view){ - i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - return(cursor.wrapped_y); -} - -internal f32 -get_view_x(Application_Links *app, View_ID view){ - i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - return(cursor.wrapped_x); -} - internal b32 is_valid_line(Application_Links *app, Buffer_ID buffer_id, i64 line){ i64 max_line = buffer_get_line_count(app, buffer_id); @@ -467,42 +493,40 @@ is_valid_line_range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range internal i64 get_line_number_from_pos(Application_Links *app, Buffer_ID buffer, i64 pos){ - Partial_Cursor partial_cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); - return(partial_cursor.line); + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); + return(cursor.line); } internal i64 -character_pos_to_pos_view(Application_Links *app, View_ID view, i64 character_pos){ - i64 result = 0; - Full_Cursor cursor = view_compute_cursor(app, view, seek_character_pos(character_pos)); - if (cursor.line > 0){ - result = cursor.pos; - } - return(result); +buffer_get_character_legal_pos_from_pos(Application_Links *app, Buffer_ID buffer, f32 width, Face_ID face, i64 pos){ + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); + i64 character = buffer_relative_character_from_pos(app, buffer, width, face, cursor.line, pos); + return(buffer_pos_from_relative_character(app, buffer, width, face, cursor.line, character)); } internal i64 -character_pos_to_pos_buffer(Application_Links *app, Buffer_ID buffer, i64 character_pos){ - Partial_Cursor cursor = buffer_compute_cursor(app, buffer, seek_character_pos(character_pos)); - return(cursor.pos); +view_get_character_legal_pos_from_pos(Application_Links *app, Buffer_ID buffer, i64 pos){ + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); + i64 character = view_relative_character_from_pos(app, buffer, cursor.line, pos); + return(view_pos_from_relative_character(app, buffer, cursor.line, character)); } -internal Partial_Cursor +internal Buffer_Cursor get_line_side(Application_Links *app, Buffer_ID buffer, i64 line_number, Side side){ i64 character_index = (side == Side_Min)?(1):(-1); - return(buffer_compute_cursor(app, buffer, seek_line_char(line_number, character_index))); + return(buffer_compute_cursor(app, buffer, seek_line_col(line_number, character_index))); } internal i64 get_line_side_pos(Application_Links *app, Buffer_ID buffer, i64 line_number, Side side){ i64 pos = -1; - Partial_Cursor partial_cursor = get_line_side(app, buffer, line_number, side); - if (partial_cursor.line != 0){ - pos = partial_cursor.pos; + Buffer_Cursor cursor = get_line_side(app, buffer, line_number, side); + if (cursor.line != 0){ + pos = cursor.pos; } return(pos); } -internal Partial_Cursor +internal Buffer_Cursor get_line_start(Application_Links *app, Buffer_ID buffer, i64 line_number){ return(get_line_side(app, buffer, line_number, Side_Min)); } @@ -513,7 +537,7 @@ get_line_start_pos(Application_Links *app, Buffer_ID buffer, i64 line_number){ // NOTE(allen): The position returned has the index of the terminating newline character, // not one past the newline character. -internal Partial_Cursor +internal Buffer_Cursor get_line_end(Application_Links *app, Buffer_ID buffer, i64 line_number){ return(get_line_side(app, buffer, line_number, Side_Max)); } @@ -523,10 +547,10 @@ get_line_end_pos(Application_Links *app, Buffer_ID buffer, i64 line_number){ } // NOTE(allen): The range returned does not include the terminating newline character -internal Range_Partial_Cursor +internal Range_Cursor get_line_range(Application_Links *app, Buffer_ID buffer, i64 line_number){ b32 success = false; - Range_Partial_Cursor result = {}; + Range_Cursor result = {}; result.begin = get_line_start(app, buffer, line_number); if (result.begin.line != 0){ result.end = get_line_end(app, buffer, line_number); @@ -543,7 +567,7 @@ get_line_range(Application_Links *app, Buffer_ID buffer, i64 line_number){ // NOTE(allen): The range returned does not include the terminating newline character internal Range_i64 get_line_pos_range(Application_Links *app, Buffer_ID buffer, i64 line_number){ - Range_Partial_Cursor range = get_line_range(app, buffer, line_number); + Range_Cursor range = get_line_range(app, buffer, line_number); Range_i64 result = {}; if (range.begin.line != 0 && range.end.line != 0){ result = Ii64(range.begin.pos, range.end.pos); @@ -552,7 +576,7 @@ get_line_pos_range(Application_Links *app, Buffer_ID buffer, i64 line_number){ } internal Range_i64 -make_range_from_cursors(Range_Partial_Cursor range){ +make_range_from_cursors(Range_Cursor range){ return(Ii64(range.begin.pos, range.end.pos)); } @@ -1406,7 +1430,7 @@ replace_in_range(Application_Links *app, Buffer_ID buffer, Range_i64 range, Stri i64 pos = range.min - 1; i64 new_pos = 0; buffer_seek_string_forward(app, buffer, pos, range.end, needle, &new_pos); - i64 shift = replace_range_compute_shift(needle.size, string.size); + i64 shift = replace_range_shift(needle.size, string.size); for (; new_pos + (imem)needle.size <= range.end;){ Range_i64 needle_range = Ii64(new_pos, new_pos + (i32)needle.size); buffer_replace_range(app, buffer, needle_range, string); @@ -1435,7 +1459,7 @@ swap_lines(Application_Links *app, Buffer_ID buffer, i64 line_1, i64 line_2){ buffer_replace_range(app, buffer, range_1, text_2); history_group_end(group); - i64 shift = replace_range_compute_shift(range_1, text_2.size); + i64 shift = replace_range_shift(range_1, text_2.size); result.min = range_1.min; result.max = range_2.min + shift; } @@ -1521,11 +1545,10 @@ exec_command(Application_Links *app, Generic_Command cmd){ exec_command(app, cmd.command); } -internal i32 +internal b32 key_is_unmodified(Key_Event_Data *key){ - int8_t *mods = key->modifiers; - i32 unmodified = (!mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX]); - return(unmodified); + b8 *mods = key->modifiers; + return(!mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX]); } internal u32 diff --git a/4coder_jump_sticky.cpp b/4coder_jump_sticky.cpp index 906b9fa3..4e59ea3c 100644 --- a/4coder_jump_sticky.cpp +++ b/4coder_jump_sticky.cpp @@ -49,7 +49,7 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe i32 colon_index = 0; b32 is_sub_error = false; Buffer_ID out_buffer_id = 0; - i32 out_pos = 0; + i64 out_pos = 0; { Scratch_Block line_auto_closer(arena); @@ -60,7 +60,7 @@ parse_buffer_to_jump_array(Application_Links *app, Arena *arena, Buffer_ID buffe Buffer_ID jump_buffer = {}; if (open_file(app, &jump_buffer, parsed_jump.location.file, false, true)){ if (buffer_exists(app, jump_buffer)){ - Partial_Cursor cursor = buffer_compute_cursor(app, jump_buffer, seek_jump(parsed_jump)); + Buffer_Cursor cursor = buffer_compute_cursor(app, jump_buffer, seek_jump(parsed_jump)); if (cursor.line > 0){ out_buffer_id = jump_buffer; out_pos = cursor.pos; @@ -359,7 +359,7 @@ CUSTOM_DOC("If the cursor is found to be on a jump location, parses the jump loc Marker_List *list = get_or_make_list_for_buffer(app, heap, buffer); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); i32 list_index = get_index_exact_from_list(app, list, cursor.line); @@ -387,7 +387,7 @@ CUSTOM_DOC("If the cursor is found to be on a jump location, parses the jump loc Marker_List *list = get_or_make_list_for_buffer(app, heap, buffer); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(pos)); i32 list_index = get_index_exact_from_list(app, list, cursor.line); @@ -440,7 +440,7 @@ goto_next_filtered_jump(Application_Links *app, Marker_List *list, View_ID jump_ if (!skip_this){ goto_jump_in_order(app, list, jump_view, location); i64 updated_line = get_line_from_list(app, list, list_index); - view_set_cursor(app, jump_view, seek_line_char(updated_line, 1), true); + view_set_cursor(app, jump_view, seek_line_col(updated_line, 1), true); break; } } @@ -459,7 +459,7 @@ get_locked_jump_state(Application_Links *app, Heap *heap){ result.list = get_or_make_list_for_buffer(app, heap, buffer); i64 cursor_position = view_get_cursor_pos(app, result.view); - Full_Cursor cursor = view_compute_cursor(app, result.view, seek_pos(cursor_position)); + Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(cursor_position)); result.list_index = get_index_nearest_from_list(app, result.list, cursor.line); } return(result); @@ -473,10 +473,10 @@ CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to th Locked_Jump_State jump_state = get_locked_jump_state(app, heap); if (jump_state.view != 0){ i64 cursor_position = view_get_cursor_pos(app, jump_state.view); - Full_Cursor cursor = view_compute_cursor(app, jump_state.view, seek_pos(cursor_position)); + Buffer_Cursor cursor = view_compute_cursor(app, jump_state.view, seek_pos(cursor_position)); i64 line = get_line_from_list(app, jump_state.list, jump_state.list_index); if (line <= cursor.line){ - ++jump_state.list_index; + jump_state.list_index += 1; } goto_next_filtered_jump(app, jump_state.list, jump_state.view, jump_state.list_index, 1, true, true); } @@ -503,7 +503,7 @@ CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to th Locked_Jump_State jump_state = get_locked_jump_state(app, heap); if (jump_state.view != 0){ i64 cursor_position = view_get_cursor_pos(app, jump_state.view); - Full_Cursor cursor = view_compute_cursor(app, jump_state.view, seek_pos(cursor_position)); + Buffer_Cursor cursor = view_compute_cursor(app, jump_state.view, seek_pos(cursor_position)); i64 line = get_line_from_list(app, jump_state.list, jump_state.list_index); if (line <= cursor.line){ ++jump_state.list_index; @@ -538,7 +538,7 @@ CUSTOM_DOC("If a buffer containing jump locations has been locked in, goes to th if (get_jump_from_list(app, jump_state.list, list_index, &location)){ goto_jump_in_order(app, jump_state.list, jump_state.view, location); i64 updated_line = get_line_from_list(app, jump_state.list, list_index); - view_set_cursor(app, jump_state.view, seek_line_char(updated_line, 1), true); + view_set_cursor(app, jump_state.view, seek_line_col(updated_line, 1), true); } } } diff --git a/4coder_jump_sticky.h b/4coder_jump_sticky.h index 661f044c..af609b83 100644 --- a/4coder_jump_sticky.h +++ b/4coder_jump_sticky.h @@ -12,7 +12,7 @@ struct Sticky_Jump{ i64 list_colon_index; b32 is_sub_error; Buffer_ID jump_buffer_id; - i32 jump_pos; + i64 jump_pos; }; struct Sticky_Jump_Stored{ diff --git a/4coder_jumping.cpp b/4coder_jumping.cpp index 22b60b88..14dfbc5f 100644 --- a/4coder_jumping.cpp +++ b/4coder_jumping.cpp @@ -246,7 +246,7 @@ set_view_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, Buf static void jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, Name_Line_Column_Location location){ view_set_active(app, view); - set_view_to_location(app, view, buffer, seek_line_char(location.line, location.column)); + set_view_to_location(app, view, buffer, seek_line_col(location.line, location.column)); if (auto_center_after_jumps){ center_view(app); } @@ -305,7 +305,7 @@ convert_name_based_to_id_based(Application_Links *app, Name_Line_Column_Location static Parsed_Jump seek_next_jump_in_view(Application_Links *app, Arena *arena, View_ID view, i32 skip_sub_errors, Scan_Direction direction, i64 *line_out){ i64 cursor_position = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(cursor_position)); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(cursor_position)); i64 line = cursor.line; Buffer_ID buffer = view_get_buffer(app, view, AccessAll); Parsed_Jump jump = seek_next_jump_in_buffer(app, arena, buffer, line + direction, skip_sub_errors, direction, &line); diff --git a/4coder_lib/4coder_heap.cpp b/4coder_lib/4coder_heap.cpp index 1e40cfd1..08168c35 100644 --- a/4coder_lib/4coder_heap.cpp +++ b/4coder_lib/4coder_heap.cpp @@ -137,7 +137,7 @@ heap_free(Heap *heap, void *memory){ } } -#define heap_array(g, T, size) (T*)heap_allocate(g, sizeof(T)*(size)) +#define heap_array(g, T, size) (T*)heap_allocate(g, (i32)(sizeof(T)*(size))) // BOTTOM diff --git a/4coder_lists.cpp b/4coder_lists.cpp index 0f2011d4..b5a19d0a 100644 --- a/4coder_lists.cpp +++ b/4coder_lists.cpp @@ -71,10 +71,10 @@ CUSTOM_COMMAND_SIG(lister__wheel_scroll) CUSTOM_DOC("A lister mode command that scrolls the list in response to the mouse wheel.") { View_ID view = get_active_view(app, AccessAll); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); + Basic_Scroll scroll = view_get_basic_scroll(app, view); Mouse_State mouse = get_mouse_state(app); - scroll.target_y += mouse.wheel; - view_set_scroll(app, view, scroll); + scroll.target.y += mouse.wheel; + view_set_basic_scroll(app, view, scroll); Lister_State *state = view_get_lister_state(view); if (state->initialized){ lister_update_ui(app, view, state); diff --git a/4coder_log_parser.cpp b/4coder_log_parser.cpp index 42108a1f..360a1824 100644 --- a/4coder_log_parser.cpp +++ b/4coder_log_parser.cpp @@ -1010,7 +1010,7 @@ CUSTOM_DOC("Jump to the code that logged the event record at the mouse point in view_end_ui_mode(app, target_view); } set_view_to_location(app, target_view, target_buffer, - seek_line_char(event->line_number, 1)); + seek_line_col(event->line_number, 1)); } } } diff --git a/4coder_scope_commands.cpp b/4coder_scope_commands.cpp index 868c0b12..efbb122e 100644 --- a/4coder_scope_commands.cpp +++ b/4coder_scope_commands.cpp @@ -5,7 +5,6 @@ // TOP static b32 parse_statement_down(Application_Links *app, Statement_Parser *parser, Cpp_Token *token_out); -static f32 scope_center_threshold = 0.75f; //////////////////////////////// @@ -287,48 +286,53 @@ find_scope_range(Application_Links *app, Buffer_ID buffer, i64 start_pos, Range_ } static void -view_set_to_region(Application_Links *app, View_ID view, i64 major_pos, i64 minor_pos, f32 normalized_threshold){ +view_set_to_region(Application_Links *app, View_ID view, i64 major_pos, i64 minor_pos){ Range_i64 range = Ii64(major_pos, minor_pos); b32 bottom_major = false; if (major_pos == range.max){ bottom_major = true; } - Full_Cursor top = view_compute_cursor(app, view, seek_pos(range.min)); + Buffer_Cursor top = view_compute_cursor(app, view, seek_pos(range.min)); if (top.line > 0){ - Full_Cursor bottom = view_compute_cursor(app, view, seek_pos(range.max)); + Buffer_Cursor bottom = view_compute_cursor(app, view, seek_pos(range.max)); if (bottom.line > 0){ - f32 top_y = top.wrapped_y; - f32 bottom_y = bottom.wrapped_y; - Rect_f32 region = view_get_buffer_region(app, view); + f32 view_height = rect_height(region); + f32 skirt_height = view_height*.1f; + Interval_f32 acceptable_y = If32(skirt_height, view_height*.9f); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); - f32 half_view_height = .5f*(f32)(rect_height(region)); - f32 threshold = normalized_threshold * half_view_height; - f32 current_center_y = ((f32)scroll.target_y) + half_view_height; + f32 target_height = view_line_y_difference(app, view, bottom.line, top.line); - if (top_y < current_center_y - threshold || bottom_y > current_center_y + threshold){ - f32 center_target_y = .5f*(top_y + bottom_y); + if (target_height > view_height){ + i64 major_line = bottom.line; + if (range.min == major_pos){ + major_line = top.line; + } - if (bottom_major){ - if (center_target_y < bottom_y - half_view_height * .9f){ - center_target_y = bottom_y - half_view_height * .9f; - } + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + scroll.target.line_number = major_line; + scroll.target.pixel_shift.y = -skirt_height; + view_set_buffer_scroll(app, view, scroll); + } + else{ + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + Vec2_f32 top_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.min); + top_p -= scroll.position.pixel_shift; + if (top_p.y < acceptable_y.min){ + scroll.target.line_number = top.line; + scroll.target.pixel_shift.y = -skirt_height; + view_set_buffer_scroll(app, view, scroll); } else{ - if (center_target_y > top_y + half_view_height * .9f){ - center_target_y = top_y + half_view_height * .9f; + Vec2_f32 bot_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.max); + bot_p -= scroll.position.pixel_shift; + if (bot_p.y > acceptable_y.max){ + scroll.target.line_number = bottom.line; + scroll.target.pixel_shift.y = skirt_height - view_height; + view_set_buffer_scroll(app, view, scroll); } } - - f32 target_y = center_target_y - half_view_height; - if (target_y < 0){ - target_y = 0; - } - - scroll.target_y = (i32)(target_y); - view_set_scroll(app, view, scroll); } } } @@ -344,7 +348,7 @@ CUSTOM_DOC("Finds the scope enclosed by '{' '}' surrounding the cursor and puts if (find_scope_range(app, buffer, pos, &range, FindScope_Brace)){ view_set_cursor(app, view, seek_pos(range.first), true); view_set_mark(app, view, seek_pos(range.end)); - view_set_to_region(app, view, range.first, range.end, scope_center_threshold); + view_set_to_region(app, view, range.first, range.end); no_mark_snap_to_cursor(app, view); } } @@ -362,7 +366,7 @@ CUSTOM_DOC("Finds the first scope started by '{' after the cursor and puts the c if (find_scope_bottom(app, buffer, top, FindScope_EndOfToken|FindScope_Brace, &bottom)){ view_set_cursor(app, view, seek_pos(top), true); view_set_mark(app, view, seek_pos(bottom)); - view_set_to_region(app, view, top, bottom, scope_center_threshold); + view_set_to_region(app, view, top, bottom); no_mark_snap_to_cursor(app, view); } } @@ -381,7 +385,7 @@ CUSTOM_DOC("Finds the first scope started by '{' before the cursor and puts the if (find_scope_bottom(app, buffer, top, FindScope_EndOfToken|FindScope_Brace, &bottom)){ view_set_cursor(app, view, seek_pos(top), true); view_set_mark(app, view, seek_pos(bottom)); - view_set_to_region(app, view, top, bottom, scope_center_threshold); + view_set_to_region(app, view, top, bottom); no_mark_snap_to_cursor(app, view); } } @@ -466,18 +470,16 @@ CUSTOM_DOC("Deletes the braces surrounding the currently selected scope. Leaves bot_len = 2; } - Buffer_Edit edits[2]; - edits[0].str_start = 0; - edits[0].len = 0; - edits[0].start = (i32)(range.min + 1 - top_len); - edits[0].end = (i32)(range.min + 1); + Batch_Edit batch_first = {}; + Batch_Edit batch_last = {}; - edits[1].str_start = 0; - edits[1].len = 0; - edits[1].start = (i32)(range.max - 1); - edits[1].end = (i32)(range.max - 1 + bot_len); + batch_first.edit.text = SCu8(); + batch_first.edit.range = Ii64(range.min + 1 - top_len, range.min + 1); + batch_first.next = &batch_last; + batch_last.edit.text = SCu8(); + batch_last.edit.range = Ii64((i32)(range.max - 1), (i32)(range.max - 1 + bot_len)); - buffer_batch_edit(app, buffer, 0, edits, 2); + buffer_batch_edit(app, buffer, &batch_first); } } @@ -701,16 +703,16 @@ CUSTOM_DOC("If a scope is currently selected, and a statement or block statement edit_str = push_u8_stringf(scratch, "%.*s\n", string_expand(string)); } - Buffer_Edit edits[2]; - edits[0].str_start = 0; - edits[0].len = (i32)edit_str.size; - edits[0].start = (i32)(range.min - 1); - edits[0].end = (i32)(range.min - 1); - edits[1].str_start = 0; - edits[1].len = 0; - edits[1].start = (i32)(range.start); - edits[1].end = (i32)(range.end); - buffer_batch_edit(app, buffer, (char*)edit_str.str, edits, 2); + Batch_Edit batch_first = {}; + Batch_Edit batch_last = {}; + + batch_first.edit.text = edit_str; + batch_first.edit.range = Ii64(range.min - 1, range.min - 1); + batch_first.next = &batch_last; + batch_last.edit.text = SCu8(); + batch_last.edit.range = range; + + buffer_batch_edit(app, buffer, &batch_first); } } diff --git a/4coder_search.cpp b/4coder_search.cpp index 6816fa46..35045c20 100644 --- a/4coder_search.cpp +++ b/4coder_search.cpp @@ -40,11 +40,13 @@ print_string_match_list_to_buffer(Application_Links *app, Buffer_ID out_buffer_i } } - Partial_Cursor partial_cursor = buffer_compute_cursor(app, current_buffer, seek_pos(node->range.first)); + Buffer_Cursor cursor = buffer_compute_cursor(app, current_buffer, seek_pos(node->range.first)); Temp_Memory line_temp = begin_temp(scratch); - String_Const_u8 full_line_str = push_buffer_line(app, scratch, current_buffer, partial_cursor.line); + String_Const_u8 full_line_str = push_buffer_line(app, scratch, current_buffer, cursor.line); String_Const_u8 line_str = string_skip_chop_whitespace(full_line_str); - insertf(&out, "%.*s:%d:%d: %.*s\n", string_expand(current_file_name), partial_cursor.line, partial_cursor.character, string_expand(line_str)); + insertf(&out, "%.*s:%d:%d: %.*s\n", + string_expand(current_file_name), cursor.line, cursor.col, + string_expand(line_str)); end_temp(line_temp); } } diff --git a/4coder_seek.cpp b/4coder_seek.cpp index c650059f..abd47601 100644 --- a/4coder_seek.cpp +++ b/4coder_seek.cpp @@ -18,10 +18,11 @@ internal void seek_pos_of_visual_line(Application_Links *app, Side side){ View_ID view = get_active_view(app, AccessProtected); i64 pos = view_get_cursor_pos(app, view); - Full_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - f32 y = cursor.wrapped_y; - f32 x = (side == Side_Min)?(0.f):(max_f32); - view_set_cursor(app, view, seek_wrapped_xy(x, y, true), true); + Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); + Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos); + p.x = (side == Side_Min)?(0.f):(max_f32); + i64 new_pos = view_pos_at_relative_xy(app, view, cursor.line, p); + view_set_cursor(app, view, seek_pos(new_pos), true); no_mark_snap_to_cursor_if_shift(app, view); } diff --git a/4coder_table.cpp b/4coder_table.cpp index 636272a2..8e18c842 100644 --- a/4coder_table.cpp +++ b/4coder_table.cpp @@ -6,7 +6,7 @@ internal u64 table_hash(Data key){ - return(table_hash_u8((u8*)key.data, key.size) | bit_63); + return(table_hash_u8((u8*)key.data, key.size) | bit_64); } global_const u64 table_empty_slot = 0; @@ -154,11 +154,10 @@ table_insert(Table_u64_u64 *table, u64 key, u64 val){ } internal b32 -table_erase(Table_u64_u64 *table, u64 key){ +table_erase(Table_u64_u64 *table, Table_Lookup lookup){ b32 result = false; - Table_Lookup lookup = table_lookup(table, key); if (lookup.found_match){ - table->keys[lookup.index] = 0; + table->keys[lookup.index] = table_erased_key; table->vals[lookup.index] = 0; table->used_count -= 1; result = true; @@ -166,6 +165,18 @@ table_erase(Table_u64_u64 *table, u64 key){ return(result); } +internal b32 +table_erase(Table_u64_u64 *table, u64 key){ + Table_Lookup lookup = table_lookup(table, key); + return(table_erase(table, lookup)); +} + +internal b32 +table_clear(Table_u64_u64 *table){ + block_zero_dynamic_array(table->keys, table->slot_count); + block_zero_dynamic_array(table->vals, table->slot_count); +} + //////////////////////////////// internal Table_u32_u16 @@ -296,11 +307,10 @@ table_insert(Table_u32_u16 *table, u32 key, u16 val){ } internal b32 -table_erase(Table_u32_u16 *table, u32 key){ +table_erase(Table_u32_u16 *table, Table_Lookup lookup){ b32 result = false; - Table_Lookup lookup = table_lookup(table, key); if (lookup.found_match){ - table->keys[lookup.index] = 0; + table->keys[lookup.index] = table_erased_u32_key; table->vals[lookup.index] = 0; table->used_count -= 1; result = true; @@ -308,6 +318,18 @@ table_erase(Table_u32_u16 *table, u32 key){ return(result); } +internal b32 +table_erase(Table_u32_u16 *table, u32 key){ + Table_Lookup lookup = table_lookup(table, key); + return(table_erase(table, lookup)); +} + +internal b32 +table_clear(Table_u32_u16 *table){ + block_zero_dynamic_array(table->keys, table->slot_count); + block_zero_dynamic_array(table->vals, table->slot_count); +} + //////////////////////////////// internal Table_Data_u64 @@ -410,7 +432,7 @@ table_rehash(Table_Data_u64 *dst, Table_Data_u64 *src){ if ((dst->dirty_count + src->used_count)*8 < dst->slot_count*7){ u64 *src_hashes = src->hashes; for (u32 i = 0; i < src_slot_count; i += 1){ - if (HasFlag(src_hashes[i], bit_63)){ + if (HasFlag(src_hashes[i], bit_64)){ Data key = src->keys[i]; Table_Lookup lookup = table_lookup(dst, key); table_insert__inner(dst, lookup, key, src->vals[i]); @@ -458,6 +480,12 @@ table_erase(Table_Data_u64 *table, Data key){ return(result); } +internal b32 +table_clear(Table_Data_u64 *table){ + block_zero_dynamic_array(table->keys, table->slot_count); + block_zero_dynamic_array(table->vals, table->slot_count); +} + //////////////////////////////// internal Table_u64_Data @@ -606,6 +634,12 @@ table_erase(Table_u64_Data *table, u64 key){ return(result); } +internal b32 +table_clear(Table_u64_Data *table){ + block_zero_dynamic_array(table->keys, table->slot_count); + block_zero_dynamic_array(table->vals, table->slot_count); +} + //////////////////////////////// internal Table_Data_Data @@ -703,7 +737,7 @@ table_rehash(Table_Data_Data *dst, Table_Data_Data *src){ if ((dst->dirty_count + src->used_count)*8 < dst->slot_count*7){ u64 *src_hashes = src->hashes; for (u32 i = 0; i < src_slot_count; i += 1){ - if (HasFlag(src_hashes[i], bit_63)){ + if (HasFlag(src_hashes[i], bit_64)){ Data key = src->keys[i]; Table_Lookup lookup = table_lookup(dst, key); table_insert__inner(dst, lookup, key, src->vals[i]); @@ -751,4 +785,10 @@ table_erase(Table_Data_Data *table, Data key){ return(result); } +internal b32 +table_clear(Table_Data_Data *table){ + block_zero_dynamic_array(table->keys, table->slot_count); + block_zero_dynamic_array(table->vals, table->slot_count); +} + // BOTTOM diff --git a/4coder_ui_helper.cpp b/4coder_ui_helper.cpp index 6522862d..418b85f0 100644 --- a/4coder_ui_helper.cpp +++ b/4coder_ui_helper.cpp @@ -160,75 +160,36 @@ ui_control_get_mouse_hit(UI_Data *data, Vec2_f32 view_p, Vec2_f32 panel_p){ return(result); } -#if 0 -static UI_Item* -ui_control_get_mouse_hit(UI_Data *data, i32 mx_scrolled, i32 my_scrolled, i32 mx_unscrolled, i32 my_unscrolled){ - return(ui_control_get_mouse_hit(data, V2i32(mx_scrolled, my_scrolled), V2i32(mx_unscrolled, my_unscrolled))); -} -#endif - //////////////////////////////// static void -view_zero_scroll(Application_Links *app, View_ID view){ - GUI_Scroll_Vars zero_scroll = {}; - view_set_scroll(app, view, zero_scroll); -} - -static void -view_set_vertical_focus(Application_Links *app, View_ID view, f32 y_top, f32 y_bot){ +view_set_vertical_focus_basic(Application_Links *app, View_ID view, f32 y_top, f32 y_bot){ Rect_f32 buffer_region = view_get_buffer_region(app, view); - GUI_Scroll_Vars scroll = view_get_scroll_vars(app, view); - f32 view_y_top = (f32)scroll.target_y; - f32 view_y_dim = rect_height(buffer_region); - f32 view_y_bot = view_y_top + view_y_dim; + Basic_Scroll scroll = view_get_basic_scroll(app, view); + f32 view_height = rect_height(buffer_region); + Interval_f32 view_y = If32(scroll.target.y, scroll.target.y + view_height); + Interval_f32 acceptable_y = If32(lerp(view_y.min, 0.10f, view_y.max), + lerp(view_y.min, 0.90f, view_y.max)); + f32 acceptable_height = range_size(acceptable_y); + f32 skirt_height = acceptable_y.min - view_y.min; - Buffer_ID buffer = view_get_buffer(app, view, AccessAll); - Face_ID face_id = get_face_id(app, buffer); - Face_Metrics metrics = get_face_metrics(app, face_id); - - f32 line_dim = metrics.line_height; - f32 hot_y_top = view_y_top + line_dim*3; - f32 hot_y_bot = view_y_bot - line_dim*3; - if (hot_y_bot - hot_y_top < line_dim*6){ - f32 quarter_view_y_dim = view_y_dim*.25f; - hot_y_top = view_y_top + quarter_view_y_dim; - hot_y_bot = view_y_bot - quarter_view_y_dim; - } - f32 hot_y_dim = hot_y_bot - hot_y_top; - f32 skirt_dim = hot_y_top - view_y_top; - f32 y_dim = y_bot - y_top; - if (y_dim > hot_y_dim){ - scroll.target_y = (i32)(y_top - skirt_dim); - view_set_scroll(app, view, scroll); + f32 height = y_bot - y_top; + if (height > acceptable_height){ + scroll.target.y = y_top - skirt_height; + view_set_basic_scroll(app, view, scroll); } else{ - if (y_top < hot_y_top){ - scroll.target_y = (i32)(y_top - skirt_dim); - view_set_scroll(app, view, scroll); + if (y_top < acceptable_y.min){ + scroll.target.y = y_top - skirt_height; + view_set_basic_scroll(app, view, scroll); } - else if (y_bot > hot_y_bot){ - scroll.target_y = (i32)(y_bot + skirt_dim - view_y_dim); - view_set_scroll(app, view, scroll); + else if (y_bot > acceptable_y.max){ + scroll.target.y = y_bot + skirt_height - view_height; + view_set_basic_scroll(app, view, scroll); } } } -static Vec2_f32 -view_space_from_screen_space(Vec2_f32 p, Vec2_f32 file_region_p0, Vec2_f32 scroll_p){ - return(p - file_region_p0 + scroll_p); -} - -static Vec2_f32 -get_mouse_position_in_view_space(Mouse_State mouse, Vec2_f32 file_region_p0, Vec2_f32 scroll_p){ - return(view_space_from_screen_space(V2f32(mouse.p), file_region_p0, scroll_p)); -} - -static Vec2_f32 -get_mouse_position_in_view_space(Application_Links *app, Vec2_f32 file_region_p0, Vec2_f32 scroll_p){ - return(get_mouse_position_in_view_space(get_mouse_state(app), file_region_p0, scroll_p)); -} - static Vec2_f32 panel_space_from_screen_space(Vec2_f32 p, Vec2_f32 file_region_p0){ return(p - file_region_p0); @@ -244,16 +205,6 @@ get_mouse_position_in_panel_space(Application_Links *app, Vec2_f32 file_region_p return(get_mouse_position_in_panel_space(get_mouse_state(app), file_region_p0)); } -static Vec2 -panel_space_from_view_space(Vec2 p, Vec2 scroll_p){ - return(p - scroll_p); -} - -static Vec2_i32 -panel_space_from_view_space(Vec2_i32 p, Vec2_i32 scroll_p){ - return(p - scroll_p); -} - //////////////////////////////// // TODO(allen): VIEW_16_LIMIT @@ -298,12 +249,11 @@ lister_get_clicked_item(Application_Links *app, View_ID view_id){ UI_Data *ui_data = 0; Arena *ui_arena = 0; if (view_get_ui_data(app, view_id, ViewGetUIFlag_KeepDataAsIs, &ui_data, &ui_arena)){ - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view_id); Mouse_State mouse = get_mouse_state(app); - Rect_f32 buffer_region = view_get_buffer_region(app, view_id); - Vec2_f32 region_p0 = buffer_region.p0; - Vec2_f32 m_view_space = get_mouse_position_in_view_space(mouse, region_p0, scroll_vars.scroll_p); - Vec2_f32 m_panel_space = get_mouse_position_in_panel_space(mouse, region_p0); + Rect_f32 region = view_get_buffer_region(app, view_id); + Vec2_f32 m_panel_space = get_mouse_position_in_panel_space(mouse, region.p0); + Basic_Scroll scroll = view_get_basic_scroll(app, view_id); + Vec2_f32 m_view_space = m_panel_space + scroll.position; UI_Item *clicked = ui_control_get_mouse_hit(ui_data, m_view_space, m_panel_space); if (clicked != 0){ result = *clicked; @@ -338,7 +288,7 @@ lister_update_ui(Application_Links *app, View_ID view, Lister_State *state){ Face_ID face_id = get_face_id(app, 0); Face_Metrics metrics = get_face_metrics(app, face_id); - GUI_Scroll_Vars scroll_vars = view_get_scroll_vars(app, view); + Basic_Scroll scroll = view_get_basic_scroll(app, view); f32 x0 = 0; f32 x1 = (rect_width(screen_rect)); @@ -349,9 +299,9 @@ lister_update_ui(Application_Links *app, View_ID view, Lister_State *state){ Arena *scratch = context_get_arena(app); Temp_Memory full_temp = begin_temp(scratch); - // TODO(allen): switch to float - Rect_f32 buffer_region = view_get_buffer_region(app, view); - Vec2_f32 view_m = get_mouse_position_in_view_space(app, buffer_region.p0, scroll_vars.scroll_p); + Rect_f32 region = view_get_buffer_region(app, view); + Vec2_f32 view_m = get_mouse_position_in_panel_space(app, region.p0); + view_m += scroll.position; f32 y_pos = text_field_height; @@ -494,9 +444,9 @@ lister_update_ui(Application_Links *app, View_ID view, Lister_State *state){ if (state->set_view_vertical_focus_to_item){ if (highlighted_item != 0){ - view_set_vertical_focus(app, view, - (f32)highlighted_item->rect_outer.y0, - (f32)highlighted_item->rect_outer.y1); + view_set_vertical_focus_basic(app, view, + (f32)highlighted_item->rect_outer.y0, + (f32)highlighted_item->rect_outer.y1); } state->set_view_vertical_focus_to_item = false; } diff --git a/4ed.cpp b/4ed.cpp index 654e2869..0b98edf7 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -60,7 +60,7 @@ app_coroutine_handle_request(Models *models, Coroutine *co, u32 *vals){ { Face_Description *description = ((Face_Description**)vals)[0]; Face_ID face_id = ((Face_ID*)vals)[3]; - b32 success = alter_font_and_update_files(system, models, face_id, description); + b32 success = font_set_modify_face(&models->font_set, face_id, description); result = coroutine_run(&models->coroutines, co, &success, vals); }break; } @@ -85,15 +85,15 @@ app_coroutine_run(Models *models, App_Coroutine_Purpose purpose, Coroutine *co, internal void output_file_append(Models *models, Editing_File *file, String_Const_u8 value){ - i32 end = buffer_size(&file->state.buffer); + i64 end = buffer_size(&file->state.buffer); Edit_Behaviors behaviors = {}; - edit_single(models->system, models, file, make_range(end), value, behaviors); + edit_single(models, file, Ii64(end), value, behaviors); } internal void file_cursor_to_end(System_Functions *system, Models *models, Editing_File *file){ Assert(file != 0); - i32 pos = buffer_size(&file->state.buffer); + i64 pos = buffer_size(&file->state.buffer); Layout *layout = &models->layout; for (Panel *panel = layout_get_first_open_panel(layout); panel != 0; @@ -102,9 +102,8 @@ file_cursor_to_end(System_Functions *system, Models *models, Editing_File *file) if (view->file != file){ continue; } - Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(pos)); - view_set_cursor(system, models, view, cursor, true); - view->mark = cursor.pos; + view_set_cursor(models, view, pos); + view->mark = pos; } } @@ -129,17 +128,9 @@ file_cursor_to_end(System_Functions *system, Models *models, Editing_File *file) #define REQ_FILE(n,v) Editing_File *n = (v)->file_data.file; if (n == 0) return #define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file_data.file; if (n == 0 || n->state.undo.undo.edits == 0) return -SCROLL_RULE_SIG(fallback_scroll_rule){ - b32 result = false; - if (target_x != *scroll_x){ - *scroll_x = target_x; - result = true; - } - if (target_y != *scroll_y){ - *scroll_y = target_y; - result = true; - } - return(result); + +DELTA_RULE_SIG(fallback_scroll_rule){ + return(pending_delta); } #define DEFAULT_MAP_SIZE 10 @@ -415,7 +406,7 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){ case special_hook_scroll_rule: { - models->scroll_rule = (Scroll_Rule_Function*)unit->hook.func; + models->scroll_rule = (Delta_Rule_Function*)unit->hook.func; }break; case special_hook_buffer_name_resolver: @@ -738,23 +729,6 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, //////////////////////////////// -internal Arena -make_arena_models(Models *models, umem chunk_size, umem align){ - return(make_arena(models->base_allocator, chunk_size, align)); -} - -internal Arena -make_arena_models(Models *models, umem chunk_size){ - return(make_arena(models->base_allocator, chunk_size, 8)); -} - -internal Arena -make_arena_models(Models *models){ - return(make_arena(models->base_allocator, KB(16), 8)); -} - -//////////////////////////////// - internal Models* app_setup_memory(System_Functions *system, Application_Memory *memory){ Cursor cursor = make_cursor(memory->vars_memory, memory->vars_memory_size); @@ -931,7 +905,7 @@ App_Init_Sig(app_init){ // NOTE(allen): global_history_init(&models->global_history); - text_layout_init(&models->app_links, &models->text_layouts); + text_layout_init(models, &models->text_layouts); // NOTE(allen): clipboard setup models->working_set.clipboard_max_size = ArrayCount(models->working_set.clipboards); @@ -978,7 +952,7 @@ App_Init_Sig(app_init){ } File_Attributes attributes = {}; - file_create_from_string(system, models, file, SCu8(), attributes); + file_create_from_string(models, file, SCu8(), attributes); if (init_files[i].read_only){ file->settings.read_only = true; history_free(&models->mem.heap, &file->state.history); @@ -986,7 +960,6 @@ App_Init_Sig(app_init){ file->settings.never_kill = true; file_set_unimportant(file, true); - file->settings.unwrapped_lines = true; } // NOTE(allen): setup first panel @@ -1104,7 +1077,6 @@ App_Step_Sig(app_step){ mouse_event.keycode = key_mouse_left_release; input->keys.keys[input->keys.count++] = mouse_event; } - if (input->mouse.press_r){ mouse_event.keycode = key_mouse_right; input->keys.keys[input->keys.count++] = mouse_event; @@ -1113,12 +1085,10 @@ App_Step_Sig(app_step){ mouse_event.keycode = key_mouse_right_release; input->keys.keys[input->keys.count++] = mouse_event; } - if (input->mouse.wheel != 0){ mouse_event.keycode = key_mouse_wheel; input->keys.keys[input->keys.count++] = mouse_event; } - if (input->mouse.p != models->prev_p){ b32 was_in_window = rect_contains_point(i32R(0, 0, prev_dim.x, prev_dim.y), models->prev_p); b32 is_in_window = rect_contains_point(i32R(0, 0, current_dim.x, current_dim.y), input->mouse.p); @@ -1127,7 +1097,6 @@ App_Step_Sig(app_step){ input->keys.keys[input->keys.count++] = mouse_event; } } - if (models->animated_last_frame){ mouse_event.keycode = key_animate; input->keys.keys[input->keys.count++] = mouse_event; @@ -1169,10 +1138,8 @@ App_Step_Sig(app_step){ if (models->hook_start != 0){ char **files = models->settings.init_files; i32 files_count = models->settings.init_files_count; - char **flags = models->settings.custom_flags; i32 flags_count = models->settings.custom_flags_count; - models->hook_start(&models->app_links, files, files_count, flags, flags_count); } } @@ -1303,39 +1270,17 @@ App_Step_Sig(app_step){ models->hooks[hook_buffer_viewer_update](&models->app_links); } - // NOTE(allen): step panels - { - Panel *active_panel = layout_get_active_panel(layout); - - for (Panel *panel = layout_get_first_open_panel(layout); - panel != 0; - panel = layout_get_next_open_panel(layout, panel)){ - View *view = panel->view; - - GUI_Scroll_Vars *scroll_vars = 0; - b32 file_scroll = false; - File_Edit_Positions edit_pos = view_get_edit_pos(view); - if (!view->ui_mode){ - scroll_vars = &edit_pos.scroll; - file_scroll = true; - } - else{ - scroll_vars = &view->ui_scroll; - file_scroll = false; - } - - b32 active = (panel == active_panel); - GUI_Scroll_Vars new_scroll = do_step_file_view(system, models, view, panel->rect_inner, active, dt, *scroll_vars); - - if (memcmp(scroll_vars, &new_scroll, sizeof(*scroll_vars)) != 0){ - if (file_scroll){ - view_set_scroll(system, models, view, new_scroll); - } - else{ - *scroll_vars = new_scroll; - } - } - } + // NOTE(allen): dt + f32 literal_dt = 0.f; + u64 now_usecond_stamp = system->now_time(); + if (!input->first_step){ + u64 elapsed_useconds = now_usecond_stamp - models->last_render_usecond_stamp; + literal_dt = (f32)((f64)(elapsed_useconds)/1000000.f); + } + models->last_render_usecond_stamp = now_usecond_stamp; + f32 animation_dt = 0.f; + if (models->animated_last_frame){ + animation_dt = literal_dt; } // NOTE(allen): on the first frame there should be no scrolling @@ -1344,10 +1289,56 @@ App_Step_Sig(app_step){ panel != 0; panel = layout_get_next_open_panel(layout, panel)){ View *view = panel->view; - File_Edit_Positions edit_pos = view_get_edit_pos(view); - edit_pos.scroll.scroll_x = (f32)edit_pos.scroll.target_x; - edit_pos.scroll.scroll_y = (f32)edit_pos.scroll.target_y; - view_set_edit_pos(view, edit_pos); + if (!view->ui_mode){ + File_Edit_Positions edit_pos = view_get_edit_pos(view); + edit_pos.scroll.position = view_normalize_buffer_point(models, view, edit_pos.scroll.target); + block_zero_struct(&edit_pos.scroll.target); + view_set_edit_pos(view, edit_pos); + } + else{ + view->ui_scroll.position = view->ui_scroll.target; + block_zero_struct(&view->ui_scroll.target); + } + } + } + + // NOTE(allen): apply pending smooth deltas + { + Delta_Rule_Function *scroll_rule = models->scroll_rule; + for (Panel *panel = layout_get_first_open_panel(layout); + panel != 0; + panel = layout_get_next_open_panel(layout, panel)){ + View *view = panel->view; + + View_ID view_id = view_get_id(&models->live_set, view); + b32 new_target = (b32)view->new_scroll_target; + if (view->ui_mode){ + Vec2_f32 pending = view->ui_scroll.target - view->ui_scroll.position; + if (!near_zero(pending, 0.5f)){ + Vec2_f32 partial = scroll_rule(pending, view_id, new_target, animation_dt); + view->ui_scroll.position += partial; + models->animate_next_frame = true; + } + else{ + view->ui_scroll.position = view->ui_scroll.target; + } + } + else{ + File_Edit_Positions edit_pos = view_get_edit_pos(view); + Vec2_f32 pending = view_buffer_point_difference(models, view, + edit_pos.scroll.target, edit_pos.scroll.position); + if (!near_zero(pending, 0.5f)){ + Vec2_f32 partial = scroll_rule(pending, view_id, new_target, animation_dt); + edit_pos.scroll.position = view_move_buffer_point(models, view, + edit_pos.scroll.position, partial); + view_set_edit_pos(view, edit_pos); + models->animate_next_frame = true; + } + else{ + edit_pos.scroll.position = edit_pos.scroll.target; + view_set_edit_pos(view, edit_pos); + } + } } } @@ -1449,19 +1440,6 @@ App_Step_Sig(app_step){ // NOTE(allen): rendering { - f32 literal_dt = 0.f; - u64 now_usecond_stamp = system->now_time(); - if (!input->first_step){ - u64 elapsed_useconds = now_usecond_stamp - models->last_render_usecond_stamp; - literal_dt = (f32)((f64)(elapsed_useconds)/1000000.f); - } - models->last_render_usecond_stamp = now_usecond_stamp; - - f32 animation_dt = 0.f; - if (models->animated_last_frame){ - animation_dt = literal_dt; - } - Frame_Info frame = {}; frame.index = models->frame_counter; frame.literal_dt = literal_dt; diff --git a/4ed_allocator_models.cpp b/4ed_allocator_models.cpp new file mode 100644 index 00000000..74237141 --- /dev/null +++ b/4ed_allocator_models.cpp @@ -0,0 +1,28 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 27.08.2019 + * + * Models based arena constructors + * + */ + +// TOP + +internal Arena +make_arena_models(Models *models, umem chunk_size, umem align){ + return(make_arena(models->base_allocator, chunk_size, align)); +} + +internal Arena +make_arena_models(Models *models, umem chunk_size){ + return(make_arena(models->base_allocator, chunk_size, 8)); +} + +internal Arena +make_arena_models(Models *models){ + return(make_arena(models->base_allocator, KB(16), 8)); +} + +// BOTTOM + diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index e1cd450d..e13688b7 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -55,11 +55,7 @@ is_running_coroutine(Application_Links *app){ API_EXPORT b32 Global_Set_Setting(Application_Links *app, Global_Setting_ID setting, i32 value) -/* -DOC_PARAM(setting, Which setting to change.) -DOC_PARAM(value, The new value to set ont he specified setting.) -DOC_SEE(Global_Setting_ID) -*/{ +{ Models *models = (Models*)app->cmd_context; b32 result = true; switch (setting){ @@ -77,12 +73,7 @@ DOC_SEE(Global_Setting_ID) API_EXPORT b32 Global_Set_Mapping(Application_Links *app, void *data, i32 size) -/* -DOC_PARAM(data, The beginning of a binding buffer. Bind_Helper is designed to make it easy to produce such a buffer.) -DOC_PARAM(size, The size of the binding buffer in bytes.) -DOC_RETURN(Returns non-zero if no errors occurred while interpretting the binding buffer. A return value of zero does not indicate that the old mappings are still in place.) -DOC(Dumps away the previous mappings and instantiates the mappings described in the binding buffer. If any of the open buffers were bound to a command map that used to exist, but no command map with the same id exist after the new mappings are instantiated, the buffer's command map will be set to mapid_file and a warning will be posted to *messages*.) -*/{ +{ Models *models = (Models*)app->cmd_context; b32 result = interpret_binding_buffer(models, data, size); return(result); @@ -153,16 +144,9 @@ Child_Process_Get_State(Application_Links *app, Child_Process_ID child_process_i return(child_process_get_state(&models->child_processes, child_process_id)); } -// TODO(allen): redocument API_EXPORT b32 Clipboard_Post(Application_Links *app, i32 clipboard_id, String_Const_u8 string) -/* -DOC_PARAM(clipboard_id, This parameter is set up to prepare for future features, it should always be 0 for now.) -DOC_PARAM(str, The str parameter specifies the string to be posted to the clipboard, it need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the str string.) -DOC(Stores the string str in the clipboard initially with index 0. Also reports the copy to the operating system, so that it may be pasted into other applications.) -DOC_SEE(The_4coder_Clipboard) -*/{ +{ Models *models = (Models*)app->cmd_context; String_Const_u8 *dest = working_set_next_clipboard_string(&models->mem.heap, &models->working_set, (i32)string.size); block_copy(dest->str, string.str, string.size); @@ -170,33 +154,16 @@ DOC_SEE(The_4coder_Clipboard) return(true); } -// TODO(casey): Allen, why does this return a bool? Like, shouldn't it just return the count? If there's nothing in that clipboard, it'd just be 0? API_EXPORT i32 Clipboard_Count(Application_Links *app, i32 clipboard_id) -/* -DOC_PARAM(clipboard_id, This parameter is set up to prepare for future features, it should always be 0 for now.) -DOC(This call returns the number of items in the clipboard.) -DOC_SEE(The_4coder_Clipboard) -*/{ +{ Models *models = (Models*)app->cmd_context; return(models->working_set.clipboard_size); } -// TODO(allen): redocument API_EXPORT String_Const_u8 Push_Clipboard_Index(Application_Links *app, Arena *arena, i32 clipboard_id, i32 item_index) -/* -DOC_PARAM(clipboard_id, This parameter is set up to prepare for future features, it should always be 0 for now.) -DOC_PARAM(item_index, This parameter specifies which item to read, 0 is the most recent copy, 1 is the second most recent copy, etc.) -DOC_PARAM(out, This parameter provides a buffer where the clipboard contents are written. This parameter may be NULL.) -DOC_PARAM(len, This parameter specifies the length of the out buffer.) -DOC_RETURN(This call returns the size of the item associated with item_index.) - -DOC(This function always returns the size of the item even if the output buffer is NULL. If the output buffer is too small to contain the whole string, -it is filled with the first len character of the clipboard contents. The output string is not null terminated.) - -DOC_SEE(The_4coder_Clipboard) -*/{ +{ Models *models = (Models*)app->cmd_context; String_Const_u8 *str = working_set_clipboard_index(&models->working_set, item_index); String_Const_u8 result = {}; @@ -208,13 +175,7 @@ DOC_SEE(The_4coder_Clipboard) API_EXPORT Parse_Context_ID Create_Parse_Context(Application_Links *app, Parser_String_And_Type *kw, u32 kw_count, Parser_String_And_Type *pp, u32 pp_count) -/* -DOC_PARAM(kw, The list of keywords and type of each.) -DOC_PARAM(kw_count, The number of keywords in the list.) -DOC_PARAM(pp, The list of preprocessor directives and the type of each.) -DOC_PARAM(pp_count, The number of preprocessor directives in the list.) -DOC_RETURN(On success returns an id for the new parse context. If id == 0, then the maximum number of parse contexts has been reached.) -*/{ +{ Models *models = (Models*)app->cmd_context; Parse_Context_ID id = parse_context_add(&models->parse_context_memory, &models->mem.heap, kw, kw_count, pp, pp_count); return(id); @@ -222,30 +183,15 @@ DOC_RETURN(On success returns an id for the new parse context. If id == 0, then API_EXPORT i32 Get_Buffer_Count(Application_Links *app) -/* -DOC(Gives the total number of buffers in the application.) -*/{ +{ Models *models = (Models*)app->cmd_context; Working_Set *working_set = &models->working_set; return(working_set->active_file_count); } -// TODO(allen): redocument API_EXPORT Buffer_ID Get_Buffer_Next(Application_Links *app, Buffer_ID buffer_id, Access_Flag access) -/* -DOC_PARAM(buffer, The pointed to by buffer is iterated to the next buffer or to a null summary if this is the last buffer.) -DOC_PARAM(access, The access parameter determines what levels of protection this call can access. The buffer outputted will be the next buffer that is accessible.) -DOC( -This call steps a to the next buffer in the global buffer order. -The global buffer order is kept roughly in the order of most recently used to least recently used. - -If the buffer outputted does not exist, the loop is finished. -Buffers should not be killed or created durring a buffer loop. -) -DOC_SEE(Access_Flag) -DOC_SEE(get_buffer_first) -*/{ +{ Models *models = (Models*)app->cmd_context; Working_Set *working_set = &models->working_set; Editing_File *file = working_set_get_file(working_set, buffer_id); @@ -260,20 +206,9 @@ DOC_SEE(get_buffer_first) return(result); } -// TODO(allen): redocument API_EXPORT Buffer_ID Get_Buffer_By_Name(Application_Links *app, String_Const_u8 name, Access_Flag access) -/* -DOC_PARAM(name, The name parameter specifies the buffer name to try to get. The string need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the name string.) -DOC_PARAM(access, The access parameter determines what levels of protection this call can access.) -DOC_RETURN(This call returns a summary that describes the indicated buffer if it exists and is accessible.) - -DOC(This call searches the buffers by their buffer name. The buffer name is the short name in the file bar. The name must match exactly including any alterations put on the buffer name to avoid duplicates.) - -DOC_SEE(get_buffer_by_file_name) -DOC_SEE(Access_Flag) -*/{ +{ Models *models = (Models*)app->cmd_context; Working_Set *working_set = &models->working_set; Editing_File *file = working_set_contains_name(working_set, name); @@ -284,20 +219,8 @@ DOC_SEE(Access_Flag) return(result); } -// TODO(allen): redocument API_EXPORT Buffer_ID Get_Buffer_By_File_Name(Application_Links *app, String_Const_u8 file_name, Access_Flag access) -/* -DOC_PARAM(name, The name parameter specifies the buffer name to try to get. The string need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the name string.) -DOC_PARAM(access, The access parameter determines what levels of protection this call can access.) -DOC_RETURN(This call returns a summary that describes the indicated buffer if it exists and is accessible.) - -DOC(This call searches the buffers by their canonicalized file names. Not all buffers have file names, only buffers that are tied to files. For instance *scratch* does not have a file name. Every file has one canonicalized file name. For instance on windows this involves converting w:/a/b into W:\a\b. If the name passed is not canonicalized a canonicalized copy is made first. This includes turning relative paths to files that exist into full paths. So the passed in name can be relative to the working directory.) - -DOC_SEE(get_buffer_by_name) -DOC_SEE(Access_Flag) -*/ { Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; @@ -314,50 +237,27 @@ DOC_SEE(Access_Flag) return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Read_Range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, char *out) -/* -DOC_PARAM(buffer, This parameter specifies the buffer to read.) -DOC_PARAM(start, This parameter specifies absolute position of the first character in the read range.) -DOC_PARAM(one_past_last, This parameter specifies the absolute position of the the character one past the end of the read range.) -DOC_PARAM(out, This paramter provides the output character buffer to fill with the result of the read.) -DOC_RETURN(This call returns non-zero if the read succeeds.) -DOC(The output buffer must have a capacity of at least (one_past_last - start). The output is not null terminated. - -This call fails if the buffer does not exist, or if the read range is not within the bounds of the buffer.) -DOC_SEE(4coder_Buffer_Positioning_System) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); b32 result = false; if (api_check_buffer(file)){ i64 size = buffer_size(&file->state.buffer); if (0 <= range.min && range.min <= range.max && range.max <= size){ - buffer_stringify(&file->state.buffer, (i32)range.min, (i32)range.max, out); + Scratch_Block scratch(app); + String_Const_u8 string = buffer_stringify(scratch, &file->state.buffer, range); + block_copy(out, string.str, string.size); result = true; } } return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Replace_Range(Application_Links *app, Buffer_ID buffer_id, Range_i64 range, String_Const_u8 string) -/* -DOC_PARAM(buffer, This parameter specifies the buffer to edit.) -DOC_PARAM(start, This parameter specifies absolute position of the first character in the replace range.) -DOC_PARAM(one_past_last, This parameter specifies the absolute position of the the character one past the end of the replace range.) -DOC_PARAM(str, This parameter specifies the the string to write into the range; it need not be null terminated.) -DOC_PARAM(len, This parameter specifies the length of the str string.) -DOC_RETURN(This call returns non-zero if the replacement succeeds.) -DOC(If this call succeeds it deletes the range from start to one_past_last and writes str in the same position. -If one_past_last == start then this call is equivalent to inserting the string at start. -If len == 0 this call is equivalent to deleteing the range from start to one_past_last. - -This call fails if the buffer does not exist, or if the replace range is not within the bounds of the buffer.) -DOC_SEE(4coder_Buffer_Positioning_System) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); b32 result = false; @@ -365,34 +265,22 @@ DOC_SEE(4coder_Buffer_Positioning_System) i64 size = buffer_size(&file->state.buffer); if (0 <= range.first && range.first <= range.one_past_last && range.one_past_last <= size){ Edit_Behaviors behaviors = {}; - edit_single(models->system, models, file, Ii32((i32)range.min, (i32)range.max), string, behaviors); + edit_single(models, file, range, string, behaviors); result = true; } } return(result); } -// TODO(allen): redocument API_EXPORT b32 -Buffer_Batch_Edit(Application_Links *app, Buffer_ID buffer_id, char *str, Buffer_Edit *edits, i32 edit_count) -/* -DOC_PARAM(buffer, The buffer on which to apply the batch of edits.) -DOC_PARAM(str, This parameter provides all of the source string for the edits in the batch.) -DOC_PARAM(str_len, This parameter specifies the length of the str string.) -DOC_PARAM(edits, This parameter provides about the source string and destination range of each edit as an array.) -DOC_PARAM(edit_count, This parameter specifies the number of Buffer_Edit structs in edits.) -DOC_PARAM(type, This prameter specifies what type of batch edit to execute.) -DOC_RETURN(This call returns non-zero if the batch edit succeeds. This call can fail if the provided buffer summary does not refer to an actual buffer in 4coder.) -DOC(Apply an array of edits all at once. This combines all the edits into one undo operation.) -DOC_SEE(Buffer_Edit) -DOC_SEE(Buffer_Batch_Edit_Type) -*/{ +Buffer_Batch_Edit(Application_Links *app, Buffer_ID buffer_id, Batch_Edit *batch) +{ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); b32 result = false; if (api_check_buffer(file)){ Edit_Behaviors behaviors = {}; - result = edit_batch(models->system, models, file, str, edits, edit_count, behaviors); + result = edit_batch(models, file, batch, behaviors); } return(result); } @@ -410,11 +298,9 @@ Buffer_Seek_String(Application_Links *app, Buffer_ID buffer, String_Const_u8 nee else{ Scratch_Block scratch(app); Gap_Buffer *gap_buffer = &file->state.buffer; - i32 size = buffer_size(gap_buffer); - String_Const_u8 space[3]; - Cursor cursor = make_cursor(space, sizeof(space)); - String_Const_u8_Array chunks = buffer_get_chunks(&cursor, gap_buffer); - Range_i64 range = {}; + i64 size = buffer_size(gap_buffer); + List_String_Const_u8 chunks = buffer_get_chunks(scratch, gap_buffer); + Interval_i64 range = {}; if (direction == Scan_Forward){ i64 adjusted_pos = start_pos + 1; start_pos = clamp_top(adjusted_pos, size); @@ -425,8 +311,9 @@ Buffer_Seek_String(Application_Links *app, Buffer_ID buffer, String_Const_u8 nee start_pos = clamp_bot(0, adjusted_pos); range = make_range_i64(0, adjusted_pos); } - chunks = buffer_chunks_clamp(chunks, range); - if (chunks.count > 0){ + buffer_chunks_clamp(&chunks, range); + if (chunks.first != 0){ + u64_Array jump_table = string_compute_needle_jump_table(scratch, needle, direction); Character_Predicate dummy = {}; String_Match_List list = find_all_matches(scratch, 1, @@ -450,16 +337,33 @@ Buffer_Seek_Character_Class(Application_Links *app, Buffer_ID buffer, Character_ Editing_File *file = imp_get_file(models, buffer); String_Match result = {}; if (api_check_buffer(file)){ - String_Const_u8 chunks_space[2]; - Cursor chunks_cursor = make_cursor(chunks_space, sizeof(chunks_space)); + Scratch_Block scratch(app); Gap_Buffer *gap_buffer = &file->state.buffer; - String_Const_u8_Array chunks = buffer_get_chunks(&chunks_cursor, gap_buffer, BufferGetChunk_Basic); + List_String_Const_u8 chunks_list = buffer_get_chunks(scratch, gap_buffer); - if (chunks.count > 0){ - // TODO(allen): rewrite as loop-in-loop for better iteration performance - i32 size = buffer_size(gap_buffer); + if (chunks_list.node_count > 0){ + // TODO(allen): If you are reading this comment, then I haven't revisited this to tighten it up yet. + // buffer_seek_character_class was originally implemented using the chunk indexer helper + // Buffer_Chunk_Position, and it was written when buffer chunks were in an array instead + // of the new method of listing strings in a linked list. + // This should probably be implemented as a direct iteration-in-an-iteration that avoids the + // extra function calls and branches to achieve the iteration. However, this is a very easy API to + // get wrong. There are _a lot_ of opportunities for off by one errors and necessary code duplication, + // really tedious stuff. Anyway, this is all just to say, cleaning this up would be really nice, but + // there are almost certainly lower hanging fruit with higher payoffs elsewhere... unless need to change + // this anyway or whatever. + String_Const_u8 chunk_mem[3] = {}; + String_Const_u8_Array chunks = {chunk_mem}; + for (Node_String_Const_u8 *node = chunks_list.first; + node != 0; + node = node->next){ + chunks.vals[chunks.count] = node->string; + chunks.count += 1; + } + + i64 size = buffer_size(gap_buffer); start_pos = clamp(-1, start_pos, size); - Buffer_Chunk_Position pos = buffer_get_chunk_position(chunks, size, (i32)start_pos); + Buffer_Chunk_Position pos = buffer_get_chunk_position(chunks, size, start_pos); for (;;){ i32 past_end = buffer_chunk_position_iterate(chunks, &pos, direction); if (past_end == -1){ @@ -481,27 +385,137 @@ Buffer_Seek_Character_Class(Application_Links *app, Buffer_ID buffer, Character_ return(result); } -// TODO(allen): redocument -API_EXPORT Partial_Cursor -Buffer_Compute_Cursor(Application_Links *app, Buffer_ID buffer_id, Buffer_Seek seek) -/* -DOC_PARAM(buffer, The buffer parameter specifies the buffer on which to run the cursor computation.) -DOC_PARAM(seek, The seek parameter specifies the target position for the seek.) -DOC_PARAM(cursor_out, On success this struct is filled with the result of the seek.) -DOC_RETURN(This call returns non-zero on success. This call can fail if the buffer summary provided -does not summarize an actual buffer in 4coder, or if the provided seek format is invalid. The valid -seek types are seek_pos and seek_line_char.) -DOC(Computes a Partial_Cursor for the given seek position with no side effects. -The seek position must be one of the types supported by Partial_Cursor. Those -types are absolute position and line,column position.) -DOC_SEE(Buffer_Seek) -DOC_SEE(Partial_Cursor) -*/{ +API_EXPORT f32 +Buffer_Line_Y_Difference(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line_a, i64 line_b){ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); - Partial_Cursor result = {}; + f32 result = {}; if (api_check_buffer(file)){ - result = file_compute_partial_cursor(file, seek); + result = file_line_y_difference(models, file, width, face_id, line_a, line_b); + } + return(result); +} + +API_EXPORT Line_Shift_Vertical +Buffer_Line_Shift_Y(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 line, f32 y_shift){ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + Line_Shift_Vertical result = {}; + if (api_check_buffer(file)){ + result = file_line_shift_y(models, file, width, face_id, line, y_shift); + } + return(result); +} + +API_EXPORT i64 +Buffer_Pos_At_Relative_XY(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy){ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + i64 result = -1; + if (api_check_buffer(file)){ + result = file_pos_at_relative_xy(models, file, width, face_id, base_line, relative_xy); + } + return(result); +} + +API_EXPORT Vec2_f32 +Buffer_Relative_XY_Of_Pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) +{ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + Vec2_f32 result = {}; + if (api_check_buffer(file)){ + result = file_relative_xy_of_pos(models, file, width, face_id, base_line, pos); + } + return(result); +} + +API_EXPORT i64 +Buffer_Relative_Character_From_Pos(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 pos) +{ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + i64 result = {}; + if (api_check_buffer(file)){ + result = file_relative_character_from_pos(models, file, width, face_id, base_line, pos); + } + return(result); +} + +API_EXPORT i64 +Buffer_Pos_From_Relative_Character(Application_Links *app, Buffer_ID buffer_id, f32 width, Face_ID face_id, i64 base_line, i64 relative_character) +{ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + i64 result = -1; + if (api_check_buffer(file)){ + result = file_pos_from_relative_character(models, file, width, face_id, base_line, relative_character); + } + return(result); +} + +API_EXPORT f32 +View_Line_Y_Difference(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + f32 result = {}; + if (api_check_view(view)){ + result = view_line_y_difference(models, view, line_a, line_b); + } + return(result); +} + +API_EXPORT Line_Shift_Vertical +View_Line_Shift_Y(Application_Links *app, View_ID view_id, i64 line, f32 y_shift){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + Line_Shift_Vertical result = {}; + if (api_check_view(view)){ + result = view_line_shift_y(models, view, line, y_shift); + } + return(result); +} + +API_EXPORT i64 +View_Pos_At_Relative_XY(Application_Links *app, View_ID view_id, i64 base_line, Vec2_f32 relative_xy){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + i64 result = -1; + if (api_check_view(view)){ + result = view_pos_at_relative_xy(models, view, base_line, relative_xy); + } + return(result); +} + +API_EXPORT Vec2_f32 +View_Relative_XY_Of_Pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + Vec2_f32 result = {}; + if (api_check_view(view)){ + result = view_relative_xy_of_pos(models, view, base_line, pos); + } + return(result); +} + +API_EXPORT i64 +View_Relative_Character_From_Pos(Application_Links *app, View_ID view_id, i64 base_line, i64 pos){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + i64 result = {}; + if (api_check_view(view)){ + result = view_relative_character_from_pos(models, view, base_line, pos); + } + return(result); +} + +API_EXPORT i64 +View_Pos_From_Relative_Character(Application_Links *app, View_ID view_id, i64 base_line, i64 character){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + i64 result = {}; + if (api_check_view(view)){ + result = view_pos_from_relative_character(models, view, base_line, character); } return(result); } @@ -552,7 +566,7 @@ Buffer_Get_Line_Count(Application_Links *app, Buffer_ID buffer_id){ Editing_File *file = imp_get_file(models, buffer_id); u64 result = 0; if (api_check_buffer(file)){ - result = file->state.buffer.line_count; + result = buffer_line_count(&file->state.buffer); } return(result); } @@ -624,15 +638,9 @@ Buffer_Tokens_Are_Ready(Application_Links *app, Buffer_ID buffer_id){ return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Get_Setting(Application_Links *app, Buffer_ID buffer_id, Buffer_Setting_ID setting, i32 *value_out) -/* -DOC_PARAM(buffer, the buffer from which to read a setting) -DOC_PARAM(setting, the setting to read from the buffer) -DOC_PARAM(value_out, address to write the setting value on success) -DOC_RETURN(returns non-zero on success) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); b32 result = false; @@ -656,17 +664,17 @@ DOC_RETURN(returns non-zero on success) case BufferSetting_WrapLine: { - *value_out = !file->settings.unwrapped_lines; + //*value_out = !file->settings.unwrapped_lines; }break; case BufferSetting_WrapPosition: { - *value_out = file->settings.display_width; + //*value_out = file->settings.display_width; }break; case BufferSetting_MinimumBaseWrapPosition: { - *value_out = file->settings.minimum_base_display_width; + //*value_out = file->settings.minimum_base_display_width; }break; case BufferSetting_MapID: @@ -691,7 +699,9 @@ DOC_RETURN(returns non-zero on success) case BufferSetting_VirtualWhitespace: { +#if 0 *value_out = file->settings.virtual_white; +#endif }break; case BufferSetting_RecordsHistory: @@ -708,15 +718,9 @@ DOC_RETURN(returns non-zero on success) return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Set_Setting(Application_Links *app, Buffer_ID buffer_id, Buffer_Setting_ID setting, i32 value) -/* -DOC_PARAM(buffer, The buffer parameter specifies the buffer on which to set a setting.) -DOC_PARAM(setting, The setting parameter identifies the setting that shall be changed.) -DOC_PARAM(value, The value parameter specifies the value to which the setting shall be changed.) -DOC_SEE(Buffer_Setting_ID) -*/{ +{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; Editing_File *file = imp_get_file(models, buffer_id); @@ -770,11 +774,12 @@ DOC_SEE(Buffer_Setting_ID) case BufferSetting_WrapLine: { - file->settings.unwrapped_lines = !value; + //file->settings.unwrapped_lines = !value; }break; case BufferSetting_WrapPosition: { +#if 0 i32 new_value = value; if (new_value < 48){ new_value = 48; @@ -785,10 +790,12 @@ DOC_SEE(Buffer_Setting_ID) file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); } +#endif }break; case BufferSetting_MinimumBaseWrapPosition: { +#if 0 i32 new_value = value; if (new_value < 0){ new_value = 0; @@ -799,11 +806,14 @@ DOC_SEE(Buffer_Setting_ID) file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); } +#endif }break; case BufferSetting_WrapIndicator: { +#if 0 file->settings.wrap_indicator = value; +#endif }break; case BufferSetting_MapID: @@ -849,6 +859,7 @@ DOC_SEE(Buffer_Setting_ID) case BufferSetting_VirtualWhitespace: { +#if 0 b32 full_remeasure = false; if (value){ if (!file->settings.virtual_white){ @@ -873,6 +884,7 @@ DOC_SEE(Buffer_Setting_ID) file_measure_wraps(system, &models->mem, file, face); adjust_views_looking_at_file_to_new_cursor(system, models, file); } +#endif }break; case BufferSetting_RecordsHistory: @@ -899,15 +911,8 @@ DOC_SEE(Buffer_Setting_ID) return(result); } -// TODO(allen): redocument API_EXPORT Managed_Scope Buffer_Get_Managed_Scope(Application_Links *app, Buffer_ID buffer_id) -/* -DOC_PARAM(buffer_id, The id of the buffer from which to get a managed scope.) -DOC_RETURN(If the buffer_id specifies a valid buffer, the scope returned is the scope tied to the -lifetime of the buffer. This is a 'basic scope' and is not considered a 'user managed scope'. -If the buffer_id does not specify a valid buffer, the returned scope is null.) -*/ { Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); @@ -918,8 +923,6 @@ If the buffer_id does not specify a valid buffer, the returned scope is null.) return(result); } -// TODO(allen): redocument -// TODO(allen): Include warning note about pointers and editing buffers. API_EXPORT Cpp_Token_Array Buffer_Get_Token_Array(Application_Links *app, Buffer_ID buffer_id) { @@ -932,15 +935,9 @@ Buffer_Get_Token_Array(Application_Links *app, Buffer_ID buffer_id) return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Send_End_Signal(Application_Links *app, Buffer_ID buffer_id) -/* -DOC_PARAM(buffer, The buffer to which to send the end signal.) -DOC_RETURN(Returns non-zero on success. This call can fail if the buffer doesn't exist.) -DOC(Whenever a buffer is killed an end signal is sent which triggers the end file hook. This call sends the end signal to the buffer without killing the buffer. -This is useful in cases such as clearing a buffer and refilling it with new contents.) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); b32 result = false; @@ -951,22 +948,9 @@ This is useful in cases such as clearing a buffer and refilling it with new cont return(result); } -// TODO(allen): redocument API_EXPORT Buffer_ID Create_Buffer(Application_Links *app, String_Const_u8 file_name, Buffer_Create_Flag flags) -/* -DOC_PARAM(filename, The name of the file to associate to the new buffer.) -DOC_PARAM(filename_len, The length of the filename string.) -DOC_PARAM(flags, Flags controlling the buffer creation behavior.) -DOC_RETURN(Returns the newly created buffer or an already existing buffer with the given name.) -DOC( -Try to create a new buffer. This call first checks to see if a buffer already exists that goes by the given name, if so, that buffer is returned. - -If no buffer exists with the given name, then a new buffer is created. If a file that matches the given filename exists, the file is loaded as the contents of the new buffer. -Otherwise a buffer is created without a matching file until the buffer is saved and the buffer is left blank. -) -DOC_SEE(Buffer_Create_Flag) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *new_file = create_file(models, file_name, flags); Buffer_ID result = 0; @@ -976,18 +960,9 @@ DOC_SEE(Buffer_Create_Flag) return(result); } -// TODO(allen): redocument API_EXPORT b32 Buffer_Save(Application_Links *app, Buffer_ID buffer_id, String_Const_u8 file_name, Buffer_Save_Flag flags) -/* -DOC_PARAM(buffer, The buffer parameter specifies the buffer to save to a file.) -DOC_PARAM(file_name, The file_name parameter specifies the name of the file to write with the contents of the buffer; it need not be null terminated.) -DOC_PARAM(file_name_len, The file_name_len parameter specifies the length of the file_name string.) -DOC_PARAM(flags, Specifies special behaviors for the save routine.) -DOC_RETURN(This call returns non-zero on success.) -DOC(Often it will make sense to set file_name and file_name_len to buffer.file_name and buffer.file_name_len) -DOC_SEE(Buffer_Save_Flag) -*/{ +{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; Editing_File *file = imp_get_file(models, buffer_id); @@ -1014,22 +989,9 @@ DOC_SEE(Buffer_Save_Flag) return(result); } -// TODO(allen): redocument API_EXPORT Buffer_Kill_Result Buffer_Kill(Application_Links *app, Buffer_ID buffer_id, Buffer_Kill_Flag flags) -/* -DOC_PARAM(buffer, The buffer parameter specifies the buffer to try to kill.) -DOC_PARAM(flags, The flags parameter specifies behaviors for the buffer kill.) -DOC_RETURN(This call returns BufferKillResult_Killed if the call successfully kills the buffer, -for extended information on other kill results see the Buffer_Kill_Result enumeration.) - -DOC(Tries to kill the idenfied buffer, if the buffer is dirty or does not exist then nothing will -happen. The default rules about when to kill or not kill a buffer can be altered by the flags.) - -DOC_SEE(Buffer_Kill_Result) -DOC_SEE(Buffer_Kill_Flag) -DOC_SEE(Buffer_Identifier) -*/{ +{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; Working_Set *working_set = &models->working_set; @@ -1052,24 +1014,22 @@ DOC_SEE(Buffer_Identifier) Layout *layout = &models->layout; - Node *used = &working_set->active_file_sentinel; - Node *file_node = used->next; + Node *order = &working_set->touch_order_sentinel; + Node *file_node = order->next; for (Panel *panel = layout_get_first_open_panel(layout); panel != 0; panel = layout_get_next_open_panel(layout, panel)){ View *view = panel->view; if (view->file == file){ - Assert(file_node != used); + Assert(file_node != order); view->file = 0; - Editing_File *new_file = CastFromMember(Editing_File, main_chain_node, file_node); + Editing_File *new_file = CastFromMember(Editing_File, touch_node, file_node); view_set_file(system, models, view, new_file); - if (file_node->next != used){ + file_node = file_node->next; + if (file_node == order){ file_node = file_node->next; } - else{ - file_node = file_node->next->next; - Assert(file_node != used); - } + Assert(file_node != order); } } @@ -1122,9 +1082,9 @@ Buffer_Reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl if (view_it->file == file){ vptrs[vptr_count] = view_it; File_Edit_Positions edit_pos = view_get_edit_pos(view_it); - Full_Cursor cursor = file_compute_cursor(models, view_it->file, seek_pos(edit_pos.cursor_pos)); + Buffer_Cursor cursor = file_compute_cursor(view_it->file, seek_pos(edit_pos.cursor_pos)); line_numbers[vptr_count] = (i32)cursor.line; - column_numbers[vptr_count] = (i32)cursor.character; + column_numbers[vptr_count] = (i32)cursor.col; view_it->file = models->scratch_buffer; ++vptr_count; } @@ -1133,15 +1093,16 @@ Buffer_Reopen(Application_Links *app, Buffer_ID buffer_id, Buffer_Reopen_Flag fl Working_Set *working_set = &models->working_set; file_free(system, &models->mem.heap, &models->lifetime_allocator, working_set, file); working_set_file_default_settings(working_set, file); - file_create_from_string(system, models, file, SCu8(file_memory, attributes.size), attributes); + file_create_from_string(models, file, SCu8(file_memory, attributes.size), attributes); for (i32 i = 0; i < vptr_count; ++i){ view_set_file(system, models, vptrs[i], file); vptrs[i]->file = file; - Full_Cursor cursor = file_compute_cursor(models, file, seek_line_char(line_numbers[i], column_numbers[i])); - - view_set_cursor(system, models, vptrs[i], cursor, true); + i64 line = line_numbers[i]; + i64 col = column_numbers[i]; + Buffer_Cursor cursor = file_compute_cursor(file, seek_line_col(line, col)); + view_set_cursor(models, vptrs[i], cursor.pos); } result = BufferReopenResult_Reopened; } @@ -1218,22 +1179,9 @@ get_view_prev__inner(Layout *layout, View *view){ return(view); } -// TODO(allen): redocument API_EXPORT View_ID Get_View_Next(Application_Links *app, View_ID view_id, Access_Flag access) -/* -DOC_PARAM(view, The pointed to by view is iterated to the next view or to a null summary if this is the last view.) -DOC_PARAM(access, The access parameter determines what levels of protection this call can access. The view outputted will be the next view that is accessible.) -DOC -( -This call steps a to the next view in the global view order. - -If the view outputted does not exist, the loop is finished. -Views should not be closed or opened durring a view loop. -) -DOC_SEE(Access_Flag) -DOC_SEE(get_view_first) -*/{ +{ Models *models = (Models*)app->cmd_context; Layout *layout = &models->layout; View *view = imp_get_view(models, view_id); @@ -1265,15 +1213,9 @@ Get_View_Prev(Application_Links *app, View_ID view_id, Access_Flag access) return(result); } -// TODO(allen): redocument API_EXPORT View_ID Get_Active_View(Application_Links *app, Access_Flag access) -/* -DOC_PARAM(access, The access parameter determines what levels of protection this call can access.) -DOC_RETURN(This call returns a summary that describes the active view.) -DOC_SEE(set_active_view) -DOC_SEE(Access_Flag) -*/{ +{ Models *models = (Models*)app->cmd_context; Panel *panel = layout_get_active_panel(&models->layout); Assert(panel != 0); @@ -1561,19 +1503,9 @@ Panel_Get_Margin(Application_Links *app, Panel_ID panel_id){ return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Close(Application_Links *app, View_ID view_id) -/* -DOC_PARAM(view, The view parameter specifies which view to close.) -DOC_RETURN(This call returns non-zero on success.) - -DOC(If the given view is open and is not the last view, it will be closed. -If the given view is the active view, the next active view in the global -order of view will be made active. If the given view is the last open view -in the system, the call will fail.) - -*/{ +{ Models *models = (Models*)app->cmd_context; Layout *layout = &models->layout; View *view = imp_get_view(models, view_id); @@ -1598,16 +1530,13 @@ View_Get_Buffer_Region(Application_Links *app, View_ID view_id){ return(result); } -API_EXPORT GUI_Scroll_Vars -View_Get_Scroll_Vars(Application_Links *app, View_ID view_id){ +API_EXPORT Buffer_Scroll +View_Get_Buffer_Scroll(Application_Links *app, View_ID view_id){ Models *models = (Models*)app->cmd_context; + Buffer_Scroll result = {}; View *view = imp_get_view(models, view_id); - GUI_Scroll_Vars result = {}; if (api_check_view(view)){ - if (view->ui_mode){ - result = view->ui_scroll; - } - else{ + if (!view->ui_mode){ File_Edit_Positions edit_pos = view_get_edit_pos(view); result = edit_pos.scroll; } @@ -1615,17 +1544,22 @@ View_Get_Scroll_Vars(Application_Links *app, View_ID view_id){ return(result); } -// TODO(allen): redocument +API_EXPORT Basic_Scroll +View_Get_Basic_Scroll(Application_Links *app, View_ID view_id){ + Models *models = (Models*)app->cmd_context; + Basic_Scroll result = {}; + View *view = imp_get_view(models, view_id); + if (api_check_view(view)){ + if (view->ui_mode){ + result = view->ui_scroll; + } + } + return(result); +} + API_EXPORT b32 View_Set_Active(Application_Links *app, View_ID view_id) -/* -DOC_PARAM(view, The view parameter specifies which view to make active.) -DOC_RETURN(This call returns non-zero on success.) -DOC(If the given view is open, it is set as the -active view, and takes subsequent commands and is returned -from get_active_view.) -DOC_SEE(get_active_view) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; @@ -1636,15 +1570,9 @@ DOC_SEE(get_active_view) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Get_Setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 *value_out) -/* -DOC_PARAM(view, the view from which to read a setting) -DOC_PARAM(setting, the view setting to read) -DOC_PARAM(value_out, address to write the setting value on success) -DOC_RETURN(returns non-zero on success) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1681,16 +1609,9 @@ DOC_RETURN(returns non-zero on success) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Set_Setting(Application_Links *app, View_ID view_id, View_Setting_ID setting, i32 value) -/* -DOC_PARAM(view, The view parameter specifies the view on which to set a setting.) -DOC_PARAM(setting, The setting parameter identifies the setting that shall be changed.) -DOC_PARAM(value, The value parameter specifies the value to which the setting shall be changed.) -DOC_RETURN(This call returns non-zero on success.) -DOC_SEE(View_Setting_ID) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1700,17 +1621,17 @@ DOC_SEE(View_Setting_ID) switch (setting){ case ViewSetting_ShowWhitespace: { - view->show_whitespace = value; + view->show_whitespace = (b8)value; }break; case ViewSetting_ShowScrollbar: { - view->hide_scrollbar = !value; + view->hide_scrollbar = (b8)!value; }break; case ViewSetting_ShowFileBar: { - view->hide_file_bar = !value; + view->hide_file_bar = (b8)!value; }break; case ViewSetting_UICommandMap: @@ -1727,15 +1648,8 @@ DOC_SEE(View_Setting_ID) return(result); } -// TODO(allen): redocument API_EXPORT Managed_Scope View_Get_Managed_Scope(Application_Links *app, View_ID view_id) -/* -DOC_PARAM(view_id, The id of the view from which to get a managed scope.) -DOC_RETURN(If the view_id specifies a valid view, the scope returned is the scope tied to the -lifetime of the view. This is a 'basic scope' and is not considered a 'user managed scope'. -If the view_id does not specify a valid view, the returned scope is null.) -*/ { Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1747,48 +1661,21 @@ If the view_id does not specify a valid view, the returned scope is null.) return(result); } -// TODO(allen): redocument -API_EXPORT Full_Cursor -View_Compute_Cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek) -/* -DOC_PARAM(view, The view parameter specifies the view on which to run the cursor computation.) -DOC_PARAM(seek, The seek parameter specifies the target position for the seek.) -DOC_PARAM(cursor_out, On success this struct is filled with the result of the seek.) -DOC_RETURN(This call returns non-zero on success.) -DOC(Computes a Full_Cursor for the given seek position with no side effects.) -DOC_SEE(Buffer_Seek) -DOC_SEE(Full_Cursor) -*/{ +API_EXPORT Buffer_Cursor +Buffer_Compute_Cursor(Application_Links *app, Buffer_ID buffer, Buffer_Seek seek) +{ Models *models = (Models*)app->cmd_context; - View *view = imp_get_view(models, view_id); - Full_Cursor result = {}; - if (api_check_view(view)){ - Editing_File *file = view->file; - if (api_check_buffer(file)){ - if (file->settings.unwrapped_lines && seek.type == buffer_seek_wrapped_xy){ - seek.type = buffer_seek_unwrapped_xy; - } - result = file_compute_cursor(models, file, seek); - if (file->settings.unwrapped_lines){ - result.wrapped_x = result.unwrapped_x; - result.wrapped_y = result.unwrapped_y; - } - } + Editing_File *file = imp_get_file(models, buffer); + Buffer_Cursor result = {}; + if (api_check_buffer(file)){ + result = file_compute_cursor(file, seek); } return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Set_Cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek, b32 set_preferred_x) -/* -DOC_PARAM(view, The view parameter specifies the view in which to set the cursor.) -DOC_PARAM(seek, The seek parameter specifies the target position for the seek.) -DOC_PARAM(set_preferred_x, If this parameter is true the preferred x is updated to match the new cursor x.) -DOC_RETURN(This call returns non-zero on success.) -DOC(This call sets the the view's cursor position. set_preferred_x should usually be true unless the change in cursor position is is a vertical motion that tries to keep the cursor in the same column or x position.) -DOC_SEE(Buffer_Seek) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; @@ -1796,55 +1683,65 @@ DOC_SEE(Buffer_Seek) Editing_File *file = view->file; Assert(file != 0); if (api_check_buffer(file)){ - if (file->settings.unwrapped_lines && seek.type == buffer_seek_wrapped_xy){ - seek.type = buffer_seek_unwrapped_xy; + Buffer_Cursor cursor = file_compute_cursor(file, seek); + f32 preferred_x = 0.f; + if (!set_preferred_x){ + preferred_x = view->preferred_x; + } + view_set_cursor(models, view, cursor.pos); + if (!set_preferred_x){ + view->preferred_x = preferred_x; } - Full_Cursor cursor = file_compute_cursor(models, file, seek); - view_set_cursor(models->system, models, view, cursor, set_preferred_x); result = true; } } return(result); } -// TODO(allen): redocument API_EXPORT b32 -View_Set_Scroll(Application_Links *app, View_ID view_id, GUI_Scroll_Vars scroll) -/* -DOC_PARAM(view, The view on which to change the scroll state.) -DOC_PARAM(scroll, The new scroll position for the view.) -DOC(Set the scrolling state of the view.) -DOC_SEE(GUI_Scroll_Vars) -*/{ +View_Set_Buffer_Scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll) +{ Models *models = (Models*)app->cmd_context; - View *view = imp_get_view(models, view_id); b32 result = false; + View *view = imp_get_view(models, view_id); if (api_check_view(view)){ - Editing_File *file = view->file; - Assert(file != 0); - if (api_check_buffer(file)){ - if (!view->ui_mode){ - view_set_scroll(models->system, models, view, scroll); - } - else{ - view->ui_scroll = scroll; - } + if (!view->ui_mode){ + scroll.position = view_normalize_buffer_point(models, view, scroll.position); + scroll.target = view_normalize_buffer_point(models, view, scroll.target); + scroll.target.pixel_shift.x = f32_round32(scroll.target.pixel_shift.x); + scroll.target.pixel_shift.y = f32_round32(scroll.target.pixel_shift.y); + scroll.target.pixel_shift.x = clamp_bot(0.f, scroll.target.pixel_shift.x); + Buffer_Layout_Item_List line = view_get_line_layout(models, view, scroll.target.line_number); + scroll.target.pixel_shift.y = clamp(0.f, scroll.target.pixel_shift.y, line.height); + view_set_scroll(models, view, scroll); + view->new_scroll_target = true; + result = true; + } + } + return(result); +} + +API_EXPORT b32 +View_Set_Basic_Scroll(Application_Links *app, View_ID view_id, Basic_Scroll scroll) +{ + Models *models = (Models*)app->cmd_context; + b32 result = false; + View *view = imp_get_view(models, view_id); + if (api_check_view(view)){ + if (view->ui_mode){ + scroll.target.x = f32_round32(scroll.target.x); + scroll.target.y = f32_round32(scroll.target.y); + view->ui_scroll = scroll; + view->new_scroll_target = true; result = true; } } return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Set_Mark(Application_Links *app, View_ID view_id, Buffer_Seek seek) -/* -DOC_PARAM(view, The view parameter specifies the view in which to set the mark.) -DOC_PARAM(seek, The seek parameter specifies the target position for the seek.) -DOC_RETURN(This call returns non-zero on success.) -DOC(This call sets the the view's mark position.) -DOC_SEE(Buffer_Seek) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1854,7 +1751,7 @@ DOC_SEE(Buffer_Seek) Assert(file != 0); if (api_check_buffer(file)){ if (seek.type != buffer_seek_pos){ - Full_Cursor cursor = file_compute_cursor(models, file, seek); + Buffer_Cursor cursor = file_compute_cursor(file, seek); view->mark = cursor.pos; } else{ @@ -1866,17 +1763,9 @@ DOC_SEE(Buffer_Seek) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Set_Buffer(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags) -/* -DOC_PARAM(view, The view parameter specifies the view in which to display the buffer.) -DOC_PARAM(buffer_id, The buffer_id parameter specifies which buffer to show in the view.) -DOC_PARAM(flags, The flags parameter specifies behaviors for setting the buffer.) -DOC_RETURN(This call returns non-zero on success.) -DOC(On success view_set_buffer sets the specified view's current buffer and cancels and dialogue shown in the view and displays the file.) -DOC_SEE(Set_Buffer_Flag) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; @@ -1895,18 +1784,9 @@ DOC_SEE(Set_Buffer_Flag) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Post_Fade(Application_Links *app, View_ID view_id, f32 seconds, Range_i64 range, int_color color) -/* -DOC_PARAM(view, The view parameter specifies the view onto which the fade effect shall be posted.) -DOC_PARAM(seconds, This parameter specifies the number of seconds the fade effect should last.) -DOC_PARAM(start, This parameter specifies the absolute position of the first character of the fade range.) -DOC_PARAM(end, This parameter specifies the absolute position of the character one past the end of the fdae range.) -DOC_PARAM(color, The color parameter specifies the initial color of the text before it fades to it's natural color.) -DOC_RETURN(This call returns non-zero on success.) -DOC_SEE(int_color) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; @@ -1920,16 +1800,8 @@ DOC_SEE(int_color) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Begin_UI_Mode(Application_Links *app, View_ID view_id) -/* -DOC_PARAM(view, A summary for the view which is to be placed into UI mode.) -DOC_RETURN(This call returns non-zero on success. It can fail if view is invalid, or if the view is already in UI mode.) -DOC(In UI mode, the view no longer renders it's buffer. Instead it renders UI elements attached to the view. The UI elements attached to a view can be modified by a view_set_ui call.) -DOC_SEE(view_end_ui_mode) -DOC_SEE(view_set_ui) -*/ { Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1943,17 +1815,8 @@ DOC_SEE(view_set_ui) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_End_UI_Mode(Application_Links *app, View_ID view_id) -/* -DOC_PARAM(view, A summary for the view which is to be taken out of UI mode.) -DOC_RETURN(This call returns non-zero on success. It can fail if view is invalid, or if the view is not in UI mode.) -DOC(Taking a view out of UI mode not only causes it to resume showing a buffer, but also sends a quit UI signal. -The exit signal calls the quit_function that is set by a view_set_ui call.) -DOC_SEE(view_begin_ui_mode) -DOC_SEE(view_set_ui) -*/ { Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -1977,20 +1840,8 @@ View_Is_In_UI_Mode(Application_Links *app, View_ID view_id){ return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Set_Quit_UI_Handler(Application_Links *app, View_ID view_id, UI_Quit_Function_Type *quit_function) -/* -DOC_PARAM(view, A summary for the view which is to get the new UI widget data.) -DOC_PARAM(control, A pointer to the baked UI widget data. To get data in the UI_Control format see the helper called ui_list_to_ui_control. More information about specifying widget data can be found in a comment in '4coder_ui_helper.cpp'. If this pointer is null the view's widget data is cleared to zero. The core maintains it's own copy of the widget data, so after this call the memory used to specify widget data may be freed.) -DOC_PARAM(quit_function, A function pointer to be called when a quit UI signal is sent to the view. This pointer may be set to null.) -DOC_RETURN(This call returns non-zero on success. It can fail if view is invalid.) -DOC(Setting the UI widget data determines what the view will look like in UI mode. The UI widget data can be set no matter what the current mode is. The UI widget data can be replaced any number of times regardless of whether the view is in UI mode or not. See documentation on the UI widget data type UI_Control and the comments at the top of '4coder_ui_helper.cpp' for more information about the types of widgets that can be used.) -DOC_SEE(view_begin_ui_mode) -DOC_SEE(view_end_ui_mode) -DOC_SEE(UI_Control) -DOC_SEE(UI_Quit_Function_Type) -*/ { Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -2002,15 +1853,8 @@ DOC_SEE(UI_Quit_Function_Type) return(result); } -// TODO(allen): redocument API_EXPORT b32 View_Get_Quit_UI_Handler(Application_Links *app, View_ID view_id, UI_Quit_Function_Type **quit_function_out) -/* -DOC_PARAM(view, A summary for the view which is to get the new UI widget data.) -DOC_PARAM(part, A memory arena onto which the UI widget data will be allocated.) -DOC_RETURN(If the view is valid, and there is enough space in part, then the UI_Control stucture returned points to a copy of the widget data currently attached to the view.) -DOC_SEE(view_set_ui) -*/ { Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); @@ -2033,10 +1877,6 @@ get_dynamic_workspace(Models *models, Managed_Scope handle){ API_EXPORT Managed_Scope Create_User_Managed_Scope(Application_Links *app) -/* -DOC_RETURN(Always returns a newly created scope with a handle that is unique from all other scopes that have been created either by the core or the custom layer. The new scope is a 'basic scope' and is a 'user managed scope'.) -DOC_SEE(destroy_user_managed_scope) -*/ { Models *models = (Models*)app->cmd_context; Heap *heap = &models->mem.heap; @@ -2048,12 +1888,6 @@ DOC_SEE(destroy_user_managed_scope) API_EXPORT b32 Destroy_User_Managed_Scope(Application_Links *app, Managed_Scope scope) -/* -DOC_PARAM(scope, The handle for the scope which is to be destroyed) -DOC_RETURN(If the scope is a valid 'user managed scope' this function returns non-zero, otherwise it returns zero.) -DOC(This call only operates on 'user managed scopes'. 'User managed scopes' are those scopes created by create_user_managed_scope. Scopes tied to views, and buffers, and the global scope are not 'user managed scopes'.) -DOC_SEE(create_user_managed_scope) -*/ { Models *models = (Models*)app->cmd_context; Dynamic_Workspace *workspace = get_dynamic_workspace(models, scope); @@ -2068,9 +1902,6 @@ DOC_SEE(create_user_managed_scope) API_EXPORT Managed_Scope Get_Global_Managed_Scope(Application_Links *app) -/* -DOC_RETURN(Always returns the handle to the 'global scope'. The 'global scope' is unique in that it is not dependent on any object at all. The handle for the 'global scope' never changes in a 4coder session, and when used as a dependency in get_managed_scope_with_multiple_dependencies it has no effect.) -*/ { Models *models = (Models*)app->cmd_context; return((Managed_Scope)models->dynamic_workspace.scope_id); @@ -2104,13 +1935,6 @@ get_lifetime_object_from_workspace(Dynamic_Workspace *workspace){ API_EXPORT Managed_Scope Get_Managed_Scope_With_Multiple_Dependencies(Application_Links *app, Managed_Scope *scopes, i32 count) -/* -DOC_PARAM(scopes, An array of scope handles which are to represent the various dependencies that the returned scope will have.) -DOC_PARAM(count, The number of scopes in the scopes array) -DOC_RETURN(Always returns the handle to a scope with the appropriate dependencies.) -DOC(Scopes with multiple dependencies are a subtle topic, for a full treatment please read -https://4coder.handmade.network/blogs/p/3412-new_features_p3__memory_management_scopes) -*/ { Models *models = (Models*)app->cmd_context; Lifetime_Allocator *lifetime_allocator = &models->lifetime_allocator; @@ -2199,11 +2023,6 @@ https://4coder.handmade.network/blogs/p/3412-new_features_p3__memory_management_ API_EXPORT b32 Managed_Scope_Clear_Contents(Application_Links *app, Managed_Scope scope) -/* -DOC_PARAM(scope, A handle to the scope which is to be cleared.) -DOC_RETURN(Returns non-zero on succes, and zero on failure. This call fails when the scope handle does not refer to a valid scope.) -DOC(Clearing the contents of a scope resets all managed variables to have their default values, and frees all managed objects. The scope handle remains valid and refers to the same scope which still has the same dependencies.) -*/ { Models *models = (Models*)app->cmd_context; Dynamic_Workspace *workspace = get_dynamic_workspace(models, scope); @@ -2217,13 +2036,6 @@ DOC(Clearing the contents of a scope resets all managed variables to have their API_EXPORT b32 Managed_Scope_Clear_Self_All_Dependent_Scopes(Application_Links *app, Managed_Scope scope) -/* -DOC_PARAM(scope, A handle to the 'basic scope' which is to be cleared.) -DOC_RETURN(Returns non-zero on succes, and zero on failure. This call fails when the scope handle does not refer to a valid 'basic scope'.) -DOC(The parameter scope must be a 'basic scope' which means a scope with a single dependency. Scopes tied to buffers and view, and 'user managed scopes' are the 'basic scopes'. This call treats the scope as an identifier for the single object up which the scope depends, and clears all scopes that depend on that object, this includes clearing 'scope' itself. The scopes returned from get_managed_scope_with_multiple_dependencies that included 'scope' via the union rule are the only other scopes that can be cleared by this call. -For more on the union rule read the full treatment of managed scopes -https://4coder.handmade.network/blogs/p/3412-new_features_p3__memory_management_scopes) -*/ { Models *models = (Models*)app->cmd_context; Dynamic_Workspace *workspace = get_dynamic_workspace(models, scope); @@ -2239,14 +2051,6 @@ https://4coder.handmade.network/blogs/p/3412-new_features_p3__memory_management_ API_EXPORT Managed_Variable_ID Managed_Variable_Create(Application_Links *app, char *null_terminated_name, u64 default_value) -/* -DOC_PARAM(null_terminated_name, The unique name for this managed variable.) -DOC_PARAM(default_value, The default value that this variable will have in a scope that has not set this variable.) -DOC_RETURN(Returns the Managed_Variable_ID for the new variable on success and zero on failure. This call fails when a variable with the given name alraedy exists.) -DOC(Variables are stored in scopes but creating a variable does not mean that all scopes will allocate space for this variable. Space for variables is allocated sparsly on demand in each scope. Once a variable exists it will exist for the entire duration of the 4coder session and will never have a different id. The id will be used to set and get the value of the variable in managed scopes.) -DOC_SEE(managed_variable_get_id) -DOC_SEE(managed_variable_create_or_get_id) -*/ { Models *models = (Models*)app->cmd_context; Heap *heap = &models->mem.heap; @@ -2256,12 +2060,6 @@ DOC_SEE(managed_variable_create_or_get_id) API_EXPORT Managed_Variable_ID Managed_Variable_Get_ID(Application_Links *app, char *null_terminated_name) -/* -DOC_PARAM(null_terminated_name, The unique name for this managed variable.) -DOC_RETURN(Returns the Managed_Variable_ID for the variable on success and zero on failure. This call fails when no variable that already exists has the given name.) -DOC_SEE(managed_variable_create) -DOC_SEE(managed_variable_create_or_get_id) -*/ { Models *models = (Models*)app->cmd_context; Dynamic_Variable_Layout *layout = &models->variable_layout; @@ -2270,14 +2068,6 @@ DOC_SEE(managed_variable_create_or_get_id) API_EXPORT Managed_Variable_ID Managed_Variable_Create_Or_Get_ID(Application_Links *app, char *null_terminated_name, u64 default_value) -/* -DOC_PARAM(null_terminated_name, The unique name for this managed variable.) -DOC_PARAM(default_value, The default value that this variable will have in a scope that has not set this variable. This parameter is ignored if the variable already exists.) -DOC_RETURN(Returns the Managed_Variable_ID for the variable on success, this call never fails.) -DOC(This call first tries to get the variable id in the same way that managed_variable_get_id would, if this fails it creates the variable and returns the new id in the way that managed_variable_create would. ) -DOC_SEE(managed_variable_create) -DOC_SEE(managed_variable_get_id) -*/ { Models *models = (Models*)app->cmd_context; Heap *heap = &models->mem.heap; @@ -2301,12 +2091,6 @@ get_dynamic_variable__internal(Models *models, Managed_Scope handle, i32 locatio API_EXPORT b32 Managed_Variable_Set(Application_Links *app, Managed_Scope scope, Managed_Variable_ID id, u64 value) -/* -DOC_PARAM(scope, A handle to the scope in which the value of the given variable will be set.) -DOC_PARAM(id, The id of the variable to set.) -DOC_PARAM(value, The new value of the variable.) -DOC_RETURN(Returns non-zero on success. This call fails if scope does not refer to a valid managed scope, or id does not refer to an existing managed variable.) -*/ { Models *models = (Models*)app->cmd_context; u64 *ptr = 0; @@ -2320,12 +2104,6 @@ DOC_RETURN(Returns non-zero on success. This call fails if scope does not refer API_EXPORT b32 Managed_Variable_Get(Application_Links *app, Managed_Scope scope, Managed_Variable_ID id, u64 *value_out) -/* -DOC_PARAM(scope, A handle to the scope from which the value of the given variable will be queried.) -DOC_PARAM(id, The id of the variable to get.) -DOC_PARAM(value_out, An address where the value of the given variable in the given scope will be stored.) -DOC_RETURN(Returns non-zero on success. This call fails if scope does not refer to a valid managed scope, or id does not refer to an existing managed variable. If the managed scope and managed variable both exist, but the variable has never been set, then the default value for the variable that was determined when the variable was created is used to fill value_out, this is treated as a success and returns non-zero.) -*/ { Models *models = (Models*)app->cmd_context; u64 *ptr = 0; @@ -2339,13 +2117,6 @@ DOC_RETURN(Returns non-zero on success. This call fails if scope does not refer API_EXPORT Managed_Object Alloc_Managed_Memory_In_Scope(Application_Links *app, Managed_Scope scope, i32 item_size, i32 count) -/* -DOC_PARAM(scope, A handle to the scope in which the new object will be allocated.) -DOC_PARAM(item_size, The size, in bytes, of a single 'item' in this memory object. This effects the size of the allocation, and the indexing of the memory in the store and load calls.) -DOC_PARAM(count, The number of 'items' allocated for this memory object. The total memory size is item_size*count.) -DOC_RETURN(Returns the handle to the new object on success, and zero on failure. This call fails if scope does not refer to a valid managed scope.) -DOC(Managed objects allocate memory that is tied to the scope. When the scope is cleared or destroyed all of the memory allocated in it is freed in bulk and the handles to the objects never again become valid. Thus the handle returned by this call will only ever refer to this memory allocation.) -*/ { Models *models = (Models*)app->cmd_context; Dynamic_Workspace *workspace = get_dynamic_workspace(models, scope); @@ -2358,15 +2129,6 @@ DOC(Managed objects allocate memory that is tied to the scope. When the scope i API_EXPORT Managed_Object Alloc_Buffer_Markers_On_Buffer(Application_Links *app, Buffer_ID buffer_id, i32 count, Managed_Scope *optional_extra_scope) -/* -DOC_PARAM(buffer_id, The id for the buffer onto which these markers will be attached. The markers will live in the scope of the buffer, or in another scope dependent on this buffer, thus guaranteeing that when the buffer is closed, all attached markers are freed in bulk with it.) -DOC_PARAM(count, The number of Marker items allocated in this object. The total memory size is sizeof(Marker)*count.) -DOC_PARAM(optional_extra_scope, If this pointer is non-null, then it is treated as a scope with additional dependencies for the allocated markers. In this case, the scope of buffer and extra scope are unioned via get_managed_scope_with_multiple_dependencies and marker object lives in the resulting scope.) -DOC_RETURN(Returns the handle to the new object on succes, and zero on failure. This call fails if buffer_id does not refer to a valid buffer, or optional_extra_scope does not refer to a valid scope.) -DOC(The created managed object is essentially a memory object with item size equal to sizeof(Marker). The primary difference is that if the buffer referred to by buffer_id is edited, the position of all markers attached to that buffer can be changed by the core. Thus this not a memory storage so much as position marking and tracking in a buffer.) -DOC_SEE(alloc_managed_memory_in_scope) -DOC_SEE(Marker) -*/ { Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); @@ -2414,10 +2176,6 @@ get_dynamic_object_ptrs(Models *models, Managed_Object object){ API_EXPORT u32 Managed_Object_Get_Item_Size(Application_Links *app, Managed_Object object) -/* -DOC_PARAM(object, The handle to the managed object to be queried.) -DOC_RETURN(Returns the size, in bytes, of a single item in the managed object. Item size is multiplied by the indices in store and load calls, and it is multiplied by item count to discover the total memory size of the managed object. If object does not refer to a valid managed object, this call returns zero.) -*/ { Models *models = (Models*)app->cmd_context; Managed_Object_Ptr_And_Workspace object_ptrs = get_dynamic_object_ptrs(models, object); @@ -2430,10 +2188,6 @@ DOC_RETURN(Returns the size, in bytes, of a single item in the managed object. API_EXPORT u32 Managed_Object_Get_Item_Count(Application_Links *app, Managed_Object object) -/* -DOC_PARAM(object, The handle to the managed object to be queried.) -DOC_RETURN(Returns the count of items this object can store, this count is used to range check the indices in store and load calls. If object does not refer to a valid managed object, this call returns zero.) -*/ { Models *models = (Models*)app->cmd_context; Managed_Object_Ptr_And_Workspace object_ptrs = get_dynamic_object_ptrs(models, object); @@ -2446,11 +2200,6 @@ DOC_RETURN(Returns the count of items this object can store, this count is used API_EXPORT Managed_Object_Type Managed_Object_Get_Type(Application_Links *app, Managed_Object object) -/* -DOC_PARAM(object, The handle to the managed object to be queried.) -DOC_RETURN(Returns the type of the managed object, see Managed_Object_Type for the enumeration of possible values and their special meanings. If object does not refer to a valid managed object, this call returns ManagedObjectType_Error.) -DOC_SEE(Managed_Object_Type) -*/ { Models *models = (Models*)app->cmd_context; Managed_Object_Ptr_And_Workspace object_ptrs = get_dynamic_object_ptrs(models, object); @@ -2466,10 +2215,6 @@ DOC_SEE(Managed_Object_Type) API_EXPORT Managed_Scope Managed_Object_Get_Containing_Scope(Application_Links *app, Managed_Object object) -/* -DOC_PARAM(object, The handle to the managed object to be queried.) -DOC_RETURN(Returns a handle to the managed scope in which this object is allocated, or zero if object does not refer to a valid managed object.) -*/ { Models *models = (Models*)app->cmd_context; u32 hi_id = (object >> 32)&max_u32; @@ -2482,11 +2227,6 @@ DOC_RETURN(Returns a handle to the managed scope in which this object is allocat API_EXPORT b32 Managed_Object_Free(Application_Links *app, Managed_Object object) -/* -DOC_PARAM(object, The handle to the managed object to be freed.) -DOC_RETURN(Returns non-zero on success and zero on failure. This call fails when object does not refer to a valid managed object.) -DOC(Permanently frees the specified object. Not only does this free up the memory this object had allocated, but it also triggers cleanup for some types of managed objects. For instance after markers are freed, any visual effects from the markers are removed as well. See Managed_Object_Type for more information about what cleanup each type performs when it is freed.) - */ { Models *models = (Models*)app->cmd_context; u32 hi_id = (object >> 32)&max_u32; @@ -2500,16 +2240,6 @@ DOC(Permanently frees the specified object. Not only does this free up the memo API_EXPORT b32 Managed_Object_Store_Data(Application_Links *app, Managed_Object object, u32 first_index, u32 count, void *mem) -/* -DOC_PARAM(object, The handle to the managed object in which data will be stored.) -DOC_PARAM(first_index, The first index of the range in the managed object to be stored. Managed object indics are zero based.) -DOC_PARAM(count, The number of items in the managed object to be stored.) -DOC_PARAM(mem, A pointer to the data to be stored, it is expected that the size of this memory is item_size*count, item_size can be queried with managed_object_get_item_size.) -DOC_RETURN(Returns non-zero on success and zero on failure. This call fails when object does not refer to a valid managed object, and when the range of indices overflows the range of this managed object. The range of the managed object can be queried with managed_object_get_item_count.) -DOC(All managed objects, in addition to whatever special behaviors they have, have the ability to store and load data. This storage can have special properties in certain managed object types, for instance, the data stored in marker objects are edited by the core when the buffer to which they are attached is edited. This call stores the data pointed to by mem into the item range specified by first_index and count.) -DOC_SEE(managed_object_get_item_size) -DOC_SEE(managed_object_get_item_count) -*/ { Models *models = (Models*)app->cmd_context; Managed_Object_Ptr_And_Workspace object_ptrs = get_dynamic_object_ptrs(models, object); @@ -2529,16 +2259,6 @@ DOC_SEE(managed_object_get_item_count) API_EXPORT b32 Managed_Object_Load_Data(Application_Links *app, Managed_Object object, u32 first_index, u32 count, void *mem_out) -/* -DOC_PARAM(object, The handle to the managed object from which data will be loaded.) -DOC_PARAM(first_index, The first index of the range in the managed object to be loaded. Managed object indics are zero based.) -DOC_PARAM(count, The number of items in the managed object to be loaded.) -DOC_PARAM(mem_out, A pointer to the memory where loaded data will be written, it is expected that the size of this memory is item_size*count, item_size can be queried with managed_object_get_item_size.) -DOC_RETURN(Returns non-zero on success and zero on failure. This call fails when object does not refer to a valid managed object, and when the range of indices overflows the range of this managed object. The range of the managed object can be queried with managed_object_get_item_count.) -DOC(All managed objects, in addition to whatever special behaviors they have, have the ability to store and load data. This storage can have special properties in certain managed object types, for instance, the data stored in marker objects are edited by the core when the buffer to which they are attached is edited. This call loads the data from the item range specified by first_index and count into mem_out.) -DOC_SEE(managed_object_get_item_size) -DOC_SEE(managed_object_get_item_count) -*/ { Models *models = (Models*)app->cmd_context; Managed_Object_Ptr_And_Workspace object_ptrs = get_dynamic_object_ptrs(models, object); @@ -2558,20 +2278,7 @@ DOC_SEE(managed_object_get_item_count) API_EXPORT User_Input Get_User_Input(Application_Links *app, Input_Type_Flag get_type, Input_Type_Flag abort_type) -/* -DOC_PARAM(get_type, The get_type parameter specifies the set of input types that should be returned.) -DOC_PARAM(abort_type, The get_type parameter specifies the set of input types that should trigger an abort signal.) -DOC_RETURN(This call returns a User_Input that describes a user input event.) -DOC( -This call preempts the command. The command is resumed if either a get or abort condition -is met, or if another command is executed. If either the abort condition is met or another -command is executed an abort signal is returned. If an abort signal is ever returned the -command should finish execution without any more calls that preempt the command. -If a get condition is met the user input is returned. -) -DOC_SEE(Input_Type_Flag) -DOC_SEE(User_Input) -*/{ +{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; User_Input result = {}; @@ -2588,10 +2295,7 @@ DOC_SEE(User_Input) API_EXPORT User_Input Get_Command_Input(Application_Links *app) -/* -DOC_RETURN(This call returns the input that triggered the currently executing command.) -DOC_SEE(User_Input) -*/{ +{ Models *models = (Models*)app->cmd_context; User_Input result = {}; result.key = models->key; @@ -2600,35 +2304,21 @@ DOC_SEE(User_Input) API_EXPORT void Set_Command_Input(Application_Links *app, Key_Event_Data key_data) -/* -DOC_PARAM(key_data, The new value of the "command input". Setting this effects the result returned by get_command_input until the end of this command.) -*/{ +{ Models *models = (Models*)app->cmd_context; models->key = key_data; } API_EXPORT Mouse_State Get_Mouse_State(Application_Links *app) -/* -DOC_RETURN(This call returns the current mouse state as of the beginning of the frame.) -DOC_SEE(Mouse_State) -*/{ +{ Models *models = (Models*)app->cmd_context; return(models->input->mouse); } API_EXPORT b32 Get_Active_Query_Bars(Application_Links *app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array *array_out) -/* -DOC_PARAM(view_id, Specifies the view for which query bars should be retrieved.) -DOC_PARAM(max_result_count, Specifies the number of Query_Bar pointers available in result_array.) -DOC_PARAM(result_array, User-supplied empty array of max_result_count Query_Bar pointers.) -DOC_RETURN(This call returns the number of Query_Bar pointers successfully placed in result_array.) -DOC(This call allows the customization layer to inspect the set of active Query_Bar slots for a given -view_id. By convention, the most recent query will be entry 0, the next most recent 1, etc., such -that if you only care about the most recent query bar, you can call Get_Active_Query_Bars with a -max_result_count of 1 and be assured you will get the most recent bar if any exist.) -*/{ +{ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; @@ -2650,18 +2340,7 @@ max_result_count of 1 and be assured you will get the most recent bar if any exi API_EXPORT b32 Start_Query_Bar(Application_Links *app, Query_Bar *bar, u32 flags) -/* -DOC_PARAM(bar, This parameter provides a Query_Bar that should remain in valid memory -until end_query_bar or the end of the command. It is commonly a good idea to make -this a pointer to a Query_Bar stored on the stack.) -DOC_PARAM(flags, This parameter is not currently used and should be 0 for now.) -DOC_RETURN(This call returns non-zero on success.) -DOC(This call tells the active view to begin displaying a "Query_Bar" which is a small -GUI element that can overlap a buffer or other 4coder GUI. The contents of the bar -can be changed after the call to start_query_bar and the query bar shown by 4coder -will reflect the change. Since the bar stops showing when the command exits the -only use for this call is in an interactive command that makes calls to get_user_input.) -*/{ +{ Models *models = (Models*)app->cmd_context; Panel *active_panel = layout_get_active_panel(&models->layout); View *active_view = active_panel->view; @@ -2675,11 +2354,7 @@ only use for this call is in an interactive command that makes calls to get_user API_EXPORT void End_Query_Bar(Application_Links *app, Query_Bar *bar, u32 flags) -/* -DOC_PARAM(bar, This parameter should be a bar pointer of a currently active query bar.) -DOC_PARAM(flags, This parameter is not currently used and should be 0 for now.) -DOC(Stops showing the particular query bar specified by the bar parameter.) -*/{ +{ Models *models = (Models*)app->cmd_context; Panel *active_panel = layout_get_active_panel(&models->layout); View *active_view = active_panel->view; @@ -2688,11 +2363,7 @@ DOC(Stops showing the particular query bar specified by the bar parameter.) API_EXPORT b32 Print_Message(Application_Links *app, String_Const_u8 message) -/* -DOC_PARAM(str, The str parameter specifies the string to post to *messages*; it need not be null terminated.) -DOC_PARAM(len, The len parameter specifies the length of the str string.) -DOC(This call posts a string to the *messages* buffer.) -*/{ +{ Models *models = (Models*)app->cmd_context; Editing_File *file = models->message_buffer; b32 result = false; @@ -2717,9 +2388,6 @@ Thread_Get_ID(Application_Links *app){ API_EXPORT Face_ID Get_Largest_Face_ID(Application_Links *app) -/* -DOC_RETURN(Returns the largest face ID that could be valid. There is no guarantee that the returned value is a valid face, or that every face less than the returned value is valid. The guarantee is that all valid face ids are in the range between 1 and the return value.) -*/ { Models *models = (Models*)app->cmd_context; return(font_set_get_largest_id(&models->font_set)); @@ -2727,12 +2395,6 @@ DOC_RETURN(Returns the largest face ID that could be valid. There is no guarant API_EXPORT b32 Set_Global_Face(Application_Links *app, Face_ID id, b32 apply_to_all_buffers) -/* -DOC_PARAM(id, The id of the face to try to make the global face.) -DOC_PARAM(apply_to_all_buffers, If the face is valid, apply the face to change to all open buffers as well as setting the global default.) -DOC(Tries to set the global default face, which new buffers will use upon creation.) -DOC_RETURN(Returns true if the given id was a valid face and the change was made successfully.) -*/ { Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; @@ -2770,8 +2432,8 @@ buffer_history__fill_record_info(Record *record, Record_Info *out){ switch (out->kind){ case RecordKind_Single: { - out->single.string_forward = SCu8(record->single.str_forward , record->single.length_forward ); - out->single.string_backward = SCu8(record->single.str_backward, record->single.length_backward); + out->single.string_forward = record->single.forward_text ; + out->single.string_backward = record->single.backward_text; out->single.first = record->single.first; }break; case RecordKind_Group: @@ -2924,12 +2586,6 @@ Global_History_Edit_Group_End(Application_Links *app){ API_EXPORT b32 Buffer_Set_Face(Application_Links *app, Buffer_ID buffer_id, Face_ID id) -/* -DOC_PARAM(buffer, The buffer on which to change the face.) -DOC_PARAM(id, The id of the face to try to set the buffer to use.) -DOC(Tries to set the buffer's face.) -DOC_RETURN(Returns true if the given id was a valid face and the change was made successfully.) -*/ { Models *models = (Models*)app->cmd_context; Editing_File *file = imp_get_file(models, buffer_id); @@ -2946,16 +2602,6 @@ DOC_RETURN(Returns true if the given id was a valid face and the change was made API_EXPORT Face_Description Get_Face_Description(Application_Links *app, Face_ID face_id) -/* -DOC_PARAM(id, The face slot from which to read a description. If zero gets default values.) -DOC(Fills out the values of a Face_Description struct, which includes all the information that determines the appearance of the face. If the id does not specify a valid face the description will be invalid. An invalid description has a zero length string in it's font.name field (i.e. description.font.name[0] == 0), and a valid description always contains a non-zero length string in the font.name field (i.e. description.font.name[0] != 0) - -If the input id is zero, the description returned will be invalid, but the pt_size and hinting fields will reflect the default values for those fields as specified on the command line. The default values, if unspecified, are pt_size=0 and hinting=false. These default values are overriden by config.4coder when instantiating fonts at startup, but the original values of pt_size=0 and hinting=false from the command line are preserved and returned here for the lifetime of the program. - -Note that the id of zero is reserved and is never a valid face.) -DOC_RETURN(Returns a Face_Description that is valid if the id references a valid face slot and is filled with the description of the face. Otherwise returns an invalid Face_Description.) -DOC_SEE(Face_Description) -*/ { Models *models = (Models*)app->cmd_context; Face_Description description = {}; @@ -2987,14 +2633,8 @@ Get_Face_Metrics(Application_Links *app, Face_ID face_id){ return(result); } -// TODO(allen): redocument API_EXPORT Face_ID Get_Face_ID(Application_Links *app, Buffer_ID buffer_id) -/* -DOC_PARAM(buffer, The buffer from which to get a face id. If NULL gets global face id.) -DOC(Retrieves a face id if buffer is a valid If buffer is set to NULL, the parameter is ignored and the global default face is returned.) -DOC_RETURN(On success a valid Face_ID, otherwise returns zero.) -*/ { Models *models = (Models*)app->cmd_context; Face_ID result = 0; @@ -3012,20 +2652,6 @@ DOC_RETURN(On success a valid Face_ID, otherwise returns zero.) API_EXPORT Face_ID Try_Create_New_Face(Application_Links *app, Face_Description *description) -/* -DOC_PARAM(description, A description of the new face to try to create.) -DOC(Attempts to create a new face and configure it with the provided description. This call can fail for a number of reasons: - -- If the description's font field is not one of the available fonts no face is created. - -- If the specified font cannot actually be loaded by the 4coder font system no face is created. - -- If the specified font with the specified configuration is too large or too small no face is created. - -Note, not all fonts will support all styles. The fields for italic, bold, underline, and hinting, are only requests that the system try to apply these configurations, but if any cannot be done the face will still be created but without the unsupported configurations. 4coder does not try to simulate the effects of missing styles.) -DOC_RETURN(Returns a new valid face id if the font system successfully instanatiates the new face, otherwise returns zero. Note that zero is a reserved id and is never a valid id.) -DOC_SEE(Face_Description) -*/ { Models *models = (Models*)app->cmd_context; Face_ID result = 0; @@ -3046,17 +2672,6 @@ DOC_SEE(Face_Description) API_EXPORT b32 Try_Modify_Face(Application_Links *app, Face_ID id, Face_Description *description) -/* -DOC_PARAM(id, The id of the face slot to try to modify.) -DOC_PARAM(description, The new description for the face slot to use.) -DOC(Attempts to modify the face in a particular face slot. If successful all buffers using the face will continue using the same face slot, and will therefore change appearance to the new configuration of the face slot. - -This call can fail for all the same reasons that try_create_new_face can fail, and the same rules about failure to apply specific styles also apply. If the call does fail, the original configuration of the face slot stays in place. A valid face slot should never become invalid except by releasing it. - -Performance Warning: Modifying a face slot should only be done a couple of times per frame in most cases. Not only does this call reconfigure a slot, it also recomputes the layout for all buffers that use this face slot.) -DOC_RETURN(Returns true on success and false on failure.) -DOC_SEE(try_create_new_face) -*/ { Models *models = (Models*)app->cmd_context; b32 result = false; @@ -3071,23 +2686,13 @@ DOC_SEE(try_create_new_face) result = *(b32*)(coroutine->in); } else{ - result = alter_font_and_update_files(models->system, models, id, description); + result = font_set_modify_face(&models->font_set, id, description); } return(result); } API_EXPORT b32 Try_Release_Face(Application_Links *app, Face_ID id, Face_ID replacement_id) -/* -DOC_PARAM(id, The id of the face slot to release.) -DOC_PARAM(replacement_id, Optional. Specifies what buffers that were using id should switch to after the release.) -DOC(Attempts to release the slot referred to by id. If successful all buffers using the face will switch to using a new valid face, and will therefore change appearance to the new face slot. If replacement_id refers to a valid face slot, it will be used for the new slot, otherwise the slot is chosen arbitrarily out of the remaining valid faces. - -This call can fail if the id does not name a valid face slot, or if there is only one face slot left in the system. - -Performance Warning: Releasing a face slot should only be done a couple of times per frame in most cases. Not only does it release all the resources used by the slot, it also recomputes the layout for all buffers that used the released slot. If no buffers use the slots that are released, it is generally okay to use it more frequently.) -DOC_RETURN(Returns true on success and zero on failure.) -*/ { Models *models = (Models*)app->cmd_context; b32 success = release_font_and_update_files(models->system, models, id, replacement_id); @@ -3096,12 +2701,7 @@ DOC_RETURN(Returns true on success and zero on failure.) API_EXPORT void Set_Theme_Colors(Application_Links *app, Theme_Color *colors, i32 count) -/* -DOC_PARAM(colors, The colors pointer provides an array of color structs pairing differet style tags to color codes.) -DOC_PARAM(count, The count parameter specifies the number of Theme_Color structs in the colors array.) -DOC(For each struct in the array, the slot in the main color pallet specified by the struct's tag is set to the color code in the struct. If the tag value is invalid no change is made to the color pallet.) -DOC_SEE(Theme_Color) -*/{ +{ Models *models = (Models*)app->cmd_context; Color_Table color_table = models->color_table; Theme_Color *theme_color = colors; @@ -3114,12 +2714,7 @@ DOC_SEE(Theme_Color) API_EXPORT void Get_Theme_Colors(Application_Links *app, Theme_Color *colors, i32 count) -/* -DOC_PARAM(colors, an array of color structs listing style tags to get color values for) -DOC_PARAM(count, the number of color structs in the colors array) -DOC(For each struct in the array, the color field of the struct is filled with the color from the slot in the main color pallet specified by the tag. If the tag value is invalid the color is filled with black.) -DOC_SEE(Theme_Color) -*/{ +{ Models *models = (Models*)app->cmd_context; Color_Table color_table = models->color_table; Theme_Color *theme_color = colors; @@ -3139,32 +2734,18 @@ Finalize_Color(Application_Links *app, int_color color){ return(color_rgb); } -// TODO(allen): redocument API_EXPORT String_Const_u8 Push_Hot_Directory(Application_Links *app, Arena *arena) -/* -DOC_PARAM(out, On success this character buffer is filled with the 4coder 'hot directory'.) -DOC_PARAM(capacity, Specifies the capacity in bytes of the of the out buffer.) -DOC(4coder has a concept of a 'hot directory' which is the directory most recently accessed in the GUI. Whenever the GUI is opened it shows the hot directory. In the future this will be deprecated and eliminated in favor of more flexible hot directories created and controlled in the custom layer.) -DOC_RETURN(This call returns the length of the hot directory string whether or not it was successfully copied into the output buffer. The call is successful if and only if capacity is greater than or equal to the return value.) -DOC_SEE(directory_set_hot) -*/{ +{ Models *models = (Models*)app->cmd_context; Hot_Directory *hot = &models->hot_directory; hot_directory_clean_end(hot); return(push_string_copy(arena, hot->string)); } -// TODO(allen): redocument API_EXPORT b32 Set_Hot_Directory(Application_Links *app, String_Const_u8 string) -/* -DOC_PARAM(str, The new value of the hot directory. This does not need to be a null terminated string.) -DOC_PARAM(len, The length of str in bytes.) -DOC_RETURN(Returns non-zero on success.) -DOC(4coder has a concept of a 'hot directory' which is the directory most recently accessed in the GUI. Whenever the GUI is opened it shows the hot directory. In the future this will be deprecated and eliminated in favor of more flexible directories controlled on the custom side.) -DOC_SEE(directory_get_hot) -*/{ +{ Models *models = (Models*)app->cmd_context; Hot_Directory *hot = &models->hot_directory; hot_directory_set(models->system, hot, string); @@ -3185,13 +2766,6 @@ Get_File_List(Application_Links *app, Arena *arena, String_Const_u8 directory){ API_EXPORT void Set_GUI_Up_Down_Keys(Application_Links *app, Key_Code up_key, Key_Modifier up_key_modifier, Key_Code down_key, Key_Modifier down_key_modifier) -/* -DOC_PARAM(up_key, the code of the key that should be interpreted as an up key) -DOC_PARAM(up_key_modifier, the modifier for the key that should be interpreted as an up key) -DOC_PARAM(down_key, the code of the key that should be interpreted as a down key) -DOC_PARAM(down_key_modifier, the modifier for the key that should be interpreted as a down key) - -DOC(This is a temporary ad-hoc solution to allow some customization of the behavior of the built in GUI. There is a high chance that it will be removed and not replaced at some point, so it is not recommended that it be heavily used.) */ { Models *models = (Models*)app->cmd_context; models->user_up_key = up_key; @@ -3202,11 +2776,7 @@ DOC(This is a temporary ad-hoc solution to allow some customization of the behav API_EXPORT void* Memory_Allocate(Application_Links *app, i32 size) -/* -DOC_PARAM(size, The size in bytes of the block that should be returned.) -DOC(This calls to a low level OS allocator which means it is best used for infrequent, large allocations. The size of the block must be remembered if it will be freed or if it's mem protection status will be changed.) -DOC_SEE(memory_free) -*/{ +{ Models *models = (Models*)app->cmd_context; void *result = models->system->memory_allocate(size); return(result); @@ -3214,38 +2784,21 @@ DOC_SEE(memory_free) API_EXPORT b32 Memory_Set_Protection(Application_Links *app, void *ptr, i32 size, Memory_Protect_Flags flags) -/* -DOC_PARAM(ptr, The base of the block on which to set memory protection flags.) -DOC_PARAM(size, The size that was originally used to allocate this block.) -DOC_PARAM(flags, The new memory protection flags.) -DOC(This call sets the memory protection flags of a block of memory that was previously allocate by memory_allocate.) -DOC_SEE(memory_allocate) -DOC_SEE(Memory_Protect_Flags) -*/{ +{ Models *models = (Models*)app->cmd_context; return(models->system->memory_set_protection(ptr, size, flags)); } API_EXPORT void Memory_Free(Application_Links *app, void *ptr, i32 size) -/* -DOC_PARAM(mem, The base of a block to free.) -DOC_PARAM(size, The size that was originally used to allocate this block.) -DOC(This call frees a block of memory that was previously allocated by memory_allocate.) -DOC_SEE(memory_allocate) -*/{ +{ Models *models = (Models*)app->cmd_context; models->system->memory_free(ptr, size); } -// TODO(allen): redocument API_EXPORT String_Const_u8 Push_4ed_Path(Application_Links *app, Arena *arena) -/* -DOC_PARAM(out, This parameter provides a character buffer that receives the path to the 4ed executable file.) -DOC_PARAM(capacity, This parameter specifies the maximum capacity of the out buffer.) -DOC_RETURN(This call returns non-zero on success.) -*/{ +{ Models *models = (Models*)app->cmd_context; System_Functions *system = models->system; return(system->get_4ed_path(arena)); @@ -3254,10 +2807,7 @@ DOC_RETURN(This call returns non-zero on success.) // TODO(allen): do(add a "shown but auto-hides on timer" setting for cursor show type) API_EXPORT void Show_Mouse_Cursor(Application_Links *app, Mouse_Cursor_Show_Type show) -/* -DOC_PARAM(show, This parameter specifies the new state of the mouse cursor.) -DOC_SEE(Mouse_Cursor_Show_Type) -*/{ +{ Models *models = (Models*)app->cmd_context; models->system->show_mouse_cursor(show); } @@ -3271,10 +2821,7 @@ Set_Edit_Finished_Hook_Repeat_Speed(Application_Links *app, u32 milliseconds){ API_EXPORT b32 Set_Fullscreen(Application_Links *app, b32 full_screen) -/* -DOC_PARAM(full_screen, The new value of the global full_screen setting.) -DOC(This call tells 4coder to set the full_screen mode. The change to full screen mode does not take effect until the end of the current frame. But is_fullscreen does report the new state.) -*/{ +{ Models *models = (Models*)app->cmd_context; b32 success = models->system->set_fullscreen(full_screen); if (!success){ @@ -3285,9 +2832,7 @@ DOC(This call tells 4coder to set the full_screen mode. The change to full scre API_EXPORT b32 Is_Fullscreen(Application_Links *app) -/* -DOC(This call returns true if the 4coder is in full screen mode. This call takes toggles that have already occured this frame into account. So it may return true even though the frame has not ended and actually put 4coder into full screen. If it returns true though, 4coder will definitely be full screen by the beginning of the next frame if the state is not changed.) -*/{ +{ Models *models = (Models*)app->cmd_context; b32 result = models->system->is_fullscreen(); return(result); @@ -3295,24 +2840,14 @@ DOC(This call returns true if the 4coder is in full screen mode. This call take API_EXPORT void Send_Exit_Signal(Application_Links *app) -/* -DOC(This call sends a signal to 4coder to attempt to exit, which will trigger the exit hook before the end of the frame. That hook will have the chance to cancel the exit. - -In the default behavior of the exit hook, the exit is cancelled if there are unsaved changes, and instead a UI querying the user for permission to close without saving is presented, if the user confirms the UI sends another exit signal that will not be canceled. - -To make send_exit_signal exit no matter what, setup your hook in such a way that it knows when you are trying to exit no matter what, such as with a global variable that you set before calling send_exit_signal.) -*/{ +{ Models *models = (Models*)app->cmd_context; models->keep_playing = false; } -// TODO(allen): redocument API_EXPORT b32 Set_Window_Title(Application_Links *app, String_Const_u8 title) -/* -DOC_PARAM(title, A null terminated string indicating the new title for the 4coder window.) -DOC(Sets 4coder's window title to the specified title string.) -*/{ +{ Models *models = (Models*)app->cmd_context; models->has_new_title = true; umem cap_before_null = (umem)(models->title_capacity - 1); @@ -3324,9 +2859,6 @@ DOC(Sets 4coder's window title to the specified title string.) API_EXPORT Microsecond_Time_Stamp Get_Microseconds_Timestamp(Application_Links *app) -/* -DOC(Returns a microsecond resolution timestamp.) -*/ { // TODO(allen): do(decrease indirection in API calls) Models *models = (Models*)app->cmd_context; @@ -3357,50 +2889,6 @@ draw_helper__models_space_to_screen_space(Models *models, f32_Rect rect){ return(rect); } -internal Vec2 -draw_helper__view_space_to_screen_space(View *view, Vec2 point){ - i32_Rect region = view->render.view_rect; - point.x += (f32)region.x0; - point.y += (f32)region.y0; - return(point); -} - -internal f32_Rect -draw_helper__view_space_to_screen_space(View *view, f32_Rect rect){ - i32_Rect region = view->render.view_rect; - f32 x_corner = (f32)region.x0; - f32 y_corner = (f32)region.y0; - rect.x0 += x_corner; - rect.y0 += y_corner; - rect.x1 += x_corner; - rect.y1 += y_corner; - return(rect); -} - -internal Vec2 -draw_helper__screen_space_to_view_space(View *view, Vec2 point){ - i32_Rect region = view->render.view_rect; - point.x -= (f32)region.x0; - point.y -= (f32)region.y0; - return(point); -} - -internal f32_Rect -draw_helper__screen_space_to_view_space(View *view, f32_Rect rect){ - i32_Rect region = view->render.view_rect; - f32 x_corner = (f32)region.x0; - f32 y_corner = (f32)region.y0; - rect.x0 -= x_corner; - rect.y0 -= y_corner; - rect.x1 -= x_corner; - rect.y1 -= y_corner; - return(rect); -} - -// NOTE(allen): Coordinate space of draw calls: -// The render space is such that 0,0 is _always_ the top left corner of the renderable region of the view. -// To make text scroll with the buffer users should read the view's scroll position and subtract it first. - API_EXPORT Vec2 Draw_String(Application_Links *app, Face_ID font_id, String_Const_u8 str, Vec2 point, int_color color, u32 flags, Vec2 delta) { @@ -3486,87 +2974,67 @@ Draw_Coordinate_Center_Pop(Application_Links *app){ return(result); } +API_EXPORT Text_Layout_ID +Text_Layout_Create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point){ + Models *models = (Models*)app->cmd_context; + Editing_File *file = imp_get_file(models, buffer_id); + Text_Layout_ID result = {}; + if (api_check_buffer(file)){ + Scratch_Block scratch(app); + Arena arena = make_arena_models(models); + Face_ID face_id = file->settings.font_id; + + Gap_Buffer *buffer = &file->state.buffer; + + Vec2_f32 dim = rect_dim(rect); + + i64 line_count = buffer_line_count(buffer); + i64 line_number = buffer_point.line_number; + f32 y = -buffer_point.pixel_shift.y; + for (;line_number <= line_count; + line_number += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, dim.x, face_id, line_number); + f32 next_y = y + line.height; + if (next_y >= dim.y){ + break; + } + y = next_y; + } + + Interval_i64 visible_line_number_range = Ii64(buffer_point.line_number, line_number); + Interval_i64 visible_range = Ii64(buffer_get_first_pos_from_line_number(buffer, visible_line_number_range.min), + buffer_get_last_pos_from_line_number(buffer, visible_line_number_range.max)); + + i64 item_count = range_size_inclusive(visible_range); + int_color *colors_array = push_array(&arena, int_color, item_count); + for (i64 i = 0; i < item_count; i += 1){ + colors_array[i] = Stag_Default; + } + result = text_layout_new(&models->text_layouts, arena, buffer_id, buffer_point, + visible_range, visible_line_number_range, rect, colors_array); + } + return(result); +} + API_EXPORT b32 Text_Layout_Get_Buffer(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID *buffer_id_out){ Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; b32 result = false; - if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - *buffer_id_out = layout.buffer_id; + Text_Layout *layout = text_layout_get(&models->text_layouts, text_layout_id); + if (layout != 0){ + *buffer_id_out = layout->buffer_id; result = true; } return(result); } -API_EXPORT b32 -Text_Layout_Buffer_Point_To_Layout_Point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 buffer_relative_p, Vec2 *p_out){ +API_EXPORT Interval_i64 +Text_Layout_Get_Visible_Range(Application_Links *app, Text_Layout_ID text_layout_id){ Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; - b32 result = false; - if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - Editing_File *file = imp_get_file(models, layout.buffer_id); - if (api_check_buffer(file)){ - System_Functions *system = models->system; - // TODO(allen): this could be computed and stored _once_ right? - Full_Cursor top = file_compute_cursor(models, file, seek_line_char(layout.point.line_number, 1)); - f32 top_y = top.wrapped_y; - if (file->settings.unwrapped_lines){ - top_y = top.unwrapped_y; - } - buffer_relative_p -= layout.point.pixel_shift; - buffer_relative_p.y -= top_y; - *p_out = buffer_relative_p; - result = true; - } - } - return(result); -} - -API_EXPORT b32 -Text_Layout_Layout_Point_To_Buffer_Point(Application_Links *app, Text_Layout_ID text_layout_id, Vec2 layout_relative_p, Vec2 *p_out){ - Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; - b32 result = false; - if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - Editing_File *file = imp_get_file(models, layout.buffer_id); - if (api_check_buffer(file)){ - System_Functions *system = models->system; - // TODO(allen): this could be computed and stored _once_ right? - Full_Cursor top = file_compute_cursor(models, file, seek_line_char(layout.point.line_number, 1)); - f32 top_y = top.wrapped_y; - if (file->settings.unwrapped_lines){ - top_y = top.unwrapped_y; - } - layout_relative_p += layout.point.pixel_shift; - layout_relative_p.y += top_y; - *p_out = layout_relative_p; - result = true; - } - } - return(result); -} - -API_EXPORT Range_i64 -Text_Layout_Get_On_Screen_Range(Application_Links *app, Text_Layout_ID text_layout_id){ - Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; Range_i64 result = {}; - if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - result = Ii64(layout.on_screen_range.min, layout.on_screen_range.max); - } - return(result); -} - -API_EXPORT Rect_f32 -Text_Layout_On_Screen(Application_Links *app, Text_Layout_ID text_layout_id){ - Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; - Rect_f32 result = {}; - if (text_layout_get(&models->text_layouts, text_layout_id, &layout)){ - result = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); - Vec2_f32 coordinate_center = models_get_coordinate_center(models); - result.p0 -= coordinate_center; - result.p1 -= coordinate_center; + Text_Layout *layout = text_layout_get(&models->text_layouts, text_layout_id); + if (layout != 0){ + result = layout->visible_range; } return(result); } @@ -3574,36 +3042,32 @@ Text_Layout_On_Screen(Application_Links *app, Text_Layout_ID text_layout_id){ API_EXPORT Rect_f32 Text_Layout_Line_On_Screen(Application_Links *app, Text_Layout_ID layout_id, i64 line_number){ Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; Rect_f32 result = {}; - if (text_layout_get(&models->text_layouts, layout_id, &layout)){ - Editing_File *file = imp_get_file(models, layout.buffer_id); + Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); + if (layout != 0 && range_contains_inclusive(layout->visible_line_number_range, line_number)){ + Editing_File *file = imp_get_file(models, layout->buffer_id); if (api_check_buffer(file)){ - Partial_Cursor first_partial = file_compute_partial_cursor(file, seek_line_char(line_number, 1)); - Partial_Cursor last_partial = file_compute_partial_cursor(file, seek_line_char(line_number, -1)); - Full_Cursor first = file_compute_cursor(models, file, seek_pos(first_partial.pos)); - Full_Cursor last = file_compute_cursor(models, file, seek_pos(last_partial.pos)); + Rect_f32 rect = layout->rect; + f32 width = rect_width(rect); + Face_ID face_id = file->settings.font_id; - f32 top = first.wrapped_y; - f32 bot = last.wrapped_y; - if (file->settings.unwrapped_lines){ - top = first.unwrapped_y; - bot = last.unwrapped_y; + f32 top = 0.f; + f32 bot = 0.f; + for (i64 line_number_it = layout->visible_line_number_range.first;; + line_number_it += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number_it); + bot += line.height; + if (line_number_it == line_number){ + break; + } + top = bot; } - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - f32 line_height = face->height; - bot += line_height; + top -= layout->point.pixel_shift.y; + bot -= layout->point.pixel_shift.y; - result = Rf32(layout.coordinates.on_screen_p0.x, top, - layout.coordinates.on_screen_p0.x + layout.coordinates.dim.x, bot); - - f32 shift_y = layout.coordinates.on_screen_p0.y - layout.coordinates.in_buffer_p0.y; - result.y0 += shift_y; - result.y1 += shift_y; - - Rect_f32 whole_layout = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); - result = rect_intersect(result, whole_layout); + result = Rf32(rect.x0, rect.y0 + top, rect.x1, rect.y0 + bot); + result = rect_intersect(rect, result); Vec2_f32 coordinate_center = models_get_coordinate_center(models); result.p0 -= coordinate_center; @@ -3616,40 +3080,53 @@ Text_Layout_Line_On_Screen(Application_Links *app, Text_Layout_ID layout_id, i64 API_EXPORT Rect_f32 Text_Layout_Character_On_Screen(Application_Links *app, Text_Layout_ID layout_id, i64 pos){ Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; Rect_f32 result = {}; - if (text_layout_get(&models->text_layouts, layout_id, &layout)){ - Editing_File *file = imp_get_file(models, layout.buffer_id); + Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); + if (layout != 0 && range_contains_inclusive(layout->visible_range, pos)){ + Editing_File *file = imp_get_file(models, layout->buffer_id); if (api_check_buffer(file)){ - Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(pos)); + Gap_Buffer *buffer = &file->state.buffer; + i64 line_number = buffer_get_line_index(buffer, pos) + 1; - f32 top = cursor.wrapped_y; - f32 left = cursor.wrapped_x; - if (file->settings.unwrapped_lines){ - top = cursor.unwrapped_y; - left = cursor.unwrapped_x; + Rect_f32 rect = layout->rect; + f32 width = rect_width(rect); + Face_ID face_id = file->settings.font_id; + + f32 y = 0.f; + Buffer_Layout_Item_List line = {}; + for (i64 line_number_it = layout->visible_line_number_range.first;; + line_number_it += 1){ + line = file_get_line_layout(models, file, width, face_id, line_number_it); + if (line_number_it == line_number){ + break; + } + y += line.height; } - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - f32 line_height = face->height; - f32 bot = top + line_height; + // TODO(allen): optimization: This is some fairly heavy computation. We really need + // to accelerate the (pos -> item) lookup within a single Buffer_Layout_Item_List. + b32 is_first_item = true; + result = Rf32_negative_infinity; + for (Buffer_Layout_Item_Block *block = line.first; + block != 0; + block = block->next){ + Buffer_Layout_Item *item_ptr = block->items; + i64 count = block->count; + for (i32 i = 0; i < count; i += 1, item_ptr += 1){ + i64 index = item_ptr->index; + if (index == pos){ + result = rect_union(result, item_ptr->rect); + } + else if (index > pos){ + break; + } + } + } - i64 size = buffer_size(&file->state.buffer); - Range_i64 range = Ii64(pos, pos + 4); - range.max = clamp_top(range.max, size); - u8 space[4]; - buffer_read_range(app, layout.buffer_id, range, (char*)space); - u32 codepoint = utf8_to_u32_unchecked(space); - f32 advance = font_get_glyph_advance(face, codepoint); - - result = Rf32(left, top, left + advance, bot); - - Vec2_f32 shift = layout.coordinates.on_screen_p0 - layout.coordinates.in_buffer_p0; + Vec2_f32 shift = V2f32(rect.x0, rect.y0 + y) - layout->point.pixel_shift; result.p0 += shift; result.p1 += shift; - - Rect_f32 whole_layout = Rf32_xy_wh(layout.coordinates.on_screen_p0, layout.coordinates.dim); - result = rect_intersect(result, whole_layout); + result = rect_intersect(rect, result); Vec2_f32 coordinate_center = models_get_coordinate_center(models); result.p0 -= coordinate_center; @@ -3660,17 +3137,18 @@ Text_Layout_Character_On_Screen(Application_Links *app, Text_Layout_ID layout_id } API_EXPORT void -Paint_Text_Color(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, int_color color){ +Paint_Text_Color(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range, int_color color){ Models *models = (Models*)app->cmd_context; - Text_Layout layout = {}; Rect_f32 result = {}; - if (text_layout_get(&models->text_layouts, layout_id, &layout)){ - range.min = clamp_bot(layout.on_screen_range.min, range.min); - range.max = clamp_top(range.max, layout.on_screen_range.max); - range.min -= layout.on_screen_range.min; - range.max -= layout.on_screen_range.min; - for (i64 i = range.min; i < range.max; i += 1){ - layout.item_colors[i] = color; + Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); + if (layout != 0){ + range.min = clamp_bot(layout->visible_range.min, range.min); + range.max = clamp_top(range.max, layout->visible_range.max); + range.min -= layout->visible_range.min; + range.max -= layout->visible_range.min; + int_color *color_ptr = layout->item_colors + range.min; + for (i64 i = range.min; i < range.max; i += 1, color_ptr += 1){ + *color_ptr = color; } } } @@ -3681,155 +3159,12 @@ Text_Layout_Free(Application_Links *app, Text_Layout_ID text_layout_id){ return(text_layout_erase(&models->text_layouts, text_layout_id)); } -API_EXPORT Text_Layout_ID -Compute_Render_Layout(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Vec2 screen_p, Vec2 layout_dim, Buffer_Point buffer_point, i32 one_past_last){ - Models *models = (Models*)app->cmd_context; - System_Functions *system = models->system; - View *view = imp_get_view(models, view_id); - Editing_File *file = imp_get_file(models, buffer_id); - Text_Layout_ID result = 0; - if (api_check_view(view) && api_check_buffer(file)){ - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - Assert(face != 0); - - f32 line_height = (f32)face->height; - f32 max_x = (f32)file->settings.display_width; - f32 max_y = layout_dim.y + line_height; - - // TODO(allen): Don't force me to over-allocate! Write a looser buffer render thingy. - f32 smallest_char_width = 6.f; - f32 smallest_char_height = 8.f; - i32 max = (i32)(layout_dim.x*layout_dim.y/(smallest_char_width*smallest_char_height))*2; - max = clamp_bot(0, max); - if (view->layout_arena.base_allocator == 0){ - view->layout_arena = make_arena_app_links(app); - } - else{ - linalloc_clear(&view->layout_arena); - } - Buffer_Render_Item *items = push_array(&view->layout_arena, Buffer_Render_Item, max); - - b32 wrapped = (!file->settings.unwrapped_lines); - - Full_Cursor intermediate_cursor = file_compute_cursor(models, file, seek_line_char(buffer_point.line_number, 1)); - f32 scroll_x = buffer_point.pixel_shift.x; - f32 scroll_y = intermediate_cursor.wrapped_y; - if (file->settings.unwrapped_lines){ - scroll_y = intermediate_cursor.unwrapped_y; - } - scroll_y += buffer_point.pixel_shift.y; - Vec2_f32 in_buffer_p = V2f32(scroll_x, scroll_y); - Full_Cursor render_cursor = file_get_render_cursor(models, file, scroll_y); - - i32 item_count = 0; - i32 end_pos = 0; - { - Buffer_Render_Params params; - params.buffer = &file->state.buffer; - params.items = items; - params.max = max; - params.count = &item_count; - params.port_x = screen_p.x; - params.port_y = screen_p.y; - params.clip_w = layout_dim.x; - params.scroll_x = scroll_x; - params.scroll_y = scroll_y; - params.width = max_x; - params.height = (f32)max_y; - params.start_cursor = render_cursor; - params.wrapped = wrapped; - params.system = system; - params.face = face; - params.virtual_white = file->settings.virtual_white; - params.wrap_slashes = file->settings.wrap_indicator; - params.one_past_last_abs_pos = one_past_last; - - Buffer_Render_State state = {}; - Buffer_Layout_Stop stop = {}; - - f32 line_shift = 0.f; - b32 do_wrap = false; - i32 wrap_unit_end = 0; - - b32 first_wrap_determination = true; - i32 wrap_array_index = 0; - - do{ - stop = buffer_render_data(&state, params, line_shift, do_wrap, wrap_unit_end); - switch (stop.status){ - case BLStatus_NeedWrapDetermination: - { - if (first_wrap_determination){ - wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count); - ++wrap_array_index; - if (file->state.wrap_positions[wrap_array_index] == stop.pos){ - do_wrap = true; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - else{ - do_wrap = false; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - first_wrap_determination = false; - } - else{ - Assert(stop.pos == wrap_unit_end); - do_wrap = true; - ++wrap_array_index; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - }break; - - case BLStatus_NeedWrapLineShift: - case BLStatus_NeedLineShift: - { - line_shift = file->state.line_indents[stop.wrap_line_index]; - }break; - } - }while(stop.status != BLStatus_Finished); - - end_pos = state.i; - } - - Range range = Ii32((i32)render_cursor.pos, (i32)end_pos); - - // TODO(allen): - int_color *item_colors = push_array_zero(&view->layout_arena, int_color, range.max - range.min); - view->render.view_rect = view->panel->rect_inner; - view->render.buffer_rect = i32R(f32R(screen_p.x, screen_p.y, - screen_p.x + layout_dim.x, screen_p.y + layout_dim.y)); - view->render.cursor = render_cursor; - view->render.range = range; - view->render.items = items; - view->render.item_colors = item_colors; - view->render.item_count = item_count; - - f32 height = 0.f; - if (item_count > 0){ - Buffer_Render_Item *render_item_first = items; - Buffer_Render_Item *render_item_last = items + item_count - 1; - height = render_item_last->y1 - render_item_first->y0; - } - Text_Layout_Coordinates coordinates = {}; - coordinates.on_screen_p0 = screen_p; - coordinates.in_buffer_p0 = in_buffer_p; - coordinates.dim = layout_dim; - result = text_layout_new(&models->mem.heap, &models->text_layouts, buffer_id, buffer_point, range, height, coordinates, item_colors); - } - return(result); -} - API_EXPORT void -Draw_Render_Layout(Application_Links *app, View_ID view_id){ +Draw_Text_Layout(Application_Links *app, Text_Layout_ID layout_id){ Models *models = (Models*)app->cmd_context; - View *view = imp_get_view(models, view_id); - if (api_check_view(view) && models->target != 0){ - render_loaded_file_in_view__inner(models, models->target, view, view->render.buffer_rect, - view->render.cursor, view->render.range, - view->render.items, - view->render.item_colors, - view->render.item_count); - linalloc_clear(&view->layout_arena); + Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); + if (layout != 0 && models->target != 0){ + text_layout_render(models, layout); } } @@ -3864,11 +3199,10 @@ Buffer_Find_All_Matches(Application_Links *app, Arena *arena, Buffer_ID buffer, String_Match_List list = {}; if (api_check_buffer(file)){ if (needle.size > 0){ - String_Const_u8 space[3]; - Cursor cursor = make_cursor(space, sizeof(space)); - String_Const_u8_Array chunks = buffer_get_chunks(&cursor, &file->state.buffer); - chunks = buffer_chunks_clamp(chunks, range); - if (chunks.count > 0){ + Scratch_Block scratch(app); + List_String_Const_u8 chunks = buffer_get_chunks(scratch, &file->state.buffer); + buffer_chunks_clamp(&chunks, range); + if (chunks.node_count > 0){ u64_Array jump_table = string_compute_needle_jump_table(arena, needle, direction); Character_Predicate dummy = {}; if (predicate == 0){ @@ -3883,22 +3217,4 @@ Buffer_Find_All_Matches(Application_Links *app, Arena *arena, Buffer_ID buffer, return(list); } -API_EXPORT Range -Get_View_Visible_Range(Application_Links *app, View_ID view_id){ - Range result = {}; - Models *models = (Models*)app->cmd_context; - View *view = imp_get_view(models, view_id); - if (api_check_view(view)){ - Editing_File *file = view->file; - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - i32 view_height = rect_height(view->panel->rect_inner); - i32 line_height = (i32)face->height; - Full_Cursor min_cursor = view_get_render_cursor(models, view); - Buffer_Seek seek = seek_unwrapped_xy(0.f, min_cursor.wrapped_y + view_height + line_height, false); - Full_Cursor max_cursor = view_compute_cursor(app, view_id, seek); - result = Ii32((i32)min_cursor.pos, (i32)max_cursor.pos); - } - return(result); -} - // BOTTOM diff --git a/4ed_app_models.h b/4ed_app_models.h index 1a7e40a0..8f7afa27 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -68,7 +68,7 @@ struct Models{ Command_Caller_Hook_Function *command_caller; Render_Caller_Function *render_caller; Input_Filter_Function *input_filter; - Scroll_Rule_Function *scroll_rule; + Delta_Rule_Function *scroll_rule; Buffer_Name_Resolver_Function *buffer_name_resolver; Modify_Color_Table_Function *modify_color_table; Clipboard_Change_Hook_Function *clipboard_change; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 1b6cdc06..4a069377 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -59,7 +59,6 @@ struct Mem_Options{ #include "4ed_buffer.h" #include "4ed_history.h" #include "4ed_file.h" -#include "4ed_code_wrap.h" #include "4ed_working_set.h" #include "4ed_hot_directory.h" @@ -74,6 +73,7 @@ struct Mem_Options{ #include "4ed_log.h" #include "4ed_app_models.h" +#include "4ed_allocator_models.cpp" #include "4ed_log.cpp" #include "4coder_log.cpp" #include "4ed_coroutine.cpp" @@ -92,7 +92,6 @@ struct Mem_Options{ #include "4ed_history.cpp" #include "4ed_file_lex.cpp" #include "4ed_file.cpp" -#include "4ed_code_wrap.cpp" #include "4ed_working_set.cpp" #include "4ed_hot_directory.cpp" #include "4ed_cli.cpp" @@ -101,7 +100,6 @@ struct Mem_Options{ #include "4coder_buffer_seek_constructors.cpp" #include "4ed_view.cpp" #include "4ed_edit.cpp" -#include "4ed_view_ui.cpp" #include "4ed_text_layout.cpp" #include "4ed.cpp" diff --git a/4ed_buffer.cpp b/4ed_buffer.cpp index ac8aec95..1ea7d16e 100644 --- a/4ed_buffer.cpp +++ b/4ed_buffer.cpp @@ -80,8 +80,9 @@ buffer_unsort_cursors(Cursor_With_Index *positions, i32 count){ } internal void -buffer_update_cursors(Cursor_With_Index *sorted_positions, i32 count, i32 start, i32 end, i32 len, b32 lean_right){ - i32 shift_amount = (len - (end - start)); +buffer_update_cursors(Cursor_With_Index *sorted_positions, i32 count, + i64 start, i64 end, i64 len, b32 lean_right){ + i64 shift_amount = replace_range_shift(start, end, len); Cursor_With_Index *position = sorted_positions + count - 1; if (lean_right){ @@ -102,87 +103,6 @@ buffer_update_cursors(Cursor_With_Index *sorted_positions, i32 count, i32 start, } } -internal i32 -buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, i32 edit_count){ - Buffer_Edit *edit = sorted_edits; - i32 i = 0, start_point = 0; - i32 result = 1; - - 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); -} - -// TODO(allen): This now relies on Edit and Edit_Array from 4ed_edit.h even though we sort of think of that -// as cheating... gotta rethink the separation of buffer from everything else moving forward or something. - -internal i32 -buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, i32 count, Edit_Array sorted_edits, b32 lean_right){ - Cursor_With_Index *position = sorted_positions; - Cursor_With_Index *one_past_last_position = sorted_positions + count; - Edit *edit = sorted_edits.vals; - Edit *one_past_last_edit = sorted_edits.vals + sorted_edits.count; - - i32 shift_amount = 0; - if (lean_right){ - for (;edit < one_past_last_edit && position < one_past_last_position; - ++edit){ - i32 start = edit->range.first; - i32 end = edit->range.one_past_last; - - for (;position->pos < start && position < one_past_last_position; - ++position){ - position->pos += shift_amount; - } - - i32 new_end = start + edit->length + shift_amount; - for (;position->pos <= end && position < one_past_last_position; - ++position){ - position->pos = new_end; - } - - shift_amount += (edit->length - (end - start)); - } - } - else{ - for (;edit < one_past_last_edit && position < one_past_last_position; - ++edit){ - i32 start = edit->range.first; - i32 end = edit->range.one_past_last; - - for (;position->pos < start && position < one_past_last_position; - ++position){ - position->pos += shift_amount; - } - - i32 new_end = start + shift_amount; - for (;position->pos <= end && position < one_past_last_position; - ++position){ - position->pos = new_end; - } - - shift_amount += (edit->length - (end - start)); - } - } - - for (;position < one_past_last_position; - ++position){ - position->pos += shift_amount; - } - - for (;edit < one_past_last_edit; - ++edit){ - shift_amount += (edit->length - (edit->range.one_past_last - edit->range.first)); - } - - return(shift_amount); -} - ////////////////////////////////////// internal i32 @@ -237,23 +157,21 @@ eol_in_place_convert_in(char *data, i32 size){ } // TODO(allen): iterative memory check? -internal i32 -eol_convert_out(char *dest, i32 max, char *src, i32 size, i32 *size_out){ - i32 result = 1; - i32 i = 0; - i32 j = 0; - - for (; i < size; ++i, ++j){ +internal b32 +eol_convert_out(char *dest, i64 max, char *src, i64 size, i64 *size_out){ + i64 j = 0; + for (i64 i = 0; i < size; ++i, ++j){ if (src[i] == '\n'){ dest[j] = '\r'; ++j; dest[j] = '\n'; } - else dest[j] = src[i]; + else{ + dest[j] = src[i]; + } } - *size_out = j; - return(result); + return(true); } // TODO(allen): iterative memory check? @@ -277,1623 +195,419 @@ eol_in_place_convert_out(char *data, i32 size, i32 max, i32 *size_out){ ////////////////////////////////////// -// -// Implementation of the gap buffer -// - -internal i32 -buffer_good(Gap_Buffer *buffer){ - i32 good = (buffer->data != 0); - return(good); -} - -internal i32 -buffer_size(Gap_Buffer *buffer){ - i32 size = buffer->size1 + buffer->size2; - return(size); -} - -internal Gap_Buffer_Init -buffer_begin_init(Gap_Buffer *buffer, u8 *data, umem size){ - Gap_Buffer_Init init; - init.buffer = buffer; - init.data = (char*)data; - init.size = (i32)size; - return(init); -} - internal b32 -buffer_init_need_more(Gap_Buffer_Init *init){ - return(init->buffer->data == 0); +buffer_good(Gap_Buffer *buffer){ + return(buffer->data != 0); } -internal i32 -buffer_init_page_size(Gap_Buffer_Init *init){ - return(init->size * 2); +internal i64 +buffer_size(Gap_Buffer *buffer){ + return(buffer->size1 + buffer->size2); +} + +internal i64 +buffer_line_count(Gap_Buffer *buffer){ + return(buffer->line_start_count - 1); } internal void -buffer_init_provide_page(Gap_Buffer_Init *init, void *page, i32 page_size){ - Gap_Buffer *buffer = init->buffer; - buffer->data = (char*)page; - buffer->max = page_size; +buffer_init(Gap_Buffer *buffer, u8 *data, umem size, Base_Allocator *allocator){ + block_zero_struct(buffer); + + buffer->allocator = allocator; + + umem capacity = round_up_umem(size*2, KB(4)); + Data memory = base_allocate(allocator, capacity); + buffer->data = (u8*)memory.data; + buffer->size1 = size/2; + buffer->gap_size = capacity - size; + buffer->size2 = size - buffer->size1; + buffer->max = capacity; + + block_copy(buffer->data, data, buffer->size1); + block_copy(buffer->data + buffer->size1 + buffer->gap_size, data + buffer->size1, buffer->size2); } internal b32 -buffer_end_init(Gap_Buffer_Init *init){ - Gap_Buffer *buffer = init->buffer; +buffer_replace_range(Gap_Buffer *buffer, Range_i64 range, String_Const_u8 text, i64 shift_amount){ + i64 size = buffer_size(buffer); + Assert(0 <= range.start); + Assert(range.start <= range.end); + Assert(range.end <= size); + + if (shift_amount + size > buffer->max){ + i64 new_max = round_up_i64(2*(shift_amount + size), KB(4)); + i64 new_gap_size = new_max - size; + Data new_memory_data = base_allocate(buffer->allocator, new_max); + u8 *new_memory = (u8*)new_memory_data.data; + block_copy(new_memory, buffer->data, buffer->size1); + block_copy(new_memory + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, + buffer->size2); + base_free(buffer->allocator, buffer->data); + buffer->data = new_memory; + buffer->gap_size = new_gap_size; + buffer->max = new_max; + } + + Assert(shift_amount + size <= buffer->max); + b32 result = false; - if (buffer->data != 0 && buffer->max >= init->size){ - i32 size = init->size; - i32 size2 = (size >> 1); - i32 osize1 = size - size2; - i32 size1 = osize1; - - if (size1 > 0){ - size1 = eol_convert_in(buffer->data, init->data, size1); - if (size2 > 0){ - size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2); - } - } - - buffer->size1 = size1; - buffer->size2 = size2; - buffer->gap_size = buffer->max - size1 - size2; - memmove(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2); - - result = true; + if (range.end < buffer->size1){ + i64 move_size = buffer->size1 - range.end; + block_copy(buffer->data + buffer->size1 + buffer->gap_size - move_size, + buffer->data + range.end, + move_size); + buffer->size1 -= move_size; + buffer->size2 += move_size; } + if (range.start > buffer->size1){ + i64 move_size = range.start - buffer->size1; + block_copy(buffer->data + buffer->size1, + buffer->data + buffer->size1 + buffer->gap_size, + move_size); + buffer->size1 += move_size; + buffer->size2 -= move_size; + } + + block_copy(buffer->data + range.start, text.str, text.size); + buffer->size2 = size - range.end; + buffer->size1 = range.start + text.size; + buffer->gap_size -= shift_amount; + + Assert(buffer->size1 + buffer->size2 == size + shift_amount); + Assert(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max); return(result); } -internal b32 -buffer_stringify_loop(Gap_Buffer_Stream *stream, Gap_Buffer *buffer, i32 start, i32 end){ - b32 result = false; - - if (0 <= start && start < end && end <= buffer->size1 + buffer->size2){ - stream->buffer = buffer; - stream->absolute_end = end; - - if (start < buffer->size1){ - if (buffer->size1 < end){ - stream->separated = true; - } - else{ - stream->separated = false; - } - stream->data = buffer->data; - } - else{ - stream->separated = false; - stream->data = buffer->data + buffer->gap_size; - } - - if (stream->separated){ - stream->end = buffer->size1; - } - else{ - stream->end = end; - } - - if (stream->end > stream->absolute_end){ - stream->end = stream->absolute_end; - } - - result = true; - } - - if (!result && stream->use_termination_character){ - stream->buffer = buffer; - stream->absolute_end = end; - stream->use_termination_character = true; - stream->data = (&stream->terminator) - buffer->size1 - buffer->size2; - stream->end = stream->absolute_end + 1; - result = true; - } - - return(result); -} +//////////////////////////////// -internal b32 -buffer_stringify_next(Gap_Buffer_Stream *stream){ - b32 result = 0; - Gap_Buffer *buffer = stream->buffer; - if (stream->separated){ - stream->data = buffer->data + buffer->gap_size; - stream->end = stream->absolute_end; - stream->separated = 0; - result = 1; - } - - if (result == 0){ - if (stream->use_termination_character){ - stream->use_termination_character = 0; - stream->data = (&stream->terminator) - buffer->size1 - buffer->size2; - stream->end = stream->absolute_end + 1; - result = 1; - } - } - - return(result); -} - -internal i32 -buffer_replace_range_compute_shift(i32 start, i32 end, i32 len){ - return(len - (end - start)); -} - -internal b32 -buffer_replace_range(Gap_Buffer *buffer, i32 start, i32 end, char *str, i32 len, i32 shift_amount, i32 *request_amount){ - char *data = buffer->data; - i32 size = buffer_size(buffer); - b32 result = false; - i32 move_size = 0; - - Assert(0 <= start); - Assert(start <= end); - Assert(end <= size); - - if (shift_amount + size <= buffer->max){ - if (end < buffer->size1){ - move_size = buffer->size1 - end; - memmove(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(data + buffer->size1, data + buffer->size1 + buffer->gap_size, move_size); - buffer->size1 += move_size; - buffer->size2 -= move_size; - } - - memcpy(data + start, str, len); - buffer->size2 = size - end; - buffer->size1 = start + len; - buffer->gap_size -= shift_amount; - - Assert(buffer->size1 + buffer->size2 == size + shift_amount); - Assert(buffer->size1 + buffer->gap_size + buffer->size2 == buffer->max); - } - else{ - *request_amount = round_up_i32(2*(shift_amount + size), KB(4)); - result = true; - } - - return(result); -} - -internal b32 -buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Edit_Array sorted_edits, i32 *request_amount){ - b32 result = false; - - i32 shift_total = state->shift_total; - i32 i = state->i; - - Edit *edit = sorted_edits.vals + i; - for (; i < sorted_edits.count; ++i, ++edit){ - char *str = edit->str; - i32 length = edit->length; - i32 start = edit->range.first + shift_total; - i32 end = edit->range.one_past_last + shift_total; - i32 shift_amount = buffer_replace_range_compute_shift(start, end, length); - result = buffer_replace_range(buffer, start, end, str, length, shift_amount, request_amount); - if (result){ - break; - } - shift_total += shift_amount; - } - - state->shift_total = shift_total; - state->i = i; - - return(result); -} - -internal void* -buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, i32 new_max){ - void *result = buffer->data; - i32 size = buffer_size(buffer); - i32 new_gap_size = new_max - size; - - Assert(new_max >= size); - - memcpy(new_data, buffer->data, buffer->size1); - memcpy((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); - - buffer->data = (char*)new_data; - buffer->gap_size = new_gap_size; - buffer->max = new_max; - - return(result); -} - -// -// High level buffer operations -// - -internal String_Const_u8_Array -buffer_get_chunks(Cursor *cursor, Gap_Buffer *buffer, Buffer_Get_Chunk_Mode mode){ - i32 total_count = (buffer->size1 > 0) + (buffer->size2 > 0) + (mode == BufferGetChunk_ZeroTerminated); - String_Const_u8_Array result = {}; - result.vals = push_array(cursor, String_Const_u8, total_count); +internal List_String_Const_u8 +buffer_get_chunks(Arena *arena, Gap_Buffer *buffer){ + List_String_Const_u8 list = {}; if (buffer->size1 > 0){ - result.vals[result.count] = SCu8(buffer->data, buffer->size1); - result.count += 1; + string_list_push(arena, &list, SCu8(buffer->data, buffer->size1)); } if (buffer->size2 > 0){ - result.vals[result.count] = SCu8(buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); - result.count += 1; + umem gap_2_pos = buffer->size1 + buffer->gap_size; + string_list_push(arena, &list, SCu8(buffer->data + gap_2_pos, buffer->size2)); } - if (mode == BufferGetChunk_ZeroTerminated){ - result.vals[result.count] = SCu8(); - result.count += 1; - } - return(result); -} - -internal String_Const_u8_Array -buffer_get_chunks(Cursor *cursor, Gap_Buffer *buffer){ - return(buffer_get_chunks(cursor, buffer, BufferGetChunk_Basic)); -} - -internal String_Const_u8_Array -buffer_chunks_clamp(String_Const_u8_Array chunks, Range_i64 range){ - i64 real_position = 0; - for (i32 i = 0; i < chunks.count; i += 1){ - Range_i64 chunk_range = Ii64(real_position, real_position + chunks.strings[i].size); - Range_i64 clamped_range = Ii64(clamp(range.min, chunk_range.min, range.max), - clamp(range.min, chunk_range.max, range.max)); - chunks.strings[i].str += clamped_range.min - chunk_range.min; - chunks.strings[i].size = range_size(clamped_range); - real_position += range_size(chunk_range); - } - for (; chunks.count > 0 && chunks.strings[0].size == 0;){ - chunks.strings += 1; - chunks.count -= 1; - } - for (; chunks.count > 0 && chunks.strings[chunks.count - 1].size == 0;){ - chunks.count -= 1; - } - return(chunks); + return(list); } internal void -buffer_stringify(Gap_Buffer *buffer, i32 start, i32 end, char *out){ - Gap_Buffer_Stream stream = {}; - - i32 i = start; - if (buffer_stringify_loop(&stream, buffer, i, end)){ - b32 still_looping = 0; - do{ - i32 size = stream.end - i; - memcpy(out, stream.data + i, size); - i = stream.end; - out += size; - still_looping = buffer_stringify_next(&stream); - }while(still_looping); +buffer_chunks_clamp(List_String_Const_u8 *chunks, Interval_i64 range){ + i64 p = 0; + List_String_Const_u8 list = {}; + for (Node_String_Const_u8 *node = chunks->first, *next = 0; + node != 0; + node = next){ + next = node->next; + Interval_i64 node_range = Ii64(p, p + node->string.size); + if (range_overlap(range, node_range)){ + i64 first = max(node_range.first, range.first) - node_range.first; + i64 one_past_last = min(node_range.one_past_last, range.one_past_last) - node_range.first; + String_Const_u8 s = string_prefix(node->string, one_past_last); + node->string = string_skip(s, first); + sll_queue_push(list.first, list.last, node); + list.total_size += node->string.size; + list.node_count += 1; + } + p = node_range.one_past_last; } + *chunks = list; } -internal void -buffer_stringify_range(Gap_Buffer *buffer, Range range, char *out){ - buffer_stringify(buffer, range.first, range.one_past_last, out); +internal String_Const_u8 +buffer_stringify(Arena *arena, Gap_Buffer *buffer, Interval_i64 range){ + List_String_Const_u8 list = buffer_get_chunks(arena, buffer); + buffer_chunks_clamp(&list, range); + return(string_list_flatten(arena, list, StringFill_NullTerminate)); } -internal i32 -buffer_convert_out(Gap_Buffer *buffer, char *dest, i32 max){ - Gap_Buffer_Stream stream = {}; - i32 i = 0; - i32 size = buffer_size(buffer); - Assert(size + buffer->line_count <= max); - - i32 pos = 0; - if (buffer_stringify_loop(&stream, buffer, 0, size)){ - b32 still_looping = 0; - do{ - i32 chunk_size = stream.end - i; - i32 out_size = 0; - i32 result = eol_convert_out(dest + pos, max - pos, stream.data + i, chunk_size, &out_size); - Assert(result); - i = stream.end; - pos += out_size; - still_looping = buffer_stringify_next(&stream); - }while(still_looping); - } - - return(pos); -} - -internal i32 -buffer_count_newlines(Gap_Buffer *buffer, i32 start, i32 end){ - Gap_Buffer_Stream stream = {}; - i32 i = start; - i32 count = 0; - - Assert(0 <= start); - Assert(start <= end); - Assert(end <= buffer_size(buffer)); - - if (buffer_stringify_loop(&stream, buffer, i, end)){ - b32 still_looping = 0; - do{ - for (; i < stream.end; ++i){ - count += (stream.data[i] == '\n'); +internal String_Const_u8 +buffer_eol_convert_out(Arena *arena, Gap_Buffer *buffer, Interval_i64 range){ + List_String_Const_u8 list = buffer_get_chunks(arena, buffer); + buffer_chunks_clamp(&list, range); + umem cap = list.total_size*2; + u8 *memory = push_array(arena, u8, cap); + u8 *memory_opl = memory + cap; + u8 *ptr = memory; + for (Node_String_Const_u8 *node = list.first; + node != 0; + node = node->next){ + u8 *byte = node->string.str; + u8 *byte_opl = byte + node->string.size; + for (;byte < byte_opl; byte += 1){ + if (*byte == '\n'){ + *ptr = '\r'; + ptr += 1; + *ptr = '\n'; + ptr += 1; } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); + else{ + *ptr = *byte; + ptr += 1; + } + } } + linalloc_pop(arena, (memory_opl - ptr)); + push_align(arena, 8); + return(SCu8(memory, ptr)); +} + +internal i64 +buffer_count_newlines(Arena *scratch, Gap_Buffer *buffer, i64 start, i64 end){ + Temp_Memory temp = begin_temp(scratch); + List_String_Const_u8 list = buffer_get_chunks(scratch, buffer); + buffer_chunks_clamp(&list, Ii64(start, end)); + + i64 count = 0; + for (Node_String_Const_u8 *node = list.first; + node != 0; + node = node->next){ + u8 *byte = node->string.str; + u8 *byte_opl = byte + node->string.size; + for (;byte < byte_opl; byte += 1){ + if (*byte == '\n'){ + count += 1; + } + } + } + + end_temp(temp); return(count); } -// TODO(allen): Rewrite this with a duff routine -// Also make it so that the array goes one past the end -// and stores the size in the extra spot. -internal i32 -buffer_measure_starts(Buffer_Measure_Starts *state, Gap_Buffer *buffer){ - Gap_Buffer_Stream stream = {}; - i32 size = buffer_size(buffer); - i32 start = state->start, i = state->i; - i32 *start_ptr = buffer->line_starts + state->count; - i32 *start_end = buffer->line_starts + buffer->line_max; - i32 result = 1; +internal void +buffer_starts__ensure_max_size(Gap_Buffer *buffer, i64 max_size){ + if (max_size > buffer->line_start_max){ + i64 new_max = round_up_i64(max_size*2, KB(1)); + Data memory = base_allocate(buffer->allocator, sizeof(*buffer->line_starts)*new_max); + i64 *new_line_starts = (i64*)memory.data; + block_copy_dynamic_array(new_line_starts, buffer->line_starts, buffer->line_start_count); + buffer->line_start_max = new_max; + base_free(buffer->allocator, buffer->line_starts); + buffer->line_starts = new_line_starts; + } +} + +internal void +buffer_measure_starts__write(Gap_Buffer *buffer, i64 pos){ + buffer_starts__ensure_max_size(buffer, buffer->line_start_count + 1); + buffer->line_starts[buffer->line_start_count] = pos; + buffer->line_start_count += 1; +} + +internal void +buffer_measure_starts(Arena *scratch, Gap_Buffer *buffer){ + Temp_Memory temp = begin_temp(scratch); + List_String_Const_u8 list = buffer_get_chunks(scratch, buffer); + buffer->line_start_count = 0; + buffer_measure_starts__write(buffer, 0); + i64 index = 0; + for (Node_String_Const_u8 *node = list.first; + node != 0; + node = node->next){ + u8 *byte = node->string.str; + u8 *byte_opl = byte + node->string.size; + for (;byte < byte_opl; byte += 1){ + index += 1; + if (*byte == '\n'){ + buffer_measure_starts__write(buffer, index); + } + } + } + buffer_measure_starts__write(buffer, buffer_size(buffer)); + end_temp(temp); +} + +internal void +buffer_remeasure_starts(Arena *scratch, Gap_Buffer *buffer, Interval_i64 old_line_indexes, i64 line_shift, i64 text_shift){ + Temp_Memory temp = begin_temp(scratch); + buffer_starts__ensure_max_size(buffer, buffer->line_start_count + line_shift); - if (buffer_stringify_loop(&stream, buffer, i, size)){ - b32 still_looping = 0; - do{ - for (; i < stream.end; ++i){ - char ch = stream.data[i]; - if (ch == '\n'){ - if (start_ptr == start_end){ - goto buffer_measure_starts_widths_end; - } - - *start_ptr++ = start; - start = i + 1; + i64 new_line_indexes_opl = old_line_indexes.one_past_last + line_shift; + i64 old_line_start_count = buffer->line_start_count; + i64 *line_start_ptr = buffer->line_starts + old_line_indexes.one_past_last; + for (i64 i = old_line_indexes.one_past_last; i < old_line_start_count; i += 1, line_start_ptr += 1){ + *line_start_ptr += text_shift; + } + block_copy_dynamic_array(buffer->line_starts + old_line_indexes.one_past_last, + buffer->line_starts + new_line_indexes_opl, + buffer->line_start_count - old_line_indexes.one_past_last); + + i64 first_pos = buffer->line_starts[old_line_indexes.first]; + i64 write_counter = old_line_indexes.first + 1; + i64 pos = first_pos; + List_String_Const_u8 list = buffer_get_chunks(scratch, buffer); + buffer_chunks_clamp(&list, Ii64(first_pos, buffer_size(buffer))); + for (Node_String_Const_u8 *node = list.first; + node != 0; + node = node->next){ + u8 *byte = node->string.str; + u8 *byte_opl = byte + node->string.size; + for (;byte < byte_opl; byte += 1){ + pos += 1; + if (*byte == '\n'){ + buffer->line_starts[write_counter] = pos; + write_counter += 1; + if (write_counter == new_line_indexes_opl){ + goto double_break; } } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); + } } + double_break:; - Assert(i == size); - - if (start_ptr == start_end){ - goto buffer_measure_starts_widths_end; + buffer->line_start_count += line_shift; + end_temp(temp); +} + +internal i64 +buffer_get_line_index(Gap_Buffer *buffer, i64 pos){ + i64 i = 0; + if (buffer->line_start_count > 2){ + i64 start = 0; + i64 one_past_last = buffer->line_start_count - 1; + i64 *array = buffer->line_starts; + pos = clamp_bot(0, pos); + for (;;){ + i = (start + one_past_last) >> 1; + if (array[i] < pos){ + start = i; + } + else if (array[i] > pos){ + one_past_last = i; + } + else{ + break; + } + if (start + 1 >= one_past_last){ + i = start; + break; + } + } } - *start_ptr++ = start; - result = 0; - - buffer_measure_starts_widths_end:; - state->i = i; - state->count = (i32)(start_ptr - buffer->line_starts); - state->start = start; - - if (!result){ - buffer->line_count = state->count; + return(i); +} + +internal Interval_i64 +buffer_get_pos_range_from_line_number(Gap_Buffer *buffer, i64 line_number){ + Interval_i64 result = {}; + if (1 <= line_number && line_number < buffer->line_start_count){ + result.first = buffer->line_starts[line_number - 1]; + result.one_past_last = buffer->line_starts[line_number]; } - return(result); } -internal void -buffer_measure_character_starts(System_Functions *system, Gap_Buffer *buffer, i32 *character_starts, i32 mode, i32 virtual_white){ - Assert(mode == 0); - - Gap_Buffer_Stream stream = {}; - i32 i = 0; - i32 size = buffer_size(buffer); - - i32 line_index = 0; - i32 character_index = 0; - - b32 skipping_whitespace = 0; - - character_starts[line_index++] = character_index; - - if (virtual_white){ - skipping_whitespace = 1; +internal i64 +buffer_get_first_pos_from_line_number(Gap_Buffer *buffer, i64 line_number){ + i64 result = {}; + if (line_number < 1){ + result = 0; } - - Translation_State tran = {}; - Translation_Emits emits = {}; - - stream.use_termination_character = 1; - stream.terminator = '\n'; - if (buffer_stringify_loop(&stream, buffer, i, size)){ - b32 still_looping = 0; - do{ - for (; i < stream.end; ++i){ - u8 ch = (u8)stream.data[i]; - - translating_fully_process_byte(&tran, ch, i, size, &emits); - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); - - if (behavior.do_newline){ - ++character_index; - character_starts[line_index++] = character_index; - if (virtual_white){ - skipping_whitespace = 1; - } - } - else if (behavior.do_codepoint_advance || behavior.do_number_advance){ - if (ch != ' ' && ch != '\t'){ - skipping_whitespace = 0; - } - - if (!skipping_whitespace){ - ++character_index; - } - } - } - } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); + else if (line_number >= buffer->line_start_count){ + result = buffer_size(buffer); } - - Assert(line_index-1 == buffer->line_count); -} - -// duff-routine defines -#define DrCase(PC) case PC: goto resumespot_##PC -#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; } -#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); } - -internal Buffer_Layout_Stop -buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Params params, f32 line_shift, b32 do_wrap, i32 wrap_unit_end){ - Buffer_Measure_Wrap_State S = *S_ptr; - Buffer_Layout_Stop S_stop; - - switch (S.__pc__){ - DrCase(1); - DrCase(2); - DrCase(3); - DrCase(4); + else{ + result = buffer->line_starts[line_number - 1]; } - - S.size = buffer_size(params.buffer); - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = S.line_index; - S_stop.wrap_line_index = S.current_wrap_index; - S_stop.pos = S.i; - DrYield(1, S_stop); - } - - S.x = line_shift; - params.wrap_line_index[S.line_index++] = 0; - - if (params.virtual_white){ - S.skipping_whitespace = true; - } - - S.first_of_the_line = 1; - if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){ - S.still_looping = 0; - do{ - for (; S.i < S.stream.end; ++S.i){ - { - u8 ch = (u8)S.stream.data[S.i]; - - if (ch != ' ' && ch != '\t'){ - S.skipping_whitespace = false; - } - - translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); - } - - for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ - TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits); - - if (S.behavior.do_newline){ - ++S.current_wrap_index; - params.wrap_line_index[S.line_index++] = S.current_wrap_index; - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = S.line_index - 1; - S_stop.wrap_line_index = S.current_wrap_index; - S_stop.pos = S.i+1; - DrYield(2, S_stop); - } - - S.x = line_shift; - - if (params.virtual_white){ - S.skipping_whitespace = 1; - } - S.first_of_the_line = 1; - } - else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){ - if (!S.skipping_whitespace){ - if (S.behavior.do_codepoint_advance){ - S.current_adv = font_get_glyph_advance(params.face, S.step.value); - } - else{ - S.current_adv = params.face->byte_advance; - } - - S.did_wrap = false; - if (S.step.i >= S.wrap_unit_end){ - S_stop.status = BLStatus_NeedWrapDetermination; - S_stop.line_index = S.line_index - 1; - S_stop.wrap_line_index = S.current_wrap_index; - S_stop.pos = S.step.i; - S_stop.x = S.x; - DrYield(4, S_stop); - - S.wrap_unit_end = wrap_unit_end; - - if (do_wrap && !S.first_of_the_line){ - S.did_wrap = true; - ++S.current_wrap_index; - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedWrapLineShift; - S_stop.line_index = S.line_index - 1; - S_stop.wrap_line_index = S.current_wrap_index; - S_stop.pos = S.step.i; - DrYield(3, S_stop); - } - - S.x = line_shift + S.current_adv; - } - } - - if (!S.did_wrap){ - S.x += S.current_adv; - } - - S.first_of_the_line = 0; - } - } - } - } - S.still_looping = buffer_stringify_next(&S.stream); - }while(S.still_looping); - } - - ++S.current_wrap_index; - params.wrap_line_index[S.line_index++] = S.current_wrap_index; - - Assert(S.line_index-1 == params.buffer->line_count); - - S_stop.status = BLStatus_Finished; - DrReturn(S_stop); -} - -#undef DrCase -#undef DrYield -#undef DrReturn - -internal void -buffer_remeasure_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 text_shift){ - i32 *starts = buffer->line_starts; - i32 line_count = buffer->line_count; - - Assert(0 <= line_start); - Assert(line_start <= line_end); - Assert(line_end < line_count); - Assert(line_count + line_shift <= buffer->line_max); - - ++line_end; - - // Adjust - if (text_shift != 0){ - i32 line_i = line_end; - starts += line_i; - for (; line_i < line_count; ++line_i, ++starts){ - *starts += text_shift; - } - starts = buffer->line_starts; - } - - // Shift - i32 new_line_count = line_count; - i32 new_line_end = line_end; - if (line_shift != 0){ - new_line_count += line_shift; - new_line_end += line_shift; - - memmove(starts + line_end + line_shift, starts + line_end, sizeof(i32)*(line_count - line_end)); - } - - // Iteration data (yikes! Need better loop system) - Gap_Buffer_Stream stream = {}; - i32 size = buffer_size(buffer); - i32 char_i = starts[line_start]; - i32 line_i = line_start; - - // Line start measurement - i32 start = char_i; - - if (buffer_stringify_loop(&stream, buffer, char_i, size)){ - b32 still_looping = 0; - do{ - for (; char_i < stream.end; ++char_i){ - u8 ch = (u8)stream.data[char_i]; - - if (ch == '\n'){ - starts[line_i] = start; - ++line_i; - start = char_i + 1; - - // TODO(allen): I would like to know that I am not guessing here, - // so let's try to turn the && into an Assert. - if (line_i >= new_line_end && (line_i >= new_line_count || start == starts[line_i])){ - goto buffer_remeasure_starts_end; - } - } - } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); - } - - // TODO(allen): I suspect this can just go away. - if (char_i == size){ - starts[line_i++] = start; - } - - buffer_remeasure_starts_end:; - Assert(line_count >= 1); - buffer->line_count = new_line_count; -} - -internal void -buffer_remeasure_character_starts(System_Functions *system, Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){ - Assert(mode == 0); - - i32 new_line_count = buffer->line_count; - - Assert(0 <= line_start); - Assert(line_start <= line_end); - Assert(line_end < new_line_count - line_shift); - - ++line_end; - - // Shift - i32 line_count = new_line_count; - i32 new_line_end = line_end; - if (line_shift != 0){ - line_count -= line_shift; - new_line_end += line_shift; - - memmove(character_starts + line_end + line_shift, character_starts + line_end, sizeof(i32)*(line_count - line_end + 1)); - } - - // Iteration data - Gap_Buffer_Stream stream = {}; - i32 size = buffer_size(buffer); - i32 char_i = buffer->line_starts[line_start]; - i32 line_i = line_start; - - // Character measurement - i32 last_char_start = character_starts[line_i]; - i32 current_char_start = last_char_start; - - b32 skipping_whitespace = 0; - - if (virtual_whitespace){ - skipping_whitespace = 1; - } - - // Translation - Translation_State tran = {}; - Translation_Emits emits = {}; - - stream.use_termination_character = 1; - stream.terminator = '\n'; - if (buffer_stringify_loop(&stream, buffer, char_i, size)){ - b32 still_looping = 0; - do{ - for (; char_i < stream.end; ++char_i){ - u8 ch = (u8)stream.data[char_i]; - translating_fully_process_byte(&tran, ch, char_i, size, &emits); - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); - - if (behavior.do_newline){ - character_starts[line_i++] = last_char_start; - ++current_char_start; - last_char_start = current_char_start; - if (virtual_whitespace){ - skipping_whitespace = 1; - } - - if (line_i >= new_line_end){ - goto buffer_remeasure_character_starts_end; - } - } - else if (behavior.do_codepoint_advance || behavior.do_number_advance){ - if (ch != ' ' && ch != '\t'){ - skipping_whitespace = 0; - } - - if (!skipping_whitespace){ - ++current_char_start; - } - } - } - } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); - } - - Assert(line_i >= new_line_end); - - buffer_remeasure_character_starts_end:; - - // Adjust - if (line_i <= new_line_end){ - i32 character_shift = current_char_start - character_starts[line_i]; - - if (character_shift != 0){ - character_starts += line_i; - for (; line_i <= new_line_count; ++line_i, ++character_starts){ - *character_starts += character_shift; - } - } - } -} - -internal void -buffer_remeasure_wrap_y(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, - f32 *wraps, f32 font_height, f32 *adv, f32 max_width){ - i32 new_line_count = buffer->line_count; - - Assert(0 <= line_start); - Assert(line_start <= line_end); - Assert(line_end < new_line_count - line_shift); - - ++line_end; - - // Shift - i32 line_count = new_line_count; - i32 new_line_end = line_end; - if (line_shift != 0){ - line_count -= line_shift; - new_line_end += line_shift; - - memmove(wraps + line_end + line_shift, wraps + line_end, sizeof(i32)*(line_count - line_end + 1)); - } - - // Iteration data (yikes! Need better loop system) - Gap_Buffer_Stream stream = {}; - i32 size = buffer_size(buffer); - i32 char_i = buffer->line_starts[line_start]; - i32 line_i = line_start; - - // Line wrap measurement - f32 last_wrap = wraps[line_i]; - f32 current_wrap = last_wrap; - f32 x = 0.f; - - if (buffer_stringify_loop(&stream, buffer, char_i, size)){ - b32 still_looping = 0; - do{ - for (; char_i < stream.end; ++char_i){ - u8 ch = (u8)stream.data[char_i]; - - if (ch == '\n'){ - wraps[line_i] = last_wrap; - ++line_i; - current_wrap += font_height; - last_wrap = current_wrap; - x = 0.f; - - // TODO(allen): I would like to know that I am not guessing here. - if (line_i >= new_line_end){ - goto buffer_remeasure_wraps_end; - } - } - else{ - f32 current_adv = adv[ch]; - if (x + current_adv > max_width){ - current_wrap += font_height; - x = current_adv; - } - else{ - x += current_adv; - } - } - } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); - } - - wraps[line_i++] = last_wrap; - - buffer_remeasure_wraps_end:; - - // Adjust - if (line_i <= new_line_end){ - f32 y_shift = current_wrap - wraps[line_i]; - - if (y_shift != 0){ - wraps += line_i; - for (; line_i <= new_line_count; ++line_i, ++wraps){ - *wraps += y_shift; - } - } - } -} - -internal i32 -binary_search(i32 *array, i32 value, i32 l_bound, i32 u_bound){ - i32 start = l_bound, end = u_bound; - i32 i = 0; - - if (value < 0){ - value = 0; - } - - for (;;){ - i = (start + end) >> 1; - if (array[i] < value){ - start = i; - } - else if (array[i] > value){ - end = i; - } - else{ - break; - } - Assert(start < end); - if (start == end - 1){ - i = start; - break; - } - } - - return(i); -} - -// TODO(allen): CHECK -internal i32 -buffer_get_line_index_range(Gap_Buffer *buffer, i32 pos, i32 l_bound, i32 u_bound){ - Assert(0 <= l_bound); - Assert(l_bound <= u_bound); - Assert(u_bound <= buffer->line_count); - - Assert(buffer->line_starts != 0); - - i32 i = binary_search(buffer->line_starts, pos, l_bound, u_bound); - return(i); -} - -internal i32 -buffer_get_line_number(Gap_Buffer *buffer, i32 pos){ - i32 result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count); return(result); } -internal i32 -buffer_get_line_index_from_character_pos(i32 *character_starts, i32 pos, i32 l_bound, i32 u_bound){ - i32 i = binary_search(character_starts, pos, l_bound, u_bound); - return(i); +internal i64 +buffer_get_last_pos_from_line_number(Gap_Buffer *buffer, i64 line_number){ + i64 result = {}; + if (line_number < 1){ + result = 0; + } + else if (line_number >= buffer->line_start_count - 1){ + result = buffer_size(buffer); + } + else{ + result = buffer->line_starts[line_number] - 1; + } + return(result); } -internal i32 -buffer_get_line_index_from_wrapped_y(i32 *wrap_line_index, f32 y, i32 line_height, i32 l_bound, i32 u_bound){ - i32 wrap_index = floor32(y/line_height); - i32 i = binary_search(wrap_line_index, wrap_index, l_bound, u_bound); - return(i); -} - -internal Partial_Cursor -buffer_partial_from_pos(Gap_Buffer *buffer, i32 pos){ - Partial_Cursor result = {}; - - i32 size = buffer_size(buffer); +internal Buffer_Cursor +buffer_cursor_from_pos(Gap_Buffer *buffer, i64 pos){ + i64 size = buffer_size(buffer); pos = clamp(0, pos, size); + i64 line_index = buffer_get_line_index(buffer, pos); - i32 line_index = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count); + Buffer_Cursor result = {}; result.pos = pos; result.line = line_index + 1; - result.character = pos - buffer->line_starts[line_index] + 1; - + result.col = pos - buffer->line_starts[line_index] + 1; return(result); } -internal Partial_Cursor -buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){ - Partial_Cursor result = {}; +internal Buffer_Cursor +buffer_cursor_from_line_col(Gap_Buffer *buffer, i64 line, i64 col){ + i64 size = buffer_size(buffer); + i64 line_index = line - 1; + i64 line_count = buffer_line_count(buffer); + line_index = clamp(0, line_index, line_count); - i32 line_index = line - 1; - i32 last_line_index = buffer->line_count - 1; - line_index = clamp(0, line_index, last_line_index); + i64 this_start = buffer->line_starts[line_index]; + i64 max_col = (buffer->line_starts[line_index + 1] - this_start); - i32 size = buffer_size(buffer); - - i32 this_start = buffer->line_starts[line_index]; - i32 max_character = (size - this_start) + 1; - if (line_index < last_line_index){ - i32 next_start = buffer->line_starts[line_index + 1]; - max_character = (next_start - this_start); - } - - i32 adjusted_pos = 0; - if (character > 0){ - if (character > max_character){ - adjusted_pos = max_character - 1; + if (col < 0){ + if (-col > max_col){ + col = 1; } else{ - adjusted_pos = character - 1; + col = max_col + col + 1; } } - else if (character == 0){ - adjusted_pos = 0; + else if (col == 0){ + col = 1; } else{ - if (-character > max_character){ - adjusted_pos = 0; - } - else{ - adjusted_pos = max_character + character; - } + col = clamp_top(col, max_col); } + Assert(col > 0); + i64 adjusted_pos = col - 1; - result.pos = this_start + adjusted_pos; + i64 pos = this_start + adjusted_pos; + + Buffer_Cursor result = {}; + result.pos = pos; result.line = line_index + 1; - result.character = character; - + result.col = col; return(result); } -// dialogical-routine defines -#define DrCase(PC) case PC: goto resumespot_##PC -#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; } -#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); } - -internal Buffer_Layout_Stop -buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params params, f32 line_shift, b32 do_wrap, i32 wrap_unit_end){ - Buffer_Cursor_Seek_State S = *S_ptr; - Buffer_Layout_Stop S_stop; - - switch (S.__pc__){ - DrCase(1); - DrCase(2); - DrCase(3); - DrCase(4); - } - - S.font_height = (i32)(params.face->height); - - S.xy_seek = (params.seek.type == buffer_seek_wrapped_xy || params.seek.type == buffer_seek_unwrapped_xy); - S.size = buffer_size(params.buffer); - - // Get cursor hint - { - i32 line_index = 0; - switch (params.seek.type){ - case buffer_seek_pos: - { - params.seek.pos = clamp(0, params.seek.pos, S.size); - - line_index = buffer_get_line_number(params.buffer, (i32)params.seek.pos); - }break; - - case buffer_seek_character_pos: - { - i32 line_count = params.buffer->line_count; - i32 max_character = params.character_starts[line_count] - 1; - params.seek.pos = clamp(0, params.seek.pos, max_character); - - line_index = buffer_get_line_index_from_character_pos(params.character_starts, (i32)params.seek.pos, 0, params.buffer->line_count); - }break; - - case buffer_seek_line_char: - { - line_index = (i32)params.seek.line - 1; - line_index = clamp_bot(0, line_index); - }break; - - case buffer_seek_unwrapped_xy: - { - line_index = (i32)(params.seek.y / S.font_height); - line_index = clamp_bot(0, line_index); - }break; - - case buffer_seek_wrapped_xy: - { - line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, S.font_height, 0, params.buffer->line_count); - }break; - - default: InvalidPath; - } - - i32 safe_line_index = line_index; - if (line_index >= params.buffer->line_count){ - safe_line_index = params.buffer->line_count-1; - } - - // Build the cursor hint - S.next_cursor.pos = params.buffer->line_starts[safe_line_index]; - S.next_cursor.character_pos = params.character_starts[safe_line_index]; - S.next_cursor.line = safe_line_index + 1; - S.next_cursor.character = 1; - S.next_cursor.wrap_line = params.wrap_line_index[safe_line_index] + 1; - S.next_cursor.unwrapped_y = (f32)(safe_line_index * S.font_height); - S.next_cursor.unwrapped_x = 0; - S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[safe_line_index] * S.font_height); - S.next_cursor.wrapped_x = 0; - } - - // Get the initial line shift. - // Adjust the non-screen based coordinates to point to the first - // non-virtual character of the line. - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = (i32)S.next_cursor.line - 1; - S_stop.wrap_line_index = (i32)S.next_cursor.wrap_line - 1; - DrYield(1, S_stop); - - S.next_cursor.unwrapped_x += line_shift; - S.next_cursor.wrapped_x += line_shift; - - S.stream.use_termination_character = 1; - S.stream.terminator = '\n'; - if (buffer_stringify_loop(&S.stream, params.buffer, (i32)S.next_cursor.pos, S.size)){ - do{ - for (; S.next_cursor.pos < S.stream.end; ++S.next_cursor.pos){ - u8 ch = (u8)S.stream.data[S.next_cursor.pos]; - - if (ch != ' ' && ch != '\t'){ - goto double_break_vwhite; - } - else{ - ++S.next_cursor.character; - } - } - S.still_looping = buffer_stringify_next(&S.stream); - }while(S.still_looping); - } - InvalidPath; - double_break_vwhite:; - } - - // If the caller just wants the hint, return that now. - if (params.return_hint){ - *params.cursor_out = S.next_cursor; - S_stop.status = BLStatus_Finished; - DrReturn(S_stop); - } - - // If we are already passed the point we want to be at, then just take this. - S.this_cursor = S.next_cursor; - switch (params.seek.type){ - case buffer_seek_pos: - { - if (S.next_cursor.pos >= params.seek.pos){ - goto buffer_cursor_seek_end; - } - }break; - - case buffer_seek_character_pos: - { - if (S.next_cursor.character_pos >= params.seek.pos){ - goto buffer_cursor_seek_end; - } - }break; - - case buffer_seek_line_char: - { - if ((S.next_cursor.line == params.seek.line && - S.next_cursor.character >= params.seek.character) || - S.next_cursor.line > params.seek.line){ - goto buffer_cursor_seek_end; - } - }break; - - case buffer_seek_unwrapped_xy: - { - if (S.next_cursor.unwrapped_y > params.seek.y){ - goto buffer_cursor_seek_end; - } - }break; - - case buffer_seek_wrapped_xy: - { - if (S.next_cursor.wrapped_y > params.seek.y){ - goto buffer_cursor_seek_end; - } - }break; - } - - // Main seek loop - S.i = (i32)S.next_cursor.pos; - - S.stream = null_buffer_stream; - S.stream.use_termination_character = 1; - S.stream.terminator = 0; - - S.first_of_the_line = 1; - if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){ - S.still_looping = 0; - do{ - for (; S.i < S.stream.end; ++S.i){ - { - u8 ch = (u8)S.stream.data[S.i]; - translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); - } - - for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ - TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits); - - S.prev_cursor = S.this_cursor; - S.this_cursor = S.next_cursor; - - if (S.behavior.do_newline){ - ++S.next_cursor.character_pos; - ++S.next_cursor.line; - ++S.next_cursor.wrap_line; - S.next_cursor.unwrapped_y += S.font_height; - S.next_cursor.wrapped_y += S.font_height; - S.next_cursor.character = 1; - S.next_cursor.unwrapped_x = 0; - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = (i32)S.next_cursor.line - 1; - S_stop.wrap_line_index = (i32)S.next_cursor.wrap_line - 1; - DrYield(2, S_stop); - } - - S.next_cursor.wrapped_x = line_shift; - S.first_of_the_line = 1; - } - else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){ - - if (S.behavior.do_codepoint_advance){ - S.ch_width = font_get_glyph_advance(params.face, S.step.value); - } - else{ - S.ch_width = params.face->byte_advance; - } - - if (S.step.i >= S.wrap_unit_end){ - S_stop.status = BLStatus_NeedWrapDetermination; - S_stop.line_index = (i32)S.next_cursor.line - 1; - S_stop.wrap_line_index = (i32)S.next_cursor.wrap_line - 1; - S_stop.pos = S.step.i; - S_stop.x = S.next_cursor.wrapped_x; - DrYield(4, S_stop); - - S.wrap_unit_end = wrap_unit_end; - - if (do_wrap && !S.first_of_the_line){ - S.next_cursor.wrapped_y += S.font_height; - - ++S.next_cursor.wrap_line; - if (params.virtual_white){ - S_stop.status = BLStatus_NeedWrapLineShift; - S_stop.line_index = (i32)S.next_cursor.line - 1; - S_stop.wrap_line_index = (i32)S.next_cursor.wrap_line - 1; - DrYield(3, S_stop); - } - - S.next_cursor.wrapped_x = line_shift; - S.this_cursor = S.next_cursor; - } - } - - ++S.next_cursor.character_pos; - ++S.next_cursor.character; - S.next_cursor.unwrapped_x += S.ch_width; - S.next_cursor.wrapped_x += S.ch_width; - - S.first_of_the_line = 0; - } - - S.next_cursor.pos += S.step.byte_length; - - f32 x = 0, px = 0, y = 0, py = 0; - switch (params.seek.type){ - case buffer_seek_pos: - if (S.this_cursor.pos >= params.seek.pos){ - goto buffer_cursor_seek_end; - }break; - - case buffer_seek_character_pos: - if (S.this_cursor.character_pos >= params.seek.pos){ - goto buffer_cursor_seek_end; - }break; - - case buffer_seek_wrapped_xy: - { - x = S.this_cursor.wrapped_x; - px = S.prev_cursor.wrapped_x; - y = S.this_cursor.wrapped_y; - py = S.prev_cursor.wrapped_y; - }break; - - case buffer_seek_unwrapped_xy: - { - x = S.this_cursor.unwrapped_x; - px = S.prev_cursor.unwrapped_x; - y = S.this_cursor.unwrapped_y; - py = S.prev_cursor.wrapped_y; - }break; - - case buffer_seek_line_char: - if (S.this_cursor.line == params.seek.line && S.this_cursor.character >= params.seek.character){ - goto buffer_cursor_seek_end; - } - else if (S.this_cursor.line > params.seek.line){ - S.this_cursor = S.prev_cursor; - goto buffer_cursor_seek_end; - }break; - } - - if (S.xy_seek){ - if (y > params.seek.y){ - S.this_cursor = S.prev_cursor; - goto buffer_cursor_seek_end; - } - - if (y > params.seek.y - S.font_height && x >= params.seek.x){ - if (!params.seek.round_down){ - if (py >= y && !S.behavior.do_newline && (params.seek.x - px) < (x - params.seek.x)){ - S.this_cursor = S.prev_cursor; - } - goto buffer_cursor_seek_end; - } - - if (py >= y){ - S.this_cursor = S.prev_cursor; - } - goto buffer_cursor_seek_end; - } - } - - if (S.next_cursor.pos > S.size){ - goto buffer_cursor_seek_end; - } - } - } - S.still_looping = buffer_stringify_next(&S.stream); - }while(S.still_looping); - } - - InvalidPath; - - buffer_cursor_seek_end:; - *params.cursor_out = S.this_cursor; - S_stop.status = BLStatus_Finished; - DrReturn(S_stop); +internal String_Const_u8 +buffer_invert_edit_shift(Arena *arena, Gap_Buffer *buffer, Edit edit, Edit *inv, i64 shift_amount){ + String_Const_u8 string = buffer_stringify(arena, buffer, edit.range); + inv->text = string; + inv->range = Ii64(edit.range.start + shift_amount, edit.range.start + edit.text.size + shift_amount); + return(string); } -#undef DrCase -#undef DrYield -#undef DrReturn - -internal void -buffer_invert_edit_shift(Gap_Buffer *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, - i32 *str_pos, i32 max, i32 shift_amount){ - i32 pos = *str_pos; - i32 len = edit.end - edit.start; - Assert(pos >= 0); - Assert(pos + len <= max); - *str_pos = pos + len; - - inverse->str_start = pos; - inverse->len = len; - inverse->start = edit.start + shift_amount; - inverse->end = edit.start + edit.len + shift_amount; - buffer_stringify(buffer, edit.start, edit.end, strings + pos); -} - -internal void -buffer_invert_edit(Gap_Buffer *buffer, Buffer_Edit edit, Buffer_Edit *inverse, char *strings, - i32 *str_pos, i32 max){ - buffer_invert_edit_shift(buffer, edit, inverse, strings, str_pos, max, 0); -} - -internal i32 -buffer_invert_batch(Buffer_Invert_Batch *state, Gap_Buffer *buffer, Buffer_Edit *edits, i32 count, - Buffer_Edit *inverse, char *strings, i32 *str_pos, i32 max){ - i32 shift_amount = state->shift_amount; - i32 i = state->i; - Buffer_Edit *edit = edits + i; - Buffer_Edit *inv_edit = inverse + i; - i32 result = 0; - - for (; i < count; ++i, ++edit, ++inv_edit){ - if (*str_pos + edit->end - edit->start <= max){ - buffer_invert_edit_shift(buffer, *edit, inv_edit, strings, str_pos, max, shift_amount); - shift_amount += (edit->len - (edit->end - edit->start)); - } - else{ - result = 1; - state->len = edit->end - edit->start; - } +internal b32 +buffer_invert_batch(Arena *arena, Gap_Buffer *buffer, Edit *edits, Edit *inverse, i64 count){ + b32 result = false; + i64 pos = 0; + i64 shift_amount = 0; + Edit *edit = edits; + Edit *inv_edit = inverse; + for (i64 i = 0; i < count; i += 1, edit += 1, inv_edit += 1){ + String_Const_u8 inv_str = buffer_invert_edit_shift(arena, buffer, *edit, inv_edit, shift_amount); + shift_amount += replace_range_shift(edit->range, edit->text.size); + pos += inv_str.size; } - - state->i = i; - state->shift_amount = shift_amount; - return(result); } -typedef u32 Render_Item_Flag; -enum{ - RenderItemFlag_ForceEmit = 1, - RenderItemFlag_NoAdvance = 2, -}; - -internal Render_Item_Write -write_render_item(Render_Item_Write write, i32 index, u32 codepoint, u32 flags, - Render_Item_Flag render_flags){ - if (write.item < write.item_end){ - f32 ch_width = font_get_glyph_advance(write.face, codepoint); - - b32 visible_on_layout = (write.x_min <= write.x + ch_width && write.x <= write.x_max); - - if (visible_on_layout || ((render_flags & RenderItemFlag_ForceEmit) != 0)){ - write.item->index = index; - write.item->codepoint = codepoint; - write.item->flags = flags; - write.item->x0 = write.x; - write.item->y0 = write.y; - write.item->x1 = write.x + ch_width; - write.item->y1 = write.y + write.font_height; - ++write.item; - } - - if ((render_flags & RenderItemFlag_NoAdvance) == 0){ - write.x += ch_width; - } - } - return(write); -} - -// duff-routine defines -#define DrCase(PC) case PC: goto resumespot_##PC -#define DrYield(PC, n) { *S_ptr = S; S_ptr->__pc__ = PC; return(n); resumespot_##PC:; } -#define DrReturn(n) { *S_ptr = S; S_ptr->__pc__ = -1; return(n); } - -internal Buffer_Layout_Stop -buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32 line_shift, b32 do_wrap, i32 wrap_unit_end){ - Buffer_Render_State S = *S_ptr; - Buffer_Layout_Stop S_stop; - - S.write.item_end = params.items + params.max; - - switch (S.__pc__){ - DrCase(1); - DrCase(2); - DrCase(3); - DrCase(4); - } - - S.size = buffer_size(params.buffer); - S.size = Min(S.size, params.one_past_last_abs_pos); - S.shift_x = params.port_x - params.scroll_x; - S.shift_y = params.port_y - params.scroll_y; - - if (params.wrapped){ - S.shift_y += params.start_cursor.wrapped_y; - } - else{ - S.shift_y += params.start_cursor.unwrapped_y; - } - - S.line = (i32)params.start_cursor.line - 1; - S.wrap_line = (i32)params.start_cursor.wrap_line - 1; - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = S.line; - S_stop.wrap_line_index = S.wrap_line; - DrYield(1, S_stop); - } - - S.write.item = params.items; - S.write.x = S.shift_x + line_shift; - S.write.y = S.shift_y; - S.write.system = params.system; - S.write.face = params.face; - S.write.font_height = (i32)params.face->height; - S.write.x_min = params.port_x; - S.write.x_max = params.port_x + params.clip_w; - - S.byte_advance = params.face->byte_advance; - - if (params.virtual_white){ - S.skipping_whitespace = true; - } - - S.first_of_the_line = true; - S.first_of_the_wrap = true; - S.i = (i32)params.start_cursor.pos; - if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){ - do{ - for (; S.i < S.stream.end; ++S.i){ - { - u8 ch = (u8)S.stream.data[S.i]; - translating_fully_process_byte(&S.tran, ch, S.i, S.size, &S.emits); - } - - for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){ - TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits); - - if (!S.behavior.do_newline && S.step.i >= S.wrap_unit_end){ - S_stop.status = BLStatus_NeedWrapDetermination; - S_stop.line_index = S.line; - S_stop.wrap_line_index = S.wrap_line; - S_stop.pos = S.step.i; - S_stop.x = S.write.x - S.shift_x; - DrYield(4, S_stop); - - S.wrap_unit_end = wrap_unit_end; - - if (do_wrap && !S.first_of_the_line){ - if (params.virtual_white){ - S_stop.status = BLStatus_NeedWrapLineShift; - S_stop.line_index = S.line; - S_stop.wrap_line_index = S.wrap_line + 1; - DrYield(2, S_stop); - } - - ++S.wrap_line; - - if (params.wrapped){ - switch (params.wrap_slashes){ - case WrapIndicator_Show_After_Line: - { - S.write = write_render_item(S.write, S.step.i - 1, '\\', BRFlag_Ghost_Character, 0); - }break; - - case WrapIndicator_Show_At_Wrap_Edge: - { - if (S.write.x < S.shift_x + params.width){ - S.write.x = S.shift_x + params.width; - } - S.write = write_render_item(S.write, S.step.i - 1, '\\', BRFlag_Ghost_Character, 0); - }break; - } - - S.write.x = S.shift_x + line_shift; - S.write.y += S.write.font_height; - S.first_of_the_wrap = true; - } - } - } - - if (S.write.y > params.height + params.port_y || S.write.item >= S.write.item_end){ - goto buffer_get_render_data_end; - } - - if (S.behavior.do_newline){ - { - Render_Item_Flag flags = 0; - if (S.first_of_the_wrap){ - flags |= RenderItemFlag_ForceEmit; - } - S.write = write_render_item(S.write, S.step.i, ' ', 0, flags); - } - - if (params.virtual_white){ - S_stop.status = BLStatus_NeedLineShift; - S_stop.line_index = S.line + 1; - S_stop.wrap_line_index = S.wrap_line + 1; - DrYield(3, S_stop); - S.skipping_whitespace = true; - } - - ++S.line; - ++S.wrap_line; - - S.write.x = S.shift_x + line_shift; - S.write.y += S.write.font_height; - - S.first_of_the_line = true; - S.first_of_the_wrap = true; - } - else if (S.behavior.do_codepoint_advance){ - u32 n = S.step.value; - if (n != ' ' && n != '\t'){ - S.skipping_whitespace = false; - } - - u32 I = S.step.i; - if (!S.skipping_whitespace){ - Render_Item_Flag flags = 0; - if (S.first_of_the_wrap){ - flags |= RenderItemFlag_ForceEmit; - } - switch (n){ - case '\r': - { - S.write = write_render_item(S.write, I, '\\', BRFlag_Special_Character, flags); - S.write = write_render_item(S.write, I, 'r', BRFlag_Special_Character, flags); - }break; - - case '\t': - { - S.ch_width = font_get_glyph_advance(params.face, '\t'); - - f32 new_x = S.write.x + S.ch_width; - S.write = write_render_item(S.write, I, ' ', 0, flags); - S.write.x = new_x; - }break; - - default: - { - S.write = write_render_item(S.write, I, n, 0, flags); - }break; - } - } - else if (S.first_of_the_wrap){ - Render_Item_Flag flags = RenderItemFlag_ForceEmit|RenderItemFlag_NoAdvance; - S.write = write_render_item(S.write, I, ' ', 0, flags); - } - - S.first_of_the_line = false; - S.first_of_the_wrap = false; - } - else if (S.behavior.do_number_advance){ - u8 n = (u8)S.step.value; - u32 I = S.step.i; - S.skipping_whitespace = false; - - S.ch_width = S.byte_advance; - f32 new_x = S.write.x + S.ch_width; - - u8 cs[3]; - cs[0] = '\\'; - byte_to_ascii(n, cs+1); - - Render_Item_Flag flags = 0; - if (S.first_of_the_wrap){ - flags |= RenderItemFlag_ForceEmit; - } - S.write = write_render_item(S.write, I, cs[0], BRFlag_Special_Character, flags); - S.write = write_render_item(S.write, I, cs[1], BRFlag_Special_Character, flags); - S.write = write_render_item(S.write, I, cs[2], BRFlag_Special_Character, flags); - - Assert(S.write.x <= new_x); - S.write.x = new_x; - - S.first_of_the_line = false; - S.first_of_the_wrap = false; - } - - - if (!S.skipping_whitespace && !S.behavior.do_newline){ - S.first_of_the_line = false; - } - } - } - S.still_looping = buffer_stringify_next(&S.stream); - }while(S.still_looping); - } - - buffer_get_render_data_end:; - if (S.write.y <= params.height + S.shift_y || S.write.item == params.items){ - S.write = write_render_item(S.write, S.size, ' ', 0, false); - } - - *params.count = (i32)(S.write.item - params.items); - Assert(*params.count <= params.max); - - S_stop.status = BLStatus_Finished; - DrReturn(S_stop); -} - -#undef DrYield -#undef DrReturn -#undef DrCase - internal Buffer_Chunk_Position -buffer_get_chunk_position(String_Const_u8_Array chunks, i32 buffer_size, i32 real_pos){ +buffer_get_chunk_position(String_Const_u8_Array chunks, i64 buffer_size, i64 real_pos){ Buffer_Chunk_Position pos = {}; pos.real_pos = real_pos; pos.chunk_pos = real_pos; @@ -1937,5 +651,359 @@ buffer_chunk_position_iterate(String_Const_u8_Array chunks, Buffer_Chunk_Positio return(past_end); } +//////////////////////////////// + +internal void +buffer_layout__write(Arena *arena, Buffer_Layout_Item_List *list, i64 index, u32 codepoint, + Buffer_Layout_Flag flags, Rect_f32 rect){ + Temp_Memory restore_point = begin_temp(arena); + Buffer_Layout_Item *item = push_array(arena, Buffer_Layout_Item, 1); + + Buffer_Layout_Item_Block *block = list->first; + if (block != 0){ + if (block->items + block->count == item){ + block->count += 1; + } + else{ + block = 0; + } + } + if (block == 0){ + end_temp(restore_point); + block = push_array(arena, Buffer_Layout_Item_Block, 1); + item = push_array(arena, Buffer_Layout_Item, 1); + sll_queue_push(list->first, list->last, block); + list->node_count += 1; + block->items = item; + block->count = 1; + } + list->total_count += 1; + + if (index > list->index_range.max){ + block->character_count += 1; + list->character_count += 1; + list->index_range.max = index; + } + + item->index = index; + item->codepoint = codepoint; + item->flags = flags; + item->rect = rect; + list->height = max(list->height, rect.y1); +} + +internal Buffer_Layout_Item_List +buffer_layout(Arena *scratch, Arena *arena, Gap_Buffer *buffer, Interval_i64 range, Face *face, f32 width){ + Temp_Memory temp = begin_temp(scratch); + + Buffer_Layout_Item_List list = {}; + list.index_range.first = range.first; + list.index_range.one_past_last = range.first - 1; + + List_String_Const_u8 chunks = buffer_get_chunks(scratch, buffer); + buffer_chunks_clamp(&chunks, range); + + f32 line_height = face->height; + f32 space_advance = face->space_advance; + + if (chunks.node_count == 0){ + f32 next_x = space_advance; + buffer_layout__write(arena, &list, range.first, ' ', 0, Rf32(V2(0.f, 0.f), V2f32(next_x, line_height))); + } + else{ + Vec2_f32 p = {}; + f32 line_y = line_height; + + String_Const_u8 text = {}; + if (chunks.node_count == 1){ + text = chunks.first->string; + } + else{ + text = string_list_flatten(scratch, chunks); + } + + i64 index = range.first; + b32 first_of_the_line = true; + + u8 *ptr = text.str; + u8 *end_ptr = ptr + text.size; + for (;ptr < end_ptr;){ + Character_Consume_Result consume = utf8_consume(ptr, (umem)(end_ptr - ptr)); + u32 render_codepoint = consume.codepoint; + switch (consume.codepoint){ + case '\t': + { + render_codepoint = ' '; + }//fallthrough; + default: + { + f32 advance = font_get_glyph_advance(face, consume.codepoint); + f32 next_x = p.x + advance; + if (!first_of_the_line && next_x >= width){ + p.y = line_y; + p.x = 0.f; + line_y += line_height; + next_x = p.x + advance; + } + buffer_layout__write(arena, &list, index, render_codepoint, 0, + Rf32(p, V2f32(next_x, line_y))); + p.x = next_x; + ptr += consume.inc; + index += consume.inc; + first_of_the_line = false; + }break; + + case '\n': + { + f32 next_x = p.x + space_advance; + buffer_layout__write(arena, &list, index, ' ', 0, Rf32(p, V2f32(next_x, line_y))); + p.y = line_y; + p.x = 0.f; + line_y += line_height; + first_of_the_line = true; + ptr += 1; + index += 1; + }break; + + case max_u32: + { + f32 next_x = p.x + face->byte_advance; + if (!first_of_the_line && next_x >= width){ + p.y = line_y; + p.x = 0.f; + line_y += line_height; + next_x = p.x + face->byte_advance; + } + u32 v = *ptr; + u32 lo = v&0xF; + u32 hi = (v >> 4)&0xF; + f32 advance = face->byte_sub_advances[0]; + buffer_layout__write(arena, &list, index, '\\', 0, + Rf32(p, V2f32(p.x + advance, line_y))); + p.x += advance; + advance = face->byte_sub_advances[1]; + buffer_layout__write(arena, &list, index, integer_symbols[lo], 0, + Rf32(p, V2f32(p.x + advance, line_y))); + p.x += advance; + face->byte_sub_advances[2]; + buffer_layout__write(arena, &list, index, integer_symbols[hi], 0, + Rf32(p, V2f32(p.x + advance, line_y))); + p.x = next_x; + ptr += 1; + index += 1; + first_of_the_line = false; + }break; + } + } + } + + end_temp(temp); + + return(list); +} + +internal i64 +buffer_layout_nearest_pos_to_xy(Buffer_Layout_Item_List list, Vec2_f32 p){ + i64 closest_match = 0; + if (p.y < 0.f){ + closest_match = list.index_range.min; + } + else if (p.y >= list.height){ + closest_match = list.index_range.max; + } + else{ + if (0.f < p.x && p.x < max_f32){ + f32 closest_x = -max_f32; + for (Buffer_Layout_Item_Block *block = list.first; + block != 0; + block = block->next){ + i64 count = block->count; + Buffer_Layout_Item *item = block->items; + for (i32 i = 0; i < count; i += 1, item += 1){ + // NOTE(allen): This only works if we build layouts in y-sorted order. + if (p.y < item->rect.y0){ + goto double_break; + } + if (item->rect.y1 <= p.y){ + continue; + } + f32 dist0 = p.x - item->rect.x0; + f32 dist1 = item->rect.x1 - p.x; + if (dist0 >= 0.f && dist1 > 0.f){ + closest_match = item->index; + goto double_break; + } + // NOTE(allen): One of dist0 and dist1 are negative, but certainly not both. + // 1. Take the negative one. + // 2. If the negative distance is larger than closest_x, then this is closer. + f32 neg_dist = min(dist0, dist1); + if (closest_x < neg_dist){ + closest_x = neg_dist; + closest_match = item->index; + } + } + } + double_break:; + } + else{ + if (p.x == max_f32){ + Buffer_Layout_Item *prev_item = 0; + for (Buffer_Layout_Item_Block *block = list.first; + block != 0; + block = block->next){ + i64 count = block->count; + Buffer_Layout_Item *item = block->items; + for (i32 i = 0; i < count; i += 1, item += 1){ + if (p.y < item->rect.y0){ + goto double_break_2; + } + prev_item = item; + if (item->rect.y1 <= p.y){ + continue; + } + } + } + double_break_2:; + if (prev_item != 0){ + closest_match = prev_item->index; + } + else{ + closest_match = list.index_range.max; + } + } + else{ + Buffer_Layout_Item *closest_item = 0; + for (Buffer_Layout_Item_Block *block = list.first; + block != 0; + block = block->next){ + i64 count = block->count; + Buffer_Layout_Item *item = block->items; + for (i32 i = 0; i < count; i += 1, item += 1){ + // NOTE(allen): This only works if we build layouts in y-sorted order. + if (p.y < item->rect.y0){ + goto double_break_3; + } + if (item->rect.y1 <= p.y){ + continue; + } + closest_item = item; + goto double_break_3; + } + } + double_break_3:; + if (closest_item != 0){ + closest_match = closest_item->index; + } + else{ + closest_match = list.index_range.min; + } + } + } + } + return(closest_match); +} + +internal i64 +buffer_layout_get_pos_at_character(Buffer_Layout_Item_List list, i64 character){ + i64 result = 0; + if (character <= 0){ + result = list.index_range.min; + } + else if (character >= list.character_count){ + result = list.index_range.max; + } + else{ + i64 counter = 0; + for (Buffer_Layout_Item_Block *node = list.first; + node != 0; + node = node->next){ + i64 next_counter = counter + node->character_count; + if (character < next_counter){ + i64 count = node->count; + i64 relative_character = character - counter; + i64 relative_character_counter = 0; + i64 prev_index = -1; + Buffer_Layout_Item *item = node->items; + for (i64 i = 0; i < count; i += 1, item += 1){ + if (prev_index != item->index){ + prev_index = item->index; + if (relative_character_counter == relative_character){ + result = prev_index; + break; + } + relative_character_counter += 1; + } + } + break; + } + counter = next_counter; + } + } + return(result); +} + +internal Buffer_Layout_Item* +buffer_layout_get_first_with_index(Buffer_Layout_Item_List list, i64 index){ + Buffer_Layout_Item *result = 0; + Buffer_Layout_Item *prev = 0; + for (Buffer_Layout_Item_Block *block = list.first; + block != 0; + block = block->next){ + i64 count = block->count; + Buffer_Layout_Item *item = block->items; + for (i32 i = 0; i < count; i += 1, item += 1){ + if (item->index > index){ + result = prev; + goto done; + } + if (item->index == index){ + result = item; + goto done; + } + prev = item; + } + } + if (result == 0){ + result = prev; + } + done:; + return(result); +} + +internal Vec2_f32 +buffer_layout_xy_center_of_pos(Buffer_Layout_Item_List list, i64 index){ + Vec2_f32 result = {}; + Buffer_Layout_Item *item = buffer_layout_get_first_with_index(list, index); + if (item != 0){ + result = rect_center(item->rect); + } + return(result); +} + +internal i64 +buffer_layout_character_from_pos(Buffer_Layout_Item_List list, i64 index){ + i64 result = 0; + i64 character_count = 0; + i64 prev_index = -1; + for (Buffer_Layout_Item_Block *node = list.first; + node != 0; + node = node->next){ + Buffer_Layout_Item *item = node->items; + i64 count = node->count; + for (i64 i = 0; i < count; i += 1, item += 1){ + if (item->index == index){ + result = character_count; + goto double_break; + } + if (item->index != prev_index){ + prev_index = item->index; + character_count += 1; + } + } + } + double_break:; + return(result); +} + // BOTTOM diff --git a/4ed_buffer.h b/4ed_buffer.h index 9c30bcda..b9da0e54 100644 --- a/4ed_buffer.h +++ b/4ed_buffer.h @@ -12,235 +12,63 @@ #if !defined(FRED_BUFFER_H) #define FRED_BUFFER_H -typedef i32 Buffer_Get_Chunk_Mode; -enum{ - BufferGetChunk_Basic, - BufferGetChunk_ZeroTerminated, -}; - struct Cursor_With_Index{ i64 pos; i32 index; }; struct Gap_Buffer{ - char *data; - i32 size1; - i32 gap_size; - i32 size2; - i32 max; + Base_Allocator *allocator; - i32 *line_starts; - i32 line_count; - i32 line_max; -}; - -struct Gap_Buffer_Init{ - Gap_Buffer *buffer; - char *data; - i32 size; -}; - -struct Gap_Buffer_Stream{ - Gap_Buffer *buffer; - char *data; - i32 end; - i32 separated; - i32 absolute_end; + u8 *data; + i64 size1; + i64 gap_size; + i64 size2; + i64 max; - b32 use_termination_character; - char terminator; + // NOTE(allen): If there are N lines I store N + 1 slots in this array with + // line_starts[N] = size of the buffer. + // The variable line_start_count stores N + 1; call buffer_line_count(buffer) + // to get "N" the actual number of lines. + i64 *line_starts; + i64 line_start_count; + i64 line_start_max; }; -global Gap_Buffer_Stream null_buffer_stream = {}; struct Buffer_Chunk_Position{ - i32 real_pos; - i32 chunk_pos; - i32 chunk_index; -}; - -struct Buffer_Batch_State{ - i32 i; - i32 shift_total; -}; - -struct Buffer_Measure_Starts{ - i32 i; - i32 count; - i32 start; + i64 real_pos; + i64 chunk_pos; + i64 chunk_index; }; +typedef u32 Buffer_Layout_Flag; enum{ - BLStatus_Finished, - BLStatus_NeedWrapLineShift, - BLStatus_NeedLineShift, - BLStatus_NeedWrapDetermination, -}; - -struct Buffer_Layout_Stop{ - u32 status; - i32 line_index; - i32 wrap_line_index; - i32 pos; - i32 next_line_pos; - f32 x; -}; - -struct Buffer_Measure_Wrap_Params{ - Gap_Buffer *buffer; - i32 *wrap_line_index; - System_Functions *system; - Face *face; - b32 virtual_white; -}; - -struct Buffer_Measure_Wrap_State{ - Gap_Buffer_Stream stream; - i32 i; - i32 size; - b32 still_looping; - - i32 line_index; - - i32 current_wrap_index; - f32 current_adv; - f32 x; - - b32 skipping_whitespace; - i32 wrap_unit_end; - b32 did_wrap; - b32 first_of_the_line; - - Translation_State tran; - Translation_Emits emits; - u32 J; - Buffer_Model_Step step; - Buffer_Model_Behavior behavior; - - i32 __pc__; -}; - -struct Buffer_Cursor_Seek_Params{ - Gap_Buffer *buffer; - Buffer_Seek seek; - System_Functions *system; - Face *face; - i32 *wrap_line_index; - i32 *character_starts; - b32 virtual_white; - b32 return_hint; - Full_Cursor *cursor_out; -}; - -struct Buffer_Cursor_Seek_State{ - Full_Cursor next_cursor; - Full_Cursor this_cursor; - Full_Cursor prev_cursor; - - Gap_Buffer_Stream stream; - b32 still_looping; - i32 i; - i32 size; - i32 wrap_unit_end; - - b32 first_of_the_line; - b32 xy_seek; - f32 ch_width; - - i32 font_height; - - Translation_State tran; - Translation_Emits emits; - u32 J; - Buffer_Model_Step step; - Buffer_Model_Behavior behavior; - - - i32 __pc__; -}; - -struct Buffer_Invert_Batch{ - i32 i; - i32 shift_amount; - i32 len; -}; - -enum Buffer_Render_Flag{ BRFlag_Special_Character = (1 << 0), BRFlag_Ghost_Character = (1 << 1) }; -struct Buffer_Render_Item{ - i32 index; +struct Buffer_Layout_Item{ + i64 index; u32 codepoint; - u32 flags; - f32 x0; - f32 y0; - f32 x1; - f32 y1; + Buffer_Layout_Flag flags; + Rect_f32 rect; }; -struct Render_Item_Write{ - Buffer_Render_Item *item; - Buffer_Render_Item *item_end; - f32 x; - f32 y; - System_Functions *system; - Face *face; - i32 font_height; - f32 x_min; - f32 x_max; +struct Buffer_Layout_Item_Block{ + Buffer_Layout_Item_Block *next; + Buffer_Layout_Item *items; + i64 count; + i64 character_count; }; -struct Buffer_Render_Params{ - Gap_Buffer *buffer; - Buffer_Render_Item *items; - i32 max; - i32 *count; - f32 port_x; - f32 port_y; - f32 clip_w; - f32 scroll_x; - f32 scroll_y; - f32 width; +struct Buffer_Layout_Item_List{ + Buffer_Layout_Item_Block *first; + Buffer_Layout_Item_Block *last; + i32 node_count; + i32 total_count; f32 height; - Full_Cursor start_cursor; - i32 wrapped; - System_Functions *system; - Face *face; - b32 virtual_white; - i32 wrap_slashes; - i32 one_past_last_abs_pos; -}; - -struct Buffer_Render_State{ - Gap_Buffer_Stream stream; - b32 still_looping; - i32 i; - i32 size; - - f32 shift_x; - f32 shift_y; - - f32 ch_width; - - Render_Item_Write write; - f32 byte_advance; - - i32 line; - i32 wrap_line; - b8 skipping_whitespace; - b8 first_of_the_line; - b8 first_of_the_wrap; - i32 wrap_unit_end; - - Translation_State tran; - Translation_Emits emits; - u32 J; - Buffer_Model_Step step; - Buffer_Model_Behavior behavior; - - i32 __pc__; + i64 character_count; + Interval_i64 index_range; }; #endif diff --git a/4ed_code_wrap.cpp b/4ed_code_wrap.cpp deleted file mode 100644 index 046ff62a..00000000 --- a/4ed_code_wrap.cpp +++ /dev/null @@ -1,941 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 24.03.2018 - * - * Code wrapping logic - * - */ - -// TOP - -internal void -wrap_state_init(Code_Wrap_State *state, Editing_File *file, Face *face){ - state->token_array = file->state.token_array; - state->token_ptr = state->token_array.tokens; - state->end_token = state->token_ptr + state->token_array.count; - - state->line_starts = file->state.buffer.line_starts; - state->line_count = file->state.buffer.line_count; - state->next_line_start = state->line_starts[1]; - - Gap_Buffer *buffer = &file->state.buffer; - i32 size = buffer_size(buffer); - buffer_stringify_loop(&state->stream, buffer, 0, size); - state->size = size; - state->i = 0; - - state->face = face; - - state->tab_indent_amount = font_get_glyph_advance(face, '\t'); - state->byte_advance = face->byte_advance; - - state->tran = null_buffer_translating_state; -} - -internal void -wrap_state_set_top(Code_Wrap_State *state, f32 line_shift){ - if (state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] > line_shift){ - state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] = line_shift; - } -} - -internal Code_Wrap_Step -wrap_state_consume_token(System_Functions *system, Face *face, Code_Wrap_State *state, i32 fixed_end_point){ - Code_Wrap_Step result = {}; - i32 i = state->i; - - result.position_start = i; - - Cpp_Token token = {}; - - token.start = state->size; - if (state->token_ptr < state->end_token){ - token = *state->token_ptr; - } - - if (state->consume_newline){ - ++i; - state->x = 0; - state->consume_newline = 0; - } - - - if (state->in_pp_body){ - if (!(token.flags & CPP_TFLAG_PP_BODY)){ - state->in_pp_body = false; - state->wrap_x = state->plane_wrap_x; - } - } - - if (!state->in_pp_body){ - if (token.flags & CPP_TFLAG_PP_DIRECTIVE){ - state->in_pp_body = true; - state->plane_wrap_x = state->wrap_x; - state->wrap_x = null_wrap_x; - } - } - - b32 skipping_whitespace = false; - if (i >= state->next_line_start){ - state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top]; - state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top]; - skipping_whitespace = true; - } - - // TODO(allen): exponential search this shit! - for (;i >= state->next_line_start;){ - state->next_line_start = state->size; - if (state->line_index < state->line_count){ - ++state->line_index; - if (state->line_index + 1 < state->line_count){ - state->next_line_start = state->line_starts[state->line_index + 1]; - } - } - else{ - break; - } - } - - i32 line_start = state->size; - if (state->line_index < 0){ - line_start = 0; - } - else if (state->line_index < state->line_count){ - line_start = state->line_starts[state->line_index]; - } - b32 still_looping = 0; - i32 end = token.start + token.size; - if (fixed_end_point >= 0 && end > fixed_end_point){ - end = fixed_end_point; - } - - i = clamp_bot(line_start, i); - if (i == line_start){ - skipping_whitespace = true; - } - - b32 recorded_start_x = false; - do{ - for (; i < state->stream.end; ++i){ - if (!(i < end)){ - goto doublebreak; - } - - u8 ch = (u8)state->stream.data[i]; - translating_fully_process_byte(&state->tran, ch, i, state->size, &state->emits); - - for (TRANSLATION_EMIT_LOOP(state->J, state->emits)){ - TRANSLATION_GET_STEP(state->step, state->behavior, state->J, state->emits); - - if (state->behavior.do_newline){ - state->consume_newline = 1; - goto doublebreak; - } - else if(state->behavior.do_number_advance || state->behavior.do_codepoint_advance){ - u32 n = state->step.value; - f32 adv = 0; - if (state->behavior.do_codepoint_advance){ - adv = font_get_glyph_advance(state->face, n); - - if (n != ' ' && n != '\t'){ - skipping_whitespace = false; - } - } - else{ - adv = state->byte_advance; - skipping_whitespace = false; - } - - if (!skipping_whitespace){ - if (!recorded_start_x){ - result.start_x = state->x; - recorded_start_x = true; - } - state->x += adv; - } - } - } - } - still_looping = buffer_stringify_next(&state->stream); - }while(still_looping); - doublebreak:; - - state->i = i; - - b32 consume_token = false; - if (state->token_ptr < state->end_token && i >= token.start + token.size){ - consume_token = true; - } - - result.this_token = state->token_ptr; - if (consume_token){ - Assert(state->token_ptr < state->end_token); - switch (state->token_ptr->type){ - case CPP_TOKEN_BRACE_OPEN: - { - state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] += state->tab_indent_amount; - }break; - - case CPP_TOKEN_BRACE_CLOSE: - { - state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] -= state->tab_indent_amount; - }break; - - case CPP_TOKEN_PARENTHESE_OPEN: - case CPP_TOKEN_BRACKET_OPEN: - { - ++state->wrap_x.paren_top; - - i32 top = state->wrap_x.paren_top; - if (top >= ArrayCount(state->wrap_x.paren_nesting)){ - top = ArrayCount(state->wrap_x.paren_nesting) - 1; - } - state->wrap_x.paren_safe_top = top; - - state->wrap_x.paren_nesting[top] = state->x; - }break; - - case CPP_TOKEN_PARENTHESE_CLOSE: - case CPP_TOKEN_BRACKET_CLOSE: - { - --state->wrap_x.paren_top; - - if (state->wrap_x.paren_top < 0){ - state->wrap_x.paren_top = 0; - } - - i32 top = state->wrap_x.paren_top; - if (top >= ArrayCount(state->wrap_x.paren_nesting)){ - top = ArrayCount(state->wrap_x.paren_nesting) - 1; - } - state->wrap_x.paren_safe_top = top; - }break; - } - - ++state->token_ptr; - if (state->token_ptr > state->end_token){ - state->token_ptr = state->end_token; - } - } - - result.position_end = state->i; - result.final_x = state->x; - - if (!recorded_start_x){ - result.start_x = state->x; - recorded_start_x = true; - } - - return(result); -} - -internal i32 -stickieness_guess(Cpp_Token_Type type, Cpp_Token_Type other_type, u16 flags, u16 other_flags, b32 on_left){ - i32 guess = 0; - - b32 is_words = false; - b32 other_is_words = false; - - Cpp_Token_Category cat = cpp_token_category_from_type(type); - Cpp_Token_Category other_cat = cpp_token_category_from_type(other_type); - - if (type == CPP_TOKEN_IDENTIFIER || (CPP_TOKEN_CAT_TYPE <= cat && cat <= CPP_TOKEN_CAT_OTHER)){ - is_words = true; - } - if (other_type == CPP_TOKEN_IDENTIFIER || (CPP_TOKEN_CAT_TYPE <= other_cat && other_cat <= CPP_TOKEN_CAT_OTHER)){ - other_is_words = true; - } - - b32 is_operator = 0, other_is_operator = 0; - if (flags & CPP_TFLAG_IS_OPERATOR){ - is_operator = 1; - } - if (other_flags & CPP_TFLAG_IS_OPERATOR){ - other_is_operator = 1; - } - - i32 operator_side_bias = 70*(!on_left); - - if (is_words && other_is_words){ - guess = 200; - } - else if (type == CPP_TOKEN_PARENTHESE_OPEN){ - if (on_left){ - guess = 100; - } - else{ - if (other_is_words){ - guess = 100; - } - else{ - guess = 0; - } - } - } - else if (type == CPP_TOKEN_SEMICOLON){ - if (on_left){ - guess = 0; - } - else{ - guess = 1000; - } - } - else if (type == CPP_TOKEN_COMMA){ - guess = 20; - } - else if (type == CPP_TOKEN_COLON || - type == CPP_TOKEN_PARENTHESE_CLOSE || - type == CPP_TOKEN_BRACKET_OPEN || - type == CPP_TOKEN_BRACKET_CLOSE){ - if (on_left){ - guess = 20; - if (other_is_words){ - guess = 100; - } - } - else{ - guess = 100; - } - } - else if (type == CPP_PP_DEFINED){ - if (on_left){ - guess = 100; - } - else{ - guess = 0; - } - } - else if (type == CPP_TOKEN_SCOPE){ - guess = 90; - } - else if (type == CPP_TOKEN_MINUS){ - if (on_left){ - guess = 80; - } - else{ - guess = 60; - } - } - else if (type == CPP_TOKEN_DOT || - type == CPP_TOKEN_ARROW){ - guess = 200; - } - else if (type == CPP_TOKEN_NOT || - type == CPP_TOKEN_TILDE){ - if (on_left){ - guess = 80; - } - else{ - guess = 20; - } - } - else if (type == CPP_TOKEN_INCREMENT || - type == CPP_TOKEN_DECREMENT || - type == CPP_TOKEN_STAR || - type == CPP_TOKEN_AMPERSAND || - (type >= CPP_TOKEN_POSTINC && - type <= CPP_TOKEN_DELETE_ARRAY)){ - guess = 80; - if (!on_left && other_is_operator){ - guess = 20; - } - } - else if (type >= CPP_TOKEN_MUL && type <= CPP_TOKEN_MOD){ - guess = 70; - } - else if (type == CPP_TOKEN_PLUS){ - guess = 60 + operator_side_bias; - } - else if (type >= CPP_TOKEN_LSHIFT && type <= CPP_TOKEN_RSHIFT){ - guess = 50; - } - else if (type >= CPP_TOKEN_LESS && type <= CPP_TOKEN_NOTEQ){ - guess = 40 + operator_side_bias; - } - else if (type >= CPP_TOKEN_BIT_XOR && type <= CPP_TOKEN_BIT_OR){ - guess = 40; - } - else if (type >= CPP_TOKEN_AND && type <= CPP_TOKEN_OR){ - guess = 30 + operator_side_bias; - } - else if (type >= CPP_TOKEN_TERNARY_QMARK && type <= CPP_TOKEN_COLON){ - guess = 20 + operator_side_bias; - } - else if (type == CPP_TOKEN_THROW){ - if (on_left){ - guess = 100; - } - else{ - guess = 0; - } - } - else if (type >= CPP_TOKEN_EQ && type <= CPP_TOKEN_XOREQ){ - guess = 15 + operator_side_bias; - } - - return(guess); -} - -internal Wrap_Current_Shift -get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start){ - Wrap_Current_Shift result = {}; - - result.shift = wrap_state->wrap_x.paren_nesting[wrap_state->wrap_x.paren_safe_top]; - - Cpp_Token next_token = {}; - if (wrap_state->token_ptr < wrap_state->end_token){ - next_token = *wrap_state->token_ptr; - } - - if (wrap_state->token_ptr > wrap_state->token_array.tokens){ - Cpp_Token prev_token = *(wrap_state->token_ptr-1); - - if (wrap_state->wrap_x.paren_safe_top != 0 && prev_token.type == CPP_TOKEN_PARENTHESE_OPEN){ - result.shift = wrap_state->wrap_x.paren_nesting[wrap_state->wrap_x.paren_safe_top-1] + wrap_state->tab_indent_amount; - result.adjust_top_to_this = 1; - } - - f32 statement_continuation_indent = 0.f; - if (result.shift != 0.f && wrap_state->wrap_x.paren_safe_top == 0){ - if (!(prev_token.flags & (CPP_TFLAG_PP_DIRECTIVE|CPP_TFLAG_PP_BODY))){ - switch (prev_token.type){ - case CPP_TOKEN_BRACKET_OPEN: - case CPP_TOKEN_BRACE_OPEN: - case CPP_TOKEN_BRACE_CLOSE: - case CPP_TOKEN_SEMICOLON: - case CPP_TOKEN_COLON: - case CPP_TOKEN_COMMA: - case CPP_TOKEN_COMMENT: break; - default: statement_continuation_indent += wrap_state->tab_indent_amount; break; - } - } - } - - switch (next_token.type){ - case CPP_TOKEN_BRACE_CLOSE: case CPP_TOKEN_BRACE_OPEN: break; - default: result.shift += statement_continuation_indent; break; - } - } - - if (next_token.start < next_line_start){ - if (next_token.flags & CPP_TFLAG_PP_DIRECTIVE){ - result.shift = 0; - } - else{ - switch (next_token.type){ - case CPP_TOKEN_BRACE_CLOSE: - { - if (wrap_state->wrap_x.paren_safe_top == 0){ - result.shift -= wrap_state->tab_indent_amount; - } - }break; - } - } - } - - result.shift = clamp_bot(0.f, result.shift); - return(result); -} - -internal void -file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *file, Face *face){ - Heap *heap = &mem->heap; - Arena *scratch = &mem->arena; - - Temp_Memory temp = begin_temp(scratch); - - file_allocate_wraps_as_needed(heap, file); - file_allocate_indents_as_needed(heap, file, file->state.buffer.line_count); - file_allocate_wrap_positions_as_needed(heap, file, file->state.buffer.line_count); - - Buffer_Measure_Wrap_Params params; - params.buffer = &file->state.buffer; - params.wrap_line_index = file->state.wrap_line_index; - params.system = system; - params.face = face; - params.virtual_white = file->settings.virtual_white; - - f32 width = (f32)file->settings.display_width; - f32 minimum_base_width = (f32)file->settings.minimum_base_display_width; - - i32 size = buffer_size(params.buffer); - - Buffer_Measure_Wrap_State state = {}; - Buffer_Layout_Stop stop = {}; - - f32 edge_tolerance = 50.f; - edge_tolerance = clamp_top(edge_tolerance, 50.f); - - f32 current_line_shift = 0.f; - b32 do_wrap = 0; - i32 wrap_unit_end = 0; - - i32 wrap_position_index = 0; - file->state.wrap_positions[wrap_position_index++] = 0; - - Code_Wrap_State wrap_state = {}; - - b32 use_tokens = false; - - // TODO(allen): REWRITE REWRITE REWRITE - Wrap_Indent_Pair *wrap_indent_marks = 0; - Potential_Wrap_Indent_Pair *potential_marks = 0; - i32 max_wrap_indent_mark = Million(1); - - if (params.virtual_white && file->state.token_array.tokens != 0){ - wrap_state_init(&wrap_state, file, face); - use_tokens = true; - - potential_marks = push_array(scratch, Potential_Wrap_Indent_Pair, floor32(width)); - - wrap_indent_marks = push_array(scratch, Wrap_Indent_Pair, max_wrap_indent_mark); - } - - i32 real_count = 0; - i32 potential_count = 0; - i32 stage = 0; - - do{ - stop = buffer_measure_wrap_y(&state, params, current_line_shift, do_wrap, wrap_unit_end); - - switch (stop.status){ - case BLStatus_NeedWrapDetermination: - { - if (use_tokens){ - if (stage == 0){ - do_wrap = 0; - wrap_unit_end = wrap_indent_marks[stage+1].wrap_position; - ++stage; - } - else{ - do_wrap = 1; - wrap_unit_end = wrap_indent_marks[stage+1].wrap_position; - file_allocate_wrap_positions_as_needed(heap, file, wrap_position_index); - file->state.wrap_positions[wrap_position_index++] = stop.pos; - } - } - else{ - Translation_State tran = {}; - Translation_Emits emits = {}; - Gap_Buffer_Stream stream = {}; - - i32 word_stage = 0; - i32 i = stop.pos; - f32 x = stop.x; - f32 self_x = 0; - i32 wrap_end_result = size; - if (buffer_stringify_loop(&stream, params.buffer, i, size)){ - b32 still_looping = false; - do{ - for (; i < stream.end; ++i){ - { - u8 ch = stream.data[i]; - translating_fully_process_byte(&tran, ch, i, size, &emits); - } - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(step, behavior, J, emits); - - u32 codepoint = step.value; - switch (word_stage){ - case 0: - { - if (codepoint_is_whitespace(codepoint)){ - word_stage = 1; - } - else{ - f32 adv = font_get_glyph_advance(params.face, codepoint); - - x += adv; - self_x += adv; - if (self_x > width){ - wrap_end_result = step.i; - goto doublebreak; - } - } - }break; - - case 1: - { - if (!codepoint_is_whitespace(codepoint)){ - wrap_end_result = step.i; - goto doublebreak; - } - }break; - } - } - } - still_looping = buffer_stringify_next(&stream); - }while(still_looping); - } - - doublebreak:; - wrap_unit_end = wrap_end_result; - if (x > width){ - do_wrap = 1; - file_allocate_wrap_positions_as_needed(heap, file, wrap_position_index); - file->state.wrap_positions[wrap_position_index++] = stop.pos; - } - else{ - do_wrap = 0; - } - } - }break; - - case BLStatus_NeedWrapLineShift: - case BLStatus_NeedLineShift: - { - f32 current_width = width; - - if (use_tokens){ - Code_Wrap_State original_wrap_state = wrap_state; - i32 next_line_start = buffer_size(params.buffer); - if (stop.line_index+1 < params.buffer->line_count){ - next_line_start = params.buffer->line_starts[stop.line_index+1]; - } - - f32 base_adjusted_width = wrap_state.wrap_x.base_x + minimum_base_width; - - if (minimum_base_width != 0 && current_width < base_adjusted_width){ - current_width = base_adjusted_width; - } - - if (stop.status == BLStatus_NeedLineShift){ - real_count = 0; - potential_count = 0; - stage = 0; - - Wrap_Current_Shift current_shift = get_current_shift(&wrap_state, next_line_start); - - if (current_shift.adjust_top_to_this){ - wrap_state_set_top(&wrap_state, current_shift.shift); - } - - wrap_indent_marks[real_count].wrap_position = 0; - wrap_indent_marks[real_count].line_shift =current_shift.shift; - ++real_count; - - wrap_state.wrap_x.base_x = wrap_state.wrap_x.paren_nesting[0]; - - for (; wrap_state.token_ptr < wrap_state.end_token; ){ - Code_Wrap_Step step = {}; - b32 emit_comment_position = false; - b32 first_word = true; - - if (wrap_state.token_ptr->type == CPP_TOKEN_COMMENT || wrap_state.token_ptr->type == CPP_TOKEN_STRING_CONSTANT){ - i32 i = wrap_state.token_ptr->start; - i32 end_i = i + wrap_state.token_ptr->size; - - if (i < wrap_state.i){ - i = wrap_state.i; - } - - if (end_i > wrap_state.next_line_start){ - end_i = wrap_state.next_line_start; - } - - f32 x = wrap_state.x; - - step.position_start = i; - step.start_x = x; - step.this_token = wrap_state.token_ptr; - - Gap_Buffer_Stream stream = {}; - Translation_State tran = {}; - Translation_Emits emits = {}; - - Potential_Wrap_Indent_Pair potential_wrap = {}; - potential_wrap.wrap_position = i; - potential_wrap.line_shift = x; - potential_wrap.wrappable_score = 5; - potential_wrap.wrap_x = x; - potential_wrap.adjust_top_to_this = 0; - - if (buffer_stringify_loop(&stream, params.buffer, i, end_i)){ - b32 still_looping = true; - - while(still_looping){ - for (; i < stream.end; ++i){ - { - u8 ch = stream.data[i]; - translating_fully_process_byte(&tran, ch, i, end_i, &emits); - } - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits); - if (!codepoint_is_whitespace(buffer_step.value)){ - i = buffer_step.i; - goto doublebreak_stage_vspace; - } - } - } - still_looping = buffer_stringify_next(&stream); - } - doublebreak_stage_vspace:; - - do{ - i32 pos_end_i = end_i; - while (still_looping){ - for (; i < stream.end; ++i){ - { - u8 ch = stream.data[i]; - translating_fully_process_byte(&tran, ch, i, end_i, &emits); - } - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits); - if (codepoint_is_whitespace(buffer_step.value)){ - pos_end_i = buffer_step.i; - goto doublebreak_stage1; - } - - f32 adv = font_get_glyph_advance(params.face, buffer_step.value); - x += adv; - - if (!first_word && x > current_width){ - pos_end_i = buffer_step.i; - emit_comment_position = true; - goto doublebreak_stage1; - } - } - } - still_looping = buffer_stringify_next(&stream); - } - doublebreak_stage1:; - first_word = 0; - - if (emit_comment_position){ - step.position_end = pos_end_i; - step.final_x = x; - goto finished_comment_split; - } - - while(still_looping){ - for (; i < stream.end; ++i){ - { - u8 ch = stream.data[i]; - translating_fully_process_byte(&tran, ch, i, end_i, &emits); - } - - for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){ - TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits); - - if (!codepoint_is_whitespace(buffer_step.value)){ - pos_end_i = buffer_step.i; - goto doublebreak_stage2; - } - - f32 adv = font_get_glyph_advance(params.face, buffer_step.value); - x += adv; - } - } - still_looping = buffer_stringify_next(&stream); - } - doublebreak_stage2:; - - potential_wrap.wrap_position = pos_end_i; - potential_wrap.wrap_x = x; - }while(still_looping); - } - - finished_comment_split:; - if (emit_comment_position){ - potential_marks[potential_count] = potential_wrap; - ++potential_count; - } - } - - if (!emit_comment_position){ - step = wrap_state_consume_token(system, face, &wrap_state, next_line_start); - } - - b32 need_to_choose_a_wrap = false; - if (step.final_x > current_width){ - need_to_choose_a_wrap = true; - } - - current_shift = get_current_shift(&wrap_state, next_line_start); - - b32 next_token_is_on_line = false; - if (wrap_state.token_ptr < wrap_state.end_token){ - if (wrap_state.token_ptr->start < next_line_start){ - next_token_is_on_line = true; - } - } - - i32 next_wrap_position = step.position_end; - f32 wrap_x = step.final_x; - if (next_token_is_on_line){ - if (wrap_state.token_ptr < wrap_state.end_token){ - i32 pos_i = wrap_state.token_ptr->start; - if (pos_i > step.position_start && next_wrap_position < pos_i){ - next_wrap_position = pos_i; - } - } - } - - if (!need_to_choose_a_wrap){ - i32 wrappable_score = 1; - - Cpp_Token *this_token = step.this_token; - Cpp_Token *next_token = 0; - if (wrap_state.token_ptr < wrap_state.end_token){ - next_token = wrap_state.token_ptr; - } - - Cpp_Token_Type this_type = this_token->type; - Cpp_Token_Type next_type = CPP_TOKEN_JUNK; - - u16 this_flags = this_token->flags; - u16 next_flags = 0; - - if (this_token == next_token || !next_token_is_on_line){ - next_token = 0; - } - - if (next_token){ - next_type = next_token->type; - next_flags = next_token->flags; - } - - i32 this_stickieness = stickieness_guess(this_type, next_type, this_flags, next_flags, 1); - - i32 next_stickieness = 0; - if (next_token){ - next_stickieness = stickieness_guess(next_type, this_type, next_flags, this_flags, 0); - } - - i32 heap_stickieness = this_stickieness; - if (heap_stickieness < next_stickieness){ - heap_stickieness = next_stickieness; - } - - if (wrap_state.wrap_x.paren_top != 0 && this_type == CPP_TOKEN_COMMA){ - heap_stickieness = 0; - } - - wrappable_score = 64*50; - wrappable_score += 101 - heap_stickieness - wrap_state.wrap_x.paren_safe_top*80; - - potential_marks[potential_count].wrap_position = next_wrap_position; - potential_marks[potential_count].line_shift = current_shift.shift; - potential_marks[potential_count].wrappable_score = wrappable_score; - potential_marks[potential_count].wrap_x = wrap_x; - potential_marks[potential_count].adjust_top_to_this = current_shift.adjust_top_to_this; - ++potential_count; - } - - if (need_to_choose_a_wrap){ - if (potential_count == 0){ - wrap_indent_marks[real_count].wrap_position = next_wrap_position; - wrap_indent_marks[real_count].line_shift = current_shift.shift; - ++real_count; - } - else{ - i32 i = 0, best_i = 0; - i32 best_score = -1; - f32 best_x_shift = 0; - - f32 x_gain_threshold = 18.f; - - for (; i < potential_count; ++i){ - i32 this_score = potential_marks[i].wrappable_score; - f32 x_shift = potential_marks[i].wrap_x - potential_marks[i].line_shift; - - f32 x_shift_adjusted = x_shift - x_gain_threshold; - f32 x_left_over = step.final_x - x_shift; - - if (x_shift_adjusted < 0){ - this_score = 0; - } - else if (x_left_over <= x_gain_threshold){ - this_score = 1; - } - - if (this_score > best_score){ - best_score = this_score; - best_x_shift = x_shift; - best_i = i; - } - else if (this_score == best_score && x_shift > best_x_shift){ - best_x_shift = x_shift; - best_i = i; - } - } - - i32 wrap_position = potential_marks[best_i].wrap_position; - f32 line_shift = potential_marks[best_i].line_shift; - b32 adjust_top_to_this = potential_marks[best_i].adjust_top_to_this; - wrap_indent_marks[real_count].wrap_position = wrap_position; - wrap_indent_marks[real_count].line_shift = line_shift; - ++real_count; - potential_count = 0; - - wrap_state = original_wrap_state; - for (;;){ - step = wrap_state_consume_token(system, face, &wrap_state, wrap_position); - if (step.position_end >= wrap_position){ - break; - } - } - - wrap_state.x = line_shift; - wrap_state.i = wrap_position; - if (adjust_top_to_this){ - wrap_state_set_top(&wrap_state, line_shift); - } - - original_wrap_state = wrap_state; - } - } - - if (step.position_end >= next_line_start-1){ - break; - } - } - - wrap_indent_marks[real_count].wrap_position = next_line_start; - wrap_indent_marks[real_count].line_shift = 0; - ++real_count; - - for (i32 l = 0; wrap_state.i < next_line_start && l < 3; ++l){ - wrap_state_consume_token(system, face, &wrap_state, next_line_start); - } - } - - current_line_shift = wrap_indent_marks[stage].line_shift; - - if (stage > 0){ - ++stage; - } - - current_line_shift = clamp_bot(0.f, current_line_shift); - } - else{ - current_line_shift = 0.f; - } - - current_line_shift = clamp_top(current_line_shift, current_width - edge_tolerance); - - if (stop.wrap_line_index >= file->state.line_indent_max){ - file_allocate_indents_as_needed(heap, file, stop.wrap_line_index); - } - - file->state.line_indents[stop.wrap_line_index] = current_line_shift; - file->state.wrap_line_count = stop.wrap_line_index; - }break; - } - }while(stop.status != BLStatus_Finished); - - ++file->state.wrap_line_count; - - file_allocate_wrap_positions_as_needed(heap, file, wrap_position_index); - file->state.wrap_positions[wrap_position_index++] = size; - file->state.wrap_position_count = wrap_position_index; - - end_temp(temp); -} - -// BOTTOM - diff --git a/4ed_code_wrap.h b/4ed_code_wrap.h deleted file mode 100644 index 0ab1fbbd..00000000 --- a/4ed_code_wrap.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 24.03.2018 - * - * Code wrapping logic - * - */ - -// TOP - -#if !defined(FRED_CODE_WRAP_H) -#define FRED_CODE_WRAP_H - -struct Code_Wrap_X{ - f32 base_x; - f32 paren_nesting[32]; - i32 paren_safe_top; - i32 paren_top; -}; -global Code_Wrap_X null_wrap_x = {}; - -struct Code_Wrap_State{ - Cpp_Token_Array token_array; - Cpp_Token *token_ptr; - Cpp_Token *end_token; - - Code_Wrap_X wrap_x; - - b32 in_pp_body; - Code_Wrap_X plane_wrap_x; - - i32 *line_starts; - i32 line_count; - i32 line_index; - i32 next_line_start; - - f32 x; - b32 consume_newline; - - Gap_Buffer_Stream stream; - i32 size; - i32 i; - - Face *face; - f32 tab_indent_amount; - f32 byte_advance; - - Translation_State tran; - Translation_Emits emits; - u32 J; - Buffer_Model_Step step; - Buffer_Model_Behavior behavior; -}; - -struct Code_Wrap_Step{ - i32 position_start; - i32 position_end; - - f32 start_x; - f32 final_x; - - Cpp_Token *this_token; -}; - -struct Wrap_Current_Shift{ - f32 shift; - b32 adjust_top_to_this; -}; - -internal void -file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *file, Face *face); - -#endif - -// BOTTOM - diff --git a/4ed_edit.cpp b/4ed_edit.cpp index 45631501..e74a9cf1 100644 --- a/4ed_edit.cpp +++ b/4ed_edit.cpp @@ -14,18 +14,6 @@ edit_pre_state_change(Models *models, Heap *heap, Editing_File *file){ System_Functions *system = models->system; file_add_dirty_flag(file, DirtyState_UnsavedChanges); file_unmark_edit_finished(&models->working_set, file); - Layout *layout = &models->layout; - for (Panel *panel = layout_get_first_open_panel(layout); - panel != 0; - panel = layout_get_next_open_panel(layout, panel)){ - View *view = panel->view; - if (view->file == file){ - Full_Cursor render_cursor = view_get_render_cursor(models, view); - Full_Cursor target_cursor = view_get_render_cursor_target(models, view); - view->temp_view_top_left_pos = (i32)render_cursor.pos; - view->temp_view_top_left_target_pos = (i32)target_cursor.pos; - } - } } internal void @@ -83,7 +71,7 @@ edit_fix_markers__compute_scroll_y(i32 line_height, i32 old_y_val, f32 new_y_val } internal void -edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, Edit edit){ +edit_fix_markers(Models *models, Editing_File *file, Edit edit){ Layout *layout = &models->layout; Lifetime_Object *file_lifetime_object = file->lifetime_object; @@ -127,8 +115,6 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E File_Edit_Positions edit_pos = view_get_edit_pos(view); write_cursor_with_index(cursors, &cursor_count, (i32)edit_pos.cursor_pos); write_cursor_with_index(cursors, &cursor_count, (i32)view->mark); - write_cursor_with_index(cursors, &cursor_count, view->temp_view_top_left_pos); - write_cursor_with_index(cursors, &cursor_count, view->temp_view_top_left_target_pos); } } @@ -152,8 +138,8 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E if (cursor_count > 0 || r_cursor_count > 0){ buffer_sort_cursors( cursors, cursor_count); buffer_sort_cursors(r_cursors, r_cursor_count); - buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.length, false); - buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.length, true); + buffer_update_cursors( cursors, cursor_count, edit.range.first, edit.range.one_past_last, edit.text.size, false); + buffer_update_cursors(r_cursors, r_cursor_count, edit.range.first, edit.range.one_past_last, edit.text.size, true); buffer_unsort_cursors( cursors, cursor_count); buffer_unsort_cursors(r_cursors, r_cursor_count); @@ -168,41 +154,9 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E View *view = panel->view; if (view->file == file){ i64 cursor_pos = cursors[cursor_count++].pos; - Full_Cursor new_cursor = file_compute_cursor(models, file, seek_pos(cursor_pos)); - - File_Edit_Positions edit_pos = view_get_edit_pos(view); - GUI_Scroll_Vars scroll = edit_pos.scroll; - view->mark = cursors[cursor_count++].pos; - - i32 line_height = (i32)face->height; - i64 top_left_pos = cursors[cursor_count++].pos; - i64 top_left_target_pos = cursors[cursor_count++].pos; - f32 new_y_val_aligned = 0; - if (view->temp_view_top_left_pos != top_left_pos){ - Full_Cursor new_position_cursor = file_compute_cursor(models, file, seek_pos(top_left_pos)); - if (file->settings.unwrapped_lines){ - new_y_val_aligned = new_position_cursor.unwrapped_y; - } - else{ - new_y_val_aligned = new_position_cursor.wrapped_y; - } - scroll.scroll_y = edit_fix_markers__compute_scroll_y(line_height, scroll.scroll_y, new_y_val_aligned); - } - if (view->temp_view_top_left_target_pos != top_left_target_pos){ - if (top_left_target_pos != top_left_pos){ - Full_Cursor new_position_cursor = file_compute_cursor(models, file, seek_pos(top_left_target_pos)); - if (file->settings.unwrapped_lines){ - new_y_val_aligned = new_position_cursor.unwrapped_y; - } - else{ - new_y_val_aligned = new_position_cursor.wrapped_y; - } - } - scroll.target_y = edit_fix_markers__compute_scroll_y(line_height, scroll.target_y, new_y_val_aligned); - } - - view_set_cursor_and_scroll(models, view, new_cursor, true, scroll); + File_Edit_Positions edit_pos = view_get_edit_pos(view); + view_set_cursor_and_scroll(models, view, cursor_pos, true, edit_pos.scroll); } } @@ -226,19 +180,18 @@ edit_fix_markers(System_Functions *system, Models *models, Editing_File *file, E } internal void -edit_single(System_Functions *system, Models *models, Editing_File *file, Range range, String_Const_u8 string, Edit_Behaviors behaviors){ +edit_single(Models *models, Editing_File *file, Interval_i64 range, String_Const_u8 string, Edit_Behaviors behaviors){ Edit edit = {}; - edit.str = (char*)string.str; - edit.length = (i32)string.size; + edit.text = string; edit.range = range; - Gap_Buffer *buffer = &file->state.buffer; Assert(0 <= edit.range.first); Assert(edit.range.first <= edit.range.one_past_last); Assert(edit.range.one_past_last <= buffer_size(buffer)); Heap *heap = &models->mem.heap; + Arena *scratch = &models->mem.arena; // NOTE(allen): history update if (!behaviors.do_not_post_to_history){ @@ -253,61 +206,34 @@ edit_single(System_Functions *system, Models *models, Editing_File *file, Range // NOTE(allen): edit range hook if (models->hook_file_edit_range != 0){ - models->hook_file_edit_range(&models->app_links, file->id, edit.range, SCu8(edit.str, edit.length)); + models->hook_file_edit_range(&models->app_links, file->id, edit.range, edit.text); } // NOTE(allen): expand spec, compute shift - i32 shift_amount = buffer_replace_range_compute_shift(edit.range.first, edit.range.one_past_last, edit.length); + i64 shift_amount = replace_range_shift(edit.range, (i64)edit.text.size); // NOTE(allen): actual text replacement - i32 request_amount = 0; - for (;buffer_replace_range(buffer, edit.range.first, edit.range.one_past_last, edit.str, edit.length, shift_amount, &request_amount);){ - void *new_data = 0; - if (request_amount > 0){ - new_data = heap_allocate(heap, request_amount); - } - void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount); - if (old_data != 0){ - heap_free(heap, old_data); - } - } + buffer_replace_range(buffer, edit.range, edit.text, shift_amount); // NOTE(allen): line meta data - i32 line_start = buffer_get_line_number(buffer, edit.range.first); - i32 line_end = buffer_get_line_number(buffer, edit.range.one_past_last); - i32 replaced_line_count = line_end - line_start; - i32 new_line_count = buffer_count_newlines(buffer, edit.range.first, edit.range.first + edit.length); - i32 line_shift = new_line_count - replaced_line_count; + i64 line_start = buffer_get_line_index(buffer, edit.range.first); + i64 line_end = buffer_get_line_index(buffer, edit.range.one_past_last); + i64 replaced_line_count = line_end - line_start; + i64 new_line_count = buffer_count_newlines(scratch, buffer, edit.range.first, edit.range.first + edit.text.size); + i64 line_shift = new_line_count - replaced_line_count; - file_grow_starts_as_needed(heap, buffer, line_shift); - buffer_remeasure_starts(buffer, line_start, line_end, line_shift, shift_amount); - - file_allocate_character_starts_as_needed(heap, file); - buffer_remeasure_character_starts(system, buffer, line_start, line_end, line_shift, file->state.character_starts, 0, file->settings.virtual_white); + buffer_remeasure_starts(scratch, buffer, Ii64(line_start, line_end + 1), line_shift, shift_amount); // NOTE(allen): token fixing if (file->settings.tokens_exist){ - file_relex(system, models, file, edit.range.first, edit.range.one_past_last, shift_amount); + file_relex(models->system, models, file, edit.range.first, edit.range.one_past_last, shift_amount); } - // NOTE(allen): wrap meta data - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - Assert(face != 0); - - file_measure_wraps(system, &models->mem, file, face); - // NOTE(allen): cursor fixing - edit_fix_markers(system, models, file, edit); + edit_fix_markers(models, file, edit); // NOTE(allen): mark edit finished - if (file->settings.tokens_exist){ - if (file->settings.virtual_white){ - file_mark_edit_finished(&models->working_set, file); - } - } - else{ - file_mark_edit_finished(&models->working_set, file); - } + file_mark_edit_finished(&models->working_set, file); } internal void @@ -329,9 +255,9 @@ edit__apply_record_forward(System_Functions *system, Models *models, Editing_Fil switch (record->kind){ case RecordKind_Single: { - String_Const_u8 str = SCu8(record->single.str_forward, record->single.length_forward); - Range range = make_range(record->single.first, record->single.first + record->single.length_backward); - edit_single(system, models, file, range, str, behaviors_prototype); + String_Const_u8 str = record->single.forward_text; + Interval_i64 range = Ii64(record->single.first, record->single.first + record->single.backward_text.size); + edit_single(models, file, range, str, behaviors_prototype); }break; case RecordKind_Group: @@ -360,9 +286,9 @@ edit__apply_record_backward(System_Functions *system, Models *models, Editing_Fi switch (record->kind){ case RecordKind_Single: { - String_Const_u8 str = SCu8(record->single.str_backward, record->single.length_backward); - Range range = make_range(record->single.first, record->single.first + record->single.length_forward); - edit_single(system, models, file, range, str, behaviors_prototype); + String_Const_u8 str = record->single.backward_text; + Interval_i64 range = Ii64(record->single.first, record->single.first + record->single.forward_text.size); + edit_single(models, file, range, str, behaviors_prototype); }break; case RecordKind_Group: @@ -464,26 +390,28 @@ edit_merge_history_range(Models *models, Editing_File *file, History_Record_Inde } internal b32 -edit_batch(System_Functions *system, Models *models, Editing_File *file, char *str, Buffer_Edit *edits, i32 edit_count, Edit_Behaviors behaviors){ +edit_batch(Models *models, Editing_File *file, Batch_Edit *batch, Edit_Behaviors behaviors){ b32 result = true; - if (edit_count > 0){ + if (batch != 0){ History_Record_Index start_index = 0; if (history_is_activated(&file->state.history)){ start_index = file->state.current_record_index; } - Buffer_Edit *edit_in = edits; - Buffer_Edit *one_past_last = edits + edit_count; - i32 shift = 0; - for (;edit_in < one_past_last; edit_in += 1){ - String_Const_u8 insert_string = SCu8(str + edit_in->str_start, edit_in->len); - Range edit_range = make_range(edit_in->start, edit_in->end); + i64 shift = 0; + for (Batch_Edit *edit = batch; + edit != 0; + edit = edit->next){ + String_Const_u8 insert_string = edit->edit.text; + Interval_i64 edit_range = edit->edit.range; edit_range.first += shift; edit_range.one_past_last += shift; - i32 size = buffer_size(&file->state.buffer); - if (0 <= edit_range.first && edit_range.first <= edit_range.one_past_last && edit_range.one_past_last <= size){ - edit_single(system, models, file, edit_range, insert_string, behaviors); - shift += replace_range_compute_shift(edit_range, (i32)insert_string.size); + i64 size = buffer_size(&file->state.buffer); + if (0 <= edit_range.first && + edit_range.first <= edit_range.one_past_last && + edit_range.one_past_last <= size){ + edit_single(models, file, edit_range, insert_string, behaviors); + shift += replace_range_shift(edit_range, insert_string.size); } else{ result = false; @@ -568,7 +496,7 @@ create_file(Models *models, String_Const_u8 file_name, Buffer_Create_Flag flags) String_Const_u8 front = string_front_of_path(file_name); buffer_bind_name(models, heap, scratch, working_set, file, front); File_Attributes attributes = {}; - file_create_from_string(system, models, file, SCu8(""), attributes); + file_create_from_string(models, file, SCu8(""), attributes); result = file; } } @@ -591,7 +519,7 @@ create_file(Models *models, String_Const_u8 file_name, Buffer_Create_Flag flags) file_bind_file_name(system, heap, working_set, file, string_from_file_name(&canon)); String_Const_u8 front = string_front_of_path(file_name); buffer_bind_name(models, heap, scratch, working_set, file, front); - file_create_from_string(system, models, file, SCu8(buffer, (i32)attributes.size), attributes); + file_create_from_string(models, file, SCu8(buffer, (i32)attributes.size), attributes); result = file; } } @@ -613,10 +541,10 @@ create_file(Models *models, String_Const_u8 file_name, Buffer_Create_Flag flags) } if (file != 0 && HasFlag(flags, BufferCreate_AlwaysNew)){ - i32 size = buffer_size(&file->state.buffer); + i64 size = buffer_size(&file->state.buffer); if (size > 0){ Edit_Behaviors behaviors = {}; - edit_single(system, models, file, make_range(0, size), string_u8_litexpr(""), behaviors); + edit_single(models, file, Ii64(0, size), string_u8_litexpr(""), behaviors); if (has_canon_name){ buffer_is_for_new_file = true; } diff --git a/4ed_edit.h b/4ed_edit.h index 19aa79b7..875c747a 100644 --- a/4ed_edit.h +++ b/4ed_edit.h @@ -12,17 +12,6 @@ #if !defined(FRED_EDIT_H) #define FRED_EDIT_H -struct Edit{ - char *str; - i32 length; - Range range; -}; - -struct Edit_Array{ - Edit *vals; - i32 count; -}; - struct Edit_Behaviors{ b32 do_not_post_to_history; }; diff --git a/4ed_file.cpp b/4ed_file.cpp index 7fcc7532..666c7100 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -17,14 +17,13 @@ string_from_file_name(Editing_File_Name *name){ //////////////////////////////// internal void -file_edit_positions_set_cursor(File_Edit_Positions *edit_pos, i32 pos){ +file_edit_positions_set_cursor(File_Edit_Positions *edit_pos, i64 pos){ edit_pos->cursor_pos = pos; edit_pos->last_set_type = EditPos_CursorSet; } internal void -file_edit_positions_set_scroll(File_Edit_Positions *edit_pos, GUI_Scroll_Vars scroll, i32 max_y){ - scroll.target_y = clamp(0, scroll.target_y, max_y); +file_edit_positions_set_scroll(File_Edit_Positions *edit_pos, Buffer_Scroll scroll){ edit_pos->scroll = scroll; edit_pos->last_set_type = EditPos_ScrollSet; } @@ -152,35 +151,7 @@ save_file_to_name(System_Functions *system, Models *models, Editing_File *file, Gap_Buffer *buffer = &file->state.buffer; b32 dos_write_mode = file->settings.dos_write_mode; - i32 max = 0; - if (dos_write_mode){ - max = buffer_size(buffer) + buffer->line_count + 1; - } - else{ - max = buffer_size(buffer); - } - Arena *scratch = &mem->arena; - Temp_Memory temp = begin_temp(scratch); - char empty = 0; - char *data = 0; - if (max == 0){ - data = ∅ - } - else{ - data = (char*)push_array(scratch, char, max); - } - Assert(data != 0); - - i32 size = 0; - if (dos_write_mode){ - size = buffer_convert_out(buffer, data, max); - } - else{ - size = max; - buffer_stringify(buffer, 0, size, data); - } - if (!using_actual_file_name){ String_Const_u8 s_file_name = SCu8(file_name); String_Const_u8 canonical_file_name = system->get_canonical(scratch, s_file_name); @@ -189,7 +160,10 @@ save_file_to_name(System_Functions *system, Models *models, Editing_File *file, } } - File_Attributes new_attributes = system->save_file(scratch, (char*)file_name, data, size); + Temp_Memory temp = begin_temp(scratch); + String_Const_u8 saveable_string = buffer_stringify(scratch, buffer, Ii64(0, buffer_size(buffer))); + + File_Attributes new_attributes = system->save_file(scratch, (char*)file_name, saveable_string); if (new_attributes.last_write_time > 0){ if (using_actual_file_name){ file->state.ignore_behind_os = 1; @@ -208,233 +182,42 @@ save_file_to_name(System_Functions *system, Models *models, Editing_File *file, internal b32 save_file(System_Functions *system, Models *models, Editing_File *file){ - b32 result = save_file_to_name(system, models, file, 0); - return(result); + return(save_file_to_name(system, models, file, 0)); } //////////////////////////////// -internal Partial_Cursor -file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek){ - Partial_Cursor result = {}; +internal Buffer_Cursor +file_compute_cursor(Editing_File *file, Buffer_Seek seek){ + Buffer_Cursor result = {}; switch (seek.type){ case buffer_seek_pos: { - result = buffer_partial_from_pos(&file->state.buffer, (i32)seek.pos); + result = buffer_cursor_from_pos(&file->state.buffer, seek.pos); }break; - case buffer_seek_line_char: + case buffer_seek_line_col: { - result = buffer_partial_from_line_character(&file->state.buffer, (i32)seek.line, (i32)seek.character); + result = buffer_cursor_from_line_col(&file->state.buffer, seek.line, seek.col); }break; - // TODO(allen): do(support buffer_seek_character_pos and character_pos coordiantes in partial cursor system) } return(result); } -internal Full_Cursor -file_compute_cursor__inner(Models *models, Editing_File *file, Buffer_Seek seek, b32 return_hint){ +//////////////////////////////// + +internal void +file_create_from_string(Models *models, Editing_File *file, String_Const_u8 val, File_Attributes attributes){ System_Functions *system = models->system; - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - Assert(face != 0); - - Full_Cursor result = {}; - - Buffer_Cursor_Seek_Params params; - params.buffer = &file->state.buffer; - params.seek = seek; - params.system = system; - params.face = face; - params.wrap_line_index = file->state.wrap_line_index; - params.character_starts = file->state.character_starts; - params.virtual_white = file->settings.virtual_white; - params.return_hint = return_hint; - params.cursor_out = &result; - - Buffer_Cursor_Seek_State state = {}; - Buffer_Layout_Stop stop = {}; - - i32 size = buffer_size(params.buffer); - - f32 line_shift = 0.f; - b32 do_wrap = false; - i32 wrap_unit_end = 0; - - b32 first_wrap_determination = true; - i32 wrap_array_index = 0; - - do{ - stop = buffer_cursor_seek(&state, params, line_shift, do_wrap, wrap_unit_end); - switch (stop.status){ - case BLStatus_NeedWrapDetermination: - { - if (stop.pos >= size){ - do_wrap = false; - wrap_unit_end = max_i32; - } - else{ - if (first_wrap_determination){ - wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count); - ++wrap_array_index; - if (file->state.wrap_positions[wrap_array_index] == stop.pos){ - do_wrap = true; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - else{ - do_wrap = false; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - first_wrap_determination = false; - } - else{ - Assert(stop.pos == wrap_unit_end); - do_wrap = true; - ++wrap_array_index; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - } - }break; - - case BLStatus_NeedWrapLineShift: - case BLStatus_NeedLineShift: - { - line_shift = file->state.line_indents[stop.wrap_line_index]; - }break; - } - }while(stop.status != BLStatus_Finished); - - return(result); -} - -internal Full_Cursor -file_compute_cursor(Models *models, Editing_File *file, Buffer_Seek seek){ - return(file_compute_cursor__inner(models, file, seek, false)); -} - -internal Full_Cursor -file_compute_cursor_hint(Models *models, Editing_File *file, Buffer_Seek seek){ - return(file_compute_cursor__inner(models, file, seek, true)); -} - -//////////////////////////////// - -internal i32 -file_grow_starts_as_needed(Heap *heap, Gap_Buffer *buffer, i32 additional_lines){ - b32 result = GROW_NOT_NEEDED; - i32 max = buffer->line_max; - i32 count = buffer->line_count; - i32 target_lines = count + additional_lines; - if (target_lines > max || max == 0){ - max = round_up_i32(target_lines + max, KB(1)); - i32 *new_lines = heap_array(heap, i32, max); - if (new_lines != 0){ - result = GROW_SUCCESS; - memcpy(new_lines, buffer->line_starts, sizeof(*new_lines)*count); - heap_free(heap, buffer->line_starts); - buffer->line_starts = new_lines; - buffer->line_max = max; - } - else{ - result = GROW_FAILED; - } - } - return(result); -} - -internal void -file_measure_starts(Heap *heap, Gap_Buffer *buffer){ - if (buffer->line_starts == 0){ - i32 max = buffer->line_max = KB(1); - buffer->line_starts = heap_array(heap, i32, max); - Assert(buffer->line_starts != 0); - } - - Buffer_Measure_Starts state = {}; - for (;buffer_measure_starts(&state, buffer);){ - i32 count = state.count; - i32 max = ((buffer->line_max + 1) << 1); - i32 *new_lines = heap_array(heap, i32, max); - Assert(new_lines != 0); - memcpy(new_lines, buffer->line_starts, sizeof(*new_lines)*count); - heap_free(heap, buffer->line_starts); - buffer->line_starts = new_lines; - buffer->line_max = max; - } -} - -internal void -file_allocate_metadata_as_needed(Heap *heap, Gap_Buffer *buffer, void **mem, i32 *mem_max_count, i32 count, i32 item_size){ - if (*mem == 0){ - i32 max = round_up_i32(((count + 1)*2), KB(1)); - *mem = heap_allocate(heap, max*item_size); - *mem_max_count = max; - Assert(*mem != 0); - } - else if (*mem_max_count < count){ - i32 old_max = *mem_max_count; - i32 max = round_up_i32(((count + 1)*2), KB(1)); - void *new_mem = heap_allocate(heap, item_size*max); - memcpy(new_mem, *mem, item_size*old_max); - heap_free(heap, *mem); - *mem = new_mem; - *mem_max_count = max; - Assert(*mem != 0); - } -} - -internal void -file_allocate_character_starts_as_needed(Heap *heap, Editing_File *file){ - file_allocate_metadata_as_needed(heap, - &file->state.buffer, (void**)&file->state.character_starts, - &file->state.character_start_max, file->state.buffer.line_count + 1, sizeof(i32)); -} - -internal void -file_allocate_indents_as_needed(Heap *heap, Editing_File *file, i32 min_last_index){ - i32 min_amount = min_last_index + 1; - file_allocate_metadata_as_needed(heap, - &file->state.buffer, (void**)&file->state.line_indents, - &file->state.line_indent_max, min_amount, sizeof(f32)); -} - -internal void -file_allocate_wraps_as_needed(Heap *heap, Editing_File *file){ - file_allocate_metadata_as_needed(heap, - &file->state.buffer, (void**)&file->state.wrap_line_index, - &file->state.wrap_max, file->state.buffer.line_count + 1, sizeof(f32)); -} - -internal void -file_allocate_wrap_positions_as_needed(Heap *heap, Editing_File *file, i32 min_last_index){ - i32 min_amount = min_last_index + 1; - file_allocate_metadata_as_needed(heap, - &file->state.buffer, (void**)&file->state.wrap_positions, - &file->state.wrap_position_max, min_amount, sizeof(f32)); -} - -//////////////////////////////// - -internal void -file_create_from_string(System_Functions *system, Models *models, Editing_File *file, String_Const_u8 val, File_Attributes attributes){ + // TODO(allen): completely eliminate the heap, then clean up the implementation or remove it too! Heap *heap = &models->mem.heap; Arena *scratch = &models->mem.arena; Application_Links *app_links = &models->app_links; + Base_Allocator *allocator = models->base_allocator; block_zero_struct(&file->state); - Gap_Buffer_Init init = buffer_begin_init(&file->state.buffer, val.str, val.size); - for (;buffer_init_need_more(&init);){ - i32 page_size = buffer_init_page_size(&init); - page_size = round_up_i32(page_size, KB(4)); - if (page_size < KB(4)){ - page_size = KB(4); - } - void *data = heap_allocate(heap, page_size); - buffer_init_provide_page(&init, data, page_size); - } + buffer_init(&file->state.buffer, val.str, val.size, allocator); - b32 init_success = buffer_end_init(&init); - Assert(init_success); - - if (buffer_size(&file->state.buffer) < val.size){ + if (buffer_size(&file->state.buffer) < (i64)val.size){ file->settings.dos_write_mode = true; } file_clear_dirty_flags(file); @@ -445,13 +228,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File * Face *face = font_set_face_from_id(&models->font_set, font_id); Assert(face != 0); - file_measure_starts(heap, &file->state.buffer); - - file_allocate_character_starts_as_needed(heap, file); - buffer_measure_character_starts(system, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white); - - file_measure_wraps(system, &models->mem, file, face); - //adjust_views_looking_at_files_to_new_cursor(system, models, file); + buffer_measure_starts(scratch, &file->state.buffer); file->lifetime_object = lifetime_alloc_object(heap, &models->lifetime_allocator, DynamicWorkspace_Buffer, file); history_init(&models->app_links, &file->state.history); @@ -475,6 +252,9 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File * file_mark_edit_finished(&models->working_set, file); } + file->state.cached_layouts_arena = make_arena(allocator); + file->state.line_layout_table = make_table_Data_u64(allocator, 500); + file->settings.is_initialized = true; { @@ -498,16 +278,15 @@ file_free(System_Functions *system, Heap *heap, Lifetime_Allocator *lifetime_all Gap_Buffer *buffer = &file->state.buffer; if (buffer->data){ - heap_free(heap, buffer->data); - heap_free(heap, buffer->line_starts); + base_free(buffer->allocator, buffer->data); + base_free(buffer->allocator, buffer->line_starts); } - heap_free(heap, file->state.wrap_line_index); - heap_free(heap, file->state.character_starts); - heap_free(heap, file->state.line_indents); - history_free(heap, &file->state.history); + linalloc_clear(&file->state.cached_layouts_arena); + table_free(&file->state.line_layout_table); + file_unmark_edit_finished(working_set, file); } @@ -533,5 +312,250 @@ file_get_managed_scope(Editing_File *file){ return(scope); } +//////////////////////////////// + +internal Buffer_Layout_Item_List +file_get_line_layout(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 line_number){ + Buffer_Layout_Item_List result = {}; + + i64 line_count = buffer_line_count(&file->state.buffer); + if (1 <= line_number && line_number <= line_count){ + // TODO(allen): optimization: most places that CALL this do so in a LOOP, which could HOIST + // this font_set_face_from_id call OUTSIDE of the LOOP. + Face *face = font_set_face_from_id(&models->font_set, face_id); + if (face != 0){ + Line_Layout_Key key = {}; + key.face_id = face_id; + key.face_version_number = face->version_number; + key.width = width; + key.line_number = line_number; + + Data key_data = make_data_struct(&key); + + Buffer_Layout_Item_List *list = 0; + + Table_Lookup lookup = table_lookup(&file->state.line_layout_table, key_data); + if (lookup.found_match){ + u64 val = 0; + table_read(&file->state.line_layout_table, lookup, &val); + list = (Buffer_Layout_Item_List*)IntAsPtr(val); + } + else{ + list = push_array(&file->state.cached_layouts_arena, Buffer_Layout_Item_List, 1); + Interval_i64 line_range = buffer_get_pos_range_from_line_number(&file->state.buffer, line_number); + *list = buffer_layout(&models->mem.arena, &file->state.cached_layouts_arena, + &file->state.buffer, line_range, face, width); + key_data = push_data_copy(&file->state.cached_layouts_arena, key_data); + table_insert(&file->state.line_layout_table, key_data, (u64)PtrAsInt(list)); + } + block_copy_struct(&result, list); + } + } + + return(result); +} + +internal void +file_clear_layout_cache(Editing_File *file){ + linalloc_clear(&file->state.cached_layouts_arena); + table_clear(&file->state.line_layout_table); +} + +internal Line_Shift_Vertical +file_line_shift_y(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 line_number, f32 y_delta){ + Line_Shift_Vertical result = {}; + + f32 line_y = 0.f; + + if (y_delta < 0.f){ + // NOTE(allen): Iterating upward + b32 has_result = false; + for (;;){ + if (line_y <= y_delta){ + has_result = true; + result.line = line_number; + result.y_delta = line_y; + break; + } + line_number -= 1; + if (line_number <= 0){ + line_number = 1; + break; + } + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + line_y -= line.height; + } + if (!has_result){ + result.line = line_number; + result.y_delta = line_y; + } + } + else{ + // NOTE(allen): Iterating downward + b32 has_result = false; + i64 line_count = buffer_line_count(&file->state.buffer); + for (;;line_number += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + f32 next_y = line_y + line.height; + if (y_delta < next_y){ + has_result = true; + result.line = line_number; + result.y_delta = line_y; + break; + } + if (line_number >= line_count){ + break; + } + line_y = next_y; + } + if (!has_result){ + result.line = line_number; + result.y_delta = line_y; + } + } + + return(result); +} + +internal f32 +file_line_y_difference(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 line_a, i64 line_b){ + f32 result = 0.f; + if (line_a != line_b){ + Interval_i64 line_range = Ii64(line_a, line_b); + for (i64 i = line_range.min; i < line_range.max; i += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, i); + result += line.height; + } + if (line_a < line_b){ + result *= -1.f; + } + } + return(result); +} + +internal i64 +file_pos_at_relative_xy(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 base_line, Vec2_f32 relative_xy){ + Line_Shift_Vertical shift = file_line_shift_y(models, file, width, face_id, base_line, relative_xy.y); + relative_xy.y -= shift.y_delta; + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, shift.line); + return(buffer_layout_nearest_pos_to_xy(line, relative_xy)); +} + +internal Vec2_f32 +file_relative_xy_of_pos(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 base_line, i64 pos){ + i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1; + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + Vec2_f32 result = buffer_layout_xy_center_of_pos(line, pos); + result.y += file_line_y_difference(models, file, width, face_id, line_number, base_line); + return(result); +} + +internal Buffer_Point +file_normalize_buffer_point(Models *models, Editing_File *file, f32 width, Face_ID face_id, Buffer_Point point){ + Line_Shift_Vertical shift = file_line_shift_y(models, file, width, face_id, point.line_number, point.pixel_shift.y); + point.line_number = shift.line; + point.pixel_shift.y -= shift.y_delta; + point.pixel_shift.x = clamp_bot(0.f, point.pixel_shift.x); + point.pixel_shift.y = clamp_bot(0.f, point.pixel_shift.y); + return(point); +} + +internal Vec2_f32 +file_buffer_point_difference(Models *models, Editing_File *file, f32 width, Face_ID face_id, Buffer_Point a, Buffer_Point b){ + f32 y_difference = file_line_y_difference(models, file, width, face_id, a.line_number, b.line_number); + Vec2_f32 result = a.pixel_shift - b.pixel_shift; + result.y += y_difference; + return(result); +} + +internal Line_Shift_Character +file_line_shift_characters(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 line_number, i64 character_delta){ + Line_Shift_Character result = {}; + + i64 line_character = 0; + + if (character_delta < 0){ + // NOTE(allen): Iterating upward + b32 has_result = false; + for (;;){ + if (line_character <= character_delta){ + has_result = true; + result.line = line_number; + result.character_delta = line_character; + break; + } + line_number -= 1; + if (line_number <= 0){ + line_number = 1; + break; + } + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + line_character -= line.character_count; + } + if (!has_result){ + result.line = line_number; + result.character_delta = line_character; + } + } + else{ + // NOTE(allen): Iterating downward + b32 has_result = false; + i64 line_count = buffer_line_count(&file->state.buffer); + for (;;line_number += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + i64 next_character = line_character + line.character_count; + if (character_delta < next_character){ + has_result = true; + result.line = line_number; + result.character_delta = line_character; + break; + } + if (line_number >= line_count){ + break; + } + line_character = next_character; + } + if (!has_result){ + result.line = line_number; + result.character_delta = line_character; + } + } + + return(result); +} + +internal i64 +file_line_character_difference(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 line_a, i64 line_b){ + i64 result = 0; + if (line_a != line_b){ + Interval_i64 line_range = Ii64(line_a, line_b); + for (i64 i = line_range.min; i < line_range.max; i += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, i); + result += line.character_count; + } + if (line_a < line_b){ + result *= -1; + } + } + return(result); +} + +internal i64 +file_pos_from_relative_character(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 base_line, i64 relative_character){ + Line_Shift_Character shift = file_line_shift_characters(models, file, width, face_id, base_line, relative_character); + relative_character -= shift.character_delta; + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, shift.line); + return(buffer_layout_get_pos_at_character(line, relative_character)); +} + +internal i64 +file_relative_character_from_pos(Models *models, Editing_File *file, f32 width, Face_ID face_id, i64 base_line, i64 pos){ + i64 line_number = buffer_get_line_index(&file->state.buffer, pos) + 1; + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, face_id, line_number); + i64 result = buffer_layout_character_from_pos(line, pos); + result += file_line_character_difference(models, file, width, face_id, line_number, base_line); + return(result); +} + // BOTTOM diff --git a/4ed_file.h b/4ed_file.h index 698a4f1d..3472023d 100644 --- a/4ed_file.h +++ b/4ed_file.h @@ -20,14 +20,14 @@ enum{ }; struct File_Edit_Positions{ Edit_Pos_Set_Type last_set_type; - GUI_Scroll_Vars scroll; + Buffer_Scroll scroll; i64 cursor_pos; }; // TODO(allen): do(replace Text_Effect with markers over time) struct Text_Effect{ - i32 start; - i32 end; + i64 start; + i64 end; u32 color; f32 seconds_down; f32 seconds_max; @@ -35,43 +35,31 @@ struct Text_Effect{ struct Editing_File_Settings{ i32 base_map_id; - i32 display_width; - i32 minimum_base_display_width; - i32 wrap_indicator; Parse_Context_ID parse_context_id; b32 dos_write_mode; Face_ID font_id; - b8 unwrapped_lines; b8 tokens_exist; b8 tokens_without_strings; b8 is_initialized; b8 unimportant; b8 read_only; b8 never_kill; - b8 virtual_white; +}; + +struct Line_Layout_Key{ + Face_ID face_id; + i32 face_version_number; + f32 width; + i64 line_number; }; struct Editing_File_State{ Gap_Buffer buffer; - i32 *wrap_line_index; - i32 wrap_max; - - i32 *character_starts; - i32 character_start_max; - - f32 *line_indents; - i32 line_indent_max; - - i32 wrap_line_count; - - i32 *wrap_positions; - i32 wrap_position_count; - i32 wrap_position_max; - History history; i32 current_record_index; + // TODO(allen): eliminate this too Cpp_Token_Array token_array; b32 in_edit_handler; @@ -85,6 +73,9 @@ struct Editing_File_State{ i32 edit_pos_stack_top; Child_Process_ID attached_child_process; + + Arena cached_layouts_arena; + Table_Data_u64 line_layout_table; }; struct Editing_File_Name{ @@ -112,6 +103,11 @@ struct Editing_File{ Editing_File_Name canon; }; +struct Buffer_Point_Delta{ + Buffer_Point new_point; + f32 y_shift; +}; + #endif // BOTTOM diff --git a/4ed_file_lex.cpp b/4ed_file_lex.cpp index 897ff512..0a7ca8f3 100644 --- a/4ed_file_lex.cpp +++ b/4ed_file_lex.cpp @@ -34,7 +34,7 @@ file_first_lex_serial(System_Functions *system, Models *models, Editing_File *fi Assert(parse_context.valid); Gap_Buffer *buffer = &file->state.buffer; - i32 text_size = buffer_size(buffer); + i64 text_size = buffer_size(buffer); // TODO(allen): REWRITE REWRITE REWRITE Cpp_Token_Array new_tokens = {}; @@ -46,25 +46,23 @@ file_first_lex_serial(System_Functions *system, Models *models, Editing_File *fi Cpp_Lex_Data lex = cpp_lex_data_init(file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table); - String_Const_u8_Array chunk_space[3]; - Cursor chunk_cursor = make_cursor(chunk_space, sizeof(chunk_space)); - String_Const_u8_Array chunks = buffer_get_chunks(&chunk_cursor, buffer, BufferGetChunk_ZeroTerminated); - - i32 chunk_index = 0; + List_String_Const_u8 chunks = buffer_get_chunks(scratch, buffer); + u8 null_terminator = 0; + string_list_push(scratch, &chunks, SCu8(&null_terminator, 1)); Cpp_Token_Array new_array = {}; - do{ - u8 *chunk = chunks.vals[chunk_index].str; - umem chunk_size = chunks.vals[chunk_index].size; + for (Node_String_Const_u8 *node = chunks.first; + node != 0;){ + u8 *chunk = node->string.str; + umem chunk_size = node->string.size; - i32 result = cpp_lex_step(&lex, (char*)chunk, (i32)chunk_size, text_size, &new_tokens, NO_OUT_LIMIT); + i32 result = cpp_lex_step(&lex, (char*)chunk, (i32)chunk_size, (i32)text_size, &new_tokens, NO_OUT_LIMIT); switch (result){ case LexResult_NeedChunk: { - ++chunk_index; - Assert(chunk_index < chunks.count); + node = node->next; }break; case LexResult_Finished: @@ -95,7 +93,11 @@ file_first_lex_serial(System_Functions *system, Models *models, Editing_File *fi case LexResult_HitTokenLimit: InvalidPath; } - } while (still_lexing); + + if (!still_lexing){ + break; + } + } Cpp_Token_Array *token_array = &file->state.token_array; token_array->count = new_array.count; @@ -116,7 +118,7 @@ file_first_lex_serial(System_Functions *system, Models *models, Editing_File *fi } internal b32 -file_relex_serial(System_Functions *system, Models *models, Editing_File *file, i32 start_i, i32 end_i, i32 shift_amount){ +file_relex_serial(System_Functions *system, Models *models, Editing_File *file, i64 start_i, i64 end_i, i64 shift_amount){ Mem_Options *mem = &models->mem; Arena *scratch = &mem->arena; Heap *heap = &mem->heap; @@ -137,35 +139,38 @@ file_relex_serial(System_Functions *system, Models *models, Editing_File *file, relex_array.max_count = Million(1); relex_array.tokens = push_array(scratch, Cpp_Token, relex_array.max_count); - i32 size = buffer_size(buffer); + i64 size = buffer_size(buffer); - Cpp_Relex_Data state = cpp_relex_init(array, start_i, end_i, shift_amount, file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table); + Cpp_Relex_Data state = cpp_relex_init(array, (i32)start_i, (i32)end_i, (i32)shift_amount, file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table); - String_Const_u8_Array chunk_space[3]; - Cursor chunk_cursor = make_cursor(chunk_space, sizeof(chunk_space)); - String_Const_u8_Array chunks = buffer_get_chunks(&chunk_cursor, buffer, BufferGetChunk_ZeroTerminated); + List_String_Const_u8 chunks = buffer_get_chunks(scratch, buffer); + u8 null_terminator = 0; + string_list_push(scratch, &chunks, SCu8(&null_terminator, 1)); + Node_String_Const_u8 *node = chunks.first; i32 chunk_index = 0; - u8 *chunk = chunks.vals[chunk_index].str; - umem chunk_size = chunks.vals[chunk_index].size; - - for (;!cpp_relex_is_start_chunk(&state, (char*)chunk, (i32)chunk_size);){ - ++chunk_index; - Assert(chunk_index < chunks.count); - chunk = chunks.vals[chunk_index].str; - chunk_size = chunks.vals[chunk_index].size; + u8 *chunk = 0; + umem chunk_size = 0; + if (node != 0){ + chunk = node->string.str; + chunk_size = node->string.size; + } + for (;!cpp_relex_is_start_chunk(&state, (char*)chunk, (i32)chunk_size);){ + node = node->next; + Assert(node != 0); + chunk = node->string.str; + chunk_size = node->string.size; } - for(;;){ - Cpp_Lex_Result lex_result = cpp_relex_step(&state, (char*)chunk, (i32)chunk_size, size, array, &relex_array); + Cpp_Lex_Result lex_result = cpp_relex_step(&state, (char*)chunk, (i32)chunk_size, (i32)size, array, &relex_array); switch (lex_result){ case LexResult_NeedChunk: { - ++chunk_index; - Assert(chunk_index < chunks.count); - chunk = chunks.vals[chunk_index].str; - chunk_size = chunks.vals[chunk_index].size; + node = node->next; + Assert(node != 0); + chunk = node->string.str; + chunk_size = node->string.size; }break; case LexResult_NeedTokenMemory: InvalidPath; @@ -199,7 +204,7 @@ file_first_lex(System_Functions *system, Models *models, Editing_File *file){ } internal void -file_relex(System_Functions *system, Models *models, Editing_File *file, i32 start, i32 end, i32 shift_amount){ +file_relex(System_Functions *system, Models *models, Editing_File *file, i64 start, i64 end, i64 shift_amount){ file_relex_serial(system, models, file, start, end, shift_amount); } diff --git a/4ed_font_interface.h b/4ed_font_interface.h index 1b24a39e..f8b17315 100644 --- a/4ed_font_interface.h +++ b/4ed_font_interface.h @@ -40,6 +40,7 @@ struct Codepoint_Index_Map{ struct Face{ Face_Description description; Face_ID id; + i32 version_number; // NOTE(allen): Metrics f32 height; diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp index efbc19ec..c9c1c6cb 100644 --- a/4ed_font_set.cpp +++ b/4ed_font_set.cpp @@ -149,12 +149,14 @@ font_set_modify_face(Font_Set *set, Face_ID id, Face_Description *description){ b32 result = false; Font_Face_Slot *slot = font_set__get_face_slot(set, id); if (slot != 0){ + i32 version_number = slot->face->version_number; Arena arena = make_arena_system(set->system); Face *face = set->system->font_make_face(&arena, description); if (face != 0){ linalloc_clear(&slot->arena); slot->arena = arena; slot->face = face; + face->version_number = version_number + 1; face->id = id; result = true; } diff --git a/4ed_history.cpp b/4ed_history.cpp index cd6e6f2d..7f2426d0 100644 --- a/4ed_history.cpp +++ b/4ed_history.cpp @@ -250,18 +250,10 @@ history_record_edit(Heap *heap, Global_History *global_history, History *history new_record->kind = RecordKind_Single; - i32 length_forward = edit.length; - i32 length_backward = edit.range.one_past_last - edit.range.first; - - new_record->single.str_forward = push_array(&history->arena, char, length_forward); - new_record->single.str_backward = push_array(&history->arena, char, length_backward); - new_record->single.length_forward = length_forward; - new_record->single.length_backward = length_backward; + new_record->single.forward_text = push_string_copy(&history->arena, edit.text); + new_record->single.backward_text = buffer_stringify(&history->arena, buffer, edit.range); new_record->single.first = edit.range.first; - block_copy(new_record->single.str_forward, edit.str, length_forward); - buffer_stringify_range(buffer, edit.range, new_record->single.str_backward); - Assert(history->record_lookup.count == history->record_count); } } @@ -313,29 +305,29 @@ history__optimize_group(Arena *scratch, History *history, Record *record){ b32 do_merge = false; Temp_Memory temp = begin_temp(scratch); - i32 new_length_forward = left->single.length_forward + right->single.length_forward ; - i32 new_length_backward = left->single.length_backward + right->single.length_backward; + i64 new_length_forward = left->single.forward_text.size + right->single.forward_text.size ; + i64 new_length_backward = left->single.backward_text.size + right->single.backward_text.size; - char *temp_str_forward = 0; - char *temp_str_backward = 0; + String_Const_u8 merged_forward = {}; + String_Const_u8 merged_backward = {}; - if (left->single.first + left->single.length_forward == right->single.first){ + if (left->single.first + (i64)left->single.forward_text.size == right->single.first){ do_merge = true; - temp_str_forward = push_array(scratch, char, new_length_forward ); - temp_str_backward = push_array(scratch, char, new_length_backward); - block_copy(temp_str_forward , left->single.str_forward , left->single.length_forward ); - block_copy(temp_str_forward + left->single.length_forward, right->single.str_forward, right->single.length_forward); - block_copy(temp_str_backward , left->single.str_backward , left->single.length_backward ); - block_copy(temp_str_backward + left->single.length_backward, right->single.str_backward, right->single.length_backward); + merged_forward = push_u8_stringf(scratch, "%.*s%.*s", + string_expand(left->single.forward_text), + string_expand(right->single.forward_text)); + merged_backward = push_u8_stringf(scratch, "%.*s%.*s", + string_expand(left->single.backward_text), + string_expand(right->single.backward_text)); } - else if (right->single.first + right->single.length_backward == left->single.first){ + else if (right->single.first + (i64)right->single.backward_text.size == left->single.first){ do_merge = true; - temp_str_forward = push_array(scratch, char, new_length_forward ); - temp_str_backward = push_array(scratch, char, new_length_backward); - block_copy(temp_str_forward , right->single.str_forward, right->single.length_forward); - block_copy(temp_str_forward + right->single.length_forward, left->single.str_forward , left->single.length_forward ); - block_copy(temp_str_backward , right->single.str_backward, right->single.length_backward); - block_copy(temp_str_backward + right->single.length_backward, left->single.str_backward , left->single.length_backward ); + merged_forward = push_u8_stringf(scratch, "%.*s%.*s", + string_expand(right->single.forward_text), + string_expand(left->single.forward_text)); + merged_backward = push_u8_stringf(scratch, "%.*s%.*s", + string_expand(right->single.backward_text), + string_expand(left->single.backward_text)); } else{ break; @@ -344,17 +336,9 @@ history__optimize_group(Arena *scratch, History *history, Record *record){ if (do_merge){ end_temp(left->restore_point); - char *new_str_forward = push_array(&history->arena, char, new_length_forward ); - char *new_str_backward = push_array(&history->arena, char, new_length_backward); - - block_copy(new_str_forward , temp_str_forward , new_length_forward ); - block_copy(new_str_backward, temp_str_backward, new_length_backward); - left->edit_number = right->edit_number; - left->single.str_forward = new_str_forward ; - left->single.str_backward = new_str_backward; - left->single.length_forward = new_length_forward ; - left->single.length_backward = new_length_backward; + left->single.forward_text = push_string_copy(&history->arena, merged_forward); + left->single.backward_text = push_string_copy(&history->arena, merged_backward); history__free_single_node(history, &right->node); record->group.count -= 1; diff --git a/4ed_history.h b/4ed_history.h index 07205384..bce76122 100644 --- a/4ed_history.h +++ b/4ed_history.h @@ -13,8 +13,8 @@ #define FRED_HISTORY_H struct Record_Batch_Slot{ - i32 length_forward; - i32 length_backward; + i64 length_forward; + i64 length_backward; i32 first; }; @@ -25,13 +25,10 @@ struct Record{ Record_Kind kind; union{ struct{ - char *str_forward; - char *str_backward; - i32 length_forward; - i32 length_backward; - i32 first; + String_Const_u8 forward_text; + String_Const_u8 backward_text; + i64 first; } single; - struct{ Node children; i32 count; diff --git a/4ed_string_matching.cpp b/4ed_string_matching.cpp index aef1f344..a23a18c9 100644 --- a/4ed_string_matching.cpp +++ b/4ed_string_matching.cpp @@ -67,21 +67,20 @@ string_compute_needle_jump_table(Arena *arena, String_Const_u8 needle, Scan_Dire internal String_Match_List find_all_matches_forward(Arena *arena, i32 maximum_output_count, - String_Const_u8_Array chunks, String_Const_u8 needle, + List_String_Const_u8 chunks, String_Const_u8 needle, u64_Array jump_table, Character_Predicate *predicate, u64 base_index, Buffer_ID buffer, i32 string_id){ String_Match_List list = {}; - if (chunks.count > 0){ + if (chunks.node_count > 0){ u64 i = 0; u64 j = 0; b8 current_l = false; i64 last_insensitive = -1; i64 last_boundary = -1; - i32 chunk_index = 0; + Node_String_Const_u8 *node = chunks.first; i64 chunk_pos = 0; - String_Const_u8 chunk = chunks.strings[chunk_index]; i32 jump_back_code = 0; @@ -89,13 +88,10 @@ find_all_matches_forward(Arena *arena, i32 maximum_output_count, iterate_forward: i += 1; chunk_pos += 1; - if (chunk_pos >= (i64)chunk.size){ + if (chunk_pos >= (i64)node->string.size){ last_boundary = i; chunk_pos = 0; - chunk_index += 1; - if (chunk_index < chunks.count){ - chunk = chunks.strings[chunk_index]; - } + node = node->next; } switch (jump_back_code){ @@ -110,8 +106,8 @@ find_all_matches_forward(Arena *arena, i32 maximum_output_count, } } - for (;chunk_index < chunks.count;){ - u8 c = chunk.str[chunk_pos]; + for (;node != 0;){ + u8 c = node->string.str[chunk_pos]; u64 n = i - j; u8 needle_c = needle.str[n]; if (character_to_upper(c) == character_to_upper(needle_c)){ @@ -135,8 +131,8 @@ find_all_matches_forward(Arena *arena, i32 maximum_output_count, (u64)last_boundary < j + needle.size)){ AddFlag(flags, StringMatch_Straddled); } - if (chunk_index < chunks.count){ - u8 next_c = chunk.str[chunk_pos]; + if (node != 0){ + u8 next_c = node->string.str[chunk_pos]; if (character_predicate_check_character(*predicate, next_c)){ AddFlag(flags, StringMatch_RightSideSloppy); } @@ -180,16 +176,15 @@ find_all_matches_forward(Arena *arena, i32 maximum_output_count, internal String_Match_List find_all_matches_backward(Arena *arena, i32 maximum_output_count, - String_Const_u8_Array chunks, String_Const_u8 needle, + List_String_Const_u8 chunks, String_Const_u8 needle, u64_Array jump_table, Character_Predicate *predicate, u64 base_index, Buffer_ID buffer, i32 string_id){ String_Match_List list = {}; - if (chunks.count > 0){ - i64 size = 0; - for (i32 i = 0; i < chunks.count; i += 1){ - size += chunks.strings[i].size; - } + string_list_reverse(&chunks); + + if (chunks.node_count > 0){ + i64 size = (i64)chunks.total_size; i64 i = size - 1; i64 j = size - 1; @@ -197,9 +192,8 @@ find_all_matches_backward(Arena *arena, i32 maximum_output_count, i64 last_insensitive = size; i64 last_boundary = size; - i32 chunk_index = chunks.count - 1; - String_Const_u8 chunk = chunks.strings[chunk_index]; - i64 chunk_pos = chunk.size - 1; + Node_String_Const_u8 *node = chunks.first; + i64 chunk_pos = node->string.size - 1; i32 jump_back_code = 0; @@ -209,11 +203,7 @@ find_all_matches_backward(Arena *arena, i32 maximum_output_count, chunk_pos -= 1; if (chunk_pos < 0){ last_boundary = i; - chunk_index -= 1; - if (chunk_index >= 0){ - chunk = chunks.strings[chunk_index]; - chunk_pos = chunk.size - 1; - } + node = node->next; } switch (jump_back_code){ @@ -228,8 +218,8 @@ find_all_matches_backward(Arena *arena, i32 maximum_output_count, } } - for (;chunk_index >= 0;){ - u8 c = chunk.str[chunk_pos]; + for (;node != 0;){ + u8 c = node->string.str[chunk_pos]; u64 n = j - i; u8 needle_c = needle.str[needle.size - 1 - n]; if (character_to_upper(c) == character_to_upper(needle_c)){ @@ -253,8 +243,8 @@ find_all_matches_backward(Arena *arena, i32 maximum_output_count, last_boundary > j - (i64)needle.size)){ AddFlag(flags, StringMatch_Straddled); } - if (chunk_index >= 0){ - u8 next_c = chunk.str[chunk_pos]; + if (node != 0){ + u8 next_c = node->string.str[chunk_pos]; if (character_predicate_check_character(*predicate, next_c)){ AddFlag(flags, StringMatch_LeftSideSloppy); } @@ -296,12 +286,14 @@ find_all_matches_backward(Arena *arena, i32 maximum_output_count, } } + string_list_reverse(&chunks); + return(list); } internal String_Match_List find_all_matches(Arena *arena, i32 maximum_output_count, - String_Const_u8_Array chunks, String_Const_u8 needle, + List_String_Const_u8 chunks, String_Const_u8 needle, u64_Array jump_table, Character_Predicate *predicate, Scan_Direction direction, u64 base_index, Buffer_ID buffer, i32 string_id){ diff --git a/4ed_system.h b/4ed_system.h index 404201e1..b9222892 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -42,7 +42,7 @@ typedef Sys_Load_File_Sig(System_Load_File); #define Sys_Load_Close_Sig(name) b32 name(Plat_Handle handle) typedef Sys_Load_Close_Sig(System_Load_Close); -#define Sys_Save_File_Sig(name) File_Attributes name(Arena *scratch, char *filename, char *buffer, u32 size) +#define Sys_Save_File_Sig(name) File_Attributes name(Arena *scratch, char *filename, String_Const_u8 data) typedef Sys_Save_File_Sig(System_Save_File); // time diff --git a/4ed_text_layout.cpp b/4ed_text_layout.cpp index 1d600eb1..5b05f237 100644 --- a/4ed_text_layout.cpp +++ b/4ed_text_layout.cpp @@ -9,46 +9,57 @@ // TOP -// TODO(allen): REWRITE REWRITE REWRITE!!! internal void -text_layout_init(Application_Links *app, Text_Layout_Container *container){ +text_layout_init(Models *models, Text_Layout_Container *container){ block_zero_struct(container); - container->node_arena = make_arena_app_links(app); + container->node_arena = make_arena_models(models); + container->table = make_table_u64_u64(models->base_allocator, 20); } internal Text_Layout* text_layout_new__alloc_layout(Text_Layout_Container *container){ - Text_Layout_Node *node = container->free_nodes; + Text_Layout *node = container->free_nodes; if (node == 0){ - node = push_array(&container->node_arena, Text_Layout_Node, 1); + node = push_array(&container->node_arena, Text_Layout, 1); } else{ - container->free_nodes = node->next; + sll_stack_pop(container->free_nodes); } - return(&node->layout); + return(node); +} + +internal void +text_layout_release(Text_Layout_Container *container, Text_Layout *layout){ + linalloc_clear(&layout->arena); + sll_stack_push(container->free_nodes, layout); } internal Text_Layout_ID -text_layout_new(Heap *heap, Text_Layout_Container *container, Buffer_ID buffer_id, Buffer_Point point, Range on_screen_range, f32 height, Text_Layout_Coordinates coordinates, int_color *item_colors){ +text_layout_new(Text_Layout_Container *container, Arena arena, + Buffer_ID buffer_id, Buffer_Point point, + Interval_i64 visible_range, Interval_i64 visible_line_number_range, + Rect_f32 rect, int_color *item_colors){ Text_Layout *new_layout_data = text_layout_new__alloc_layout(container); + new_layout_data->arena = arena; new_layout_data->buffer_id = buffer_id; new_layout_data->point = point; - new_layout_data->on_screen_range = on_screen_range; - new_layout_data->height = height; - new_layout_data->coordinates = coordinates; + new_layout_data->visible_range = visible_range; + new_layout_data->visible_line_number_range = visible_line_number_range; + new_layout_data->rect = rect; new_layout_data->item_colors = item_colors; Text_Layout_ID new_id = ++container->id_counter; - insert_u32_Ptr_table(heap, &container->table, new_id, new_layout_data); + table_insert(&container->table, new_id, (u64)PtrAsInt(new_layout_data)); return(new_id); } -internal b32 -text_layout_get(Text_Layout_Container *container, Text_Layout_ID id, Text_Layout *out){ - b32 result = false; - void *ptr = 0; - if (lookup_u32_Ptr_table(&container->table, id, &ptr)){ - block_copy(out, ptr, sizeof(*out)); - result = true; +internal Text_Layout* +text_layout_get(Text_Layout_Container *container, Text_Layout_ID id){ + Text_Layout *result = 0; + Table_Lookup lookup = table_lookup(&container->table, id); + if (lookup.found_match){ + u64 ptr_val = 0; + table_read(&container->table, lookup, &ptr_val); + result = (Text_Layout*)IntAsPtr(ptr_val); } return(result); } @@ -56,15 +67,73 @@ text_layout_get(Text_Layout_Container *container, Text_Layout_ID id, Text_Layout internal b32 text_layout_erase(Text_Layout_Container *container, Text_Layout_ID id){ b32 result = false; - void *ptr = 0; - if (lookup_u32_Ptr_table(&container->table, id, &ptr)){ - erase_u32_Ptr_table(&container->table, id); - Text_Layout_Node *node = CastFromMember(Text_Layout_Node, layout, ptr); - node->next = container->free_nodes; - container->free_nodes = node; + Table_Lookup lookup = table_lookup(&container->table, id); + if (lookup.found_match){ + u64 ptr_val = 0; + table_read(&container->table, lookup, &ptr_val); + Text_Layout *ptr = (Text_Layout*)IntAsPtr(ptr_val); + text_layout_release(container, ptr); + table_erase(&container->table, lookup); result = true; } return(result); } +//////////////////////////////// + +internal void +text_layout_render(Models *models, Text_Layout *layout){ + Editing_File *file = imp_get_file(models, layout->buffer_id); + if (file != 0){ + Arena *scratch = &models->mem.arena; + Render_Target *target = models->target; + Color_Table color_table = models->color_table; + Font_Set *font_set = &models->font_set; + Face_ID font_id = file->settings.font_id; + f32 width = rect_width(layout->rect); + + u32 special_color = color_table.vals[Stag_Special_Character]; + u32 ghost_color = color_table.vals[Stag_Ghost_Character]; + + Vec2_f32 shift_p = layout->rect.p0 - layout->point.pixel_shift; + i64 first_index = layout->visible_range.first; + i64 line_number = layout->visible_line_number_range.min; + i64 line_number_last = layout->visible_line_number_range.max; + for (;line_number <= line_number_last; line_number += 1){ + Buffer_Layout_Item_List line = file_get_line_layout(models, file, width, font_id, line_number); + for (Buffer_Layout_Item_Block *block = line.first; + block != 0; + block = block->next){ + Buffer_Layout_Item *item = block->items; + i64 count = block->count; + int_color *item_colors = layout->item_colors; + for (i32 i = 0; i < count; i += 1, item += 1){ + if (item->codepoint != 0){ + int_color symbol_color = item_colors[item->index - first_index]; + u32 color = 0; + if (symbol_color == Stag_Default){ + if (HasFlag(item->flags, BRFlag_Special_Character)){ + color = special_color; + } + else if (HasFlag(item->flags, BRFlag_Ghost_Character)){ + color = ghost_color; + } + else{ + color = finalize_color(color_table, symbol_color); + } + } + else{ + color = finalize_color(color_table, symbol_color); + } + + Vec2_f32 p = item->rect.p0 + shift_p; + draw_font_glyph(target, font_set, font_id, item->codepoint, p.x, p.y, color, GlyphFlag_None); + } + } + } + shift_p.y += line.height; + } + } +} + // BOTTOM diff --git a/4ed_text_layout.h b/4ed_text_layout.h index 35602093..47d28f02 100644 --- a/4ed_text_layout.h +++ b/4ed_text_layout.h @@ -12,33 +12,24 @@ #if !defined(FRED_TEXT_LAYOUT_H) #define FRED_TEXT_LAYOUT_H -struct Text_Layout{ - // NOTE(allen): This is not a _real_ text layout yet. - // The eventual destiny of this type is that it will store the fairly - // costly to generate results of the text layout engine. - // For now, since the engine cannot be easily consolidated, - // this just stores the parameters that should be handed to any - // system that attempts to query the layout for hit testing. - View_ID view_id; - Buffer_ID buffer_id; - Buffer_Point point; - Range on_screen_range; - f32 height; - - Text_Layout_Coordinates coordinates; - int_color *item_colors; -}; - -union Text_Layout_Node{ - Text_Layout_Node *next; - Text_Layout layout; +union Text_Layout{ + Text_Layout *next; + struct{ + Arena arena; + Buffer_ID buffer_id; + Buffer_Point point; + Interval_i64 visible_range; + Interval_i64 visible_line_number_range; + Rect_f32 rect; + int_color *item_colors; + }; }; struct Text_Layout_Container{ Arena node_arena; - Text_Layout_Node *free_nodes; - u32_Ptr_Table table; - u32 id_counter; + Text_Layout *free_nodes; + Table_u64_u64 table; + Text_Layout_ID id_counter; }; #endif diff --git a/4ed_translation.cpp b/4ed_translation.cpp index b5b10565..7f33ca4a 100644 --- a/4ed_translation.cpp +++ b/4ed_translation.cpp @@ -9,6 +9,31 @@ // TOP +// TODO(allen): I don't like this code _AT ALL_ +// unravel the mess! +// +// +// So what happened here was I thought, "Hey I have text in non-contiguous chunks and now I +// need to translates it into unicode codepoints (interpreting it as utf8), so I should make +// a system that translates utf-8 by taking in one byte at a time then emitting one or more +// codepoints whenever there is enough information, all the while ensuring there is no backtracking" +// +// Even though this may make the iteration sound nice, it's a HUGE FREAKING PAIN IN THE ASS. +// You can't optimize it very well, the code is inscrutible both on the implementation side +// and the calling side. Besides the fact that I "got it working" there isn't one good thing +// about this code. +// +// My next idea would be to try to make translation systems that take in the chunks themselves as +// a linked list, and then just does the WHOLE translation, MAYBE with optional "stop conditions". +// This way someone can actually optimize the translation loop by hand in _ONE SPOT_. The downside +// is that the caller will have to put up with maybe more translation work than they needed, but that +// translation work will be so much cheaper, and easier to maintain, that the caller will be happier +// overall. +// +// +// If this comment is still here, then I haven't fixed any of this garbage yet, but it should really +// be fixed! + #define ERROR_BYTE (max_u8-1) #define CONTINUATION_BYTE max_u8 diff --git a/4ed_translation.h b/4ed_translation.h index 353f0ba8..2cca58f4 100644 --- a/4ed_translation.h +++ b/4ed_translation.h @@ -18,7 +18,6 @@ struct Translation_State{ u8 fill_i; u8 fill_expected; }; -global_const Translation_State null_buffer_translating_state = {}; enum{ TranLBH_None, diff --git a/4ed_view.cpp b/4ed_view.cpp index 9c40daa0..8dcc2c44 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -34,9 +34,9 @@ view_get_index(Live_Views *live_set, View *view){ return((i32)(view - live_set->views)); } -internal i32 +internal View_ID view_get_id(Live_Views *live_set, View *view){ - return((i32)(view - live_set->views) + 1); + return((View_ID)(view - live_set->views) + 1); } internal View* @@ -80,6 +80,8 @@ view_get_edit_pos(View *view){ internal void view_set_edit_pos(View *view, File_Edit_Positions edit_pos){ + edit_pos.scroll.position.line_number = clamp_bot(1, edit_pos.scroll.position.line_number); + edit_pos.scroll.target.line_number = clamp_bot(1, edit_pos.scroll.target.line_number); view->edit_pos_ = edit_pos; view->file->state.edit_pos_most_recent = edit_pos; } @@ -116,179 +118,225 @@ view_height(Models *models, View *view){ return(rect_height(view_get_buffer_rect(models, view))); } -internal Vec2_i32 -view_get_cursor_xy(Models *models, View *view){ - File_Edit_Positions edit_pos = view_get_edit_pos(view); - Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(edit_pos.cursor_pos)); - Vec2_i32 result = {}; - if (view->file->settings.unwrapped_lines){ - result = V2i32((i32)cursor.unwrapped_x, (i32)cursor.unwrapped_y); - } - else{ - result = V2i32((i32)cursor.wrapped_x, (i32)cursor.wrapped_y); - } - return(result); -} +//////////////////////////////// -internal Cursor_Limits -view_cursor_limits(Models *models, View *view){ +internal Buffer_Layout_Item_List +view_get_line_layout(Models *models, View *view, i64 line_number){ Editing_File *file = view->file; - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - i32 line_height = (i32)face->height; - i32 visible_height = (i32)view_height(models, view); - Cursor_Limits limits = {}; - limits.min = line_height*2; - limits.max = visible_height - line_height*3; - if (limits.max - limits.min <= line_height){ - if (visible_height >= line_height){ - limits.max = visible_height - line_height; - } - else{ - limits.max = visible_height; - } - limits.min = 0; - } - limits.min = clamp(0, limits.min, limits.max); - limits.max = clamp_bot(0, limits.max); - limits.delta = clamp_top(line_height*5, (limits.max - limits.min + 1)/2); - return(limits); + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_get_line_layout(models, file, width, face, line_number)); } -internal i32 -view_compute_max_target_y_from_bottom_y(Models *models, View *view, f32 max_item_y, f32 line_height){ - f32 height = clamp_bot(line_height, view_height(models, view)); - f32 max_target_y = clamp_bot(0.f, max_item_y - height*0.5f); - return(ceil32(max_target_y)); -} - -internal i32 -view_compute_max_target_y(Models *models, View *view){ +internal Line_Shift_Vertical +view_line_shift_y(Models *models, View *view, i64 line_number, f32 y_delta){ Editing_File *file = view->file; - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - f32 line_height = face->height; - Gap_Buffer *buffer = &file->state.buffer; - i32 lowest_line = buffer->line_count; - if (!file->settings.unwrapped_lines){ - lowest_line = file->state.wrap_line_index[buffer->line_count]; - } - return(view_compute_max_target_y_from_bottom_y(models, view, (lowest_line + 0.5f)*line_height, line_height)); + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_line_shift_y(models, file, width, face, line_number, y_delta)); +} + +internal f32 +view_line_y_difference(Models *models, View *view, i64 line_a, i64 line_b){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_line_y_difference(models, file, width, face, line_a, line_b)); +} + +internal i64 +view_pos_at_relative_xy(Models *models, View *view, i64 base_line, Vec2_f32 relative_xy){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_pos_at_relative_xy(models, file, width, face, base_line, relative_xy)); +} + +internal Vec2_f32 +view_relative_xy_of_pos(Models *models, View *view, i64 base_line, i64 pos){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_relative_xy_of_pos(models, file, width, face, base_line, pos)); +} + +internal Buffer_Point +view_normalize_buffer_point(Models *models, View *view, Buffer_Point point){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_normalize_buffer_point(models, file, width, face, point)); +} + +internal Vec2_f32 +view_buffer_point_difference(Models *models, View *view, Buffer_Point a, Buffer_Point b){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_buffer_point_difference(models, file, width, face, a, b)); +} + +internal Buffer_Point +view_move_buffer_point(Models *models, View *view, Buffer_Point buffer_point, Vec2_f32 delta){ + delta += buffer_point.pixel_shift; + Line_Shift_Vertical shift = view_line_shift_y(models, view, buffer_point.line_number, delta.y); + buffer_point.line_number = shift.line; + buffer_point.pixel_shift = V2f32(delta.x, delta.y - shift.y_delta); + return(buffer_point); +} + +internal Line_Shift_Character +view_line_shift_characters(Models *models, View *view, i64 line_number, i64 character_delta){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_line_shift_characters(models, file, width, face, line_number, character_delta)); +} + +internal i64 +view_line_character_difference(Models *models, View *view, i64 line_a, i64 line_b){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_line_character_difference(models, file, width, face, line_a, line_b)); +} + +internal i64 +view_pos_from_relative_character(Models *models, View *view, i64 base_line, i64 relative_character){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_pos_from_relative_character(models, file, width, face, base_line, relative_character)); +} + +internal i64 +view_relative_character_from_pos(Models *models, View *view, i64 base_line, i64 pos){ + Editing_File *file = view->file; + Face_ID face = file->settings.font_id; + f32 width = view_width(models, view); + return(file_relative_character_from_pos(models, file, width, face, base_line, pos)); } //////////////////////////////// -internal b32 -view_move_view_to_cursor(Models *models, View *view, GUI_Scroll_Vars *scroll){ - System_Functions *system = models->system; - b32 result = false; - i32 max_x = (i32)view_width(models, view); - i32 max_y = view_compute_max_target_y(models, view); - - Vec2_i32 cursor = view_get_cursor_xy(models, view); - - GUI_Scroll_Vars scroll_vars = *scroll; - i32 target_x = scroll_vars.target_x; - i32 target_y = scroll_vars.target_y; - - Cursor_Limits limits = view_cursor_limits(models, view); - if (target_y < cursor.y - limits.max){ - target_y = cursor.y - limits.max + limits.delta; - } - if (target_y > cursor.y - limits.min){ - target_y = cursor.y - limits.min - limits.delta; - } - - target_y = clamp(0, target_y, max_y); - - if (cursor.x >= target_x + max_x){ - target_x = cursor.x - max_x/2; - } - else if (cursor.x < target_x){ - target_x = clamp_bot(0, cursor.x - max_x/2); - } - - if (target_x != scroll_vars.target_x || target_y != scroll_vars.target_y){ - scroll->target_x = target_x; - scroll->target_y = target_y; - result = true; - } - - return(result); -} - -internal b32 -view_move_cursor_to_view(Models *models, View *view, GUI_Scroll_Vars scroll, i32 *pos_in_out, f32 preferred_x){ - System_Functions *system = models->system; - Editing_File *file = view->file; - Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(*pos_in_out)); - Face *face = font_set_face_from_id(&models->font_set, file->settings.font_id); - f32 line_height = face->height; - f32 old_cursor_y = 0.f; - if (file->settings.unwrapped_lines){ - old_cursor_y = cursor.unwrapped_y; - } - else{ - old_cursor_y = cursor.wrapped_y; - } - f32 cursor_y = old_cursor_y; - f32 target_y = (f32)scroll.target_y; - - Cursor_Limits limits = view_cursor_limits(models, view); - - if (cursor_y > target_y + limits.max){ - cursor_y = target_y + limits.max; - } - if (target_y != 0 && cursor_y < target_y + limits.min){ - cursor_y = target_y + limits.min; - } - - b32 result = false; - if (cursor_y != old_cursor_y){ - if (cursor_y > old_cursor_y){ - cursor_y += line_height; +internal Interval_f32 +view_acceptable_y(f32 view_height, f32 line_height){ + Interval_f32 acceptable_y = {}; + if (view_height <= line_height*5.f){ + if (view_height < line_height){ + acceptable_y.max = view_height; } else{ - cursor_y -= line_height; + acceptable_y.max = view_height - line_height; } - Buffer_Seek seek = seek_xy(preferred_x, cursor_y, false, file->settings.unwrapped_lines); - cursor = file_compute_cursor(models, file, seek); - *pos_in_out = (i32)cursor.pos; + } + else{ + acceptable_y = If32(line_height*2.f, view_height - line_height*2.f); + } + return(acceptable_y); +} + +internal Vec2_f32 +view_safety_margin(f32 view_width, f32 acceptable_y_height, f32 line_height, f32 typical_advance){ + Vec2_f32 safety = {}; + safety.y = min(line_height*5.f, (acceptable_y_height + 1.f)*0.5f); + safety.x = min(view_width*0.5f, typical_advance*8.f); + return(safety); +} + +internal b32 +view_move_view_to_cursor(Models *models, View *view, Buffer_Scroll *scroll){ + Editing_File *file = view->file; + Face_ID face_id = file->settings.font_id; + Rect_f32 rect = view_get_buffer_rect(models, view); + Vec2_f32 view_dim = rect_dim(rect); + + File_Edit_Positions edit_pos = view_get_edit_pos(view); + Vec2_f32 p = file_relative_xy_of_pos(models, file, view_dim.x, face_id, scroll->target.line_number, + edit_pos.cursor_pos); + p -= scroll->target.pixel_shift; + + Face *face = font_set_face_from_id(&models->font_set, face_id); + f32 line_height = face->height; + f32 typical_advance = face->typical_advance; + Interval_f32 acceptable_y = view_acceptable_y(view_dim.y, line_height); + Vec2_f32 safety = view_safety_margin(view_dim.x, range_size(acceptable_y), line_height, typical_advance); + + Vec2_f32 target_p_relative = {}; + if (p.y < acceptable_y.min){ + target_p_relative.y = p.y - safety.y; + } + else if (p.y > acceptable_y.max){ + target_p_relative.y = (p.y + safety.y) - view_dim.y; + } + if (p.x < 0.f){ + target_p_relative.x = p.x - safety.x; + } + else if (p.x > view_dim.x){ + target_p_relative.x = (p.x + safety.x) - view_dim.x; + } + scroll->target.pixel_shift = target_p_relative; + scroll->target = view_normalize_buffer_point(models, view, scroll->target); + scroll->target.pixel_shift.x = f32_round32(scroll->target.pixel_shift.x); + scroll->target.pixel_shift.y = f32_round32(scroll->target.pixel_shift.y); + + return(target_p_relative != V2f32(0.f, 0.f)); +} + +internal b32 +view_move_cursor_to_view(Models *models, View *view, Buffer_Scroll scroll, i64 *pos_in_out, f32 preferred_x){ + Editing_File *file = view->file; + Face_ID face_id = file->settings.font_id; + Rect_f32 rect = view_get_buffer_rect(models, view); + Vec2_f32 view_dim = rect_dim(rect); + + Vec2_f32 p = file_relative_xy_of_pos(models, file, view_dim.x, face_id, scroll.target.line_number, *pos_in_out); + p -= scroll.target.pixel_shift; + + Face *face = font_set_face_from_id(&models->font_set, face_id); + f32 line_height = face->height; + Interval_f32 acceptable_y = view_acceptable_y(view_dim.y, line_height); + Vec2_f32 safety = view_safety_margin(view_dim.x, range_size(acceptable_y), + line_height, face->typical_advance); + + b32 adjusted_y = true; + if (p.y < acceptable_y.min){ + p.y = acceptable_y.min + safety.y; + } + else if (p.y > acceptable_y.max){ + p.y = acceptable_y.max - safety.y; + } + else{ + adjusted_y = false; + } + + b32 result = false; + if (adjusted_y){ + p += scroll.target.pixel_shift; + *pos_in_out = file_pos_at_relative_xy(models, file, view_dim.x, face_id, scroll.target.line_number, p); result = true; } return(result); } -internal b32 -view_has_unwrapped_lines(View *view){ - return(view->file->settings.unwrapped_lines); -} - -internal void -view_set_preferred_x(View *view, Full_Cursor cursor){ - if (view_has_unwrapped_lines(view)){ - view->preferred_x = cursor.unwrapped_x; - } - else{ - view->preferred_x = cursor.wrapped_x; - } -} - internal void view_set_preferred_x_to_current_position(Models *models, View *view){ + view->preferred_x = 0.f; +#if 0 File_Edit_Positions edit_pos = view_get_edit_pos(view); Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(edit_pos.cursor_pos)); view_set_preferred_x(view, cursor); +#endif } internal void -view_set_cursor(System_Functions *system, Models *models, View *view, Full_Cursor cursor, b32 set_preferred_x){ +view_set_cursor(Models *models, View *view, i64 pos){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - file_edit_positions_set_cursor(&edit_pos, (i32)cursor.pos); - if (set_preferred_x){ - view_set_preferred_x(view, cursor); - } + file_edit_positions_set_cursor(&edit_pos, pos); + view->preferred_x = 0.f; view_set_edit_pos(view, edit_pos); - GUI_Scroll_Vars scroll = edit_pos.scroll; + Buffer_Scroll scroll = edit_pos.scroll; if (view_move_view_to_cursor(models, view, &scroll)){ edit_pos.scroll = scroll; view_set_edit_pos(view, edit_pos); @@ -296,32 +344,27 @@ view_set_cursor(System_Functions *system, Models *models, View *view, Full_Curso } internal void -view_set_scroll(System_Functions *system, Models *models, View *view, GUI_Scroll_Vars scroll){ +view_set_scroll(Models *models, View *view, Buffer_Scroll scroll){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - file_edit_positions_set_scroll(&edit_pos, scroll, view_compute_max_target_y(models, view)); + file_edit_positions_set_scroll(&edit_pos, scroll); view_set_edit_pos(view, edit_pos); - i32 pos = (i32)edit_pos.cursor_pos; - if (view_move_cursor_to_view(models, view, edit_pos.scroll, &pos, view->preferred_x)){ - Full_Cursor cursor = file_compute_cursor(models, view->file, seek_pos(pos)); - edit_pos.cursor_pos = cursor.pos; + if (view_move_cursor_to_view(models, view, edit_pos.scroll, &edit_pos.cursor_pos, view->preferred_x)){ view_set_edit_pos(view, edit_pos); } } internal void -view_set_cursor_and_scroll(Models *models, View *view, Full_Cursor cursor, b32 set_preferred_x, GUI_Scroll_Vars scroll){ +view_set_cursor_and_scroll(Models *models, View *view, i64 pos, b32 set_preferred_x, Buffer_Scroll scroll){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - file_edit_positions_set_cursor(&edit_pos, (i32)cursor.pos); - if (set_preferred_x){ - view_set_preferred_x(view, cursor); - } - file_edit_positions_set_scroll(&edit_pos, scroll, view_compute_max_target_y(models, view)); + file_edit_positions_set_cursor(&edit_pos, pos); + view->preferred_x = 0.f; + file_edit_positions_set_scroll(&edit_pos, scroll); edit_pos.last_set_type = EditPos_None; view_set_edit_pos(view, edit_pos); } internal void -view_post_paste_effect(View *view, f32 seconds, i32 start, i32 size, u32 color){ +view_post_paste_effect(View *view, f32 seconds, i64 start, i64 size, u32 color){ Editing_File *file = view->file; file->state.paste_effect.start = start; file->state.paste_effect.end = start + size; @@ -381,24 +424,14 @@ adjust_views_looking_at_file_to_new_cursor(System_Functions *system, Models *mod View *view = panel->view; if (view->file == file){ File_Edit_Positions edit_pos = view_get_edit_pos(view); - Full_Cursor cursor = file_compute_cursor(models, file, seek_pos(edit_pos.cursor_pos)); - view_set_cursor(system, models, view, cursor, true); + view_set_cursor(models, view, edit_pos.cursor_pos); } } } -internal void -file_full_remeasure(System_Functions *system, Models *models, Editing_File *file){ - Face_ID font_id = file->settings.font_id; - Face *face = font_set_face_from_id(&models->font_set, font_id); - file_measure_wraps(system, &models->mem, file, face); - adjust_views_looking_at_file_to_new_cursor(system, models, file); -} - internal void file_set_font(System_Functions *system, Models *models, Editing_File *file, Face_ID font_id){ file->settings.font_id = font_id; - file_full_remeasure(system, models, file); } internal void @@ -412,23 +445,6 @@ global_set_font_and_update_files(System_Functions *system, Models *models, Face_ models->global_font_id = font_id; } -internal b32 -alter_font_and_update_files(System_Functions *system, Models *models, Face_ID face_id, Face_Description *new_description){ - b32 success = false; - if (font_set_modify_face(&models->font_set, face_id, new_description)){ - success = true; - for (Node *node = models->working_set.active_file_sentinel.next; - node != &models->working_set.active_file_sentinel; - node = node->next){ - Editing_File *file = CastFromMember(Editing_File, main_chain_node, node); - if (file->settings.font_id == face_id){ - file_full_remeasure(system, models, file); - } - } - } - return(success); -} - internal b32 release_font_and_update_files(System_Functions *system, Models *models, Face_ID font_id, Face_ID replacement_id){ b32 success = false; @@ -511,110 +527,57 @@ get_token_color(Color_Table color_table, Cpp_Token token){ return(result); } +internal void +view_quit_ui(System_Functions *system, Models *models, View *view){ + Assert(view != 0); + view->ui_mode = false; + if (view->ui_quit != 0){ + view->ui_quit(&models->app_links, view_get_id(&models->live_set, view)); + view->ui_quit = 0; + } +} + +//////////////////////////////// + +internal View* +imp_get_view(Models *models, View_ID view_id){ + Live_Views *live_set = &models->live_set; + View *view = 0; + view_id -= 1; + if (0 <= view_id && view_id < live_set->max){ + view = live_set->views + view_id; + if (!view->in_use){ + view = 0; + } + } + return(view); +} + +//////////////////////////////// + +#if 0 internal void render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *view, - Rect_i32 rect, Full_Cursor render_cursor, Range on_screen_range, - Buffer_Render_Item *items, int_color *item_colors, i32 item_count){ - Editing_File *file = view->file; - Arena *scratch = &models->mem.arena; - Color_Table color_table = models->color_table; - Font_Set *font_set = &models->font_set; - - Assert(file != 0); - Assert(buffer_good(&file->state.buffer)); - + Rect_i32 rect, + Full_Cursor render_cursor, + Interval_i64 on_screen_range, + Buffer_Layout_Item_List list, + int_color *item_colors){ Cpp_Token_Array token_array = file->state.token_array; b32 tokens_use = (token_array.tokens != 0); - b32 wrapped = (!file->settings.unwrapped_lines); - Face_ID font_id = file->settings.font_id; + i64 token_i = 0; - i32 *line_starts = file->state.buffer.line_starts; - i32 line_count = file->state.buffer.line_count; - i32 line_scan_index = (i32)render_cursor.line - 1; - i32 first_byte_index_of_next_line = 0; - if (line_scan_index + 1 < line_count){ - first_byte_index_of_next_line = line_starts[line_scan_index + 1]; - } - else{ - first_byte_index_of_next_line = max_i32; - } - - i32 *wrap_starts = file->state.wrap_positions; - i32 wrap_count = file->state.wrap_position_count; - if (wrap_count > 0 && wrap_starts[wrap_count - 1] == buffer_size(&file->state.buffer)){ - wrap_count -= 1; - } - i32 wrap_scan_index = (i32)render_cursor.wrap_line - (i32)render_cursor.line; - i32 first_byte_index_of_next_wrap = 0; - if (wrap_scan_index + 1 < wrap_count){ - first_byte_index_of_next_wrap = wrap_starts[wrap_scan_index + 1]; - } - else{ - first_byte_index_of_next_wrap = max_i32; - } - - i32 visual_markers_scan_index = 0; - - i32 visual_line_markers_scan_index = 0; - u32 visual_line_markers_color = 0; - - i32 visual_range_markers_scan_index = 0; - i32 visual_line_range_markers_scan_index = 0; - - i32 token_i = 0; u32 main_color = color_table.vals[Stag_Default]; u32 special_color = color_table.vals[Stag_Special_Character]; u32 ghost_color = color_table.vals[Stag_Ghost_Character]; if (tokens_use){ - Cpp_Get_Token_Result result = cpp_get_token(token_array, items->index); + Cpp_Get_Token_Result result = cpp_get_token(token_array, (i32)items->index); main_color = get_token_color(color_table, token_array.tokens[result.token_index]); token_i = result.token_index + 1; } - Buffer_Render_Item *item = items; - Buffer_Render_Item *item_end = item + item_count; - i32 prev_ind = -1; - u32 highlight_color = 0; - - for (i32 i = 0; item < item_end; item += 1, i += 1){ - i32 ind = item->index; - - // NOTE(allen): Line scanning - b32 is_new_line = false; - for (; line_scan_index < line_count;){ - if (ind < first_byte_index_of_next_line){ - break; - } - line_scan_index += 1; - is_new_line = true; - if (line_scan_index + 1 < line_count){ - first_byte_index_of_next_line = line_starts[line_scan_index + 1]; - } - else{ - first_byte_index_of_next_line = max_i32; - } - } - if (item == items){ - is_new_line = true; - } - - // NOTE(allen): Wrap scanning - b32 is_new_wrap = false; - if (wrapped){ - for (; wrap_scan_index < wrap_count;){ - if (ind < first_byte_index_of_next_wrap){ - break; - } - wrap_scan_index += 1; - is_new_wrap = true; - if (wrap_scan_index + 1 < wrap_count){ - first_byte_index_of_next_wrap = wrap_starts[wrap_scan_index + 1]; - } - else{ - first_byte_index_of_next_wrap = max_i32; - } - } - } + { + i64 ind = item->index; // NOTE(allen): Token scanning u32 highlight_this_color = 0; @@ -641,126 +604,61 @@ render_loaded_file_in_view__inner(Models *models, Render_Target *target, View *v } } - if (item->y1 > 0){ - Rect_f32 char_rect = f32R(item->x0, item->y0, item->x1, item->y1); - - u32 char_color = main_color; - if (on_screen_range.min <= ind && ind < on_screen_range.max){ - i32 index_shifted = ind - on_screen_range.min; - if (item_colors[index_shifted] != 0){ - char_color = finalize_color(color_table, item_colors[index_shifted]); - } + u32 char_color = main_color; + if (on_screen_range.min <= ind && ind < on_screen_range.max){ + i64 index_shifted = ind - on_screen_range.min; + if (item_colors[index_shifted] != 0){ + char_color = finalize_color(color_table, item_colors[index_shifted]); } - if (HasFlag(item->flags, BRFlag_Special_Character)){ - char_color = special_color; - } - else if (HasFlag(item->flags, BRFlag_Ghost_Character)){ - char_color = ghost_color; - } - - if (view->show_whitespace && highlight_color == 0 && codepoint_is_whitespace(item->codepoint)){ - highlight_this_color = color_table.vals[Stag_Highlight_White]; - } - else{ - highlight_this_color = highlight_color; - } - - // NOTE(allen): Perform highlight, wireframe, and ibar renders - u32 color_highlight = 0; - u32 color_wireframe = 0; - u32 color_ibar = 0; - - if (highlight_this_color != 0){ - if (color_highlight == 0){ - color_highlight = highlight_this_color; - } - } - - if (color_highlight != 0){ - draw_rectangle(target, char_rect, color_highlight); - } - - u32 fade_color = 0xFFFF00FF; - f32 fade_amount = 0.f; - if (file->state.paste_effect.seconds_down > 0.f && - file->state.paste_effect.start <= ind && - ind < file->state.paste_effect.end){ - fade_color = file->state.paste_effect.color; - fade_amount = file->state.paste_effect.seconds_down; - fade_amount /= file->state.paste_effect.seconds_max; - } - char_color = color_blend(char_color, fade_amount, fade_color); - if (item->codepoint != 0){ - draw_font_glyph(target, font_set, font_id, item->codepoint, item->x0, item->y0, char_color, GlyphFlag_None); - } - - if (color_wireframe != 0){ - draw_rectangle_outline(target, char_rect, color_wireframe); + } + if (HasFlag(item->flags, BRFlag_Special_Character)){ + char_color = special_color; + } + else if (HasFlag(item->flags, BRFlag_Ghost_Character)){ + char_color = ghost_color; + } + + if (view->show_whitespace && highlight_color == 0 && codepoint_is_whitespace(item->codepoint)){ + highlight_this_color = color_table.vals[Stag_Highlight_White]; + } + else{ + highlight_this_color = highlight_color; + } + + // NOTE(allen): Perform highlight, wireframe, and ibar renders + u32 color_highlight = 0; + u32 color_wireframe = 0; + u32 color_ibar = 0; + + if (highlight_this_color != 0){ + if (color_highlight == 0){ + color_highlight = highlight_this_color; } } - prev_ind = ind; - } -} - -internal Full_Cursor -file_get_render_cursor(Models *models, Editing_File *file, f32 scroll_y){ - Full_Cursor result = {}; - if (file->settings.unwrapped_lines){ - result = file_compute_cursor_hint(models, file, seek_unwrapped_xy(0, scroll_y, false)); - } - else{ - result = file_compute_cursor(models, file, seek_wrapped_xy(0, scroll_y, false)); - } - return(result); -} - -internal Full_Cursor -view_get_render_cursor(Models *models, View *view, f32 scroll_y){ - return(file_get_render_cursor(models, view->file, scroll_y)); -} - -internal Full_Cursor -view_get_render_cursor(Models *models, View *view){ - File_Edit_Positions edit_pos = view_get_edit_pos(view); - f32 scroll_y = edit_pos.scroll.scroll_y; - //scroll_y += view->widget_height; - return(view_get_render_cursor(models, view, scroll_y)); -} - -internal Full_Cursor -view_get_render_cursor_target(Models *models, View *view){ - File_Edit_Positions edit_pos = view_get_edit_pos(view); - f32 scroll_y = (f32)edit_pos.scroll.target_y; - //scroll_y += view->widget_height; - return(view_get_render_cursor(models, view, scroll_y)); -} - -internal void -view_quit_ui(System_Functions *system, Models *models, View *view){ - Assert(view != 0); - view->ui_mode = false; - if (view->ui_quit != 0){ - view->ui_quit(&models->app_links, view_get_id(&models->live_set, view)); - view->ui_quit = 0; - } -} - -//////////////////////////////// - -internal View* -imp_get_view(Models *models, View_ID view_id){ - Live_Views *live_set = &models->live_set; - View *view = 0; - view_id -= 1; - if (0 <= view_id && view_id < live_set->max){ - view = live_set->views + view_id; - if (!view->in_use){ - view = 0; + if (color_highlight != 0){ + draw_rectangle(target, char_rect, color_highlight); + } + + u32 fade_color = 0xFFFF00FF; + f32 fade_amount = 0.f; + if (file->state.paste_effect.seconds_down > 0.f && + file->state.paste_effect.start <= ind && + ind < file->state.paste_effect.end){ + fade_color = file->state.paste_effect.color; + fade_amount = file->state.paste_effect.seconds_down; + fade_amount /= file->state.paste_effect.seconds_max; + } + char_color = color_blend(char_color, fade_amount, fade_color); + + if (color_wireframe != 0){ + draw_rectangle_outline(target, char_rect, color_wireframe); } } - return(view); + } +#endif + // BOTTOM diff --git a/4ed_view.h b/4ed_view.h index 33104609..e26f27a6 100644 --- a/4ed_view.h +++ b/4ed_view.h @@ -25,36 +25,24 @@ struct View{ i64 mark; f32 preferred_x; + // TODO(allen): ELIMINATE THESE i32 temp_view_top_left_pos; i32 temp_view_top_left_target_pos; - b32 ui_mode; + b8 new_scroll_target; + + b8 ui_mode; i32 ui_map_id; - GUI_Scroll_Vars ui_scroll; + Basic_Scroll ui_scroll; UI_Quit_Function_Type *ui_quit; - Vec2_i32 prev_target; - - b32 hide_scrollbar; - b32 hide_file_bar; - b32 show_whitespace; + b8 hide_scrollbar; + b8 hide_file_bar; + b8 show_whitespace; // misc Query_Set query_set; - - // Render Context - Arena layout_arena; - - struct{ - Rect_i32 view_rect; - Rect_i32 buffer_rect; - Full_Cursor cursor; - Range range; - Buffer_Render_Item *items; - int_color *item_colors; - i32 item_count; - } render; }; struct Live_Views{ @@ -64,12 +52,6 @@ struct Live_Views{ i32 max; }; -struct Cursor_Limits{ - i32 min; - i32 max; - i32 delta; -}; - enum{ GROW_FAILED, GROW_NOT_NEEDED, diff --git a/4ed_view_ui.cpp b/4ed_view_ui.cpp deleted file mode 100644 index 2ab6002d..00000000 --- a/4ed_view_ui.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * ??.??.2018 - * - * View GUI layouts and implementations - * - */ - -// TOP - -internal GUI_Scroll_Vars -do_step_file_view(System_Functions *system, Models *models, View *view, i32_Rect rect, b32 is_active, f32 dt, GUI_Scroll_Vars scroll){ - Editing_File *file = view->file; - - // TODO(allen): do(eliminate the built in paste_effect) - if (!file->is_loading && file->state.paste_effect.seconds_down > 0.f){ - file->state.paste_effect.seconds_down -= dt; - models->animate_next_frame = true; - } - - // NOTE(allen): call scroll rule hook - b32 is_new_target = (scroll.target_x != view->prev_target.x || scroll.target_y != view->prev_target.y); - - f32 target_x = (f32)scroll.target_x; - f32 target_y = (f32)scroll.target_y; - - View_ID view_id = view_get_id(&models->live_set, view); - if (models->scroll_rule(target_x, target_y, &scroll.scroll_x, &scroll.scroll_y, view_id, is_new_target, dt)){ - models->animate_next_frame = true; - } - - view->prev_target.x = scroll.target_x; - view->prev_target.y = scroll.target_y; - - return(scroll); -} - -//////////////////////////////// - -#if 0 -internal void -do_render_file_view(System_Functions *system, View *view, Models *models, GUI_Scroll_Vars *scroll, View *active, i32_Rect rect, b32 is_active, Render_Target *target){ - Editing_File *file = view->file; - Assert(file != 0); - draw_push_clip(target, rect); - if (!view->ui_mode){ - if (file_is_ready(file)){ - Rect_i32 buffer_rect = view_get_buffer_rect(models, view); - //render_loaded_file_in_view(system, view, models, buffer_rect, is_active, target); - - Editing_File *file = view->file; - i32 line_height = view->line_height; - - f32 max_x = (f32)file->settings.display_width; - i32 max_y = buffer_rect.y1 - buffer_rect.y0 + line_height; - - Assert(file != 0); - Assert(!file->is_dummy); - Assert(buffer_good(&file->state.buffer)); - - Partition *part = &models->mem.part; - Temp_Memory temp = begin_temp_memory(part); - - push_align(part, 4); - - f32 left_side_space = 0; - - i32 max = part_remaining(part)/sizeof(Buffer_Render_Item); - Buffer_Render_Item *items = push_array(part, Buffer_Render_Item, 0); - - b32 wrapped = !file->settings.unwrapped_lines; - Face_ID font_id = file->settings.font_id; - Font_Pointers font = system->font.get_pointers_by_id(font_id); - - File_Edit_Positions edit_pos = view_get_edit_pos(view); - f32 scroll_x = edit_pos.scroll.scroll_x; - f32 scroll_y = edit_pos.scroll.scroll_y; - - Full_Cursor render_cursor = view_get_render_cursor(system, view); - - i32 item_count = 0; - i32 end_pos = 0; - { - Buffer_Render_Params params; - params.buffer = &file->state.buffer; - params.items = items; - params.max = max; - params.count = &item_count; - params.port_x = (f32)buffer_rect.x0 + left_side_space; - params.port_y = (f32)buffer_rect.y0; - params.clip_w = view_width(models, view) - left_side_space; - params.scroll_x = scroll_x; - params.scroll_y = scroll_y; - params.width = max_x; - params.height = (f32)max_y; - params.start_cursor = render_cursor; - params.wrapped = wrapped; - params.system = system; - params.font = font; - params.virtual_white = file->settings.virtual_white; - params.wrap_slashes = file->settings.wrap_indicator; - - Buffer_Render_State state = {}; - Buffer_Layout_Stop stop = {}; - - f32 line_shift = 0.f; - b32 do_wrap = false; - i32 wrap_unit_end = 0; - - b32 first_wrap_determination = true; - i32 wrap_array_index = 0; - - do{ - stop = buffer_render_data(&state, params, line_shift, do_wrap, wrap_unit_end); - switch (stop.status){ - case BLStatus_NeedWrapDetermination: - { - if (first_wrap_determination){ - wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count); - ++wrap_array_index; - if (file->state.wrap_positions[wrap_array_index] == stop.pos){ - do_wrap = true; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - else{ - do_wrap = false; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - first_wrap_determination = false; - } - else{ - Assert(stop.pos == wrap_unit_end); - do_wrap = true; - ++wrap_array_index; - wrap_unit_end = file->state.wrap_positions[wrap_array_index]; - } - }break; - - case BLStatus_NeedWrapLineShift: - case BLStatus_NeedLineShift: - { - line_shift = file->state.line_indents[stop.wrap_line_index]; - }break; - } - }while(stop.status != BLStatus_Finished); - - end_pos = state.i; - } - push_array(part, Buffer_Render_Item, item_count); - - Range on_screen_range = {}; - on_screen_range.first = render_cursor.pos; - on_screen_range.one_past_last = end_pos; - - //////////////////////////////// - - if (models->render_caller != 0){ - view_call_render_caller(models, target, view, buffer_rect, render_cursor, on_screen_range, items, item_count, do_core_render); - } - else{ - render_loaded_file_in_view__inner(models, target, view, buffer_rect, render_cursor, on_screen_range, items, item_count); - } - - end_temp_memory(temp); - } - } - else{ - Full_Cursor render_cursor = {}; - Range on_screen_range = {}; - if (models->render_caller != 0){ - view_call_render_caller(models, target, view, buffer_rect, render_cursor, on_screen_range, 0, 0, dont_do_core_render); - } - } - draw_pop_clip(target); -} -#endif - -// BOTTOM - diff --git a/4ed_working_set.cpp b/4ed_working_set.cpp index fbb2a6a5..cc07fefb 100644 --- a/4ed_working_set.cpp +++ b/4ed_working_set.cpp @@ -12,9 +12,9 @@ internal void working_set_file_default_settings(Working_Set *working_set, Editing_File *file){ block_zero_struct(&file->settings); - file->settings.display_width = working_set->default_display_width; - file->settings.minimum_base_display_width = working_set->default_minimum_base_display_width; - file->settings.wrap_indicator = WrapIndicator_Show_At_Wrap_Edge; + //file->settings.display_width = working_set->default_display_width; + //file->settings.minimum_base_display_width = working_set->default_minimum_base_display_width; + //file->settings.wrap_indicator = WrapIndicator_Show_At_Wrap_Edge; } //////////////////////////////// diff --git a/meta/4ed_build.cpp b/meta/4ed_build.cpp index e2632799..c99546ad 100644 --- a/meta/4ed_build.cpp +++ b/meta/4ed_build.cpp @@ -13,11 +13,6 @@ #include "../4coder_base_types.h" -#if 0 -# define FSTRING_IMPLEMENTATION -# include "../4coder_lib/4coder_string.h" -#endif - #define FTECH_FILE_MOVING_IMPLEMENTATION #include "4ed_file_moving.h" @@ -584,12 +579,14 @@ build_main(Arena *arena, char *cdir, b32 update_local_theme, u32 flags, u32 arch internal void standard_build(Arena *arena, char *cdir, u32 flags, u32 arch){ - fsm_generator(arena, cdir); + //fsm_generator(arena, cdir); metagen(arena, cdir); + //do_buildsuper(arena, cdir, fm_str(arena, custom_files[Custom_Default]), arch); do_buildsuper(arena, cdir, fm_str(arena, custom_files[Custom_Experiments]), arch); //do_buildsuper(arena, cdir, fm_str(arena, custom_files[Custom_Casey]), arch); //do_buildsuper(arena, cdir, fm_str(arena, custom_files[Custom_ChronalVim]), arch); + build_main(arena, cdir, true, flags, arch); } diff --git a/old_string_api.h b/old_string_api.h deleted file mode 100644 index 009f923f..00000000 --- a/old_string_api.h +++ /dev/null @@ -1,245 +0,0 @@ -// old string api - -// TOP - -#if !defined(OLD_STRING_API_H) -#define OLD_STRING_API_H - -struct String_OLD{ - char *str; - i32 size; - i32 memory_size; -}; - -static String null_string = {}; - -FSTRING_INLINE b32_4tech char_is_slash(char c); -FSTRING_INLINE b32_4tech char_is_upper(char c); -FSTRING_INLINE b32_4tech char_is_upper_utf8(char c); -FSTRING_INLINE b32_4tech char_is_lower(char c); -FSTRING_INLINE b32_4tech char_is_lower_utf8(u8_4tech c); -FSTRING_INLINE char char_to_upper(char c); -FSTRING_INLINE char char_to_lower(char c); -FSTRING_INLINE b32_4tech char_is_whitespace(char c); -FSTRING_INLINE b32_4tech char_is_alpha_numeric(char c); -FSTRING_INLINE b32_4tech char_is_alpha_numeric_utf8(u8_4tech c); -FSTRING_INLINE b32_4tech char_is_alpha_numeric_true(char c); -FSTRING_INLINE b32_4tech char_is_alpha_numeric_true_utf8(u8_4tech c); -FSTRING_INLINE b32_4tech char_is_alpha(char c); -FSTRING_INLINE b32_4tech char_is_alpha_utf8(u8_4tech c); -FSTRING_INLINE b32_4tech char_is_alpha_true(char c); -FSTRING_INLINE b32_4tech char_is_alpha_true_utf8(u8_4tech c); -FSTRING_INLINE b32_4tech char_is_hex(char c); -FSTRING_INLINE b32_4tech char_is_hex_utf8(u8_4tech c); -FSTRING_INLINE b32_4tech char_is_numeric(char c); -FSTRING_INLINE b32_4tech char_is_numeric_utf8(u8_4tech c); -FSTRING_INLINE String make_string_cap(void *str, i32_4tech size, i32_4tech mem_size); -FSTRING_INLINE String make_string(void *str, i32_4tech size); -#ifndef make_lit_string -# define make_lit_string(s) (make_string_cap((char*)(s), sizeof(s)-1, sizeof(s))) -#endif -#ifndef lit -# define lit(s) make_lit_string(s) -#endif -#ifndef make_fixed_width_string -# define make_fixed_width_string(s) (make_string_cap((char*)(s), 0, sizeof(s))) -#endif -#ifndef expand_str -# define expand_str(s) ((s).str), ((s).size) -#endif -FSTRING_LINK i32_4tech str_size(char *str); -FSTRING_INLINE String make_string_slowly(void *str); -FSTRING_INLINE String substr_tail(String str, i32_4tech start); -FSTRING_INLINE String substr(String str, i32_4tech start, i32_4tech size); -FSTRING_LINK String skip_whitespace(String str); -FSTRING_LINK String skip_whitespace_measure(String str, i32_4tech *skip_length); -FSTRING_LINK String chop_whitespace(String str); -FSTRING_LINK String skip_chop_whitespace(String str); -FSTRING_LINK String skip_chop_whitespace_measure(String str, i32_4tech *skip_length); -FSTRING_INLINE String tailstr(String str); -FSTRING_LINK b32_4tech match_cc(char *a, char *b); -FSTRING_LINK b32_4tech match_sc(String a, char *b); -FSTRING_INLINE b32_4tech match_cs(char *a, String b); -FSTRING_LINK b32_4tech match_ss(String a, String b); -FSTRING_LINK b32_4tech match_part_ccl(char *a, char *b, i32_4tech *len); -FSTRING_LINK b32_4tech match_part_scl(String a, char *b, i32_4tech *len); -FSTRING_INLINE b32_4tech match_part_cc(char *a, char *b); -FSTRING_INLINE b32_4tech match_part_sc(String a, char *b); -FSTRING_LINK b32_4tech match_part_cs(char *a, String b); -FSTRING_LINK b32_4tech match_part_ss(String a, String b); -FSTRING_LINK b32_4tech match_insensitive_cc(char *a, char *b); -FSTRING_LINK b32_4tech match_insensitive_sc(String a, char *b); -FSTRING_INLINE b32_4tech match_insensitive_cs(char *a, String b); -FSTRING_LINK b32_4tech match_insensitive_ss(String a, String b); -FSTRING_LINK b32_4tech match_part_insensitive_ccl(char *a, char *b, i32_4tech *len); -FSTRING_LINK b32_4tech match_part_insensitive_scl(String a, char *b, i32_4tech *len); -FSTRING_INLINE b32_4tech match_part_insensitive_cc(char *a, char *b); -FSTRING_INLINE b32_4tech match_part_insensitive_sc(String a, char *b); -FSTRING_LINK b32_4tech match_part_insensitive_cs(char *a, String b); -FSTRING_LINK b32_4tech match_part_insensitive_ss(String a, String b); -FSTRING_LINK i32_4tech compare_cc(char *a, char *b); -FSTRING_LINK i32_4tech compare_sc(String a, char *b); -FSTRING_INLINE i32_4tech compare_cs(char *a, String b); -FSTRING_LINK i32_4tech compare_ss(String a, String b); -FSTRING_LINK i32_4tech find_c_char(char *str, i32_4tech start, char character); -FSTRING_LINK i32_4tech find_s_char(String str, i32_4tech start, char character); -FSTRING_LINK i32_4tech rfind_s_char(String str, i32_4tech start, char character); -FSTRING_LINK i32_4tech find_c_chars(char *str, i32_4tech start, char *characters); -FSTRING_LINK i32_4tech find_s_chars(String str, i32_4tech start, char *characters); -FSTRING_LINK i32_4tech find_substr_c(char *str, i32_4tech start, String seek); -FSTRING_LINK i32_4tech find_substr_s(String str, i32_4tech start, String seek); -FSTRING_LINK i32_4tech rfind_substr_s(String str, i32_4tech start, String seek); -FSTRING_LINK i32_4tech find_substr_insensitive_c(char *str, i32_4tech start, String seek); -FSTRING_LINK i32_4tech find_substr_insensitive_s(String str, i32_4tech start, String seek); -FSTRING_INLINE b32_4tech has_substr_c(char *s, String seek); -FSTRING_INLINE b32_4tech has_substr_s(String s, String seek); -FSTRING_INLINE b32_4tech has_substr_insensitive_c(char *s, String seek); -FSTRING_INLINE b32_4tech has_substr_insensitive_s(String s, String seek); -FSTRING_LINK i32_4tech copy_fast_unsafe_cc(char *dest, char *src); -FSTRING_LINK i32_4tech copy_fast_unsafe_cs(char *dest, String src); -FSTRING_LINK b32_4tech copy_checked_ss(String *dest, String src); -FSTRING_LINK b32_4tech copy_checked_cs(char *dest, i32_4tech dest_cap, String src); -FSTRING_LINK b32_4tech copy_partial_sc(String *dest, char *src); -FSTRING_LINK b32_4tech copy_partial_ss(String *dest, String src); -FSTRING_LINK b32_4tech copy_partial_cs(char *dest, i32_4tech dest_cap, String src); -FSTRING_INLINE i32_4tech copy_cc(char *dest, char *src); -FSTRING_INLINE void copy_ss(String *dest, String src); -FSTRING_INLINE void copy_sc(String *dest, char *src); -FSTRING_LINK b32_4tech append_checked_ss(String *dest, String src); -FSTRING_LINK b32_4tech append_partial_sc(String *dest, char *src); -FSTRING_LINK b32_4tech append_partial_ss(String *dest, String src); -FSTRING_LINK b32_4tech append_s_char(String *dest, char c); -FSTRING_INLINE b32_4tech append_ss(String *dest, String src); -FSTRING_INLINE b32_4tech append_sc(String *dest, char *src); -FSTRING_LINK b32_4tech terminate_with_null(String *str); -FSTRING_LINK b32_4tech append_padding(String *dest, char c, i32_4tech target_size); -FSTRING_LINK void string_interpret_escapes(String src, char *dst); -FSTRING_LINK void replace_char(String *str, char replace, char with); -FSTRING_LINK void replace_str_ss(String *str, String replace, String with); -FSTRING_LINK void replace_str_sc(String *str, String replace, char *with); -FSTRING_LINK void replace_str_cs(String *str, char *replace, String with); -FSTRING_LINK void replace_str_cc(String *str, char *replace, char *with); -FSTRING_LINK void to_lower_cc(char *src, char *dst); -FSTRING_LINK void to_lower_ss(String *dst, String src); -FSTRING_LINK void to_lower_s(String *str); -FSTRING_LINK void to_upper_cc(char *src, char *dst); -FSTRING_LINK void to_upper_ss(String *dst, String src); -FSTRING_LINK void to_upper_s(String *str); -FSTRING_LINK void to_camel_cc(char *src, char *dst); -FSTRING_LINK i32_4tech int_to_str_size(i32_4tech x); -FSTRING_LINK b32_4tech int_to_str(String *dest, i32_4tech x); -FSTRING_LINK b32_4tech append_int_to_str(String *dest, i32_4tech x); -FSTRING_LINK i32_4tech u64_to_str_size(uint64_t x); -FSTRING_LINK b32_4tech u64_to_str(String *dest, uint64_t x); -FSTRING_LINK b32_4tech append_u64_to_str(String *dest, uint64_t x); -FSTRING_LINK i32_4tech float_to_str_size(float x); -FSTRING_LINK b32_4tech append_float_to_str(String *dest, float x); -FSTRING_LINK b32_4tech float_to_str(String *dest, float x); -FSTRING_LINK i32_4tech str_is_int_c(char *str); -FSTRING_LINK b32_4tech str_is_int_s(String str); -FSTRING_LINK i32_4tech str_to_int_c(char *str); -FSTRING_LINK i32_4tech str_to_int_s(String str); -FSTRING_LINK i32_4tech hexchar_to_int(char c); -FSTRING_LINK char int_to_hexchar(i32_4tech x); -FSTRING_LINK u32_4tech hexstr_to_int(String str); -FSTRING_LINK b32_4tech color_to_hexstr(String *s, u32_4tech color); -FSTRING_LINK b32_4tech hexstr_to_color(String s, u32_4tech *out); -FSTRING_LINK i32_4tech reverse_seek_slash_pos(String str, i32_4tech pos); -FSTRING_INLINE i32_4tech reverse_seek_slash(String str); -FSTRING_INLINE String front_of_directory(String dir); -FSTRING_INLINE String path_of_directory(String dir); -FSTRING_LINK b32_4tech set_last_folder_sc(String *dir, char *folder_name, char slash); -FSTRING_LINK b32_4tech set_last_folder_ss(String *dir, String folder_name, char slash); -FSTRING_LINK String file_extension(String str); -FSTRING_LINK b32_4tech remove_extension(String *str); -FSTRING_LINK b32_4tech remove_last_folder(String *str); -FSTRING_LINK b32_4tech string_set_match_table(void *str_set, i32_4tech item_size, i32_4tech count, String str, i32_4tech *match_index); -FSTRING_LINK b32_4tech string_set_match(String *str_set, i32_4tech count, String str, i32_4tech *match_index); -FSTRING_LINK String get_first_double_line(String source); -FSTRING_LINK String get_next_double_line(String source, String line); -FSTRING_LINK String get_next_word(String source, String prev_word); -FSTRING_LINK String get_first_word(String source); -FSTRING_LINK String string_push(Partition *part, i32_4tech size); -FSTRING_LINK String string_push_copy(Partition *part, String str); - -FSTRING_INLINE String make_string(void *str, i32_4tech size, i32_4tech mem_size){return(make_string_cap(str,size,mem_size));} -FSTRING_INLINE String substr(String str, i32_4tech start){return(substr_tail(str,start));} -FSTRING_LINK String skip_whitespace(String str, i32_4tech *skip_length){return(skip_whitespace_measure(str,skip_length));} -FSTRING_LINK String skip_chop_whitespace(String str, i32_4tech *skip_length){return(skip_chop_whitespace_measure(str,skip_length));} -FSTRING_LINK b32_4tech match(char *a, char *b){return(match_cc(a,b));} -FSTRING_LINK b32_4tech match(String a, char *b){return(match_sc(a,b));} -FSTRING_INLINE b32_4tech match(char *a, String b){return(match_cs(a,b));} -FSTRING_LINK b32_4tech match(String a, String b){return(match_ss(a,b));} -FSTRING_LINK b32_4tech match_part(char *a, char *b, i32_4tech *len){return(match_part_ccl(a,b,len));} -FSTRING_LINK b32_4tech match_part(String a, char *b, i32_4tech *len){return(match_part_scl(a,b,len));} -FSTRING_INLINE b32_4tech match_part(char *a, char *b){return(match_part_cc(a,b));} -FSTRING_INLINE b32_4tech match_part(String a, char *b){return(match_part_sc(a,b));} -FSTRING_LINK b32_4tech match_part(char *a, String b){return(match_part_cs(a,b));} -FSTRING_LINK b32_4tech match_part(String a, String b){return(match_part_ss(a,b));} -FSTRING_LINK b32_4tech match_insensitive(char *a, char *b){return(match_insensitive_cc(a,b));} -FSTRING_LINK b32_4tech match_insensitive(String a, char *b){return(match_insensitive_sc(a,b));} -FSTRING_INLINE b32_4tech match_insensitive(char *a, String b){return(match_insensitive_cs(a,b));} -FSTRING_LINK b32_4tech match_insensitive(String a, String b){return(match_insensitive_ss(a,b));} -FSTRING_LINK b32_4tech match_part_insensitive(char *a, char *b, i32_4tech *len){return(match_part_insensitive_ccl(a,b,len));} -FSTRING_LINK b32_4tech match_part_insensitive(String a, char *b, i32_4tech *len){return(match_part_insensitive_scl(a,b,len));} -FSTRING_INLINE b32_4tech match_part_insensitive(char *a, char *b){return(match_part_insensitive_cc(a,b));} -FSTRING_INLINE b32_4tech match_part_insensitive(String a, char *b){return(match_part_insensitive_sc(a,b));} -FSTRING_LINK b32_4tech match_part_insensitive(char *a, String b){return(match_part_insensitive_cs(a,b));} -FSTRING_LINK b32_4tech match_part_insensitive(String a, String b){return(match_part_insensitive_ss(a,b));} -FSTRING_LINK i32_4tech compare(char *a, char *b){return(compare_cc(a,b));} -FSTRING_LINK i32_4tech compare(String a, char *b){return(compare_sc(a,b));} -FSTRING_INLINE i32_4tech compare(char *a, String b){return(compare_cs(a,b));} -FSTRING_LINK i32_4tech compare(String a, String b){return(compare_ss(a,b));} -FSTRING_LINK i32_4tech find(char *str, i32_4tech start, char character){return(find_c_char(str,start,character));} -FSTRING_LINK i32_4tech find(String str, i32_4tech start, char character){return(find_s_char(str,start,character));} -FSTRING_LINK i32_4tech rfind(String str, i32_4tech start, char character){return(rfind_s_char(str,start,character));} -FSTRING_LINK i32_4tech find(char *str, i32_4tech start, char *characters){return(find_c_chars(str,start,characters));} -FSTRING_LINK i32_4tech find(String str, i32_4tech start, char *characters){return(find_s_chars(str,start,characters));} -FSTRING_LINK i32_4tech find_substr(char *str, i32_4tech start, String seek){return(find_substr_c(str,start,seek));} -FSTRING_LINK i32_4tech find_substr(String str, i32_4tech start, String seek){return(find_substr_s(str,start,seek));} -FSTRING_LINK i32_4tech rfind_substr(String str, i32_4tech start, String seek){return(rfind_substr_s(str,start,seek));} -FSTRING_LINK i32_4tech find_substr_insensitive(char *str, i32_4tech start, String seek){return(find_substr_insensitive_c(str,start,seek));} -FSTRING_LINK i32_4tech find_substr_insensitive(String str, i32_4tech start, String seek){return(find_substr_insensitive_s(str,start,seek));} -FSTRING_INLINE b32_4tech has_substr(char *s, String seek){return(has_substr_c(s,seek));} -FSTRING_INLINE b32_4tech has_substr(String s, String seek){return(has_substr_s(s,seek));} -FSTRING_INLINE b32_4tech has_substr_insensitive(char *s, String seek){return(has_substr_insensitive_c(s,seek));} -FSTRING_INLINE b32_4tech has_substr_insensitive(String s, String seek){return(has_substr_insensitive_s(s,seek));} -FSTRING_LINK i32_4tech copy_fast_unsafe(char *dest, char *src){return(copy_fast_unsafe_cc(dest,src));} -FSTRING_LINK i32_4tech copy_fast_unsafe(char *dest, String src){return(copy_fast_unsafe_cs(dest,src));} -FSTRING_LINK b32_4tech copy_checked(String *dest, String src){return(copy_checked_ss(dest,src));} -FSTRING_LINK b32_4tech copy_checked(char *dest, i32_4tech dest_cap, String src){return(copy_checked_cs(dest,dest_cap,src));} -FSTRING_LINK b32_4tech copy_partial(String *dest, char *src){return(copy_partial_sc(dest,src));} -FSTRING_LINK b32_4tech copy_partial(String *dest, String src){return(copy_partial_ss(dest,src));} -FSTRING_LINK b32_4tech copy_partial(char *dest, i32_4tech dest_cap, String src){return(copy_partial_cs(dest,dest_cap,src));} -FSTRING_INLINE i32_4tech copy(char *dest, char *src){return(copy_cc(dest,src));} -FSTRING_INLINE void copy(String *dest, String src){return(copy_ss(dest,src));} -FSTRING_INLINE void copy(String *dest, char *src){return(copy_sc(dest,src));} -FSTRING_LINK b32_4tech append_checked(String *dest, String src){return(append_checked_ss(dest,src));} -FSTRING_LINK b32_4tech append_partial(String *dest, char *src){return(append_partial_sc(dest,src));} -FSTRING_LINK b32_4tech append_partial(String *dest, String src){return(append_partial_ss(dest,src));} -FSTRING_LINK b32_4tech append(String *dest, char c){return(append_s_char(dest,c));} -FSTRING_INLINE b32_4tech append(String *dest, String src){return(append_ss(dest,src));} -FSTRING_INLINE b32_4tech append(String *dest, char *src){return(append_sc(dest,src));} -FSTRING_LINK void replace_str(String *str, String replace, String with){return(replace_str_ss(str,replace,with));} -FSTRING_LINK void replace_str(String *str, String replace, char *with){return(replace_str_sc(str,replace,with));} -FSTRING_LINK void replace_str(String *str, char *replace, String with){return(replace_str_cs(str,replace,with));} -FSTRING_LINK void replace_str(String *str, char *replace, char *with){return(replace_str_cc(str,replace,with));} -FSTRING_LINK void to_lower(char *src, char *dst){return(to_lower_cc(src,dst));} -FSTRING_LINK void to_lower(String *dst, String src){return(to_lower_ss(dst,src));} -FSTRING_LINK void to_lower(String *str){return(to_lower_s(str));} -FSTRING_LINK void to_upper(char *src, char *dst){return(to_upper_cc(src,dst));} -FSTRING_LINK void to_upper(String *dst, String src){return(to_upper_ss(dst,src));} -FSTRING_LINK void to_upper(String *str){return(to_upper_s(str));} -FSTRING_LINK void to_camel(char *src, char *dst){return(to_camel_cc(src,dst));} -FSTRING_LINK i32_4tech str_is_int(char *str){return(str_is_int_c(str));} -FSTRING_LINK b32_4tech str_is_int(String str){return(str_is_int_s(str));} -FSTRING_LINK i32_4tech str_to_int(char *str){return(str_to_int_c(str));} -FSTRING_LINK i32_4tech str_to_int(String str){return(str_to_int_s(str));} -FSTRING_LINK i32_4tech reverse_seek_slash(String str, i32_4tech pos){return(reverse_seek_slash_pos(str,pos));} -FSTRING_LINK b32_4tech set_last_folder(String *dir, char *folder_name, char slash){return(set_last_folder_sc(dir,folder_name,slash));} -FSTRING_LINK b32_4tech set_last_folder(String *dir, String folder_name, char slash){return(set_last_folder_ss(dir,folder_name,slash));} -FSTRING_LINK b32_4tech string_set_match(void *str_set, i32_4tech item_size, i32_4tech count, String str, i32_4tech *match_index){return(string_set_match_table(str_set,item_size,count,str,match_index));} - -#endif - -// BOTTOM diff --git a/platform_win32/win32_4ed_functions.cpp b/platform_win32/win32_4ed_functions.cpp index b8f72cfd..d9f178f4 100644 --- a/platform_win32/win32_4ed_functions.cpp +++ b/platform_win32/win32_4ed_functions.cpp @@ -317,16 +317,20 @@ Sys_Save_File_Sig(system_save_file){ HANDLE file = CreateFile_utf8(scratch, (u8*)filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (file != INVALID_HANDLE_VALUE){ - DWORD written_total = 0; - DWORD written_size = 0; + u64 written_total = 0; b32 success = true; - for (;written_total < size;){ - if (!WriteFile(file, buffer + written_total, size - written_total, &written_size, 0)){ + for (;written_total < data.size;){ + DWORD read_size = max_u32; + DWORD write_size = 0; + if ((data.size - written_total) < max_u32){ + read_size = (DWORD)data.size; + } + if (!WriteFile(file, data.str + written_total, read_size, &write_size, 0)){ success = false; break; } - written_total += written_size; + written_total += write_size; } if (success){