diff --git a/4ed.cpp b/4ed.cpp index ec75bc9a..df5977fa 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -54,9 +54,8 @@ file_cursor_to_end(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 - DELTA_RULE_SIG(fallback_scroll_rule){ - return(pending_delta); + return(pending); } #include "4ed_api_implementation.cpp" @@ -339,7 +338,6 @@ App_Init_Sig(app_init){ // NOTE(allen): live set Arena *arena = models->arena; { - models->live_set.node_arena = reserve_arena(models->tctx); models->live_set.count = 0; models->live_set.max = MAX_VIEWS; models->live_set.views = push_array(arena, View, models->live_set.max); @@ -776,9 +774,10 @@ App_Step_Sig(app_step){ } } +#if 0 // NOTE(allen): apply pending smooth deltas { - Delta_Rule_Function *scroll_rule = models->scroll_rule; + Delta_Rule_Function *delta_rule = models->delta_rule; for (Panel *panel = layout_get_first_open_panel(layout); panel != 0; panel = layout_get_next_open_panel(layout, panel)){ @@ -803,6 +802,7 @@ App_Step_Sig(app_step){ } } } +#endif // NOTE(allen): hook for files reloaded { diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 6463193d..b8b08247 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -450,6 +450,8 @@ buffer_pos_from_relative_character(Application_Links *app, Buffer_ID buffer_id, return(result); } + + api(custom) function f32 view_line_y_difference(Application_Links *app, View_ID view_id, i64 line_a, i64 line_b){ Models *models = (Models*)app->cmd_context; @@ -1492,7 +1494,8 @@ view_set_cursor(Application_Links *app, View_ID view_id, Buffer_Seek seek) } api(custom) function b32 -view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll) +view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll scroll, + Set_Buffer_Scroll_Rule rule) { Models *models = (Models*)app->cmd_context; b32 result = false; @@ -1505,7 +1508,14 @@ view_set_buffer_scroll(Application_Links *app, View_ID view_id, Buffer_Scroll sc 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); + if (rule == SetBufferScroll_SnapCursorIntoView){ + view_set_scroll(models, view, scroll); + } + else{ + File_Edit_Positions edit_pos = view_get_edit_pos(view); + edit_pos.scroll = scroll; + view_set_edit_pos(view, edit_pos); + } view->new_scroll_target = true; result = true; } @@ -1580,7 +1590,7 @@ view_push_context(Application_Links *app, View_ID view_id, View_Context *ctx){ View *view = imp_get_view(models, view_id); b32 result = false; if (api_check_view(view)){ - view_push_context(models, view, ctx); + view_push_context(view, ctx); result = true; } return(result); @@ -1592,7 +1602,7 @@ view_pop_context(Application_Links *app, View_ID view_id){ View *view = imp_get_view(models, view_id); b32 result = false; if (api_check_view(view)){ - view_pop_context(models, view); + view_pop_context(view); result = true; } return(result); @@ -1609,6 +1619,27 @@ view_current_context(Application_Links *app, View_ID view_id){ return(result); } +api(custom) function Data +view_current_context_hook_memory(Application_Links *app, View_ID view_id, + Hook_ID hook_id){ + Models *models = (Models*)app->cmd_context; + View *view = imp_get_view(models, view_id); + Data result = {}; + if (api_check_view(view)){ + View_Context_Node *ctx = view_current_context_node(models, view); + if (ctx != 0){ + switch (hook_id){ + case HookID_DeltaRule: + { + result = make_data(ctx->delta_rule_memory, + ctx->ctx.delta_rule_memory_size); + }break; + } + } + } + return(result); +} + function Dynamic_Workspace* get_dynamic_workspace(Models *models, Managed_Scope handle){ Dynamic_Workspace *result = 0; @@ -2062,9 +2093,9 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){ { models->buffer_viewer_update = (Hook_Function*)func_ptr; }break; - case HookID_ScrollRule: + case HookID_DeltaRule: { - models->scroll_rule = (Delta_Rule_Function*)func_ptr; + models->delta_rule = (Delta_Rule_Function*)func_ptr; }break; case HookID_ViewEventHandler: { @@ -2101,6 +2132,23 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){ } } +api(custom) function b32 +set_custom_hook_memory_size(Application_Links *app, Hook_ID hook_id, umem size){ + Models *models = (Models*)app->cmd_context; + b32 result = true; + switch (hook_id){ + case HookID_DeltaRule: + { + models->delta_rule_memory_size = size; + }break; + default: + { + result = false; + }break; + } + return(result); +} + api(custom) function Mouse_State get_mouse_state(Application_Links *app) { diff --git a/4ed_app_models.h b/4ed_app_models.h index 24423c37..ecdb6ae7 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -52,10 +52,12 @@ struct Models{ Application_Links app_links; - Hook_Function *buffer_viewer_update; - Delta_Rule_Function *scroll_rule; - Custom_Command_Function *view_event_handler; Render_Caller_Function *render_caller; + Delta_Rule_Function *delta_rule; + umem delta_rule_memory_size; + + Hook_Function *buffer_viewer_update; + Custom_Command_Function *view_event_handler; Buffer_Name_Resolver_Function *buffer_name_resolver; Buffer_Hook_Function *begin_buffer; Buffer_Hook_Function *end_buffer; diff --git a/4ed_view.cpp b/4ed_view.cpp index daec613a..a8551da2 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -453,39 +453,30 @@ view_set_file(Models *models, View *view, Editing_File *file){ //////////////////////////////// -function View_Context_Node* -view__alloc_context_node(Live_Views *views){ - View_Context_Node *node = views->free_nodes; - if (node != 0){ - sll_stack_pop(views->free_nodes); - } - else{ - node = push_array(views->node_arena, View_Context_Node, 1); - } - return(node); -} - function void -view__free_context_node(Live_Views *views, View_Context_Node *node){ - sll_stack_push(views->free_nodes, node); -} - -function void -view_push_context(Models *models, View *view, View_Context *ctx){ - View_Context_Node *node = view__alloc_context_node(&models->live_set); +view_push_context(View *view, View_Context *ctx){ + Temp_Memory pop_me = begin_temp(view->node_arena); + View_Context_Node *node = push_array_zero(view->node_arena, View_Context_Node, 1); sll_stack_push(view->ctx, node); + node->pop_me = pop_me; block_copy_struct(&node->ctx, ctx); + node->delta_rule_memory = push_array_zero(view->node_arena, u8, ctx->delta_rule_memory_size); } function void -view_pop_context(Models *models, View *view){ +view_pop_context(View *view){ View_Context_Node *node = view->ctx; - if (node != 0){ + if (node != 0 && node->next != 0){ sll_stack_pop(view->ctx); - view__free_context_node(&models->live_set, node); + end_temp(node->pop_me); } } +function View_Context_Node* +view_current_context_node(Models *models, View *view){ + return(view->ctx); +} + function View_Context view_current_context(Models *models, View *view){ View_Context ctx = {}; @@ -566,9 +557,13 @@ view_init(Models *models, View *view, Editing_File *initial_buffer, Custom_Command_Function *event_context_base){ view_set_file(models, view, initial_buffer); + view->node_arena = reserve_arena(models->tctx); + View_Context first_ctx = {}; first_ctx.render_caller = models->render_caller; - view_push_context(models, view, &first_ctx); + first_ctx.delta_rule = models->delta_rule; + first_ctx.delta_rule_memory_size = models->delta_rule_memory_size; + view_push_context(view, &first_ctx); view->co = coroutine_create(&models->coroutines, view_event_context_base__inner); Co_In in = {}; diff --git a/4ed_view.h b/4ed_view.h index 26c8ee62..3d2c1947 100644 --- a/4ed_view.h +++ b/4ed_view.h @@ -58,7 +58,9 @@ struct Query_Set{ struct View_Context_Node{ View_Context_Node *next; + Temp_Memory pop_me; View_Context ctx; + void *delta_rule_memory; }; struct View{ @@ -79,6 +81,7 @@ struct View{ Coroutine *co; Co_Out co_out; + Arena *node_arena; View_Context_Node *ctx; b8 hide_scrollbar; @@ -89,8 +92,6 @@ struct View{ }; struct Live_Views{ - Arena *node_arena; - View_Context_Node *free_nodes; View *views; View free_sentinel; i32 count; diff --git a/custom/4coder_base_commands.cpp b/custom/4coder_base_commands.cpp index 40bb30b4..8c16e6e8 100644 --- a/custom/4coder_base_commands.cpp +++ b/custom/4coder_base_commands.cpp @@ -207,7 +207,7 @@ CUSTOM_DOC("Centers the view vertically on the line on which the cursor sits.") 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } CUSTOM_COMMAND_SIG(left_adjust_view) @@ -219,7 +219,7 @@ CUSTOM_DOC("Sets the left size of the view near the x position of the cursor.") 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } CUSTOM_COMMAND_SIG(click_set_cursor_and_mark) @@ -272,7 +272,7 @@ CUSTOM_DOC("Reads the scroll wheel value from the mouse state and scrolls accord if (mouse.wheel != 0){ 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } } @@ -1581,10 +1581,10 @@ CUSTOM_DOC("Set the other non-active panel to view the buffer that the active pa view_set_cursor_and_preferred_x(app, view1, seek_pos(p2)); view_set_mark(app, view1, seek_pos(m2)); - view_set_buffer_scroll(app, view1, sc2); + view_set_buffer_scroll(app, view1, sc2, SetBufferScroll_SnapCursorIntoView); view_set_cursor_and_preferred_x(app, view2, seek_pos(p1)); view_set_mark(app, view2, seek_pos(m1)); - view_set_buffer_scroll(app, view2, sc1); + view_set_buffer_scroll(app, view2, sc1, SetBufferScroll_SnapCursorIntoView); } } } diff --git a/custom/4coder_base_types.cpp b/custom/4coder_base_types.cpp index ca75b0fb..22c90389 100644 --- a/custom/4coder_base_types.cpp +++ b/custom/4coder_base_types.cpp @@ -2438,6 +2438,46 @@ rect_union(Rect_f32 a, Rect_f32 b){ //////////////////////////////// +internal Rect_f32_Pair +rect_split_top_bottom(Rect_f32 rect, f32 y){ + y = clamp(rect.y0, y, rect.y1); + Rect_f32_Pair pair = {}; + pair.a = Rf32(rect.x0, rect.y0, rect.x1, y ); + pair.b = Rf32(rect.x0, y , rect.x1, rect.y1); + return(pair); +} + +internal Rect_f32_Pair +rect_split_left_right(Rect_f32 rect, f32 x){ + x = clamp(rect.x0, x, rect.x1); + Rect_f32_Pair pair = {}; + pair.a = Rf32(rect.x0, rect.y0, x , rect.y1); + pair.b = Rf32(x , rect.y0, rect.x1, rect.y1); + return(pair); +} + +internal Rect_f32_Pair +rect_split_top_bottom_neg(Rect_f32 rect, f32 y){ + return(rect_split_top_bottom(rect, rect.y1 - y)); +} + +internal Rect_f32_Pair +rect_split_left_right_neg(Rect_f32 rect, f32 x){ + return(rect_split_left_right(rect, rect.x1 - x)); +} + +internal Rect_f32_Pair +rect_split_top_bottom_lerp(Rect_f32 rect, f32 t){ + return(rect_split_top_bottom(rect, lerp(rect.y0, t, rect.y1))); +} + +internal Rect_f32_Pair +rect_split_left_right_lerp(Rect_f32 rect, f32 t){ + return(rect_split_left_right(rect, lerp(rect.x0, t, rect.x1))); +} + +//////////////////////////////// + internal Scan_Direction flip_direction(Scan_Direction direction){ switch (direction){ diff --git a/custom/4coder_base_types.h b/custom/4coder_base_types.h index 98ac7903..bfd44934 100644 --- a/custom/4coder_base_types.h +++ b/custom/4coder_base_types.h @@ -760,8 +760,18 @@ typedef Vec2_f32 Vec2; typedef Vec3_f32 Vec3; typedef Vec4_f32 Vec4; -struct Rect_f32_Pair{ - Rect_f32 e[2]; +union Rect_f32_Pair{ + struct{ + Rect_f32 a; + Rect_f32 b; + }; + struct{ + Rect_f32 min; + Rect_f32 max; + }; + struct{ + Rect_f32 e[2]; + }; }; //////////////////////////////// diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index e518e92d..fb3bbb5f 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -278,21 +278,31 @@ MODIFY_COLOR_TABLE_SIG(default_modify_color_table){ } #endif +function Rect_f32_Pair +layout_file_bar_on_top(Rect_f32 rect, f32 line_height){ + return(rect_split_top_bottom(rect, line_height + 2.f)); +} + +function Rect_f32_Pair +layout_file_bar_on_bot(Rect_f32 rect, f32 line_height){ + return(rect_split_top_bottom_neg(rect, line_height + 2.f)); +} + function Rect_f32 -default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub_region){ +default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){ + region = rect_inner(region, 3.f); + Buffer_ID buffer = view_get_buffer(app, view_id, AccessAll); Face_ID face_id = get_face_id(app, buffer); Face_Metrics metrics = get_face_metrics(app, face_id); - i32 line_height = i32_ceil32(metrics.line_height); + f32 line_height = metrics.line_height; // file bar - { - b64 showing_file_bar = false; - if (view_get_setting(app, view_id, ViewSetting_ShowFileBar, &showing_file_bar)){ - if (showing_file_bar){ - sub_region.y0 += line_height + 2; - } - } + b64 showing_file_bar = false; + if (view_get_setting(app, view_id, ViewSetting_ShowFileBar, &showing_file_bar) && + showing_file_bar){ + Rect_f32_Pair pair = layout_file_bar_on_top(region, line_height); + region = pair.b; } // query bar @@ -301,8 +311,8 @@ default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub Query_Bar_Ptr_Array query_bars = {}; query_bars.ptrs = space; if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){ - i32 widget_height = (line_height + 2)*query_bars.count; - sub_region.y0 += widget_height; + f32 widget_height = (line_height + 2)*query_bars.count; + region.y0 += widget_height; } } @@ -311,10 +321,10 @@ default_view_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 sub i64 line_count = buffer_get_line_count(app, buffer); i64 line_count_digit_count = digit_count_from_integer(line_count, 10); i32 margin_width = i32_ceil32((f32)line_count_digit_count*metrics.normal_advance); - sub_region.x0 += margin_width + 2; + region.x0 += margin_width + 2; } - return(sub_region); + return(region); } internal int_color @@ -447,10 +457,36 @@ default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID vie draw_fancy_string(app, face_id, list.first, p, Stag_Default, 0); } - Rect_f32 sub_region = default_view_buffer_region(app, view_id, inner); - Rect_f32 buffer_rect = rect_intersect(sub_region, inner); - + Rect_f32 buffer_rect = default_buffer_region(app, view_id, view_rect); Buffer_Scroll scroll = view_get_buffer_scroll(app, view_id); + + Buffer_Point_Delta_Result delta = delta_apply(app, view_id, + frame_info.animation_dt, scroll); + if (!block_match_struct(&scroll.position, &delta.point)){ + block_copy_struct(&scroll.position, &delta.point); + view_set_buffer_scroll(app, view_id, scroll, SetBufferScroll_NoCursorChange); + } + if (delta.still_animating){ + animate_in_n_milliseconds(app, 0); + } + +#if 0 + // NOTE(allen): clamp scroll target and position; smooth scroll rule + { + Vec2_f32 pending = view_point_difference(app, view_id, scroll.target, scroll.position); + if (!near_zero(pending, 0.5f)){ + // TODO(allen): use the real delta rule from the context + Vec2_f32 partial = pending; + scroll.position = view_move_buffer_point(app, view_id, scroll.position, partial); + animate_in_n_milliseconds(app, 0); + } + else{ + scroll.position = scroll.target; + } + view_set_buffer_scroll(app, view_id, scroll, SetBufferScroll_NoCursorChange); + } +#endif + 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); @@ -762,8 +798,8 @@ default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID vie } HOOK_SIG(default_view_adjust){ - // NOTE(allen): Called whenever the view layout/sizes have been modified, including - // by full window resize. + // NOTE(allen): Called whenever the view layout/sizes have been modified, + // including by full window resize. return(0); } @@ -1120,85 +1156,6 @@ BUFFER_HOOK_SIG(default_end_file){ return(0); } -// TODO(allen): FIX FIX FIX FIX -// NOTE(allen|a4): scroll rule information -// -// The parameters: -// target_x, target_y -// This is where the view would like to be for the purpose of -// following the cursor, doing mouse wheel work, etc. -// -// scroll_x, scroll_y -// These are pointers to where the scrolling actually is. If you bind -// the scroll rule it is you have to update these in some way to move -// the actual location of the scrolling. -// -// view_id -// This corresponds to which view is computing it's new scrolling position. -// This id DOES correspond to the views that View_ _Summary contains. -// This will always be between 1 and 16 (0 is a null id). -// See below for an example of having state that carries across scroll udpates. -// -// is_new_target -// If the target of the view is different from the last target in either x or y -// this is true, otherwise it is false. -// -// The return: -// Should be true if and only if scroll_x or scroll_y are changed. -// -// Don't try to use the app pointer in a scroll rule, you're asking for trouble. -// -// If you don't bind scroll_rule, nothing bad will happen, yo will get default -// 4coder scrolling behavior. -// - -Vec2_f32 scroll_velocity_[16] = {}; -Vec2_f32 *scroll_velocity = scroll_velocity_ - 1; - -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 = 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; - } - } - } - return(step); -} - -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; - } - 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)); -} - internal void set_all_default_hooks(Application_Links *app){ #if 0 @@ -1213,7 +1170,15 @@ set_all_default_hooks(Application_Links *app){ set_custom_hook(app, HookID_ViewEventHandler, default_view_input_handler); set_custom_hook(app, HookID_RenderCaller, default_render_caller); - set_custom_hook(app, HookID_ScrollRule, smooth_scroll_rule); +#if 0 + set_custom_hook(app, HookID_DeltaRule, original_delta); + set_custom_hook_memory_size(app, HookID_DeltaRule, + delta_ctx_size(original_delta_memory_size)); +#else + set_custom_hook(app, HookID_DeltaRule, fixed_time_cubic_delta); + set_custom_hook_memory_size(app, HookID_DeltaRule, + delta_ctx_size(fixed_time_cubic_delta_memory_size)); +#endif set_custom_hook(app, HookID_BufferNameResolver, default_buffer_name_resolution); set_custom_hook(app, HookID_BeginBuffer, default_file_settings); @@ -1221,7 +1186,7 @@ set_all_default_hooks(Application_Links *app){ set_custom_hook(app, HookID_NewFile, default_new_file); set_custom_hook(app, HookID_SaveFile, default_file_save); set_custom_hook(app, HookID_BufferEditRange, default_buffer_edit_range); - set_custom_hook(app, HookID_BufferRegion, default_view_buffer_region); + set_custom_hook(app, HookID_BufferRegion, default_buffer_region); } // BOTTOM diff --git a/custom/4coder_default_include.cpp b/custom/4coder_default_include.cpp index 13359933..365973b3 100644 --- a/custom/4coder_default_include.cpp +++ b/custom/4coder_default_include.cpp @@ -29,6 +29,7 @@ #include "4coder_command_map.h" #include "4coder_string_match.h" #include "4coder_helper.h" +#include "4coder_delta_rule.h" #include "4coder_insertion.h" #include "4coder_fancy.h" #include "4coder_lister_base.h" @@ -66,6 +67,7 @@ #include "4coder_command_map.cpp" #include "4coder_default_framework_variables.cpp" #include "4coder_helper.cpp" +#include "4coder_delta_rule.cpp" #include "4coder_fancy.cpp" #include "4coder_lister_base.cpp" #include "4coder_font_helper.cpp" diff --git a/custom/4coder_delta_rule.cpp b/custom/4coder_delta_rule.cpp new file mode 100644 index 00000000..ce7bf7ef --- /dev/null +++ b/custom/4coder_delta_rule.cpp @@ -0,0 +1,218 @@ +/* +4coder_delta_rule.cpp - Built in delta rules and delta rule helpers. +*/ + +// TOP + +function umem +delta_ctx_size(umem base_size){ + return(base_size + sizeof(Delta_Context_Header)); +} + +function Delta_Context_Header* +delta_ctx_get_header(Data delta_ctx){ + return((Delta_Context_Header*)delta_ctx.data); +} + +function void* +delta_ctx_get_user_data(Data delta_ctx){ + Delta_Context_Header *ctx = (Delta_Context_Header*)delta_ctx.data; + return(ctx + 1); +} + +function Buffer_Point_Delta_Result +delta_apply(Application_Links *app, View_ID view, + Delta_Rule_Function *func, Data delta_ctx, + f32 dt, Buffer_Point position, Buffer_Point target){ + Buffer_Point_Delta_Result result = {}; + Vec2_f32 pending = view_point_difference(app, view, target, position); + if (!near_zero(pending, 0.5f)){ + Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx); + b32 is_new_target = false; + if (!block_match_struct(&ctx->point, &target)){ + block_copy_struct(&ctx->point, &target); + is_new_target = true; + } + void *rule_data = delta_ctx_get_user_data(delta_ctx); + Vec2_f32 partial = func(pending, is_new_target, dt, rule_data); + + // NOTE(allen): clamp partial into the box from the origin + // to the pending delta. + Range_f32 x = If32(pending.x, 0.f); + Range_f32 y = If32(pending.y, 0.f); + partial.x = clamp_range(x, partial.x); + partial.y = clamp_range(y, partial.y); + + result.point = view_move_buffer_point(app, view, position, partial); + result.still_animating = true; + } + else{ + result.point = target; + } + return(result); +} + +function Buffer_Point_Delta_Result +delta_apply(Application_Links *app, View_ID view, + Delta_Rule_Function *func, Data delta_ctx, + f32 dt, Buffer_Scroll scroll){ + return(delta_apply(app, view, func, delta_ctx, + dt, scroll.position, scroll.target)); +} + +function Buffer_Point_Delta_Result +delta_apply(Application_Links *app, View_ID view, + f32 dt, Buffer_Point position, Buffer_Point target){ + View_Context ctx = view_current_context(app, view); + Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); + return(delta_apply(app, view, ctx.delta_rule, delta_ctx, + dt, position, target)); +} + +function Buffer_Point_Delta_Result +delta_apply(Application_Links *app, View_ID view, + f32 dt, Buffer_Scroll scroll){ + View_Context ctx = view_current_context(app, view); + Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); + return(delta_apply(app, view, ctx.delta_rule, delta_ctx, + dt, scroll.position, scroll.target)); +} + +function Vec2_f32_Delta_Result +delta_apply(Application_Links *app, View_ID view, + Delta_Rule_Function *func, Data delta_ctx, + f32 dt, Vec2_f32 position, Vec2_f32 target){ + Vec2_f32_Delta_Result result = {}; + Vec2_f32 pending = target - position; + if (!near_zero(pending, 0.5f)){ + Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx); + b32 is_new_target = false; + if (!near_zero(ctx->p - target, 0.1f)){ + block_copy_struct(&ctx->p, &target); + is_new_target = true; + } + void *rule_data = delta_ctx_get_user_data(delta_ctx); + Vec2_f32 partial = func(pending, is_new_target, dt, rule_data); + + // NOTE(allen): clamp partial into the box from the origin + // to the pending delta. + Range_f32 x = If32(pending.x, 0.f); + Range_f32 y = If32(pending.y, 0.f); + partial.x = clamp_range(x, partial.x); + partial.y = clamp_range(y, partial.y); + + result.p = position + partial; + result.still_animating = true; + } + else{ + result.p = target; + } + return(result); +} + +function Vec2_f32_Delta_Result +delta_apply(Application_Links *app, View_ID view, + Delta_Rule_Function *func, Data delta_ctx, + f32 dt, Basic_Scroll scroll){ + return(delta_apply(app, view, func, delta_ctx, + dt, scroll.position, scroll.target)); +} + +function Vec2_f32_Delta_Result +delta_apply(Application_Links *app, View_ID view, + f32 dt, Vec2_f32 position, Vec2_f32 target){ + View_Context ctx = view_current_context(app, view); + Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); + return(delta_apply(app, view, ctx.delta_rule, delta_ctx, + dt, position, target)); +} + +function Vec2_f32_Delta_Result +delta_apply(Application_Links *app, View_ID view, + f32 dt, Basic_Scroll scroll){ + View_Context ctx = view_current_context(app, view); + Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); + return(delta_apply(app, view, ctx.delta_rule, delta_ctx, + dt, scroll.position, scroll.target)); +} + +//////////////////////////////// + +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 = 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; + } + } + } + return(step); +} +DELTA_RULE_SIG(original_delta){ + Vec2_f32 *velocity = (Vec2_f32*)data; + if (velocity->x == 0.f){ + velocity->x = 1.f; + velocity->y = 1.f; + } + Smooth_Step step_x = smooth_camera_step(pending.x, velocity->x, 80.f, 1.f/2.f); + Smooth_Step step_y = smooth_camera_step(pending.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)); +} +global_const umem original_delta_memory_size = sizeof(Vec2_f32); + +DELTA_RULE_SIG(snap_delta){ + return(pending); +} +global_const umem snap_delta_memory_size = 0; + +function f32 +cubic_reinterpolate(f32 t){ + f32 t2 = t*t; + f32 t3 = t2*t; + return(3*t2 - 2*t3); +} +DELTA_RULE_SIG(fixed_time_cubic_delta){ + local_const f32 duration_in_seconds = (1.f/8.f); + local_const f32 dt_multiplier = 1.f/duration_in_seconds; + f32 step = dt*dt_multiplier; + f32 *t = (f32*)data; + *t = clamp(0.f, *t, 1.f); + f32 prev_t = *t; + if (is_new_target){ + prev_t = 0.f; + *t = step; + } + else{ + *t += step; + } + *t = clamp(0.f, *t, 1.f); + Vec2_f32 result = pending; + if (*t < 1.f){ + f32 prev_x = cubic_reinterpolate(prev_t); + f32 x = cubic_reinterpolate(*t); + f32 portion = ((x - prev_x)/(1.f - prev_x)); + result *= portion; + } + return(result); +} +global_const umem fixed_time_cubic_delta_memory_size = sizeof(f32); + +// BOTTOM + diff --git a/custom/4coder_delta_rule.h b/custom/4coder_delta_rule.h new file mode 100644 index 00000000..51d3c5f8 --- /dev/null +++ b/custom/4coder_delta_rule.h @@ -0,0 +1,31 @@ +/* +4coder_delta_rule.h - Types for built in delta rules and delta rule helpers. +*/ + +// TOP + +#if !defined(FCODER_DELTA_RULE_H) +#define FCODER_DELTA_RULE_H + +union Delta_Context_Header{ + Buffer_Point point; + Vec2_f32 p; +}; +struct Buffer_Point_Delta_Result{ + Buffer_Point point; + b32 still_animating; +}; +struct Vec2_f32_Delta_Result{ + Vec2_f32 p; + b32 still_animating; +}; + +struct Smooth_Step{ + f32 p; + f32 v; +}; + +#endif + +// BOTTOM + diff --git a/custom/4coder_helper.cpp b/custom/4coder_helper.cpp index 998c7f1f..96163ce4 100644 --- a/custom/4coder_helper.cpp +++ b/custom/4coder_helper.cpp @@ -167,7 +167,7 @@ view_move_buffer_point(Application_Links *app, View_ID view, Buffer_Point buffer internal void view_zero_scroll(Application_Links *app, View_ID view){ Buffer_Scroll scroll = {}; - view_set_buffer_scroll(app, view, scroll); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } internal void @@ -178,6 +178,23 @@ view_set_cursor_and_preferred_x(Application_Links *app, View_ID view, Buffer_See view_set_preferred_x(app, view, p.x); } +function Vec2_f32 +buffer_point_difference(Application_Links *app, Buffer_ID buffer, f32 width, Face_ID face_id, + Buffer_Point a, Buffer_Point b){ + f32 y_difference = buffer_line_y_difference(app, buffer, width, face_id, a.line_number, b.line_number); + Vec2_f32 result = a.pixel_shift - b.pixel_shift; + result.y += y_difference; + return(result); +} + +function Vec2_f32 +view_point_difference(Application_Links *app, View_ID view, Buffer_Point a, Buffer_Point b){ + f32 y_difference = view_line_y_difference(app, view, a.line_number, b.line_number); + Vec2_f32 result = a.pixel_shift - b.pixel_shift; + result.y += y_difference; + return(result); +} + //////////////////////////////// internal Range_i64 @@ -1625,7 +1642,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } else{ Buffer_Scroll scroll = view_get_buffer_scroll(app, view); @@ -1634,7 +1651,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } else{ Vec2_f32 bot_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.max); @@ -1642,7 +1659,7 @@ view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 min 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); + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); } } } diff --git a/custom/4coder_lister_base.cpp b/custom/4coder_lister_base.cpp index fc8143b3..a79fdf9c 100644 --- a/custom/4coder_lister_base.cpp +++ b/custom/4coder_lister_base.cpp @@ -139,6 +139,11 @@ lister_append_key(Lister *lister, char *string){ lister_append_string(SCu8(string), &lister->key_string); } +function void +lister_zero_scroll(Lister *lister){ + block_zero_struct(&lister->scroll); +} + function void lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Scratch_Block scratch(app); @@ -171,6 +176,9 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ f32 block_height = lister_get_block_height(line_height); f32 text_field_height = lister_get_text_field_height(line_height); + lister->visible_count = (i32)((rect_height(region)/block_height)) - 3; + lister->visible_count = clamp_bot(1, lister->visible_count); + Lister_Top_Level_Layout layout = lister_get_top_level_layout(region, text_field_height); { @@ -188,19 +196,48 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Range_f32 x = rect_range_x(layout.list_rect); draw_set_clip(app, layout.list_rect); + // NOTE(allen): auto scroll to the item if the flag is set. + f32 scroll_y = lister->scroll.position.y; + + if (lister->set_vertical_focus_to_item){ + lister->set_vertical_focus_to_item = false; + Range_f32 item_y = If32_size(lister->item_index*block_height, block_height); + f32 view_h = rect_height(layout.list_rect); + Range_f32 view_y = If32_size(scroll_y, view_h); + if (view_y.min > item_y.min || item_y.max > view_y.max){ + f32 item_center = (item_y.min + item_y.max)*0.5f; + f32 view_center = (view_y.min + view_y.max)*0.5f; + f32 margin = view_h*.3f; + margin = clamp_top(margin, block_height*3.f); + if (item_center < view_center){ + lister->scroll.target.y = item_y.min - margin; + } + else{ + f32 target_bot = item_y.max + margin; + lister->scroll.target.y = target_bot - view_h; + } + } + } + + // NOTE(allen): clamp scroll target and position; smooth scroll rule i32 count = lister->filtered.count; Range_f32 scroll_range = If32(0.f, clamp_bot(0.f, count*block_height - block_height)); - lister->scroll.position.y = clamp_range(scroll_range, lister->scroll.position.y); - lister->scroll.position.x = 0.f; lister->scroll.target.y = clamp_range(scroll_range, lister->scroll.target.y); lister->scroll.target.x = 0.f; - // TODO(allen): get scroll rule from context - lister->scroll.position = lister->scroll.target; + Vec2_f32_Delta_Result delta = delta_apply(app, view, + frame_info.animation_dt, lister->scroll); + lister->scroll.position = delta.p; + if (delta.still_animating){ + animate_in_n_milliseconds(app, 0); + } - f32 scroll_y = lister->scroll.position.y; + lister->scroll.position.y = clamp_range(scroll_range, lister->scroll.position.y); + lister->scroll.position.x = 0.f; + scroll_y = lister->scroll.position.y; f32 y_pos = layout.list_rect.y0 - scroll_y; + i32 first_index = (i32)(scroll_y/block_height); y_pos += first_index*block_height; @@ -308,6 +345,20 @@ lister_get_filtered(Arena *arena, Lister *lister){ return(filtered); } +function void +lister_update_selection_values(Lister *lister){ + lister->raw_item_index = -1; + lister->highlighted_node = 0; + i32 count = lister->filtered.count; + for (i32 i = 0; i < count; i += 1){ + Lister_Node *node = lister->filtered.node_ptrs[i]; + if (lister->item_index == i){ + lister->highlighted_node = node; + lister->raw_item_index = node->raw_index; + } + } +} + function void lister_update_filtered_list(Application_Links *app, View_ID view, Lister *lister){ Scratch_Block scratch(app, Scratch_Share); @@ -332,23 +383,17 @@ lister_update_filtered_list(Application_Links *app, View_ID view, Lister *lister Lister_Node **node_ptrs = push_array(arena, Lister_Node*, total_count); lister->filtered.node_ptrs = node_ptrs; lister->filtered.count = total_count; - - lister->raw_item_index = -1; - lister->highlighted_node = 0; - i32 counter = 0; for (i32 array_index = 0; array_index < ArrayCount(node_ptr_arrays); array_index += 1){ Lister_Node_Ptr_Array node_ptr_array = node_ptr_arrays[array_index]; for (i32 node_index = 0; node_index < node_ptr_array.count; node_index += 1){ Lister_Node *node = node_ptr_array.node_ptrs[node_index]; node_ptrs[counter] = node; - if (lister->item_index == counter){ - lister->highlighted_node = node; - lister->raw_item_index = node->raw_index; - } counter += 1; } } + + lister_update_selection_values(lister); } function void @@ -474,8 +519,8 @@ lister_run(Application_Links *app, View_ID view, Lister *lister){ case KeyCode_Up: { - if (lister->handlers.navigate_up != 0){ - lister->handlers.navigate_up(app); + if (lister->handlers.navigate != 0){ + lister->handlers.navigate(app, view, lister, -1); } else{ handled = false; @@ -484,8 +529,30 @@ lister_run(Application_Links *app, View_ID view, Lister *lister){ case KeyCode_Down: { - if (lister->handlers.navigate_down != 0){ - lister->handlers.navigate_down(app); + if (lister->handlers.navigate != 0){ + lister->handlers.navigate(app, view, lister, 1); + } + else{ + handled = false; + } + }break; + + case KeyCode_PageUp: + { + if (lister->handlers.navigate != 0){ + lister->handlers.navigate(app, view, lister, + -lister->visible_count); + } + else{ + handled = false; + } + }break; + + case KeyCode_PageDown: + { + if (lister->handlers.navigate != 0){ + lister->handlers.navigate(app, view, lister, + lister->visible_count); } else{ handled = false; @@ -645,5 +712,53 @@ lister_add_item(Lister *lister, String_Const_u8 string, String_Const_u8 status, user_data, extra_space)); } +function void +lister__write_string__default(Application_Links *app){ + View_ID view = get_active_view(app, AccessAll); + Lister *lister = view_get_lister(view); + if (lister != 0){ + User_Input in = get_current_input(app); + String_Const_u8 string = to_writable(&in); + if (string.str != 0 && string.size > 0){ + lister_append_text_field(lister, string); + lister_append_key(lister, string); + lister->item_index = 0; + lister_zero_scroll(lister); + lister_update_filtered_list(app, view, lister); + } + } +} + +function void +lister__backspace_text_field__default(Application_Links *app){ + View_ID view = get_active_view(app, AccessAll); + Lister *lister = view_get_lister(view); + if (lister != 0){ + lister->text_field.string = backspace_utf8(lister->text_field.string); + lister->key_string.string = backspace_utf8(lister->key_string.string); + lister->item_index = 0; + lister_zero_scroll(lister); + lister_update_filtered_list(app, view, lister); + } +} + +function void +lister__navigate__default(Application_Links *app, View_ID view, Lister *lister, + i32 delta){ + i32 new_index = lister->item_index + delta; + if (new_index < 0 && lister->item_index == 0){ + lister->item_index = lister->filtered.count - 1; + } + else if (new_index >= lister->filtered.count && + lister->item_index == lister->filtered.count - 1){ + lister->item_index = 0; + } + else{ + lister->item_index = clamp(0, new_index, lister->filtered.count - 1); + } + lister->set_vertical_focus_to_item = true; + lister_update_selection_values(lister); +} + // BOTTOM diff --git a/custom/4coder_lister_base.h b/custom/4coder_lister_base.h index 7e7524dc..3ead6dab 100644 --- a/custom/4coder_lister_base.h +++ b/custom/4coder_lister_base.h @@ -44,14 +44,16 @@ struct Lister_Node_Ptr_Array{ }; typedef Lister_Activation_Code Lister_Key_Stroke_Function(Application_Links *app); +typedef void Lister_Navigate_Function(Application_Links *app, + View_ID view, struct Lister *lister, + i32 index_delta); struct Lister_Handlers{ Lister_Activation_Type *activate; Lister_Regenerate_List_Function_Type *refresh; Custom_Command_Function *write_character; Custom_Command_Function *backspace; - Custom_Command_Function *navigate_up; - Custom_Command_Function *navigate_down; + Lister_Navigate_Function *navigate; Lister_Key_Stroke_Function *key_stroke; }; @@ -78,13 +80,14 @@ struct Lister{ Temp_Memory filter_restore_point; Lister_Node_Ptr_Array filtered; - b32 set_view_vertical_focus_to_item; + b32 set_vertical_focus_to_item; Lister_Node *highlighted_node; void *hot_user_data; i32 item_index; i32 raw_item_index; Basic_Scroll scroll; + i32 visible_count; }; struct Lister_Prealloced_String{ diff --git a/custom/4coder_lists.cpp b/custom/4coder_lists.cpp index 9349598c..ff7c97b0 100644 --- a/custom/4coder_lists.cpp +++ b/custom/4coder_lists.cpp @@ -5,64 +5,6 @@ such as open file, switch buffer, or kill buffer. // TOP -function void -lister__write_string__default(Application_Links *app){ - View_ID view = get_active_view(app, AccessAll); - Lister *lister = view_get_lister(view); - if (lister != 0){ - User_Input in = get_current_input(app); - String_Const_u8 string = to_writable(&in); - if (string.str != 0 && string.size > 0){ - lister_append_text_field(lister, string); - lister_append_key(lister, string); - lister->item_index = 0; - view_zero_scroll(app, view); - lister_update_filtered_list(app, view, lister); - } - } -} - -function void -lister__backspace_text_field__default(Application_Links *app){ - View_ID view = get_active_view(app, AccessAll); - Lister *lister = view_get_lister(view); - if (lister != 0){ - lister->text_field.string = backspace_utf8(lister->text_field.string); - lister->key_string.string = backspace_utf8(lister->key_string.string); - lister->item_index = 0; - view_zero_scroll(app, view); - lister_update_filtered_list(app, view, lister); - } -} - -function void -lister__move_up__default(Application_Links *app){ - View_ID view = get_active_view(app, AccessAll); - Lister *lister = view_get_lister(view); - if (lister != 0){ - lister->item_index = lister->item_index - 1; - if (lister->item_index < 0){ - lister->item_index = lister->filtered.count - 1; - } - lister->set_view_vertical_focus_to_item = true; - lister_update_filtered_list(app, view, lister); - } -} - -function void -lister__move_down__default(Application_Links *app){ - View_ID view = get_active_view(app, AccessAll); - Lister *lister = view_get_lister(view); - if (lister != 0){ - lister->item_index = lister->item_index + 1; - if (lister->item_index > lister->filtered.count - 1){ - lister->item_index = 0; - } - lister->set_view_vertical_focus_to_item = true; - lister_update_filtered_list(app, view, lister); - } -} - function void lister__write_character__file_path(Application_Links *app){ View_ID view = get_active_view(app, AccessAll); @@ -80,7 +22,7 @@ lister__write_character__file_path(Application_Links *app){ lister_call_refresh_handler(app, view, lister); } lister->item_index = 0; - view_zero_scroll(app, view); + lister_zero_scroll(lister); lister_update_filtered_list(app, view, lister); } } @@ -117,7 +59,7 @@ lister__backspace_text_field__file_path(Application_Links *app){ } lister->item_index = 0; - view_zero_scroll(app, view); + lister_zero_scroll(lister); lister_update_filtered_list(app, view, lister); } } @@ -158,16 +100,14 @@ lister_get_default_handlers(void){ Lister_Handlers handlers = {}; handlers.write_character = lister__write_string__default; handlers.backspace = lister__backspace_text_field__default; - handlers.navigate_up = lister__move_up__default; - handlers.navigate_down = lister__move_down__default; + handlers.navigate = lister__navigate__default; return(handlers); } function Lister_Handlers lister_get_fixed_list_handlers(void){ Lister_Handlers handlers = {}; - handlers.navigate_up = lister__move_up__default; - handlers.navigate_down = lister__move_down__default; + handlers.navigate = lister__navigate__default; handlers.key_stroke = lister__key_stroke__fixed_list; return(handlers); } @@ -197,8 +137,6 @@ run_lister_with_refresh_handler(Application_Links *app, char *query_string, } } -global_const i32 default_string_size_estimation = 0; - function i32 lister__get_arena_size_(i32 option_count, i32 user_data_size, i32 estimated_string_space_size){ @@ -230,7 +168,6 @@ run_lister_with_fixed_options(Application_Links *app, char *query_string, Lister_Handlers handlers, void *user_data, i32 user_data_size, Lister_Fixed_Option *options, i32 option_count, - i32 estimated_string_space_size, View_ID view){ Scratch_Block scratch(app); Lister *lister = begin_lister(app, scratch, view, user_data, user_data_size); @@ -252,14 +189,12 @@ run_lister_with_fixed_options(Application_Links *app, char *query_string, Lister_Activation_Type *activate, void *user_data, i32 user_data_size, Lister_Fixed_Option *options, i32 option_count, - i32 estimated_string_space_size, View_ID view){ Lister_Handlers handlers = lister_get_fixed_list_handlers(); handlers.activate = activate; run_lister_with_fixed_options(app, query_string, handlers, user_data, user_data_size, options, option_count, - estimated_string_space_size, view); } @@ -486,7 +421,7 @@ do_gui_sure_to_kill(Application_Links *app, Buffer_ID buffer, View_ID view){ data.id = buffer; run_lister_with_fixed_options(app, "There are unsaved changes, close anyway?", activate_confirm_kill, &data, sizeof(data), - options, option_count, default_string_size_estimation, + options, option_count, view); return(data.do_kill); } @@ -530,7 +465,7 @@ do_gui_sure_to_close_4coder(Application_Links *app, View_ID view){ run_lister_with_fixed_options(app, "There are one or more buffers with unsave changes, close anyway?", activate_confirm_close_4coder, &do_exit, sizeof(do_exit), - options, option_count, default_string_size_estimation, + options, option_count, view); return(do_exit); } diff --git a/custom/4coder_types.h b/custom/4coder_types.h index 663ce09c..c3bb2145 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -253,6 +253,12 @@ STRUCT Buffer_Identifier{ Buffer_ID id; }; +typedef i32 Set_Buffer_Scroll_Rule; +enum{ + SetBufferScroll_NoCursorChange, + SetBufferScroll_SnapCursorIntoView, +}; + struct Buffer_Scroll{ Buffer_Point position; Buffer_Point target; @@ -476,8 +482,8 @@ STRUCT User_Input{ typedef i32 Hook_ID; enum{ HookID_RenderCaller, + HookID_DeltaRule, HookID_BufferViewerUpdate, - HookID_ScrollRule, HookID_ViewEventHandler, HookID_BufferNameResolver, HookID_BeginBuffer, @@ -512,9 +518,9 @@ typedef i32 Buffer_Edit_Range_Function(Application_Links *app, Buffer_ID buffer_ #define BUFFER_EDIT_RANGE_SIG(name) i32 name(Application_Links *app, Buffer_ID buffer_id,\ Interval_i64 range, String_Const_u8 text) -typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt); +typedef Vec2_f32 Delta_Rule_Function(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data); #define DELTA_RULE_SIG(name) \ -Vec2_f32 name(Vec2_f32 pending_delta, View_ID view_id, b32 is_new_target, f32 dt) +Vec2_f32 name(Vec2_f32 pending, b32 is_new_target, f32 dt, void *data) typedef Rect_f32 Buffer_Region_Function(Application_Links *app, View_ID view_id, Rect_f32 region); @@ -532,6 +538,8 @@ typedef void Render_Caller_Function(Application_Links *app, Frame_Info frame_inf struct View_Context{ Render_Caller_Function *render_caller; + Delta_Rule_Function *delta_rule; + umem delta_rule_memory_size; b32 hides_buffer; }; diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index bb235c3b..73b3a39d 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -227,12 +227,12 @@ i32 line_number; }; static Command_Metadata fcoder_metacmd_table[205] = { { PROC_LINKS(default_view_input_handler, 0), "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 }, -{ 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\\custom\\4coder_helper.cpp", 36, 1979 }, -{ 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\\custom\\4coder_helper.cpp", 36, 1985 }, -{ 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\\custom\\4coder_helper.cpp", 36, 1991 }, -{ 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\\custom\\4coder_helper.cpp", 36, 1997 }, -{ 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\\custom\\4coder_helper.cpp", 36, 2003 }, -{ 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\\custom\\4coder_helper.cpp", 36, 2011 }, +{ 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\\custom\\4coder_helper.cpp", 36, 1996 }, +{ 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\\custom\\4coder_helper.cpp", 36, 2002 }, +{ 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\\custom\\4coder_helper.cpp", 36, 2008 }, +{ 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\\custom\\4coder_helper.cpp", 36, 2014 }, +{ 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\\custom\\4coder_helper.cpp", 36, 2020 }, +{ 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\\custom\\4coder_helper.cpp", 36, 2028 }, { 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\\custom\\4coder_default_framework.cpp", 47, 196 }, { 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\\custom\\4coder_default_framework.cpp", 47, 206 }, { PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 216 }, @@ -344,12 +344,12 @@ static Command_Metadata fcoder_metacmd_table[205] = { { 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\\custom\\4coder_base_commands.cpp", 43, 1939 }, { PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2040 }, { PROC_LINKS(default_file_externally_modified, 0), "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2047 }, -{ PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 552 }, -{ PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 571 }, -{ PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 642 }, -{ PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 681 }, -{ PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 714 }, -{ PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 774 }, +{ PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 487 }, +{ PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 506 }, +{ PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 577 }, +{ PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 616 }, +{ PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 649 }, +{ PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 709 }, { PROC_LINKS(auto_indent_whole_file, 0), "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 356 }, { PROC_LINKS(auto_indent_line_at_cursor, 0), "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 365 }, { PROC_LINKS(auto_indent_range, 0), "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 }, diff --git a/custom/generated/custom_api.cpp b/custom/generated/custom_api.cpp index 14d90ba4..353d1f6d 100644 --- a/custom/generated/custom_api.cpp +++ b/custom/generated/custom_api.cpp @@ -91,6 +91,7 @@ vtable->view_post_fade = view_post_fade; vtable->view_push_context = view_push_context; vtable->view_pop_context = view_pop_context; vtable->view_current_context = view_current_context; +vtable->view_current_context_hook_memory = view_current_context_hook_memory; vtable->create_user_managed_scope = create_user_managed_scope; vtable->destroy_user_managed_scope = destroy_user_managed_scope; vtable->get_global_managed_scope = get_global_managed_scope; @@ -117,6 +118,7 @@ vtable->get_current_input = get_current_input; vtable->set_current_input = set_current_input; vtable->leave_current_input_unhandled = leave_current_input_unhandled; vtable->set_custom_hook = set_custom_hook; +vtable->set_custom_hook_memory_size = set_custom_hook_memory_size; vtable->get_mouse_state = get_mouse_state; vtable->get_active_query_bars = get_active_query_bars; vtable->start_query_bar = start_query_bar; @@ -263,6 +265,7 @@ view_post_fade = vtable->view_post_fade; view_push_context = vtable->view_push_context; view_pop_context = vtable->view_pop_context; view_current_context = vtable->view_current_context; +view_current_context_hook_memory = vtable->view_current_context_hook_memory; create_user_managed_scope = vtable->create_user_managed_scope; destroy_user_managed_scope = vtable->destroy_user_managed_scope; get_global_managed_scope = vtable->get_global_managed_scope; @@ -289,6 +292,7 @@ get_current_input = vtable->get_current_input; set_current_input = vtable->set_current_input; leave_current_input_unhandled = vtable->leave_current_input_unhandled; set_custom_hook = vtable->set_custom_hook; +set_custom_hook_memory_size = vtable->set_custom_hook_memory_size; get_mouse_state = vtable->get_mouse_state; get_active_query_bars = vtable->get_active_query_bars; start_query_bar = vtable->start_query_bar; diff --git a/custom/generated/custom_api.h b/custom/generated/custom_api.h index 5ce998cc..f5b35b46 100644 --- a/custom/generated/custom_api.h +++ b/custom/generated/custom_api.h @@ -82,13 +82,14 @@ #define custom_buffer_compute_cursor_sig() Buffer_Cursor custom_buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek) #define custom_view_compute_cursor_sig() Buffer_Cursor custom_view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek) #define custom_view_set_cursor_sig() b32 custom_view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek) -#define custom_view_set_buffer_scroll_sig() b32 custom_view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll) +#define custom_view_set_buffer_scroll_sig() b32 custom_view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule) #define custom_view_set_mark_sig() b32 custom_view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek) #define custom_view_set_buffer_sig() b32 custom_view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags) #define custom_view_post_fade_sig() b32 custom_view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color) #define custom_view_push_context_sig() b32 custom_view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx) #define custom_view_pop_context_sig() b32 custom_view_pop_context(Application_Links* app, View_ID view_id) #define custom_view_current_context_sig() View_Context custom_view_current_context(Application_Links* app, View_ID view_id) +#define custom_view_current_context_hook_memory_sig() Data custom_view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id) #define custom_create_user_managed_scope_sig() Managed_Scope custom_create_user_managed_scope(Application_Links* app) #define custom_destroy_user_managed_scope_sig() b32 custom_destroy_user_managed_scope(Application_Links* app, Managed_Scope scope) #define custom_get_global_managed_scope_sig() Managed_Scope custom_get_global_managed_scope(Application_Links* app) @@ -115,6 +116,7 @@ #define custom_set_current_input_sig() void custom_set_current_input(Application_Links* app, User_Input* input) #define custom_leave_current_input_unhandled_sig() void custom_leave_current_input_unhandled(Application_Links* app) #define custom_set_custom_hook_sig() void custom_set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr) +#define custom_set_custom_hook_memory_size_sig() b32 custom_set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size) #define custom_get_mouse_state_sig() Mouse_State custom_get_mouse_state(Application_Links* app) #define custom_get_active_query_bars_sig() b32 custom_get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out) #define custom_start_query_bar_sig() b32 custom_start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags) @@ -250,13 +252,14 @@ typedef Managed_Scope custom_view_get_managed_scope_type(Application_Links* app, typedef Buffer_Cursor custom_buffer_compute_cursor_type(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek); typedef Buffer_Cursor custom_view_compute_cursor_type(Application_Links* app, View_ID view_id, Buffer_Seek seek); typedef b32 custom_view_set_cursor_type(Application_Links* app, View_ID view_id, Buffer_Seek seek); -typedef b32 custom_view_set_buffer_scroll_type(Application_Links* app, View_ID view_id, Buffer_Scroll scroll); +typedef b32 custom_view_set_buffer_scroll_type(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule); typedef b32 custom_view_set_mark_type(Application_Links* app, View_ID view_id, Buffer_Seek seek); typedef b32 custom_view_set_buffer_type(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags); typedef b32 custom_view_post_fade_type(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color); typedef b32 custom_view_push_context_type(Application_Links* app, View_ID view_id, View_Context* ctx); typedef b32 custom_view_pop_context_type(Application_Links* app, View_ID view_id); typedef View_Context custom_view_current_context_type(Application_Links* app, View_ID view_id); +typedef Data custom_view_current_context_hook_memory_type(Application_Links* app, View_ID view_id, Hook_ID hook_id); typedef Managed_Scope custom_create_user_managed_scope_type(Application_Links* app); typedef b32 custom_destroy_user_managed_scope_type(Application_Links* app, Managed_Scope scope); typedef Managed_Scope custom_get_global_managed_scope_type(Application_Links* app); @@ -283,6 +286,7 @@ typedef User_Input custom_get_current_input_type(Application_Links* app); typedef void custom_set_current_input_type(Application_Links* app, User_Input* input); typedef void custom_leave_current_input_unhandled_type(Application_Links* app); typedef void custom_set_custom_hook_type(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr); +typedef b32 custom_set_custom_hook_memory_size_type(Application_Links* app, Hook_ID hook_id, umem size); typedef Mouse_State custom_get_mouse_state_type(Application_Links* app); typedef b32 custom_get_active_query_bars_type(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); typedef b32 custom_start_query_bar_type(Application_Links* app, Query_Bar* bar, u32 flags); @@ -426,6 +430,7 @@ custom_view_post_fade_type *view_post_fade; custom_view_push_context_type *view_push_context; custom_view_pop_context_type *view_pop_context; custom_view_current_context_type *view_current_context; +custom_view_current_context_hook_memory_type *view_current_context_hook_memory; custom_create_user_managed_scope_type *create_user_managed_scope; custom_destroy_user_managed_scope_type *destroy_user_managed_scope; custom_get_global_managed_scope_type *get_global_managed_scope; @@ -452,6 +457,7 @@ custom_get_current_input_type *get_current_input; custom_set_current_input_type *set_current_input; custom_leave_current_input_unhandled_type *leave_current_input_unhandled; custom_set_custom_hook_type *set_custom_hook; +custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size; custom_get_mouse_state_type *get_mouse_state; custom_get_active_query_bars_type *get_active_query_bars; custom_start_query_bar_type *start_query_bar; @@ -589,13 +595,14 @@ internal Managed_Scope view_get_managed_scope(Application_Links* app, View_ID vi internal Buffer_Cursor buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek); internal Buffer_Cursor view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek); internal b32 view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek); -internal b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll); +internal b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule); internal b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek); internal b32 view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags); internal b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color); internal b32 view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx); internal b32 view_pop_context(Application_Links* app, View_ID view_id); internal View_Context view_current_context(Application_Links* app, View_ID view_id); +internal Data view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id); internal Managed_Scope create_user_managed_scope(Application_Links* app); internal b32 destroy_user_managed_scope(Application_Links* app, Managed_Scope scope); internal Managed_Scope get_global_managed_scope(Application_Links* app); @@ -622,6 +629,7 @@ internal User_Input get_current_input(Application_Links* app); internal void set_current_input(Application_Links* app, User_Input* input); internal void leave_current_input_unhandled(Application_Links* app); internal void set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr); +internal b32 set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size); internal Mouse_State get_mouse_state(Application_Links* app); internal b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); internal b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags); @@ -766,6 +774,7 @@ global custom_view_post_fade_type *view_post_fade = 0; global custom_view_push_context_type *view_push_context = 0; global custom_view_pop_context_type *view_pop_context = 0; global custom_view_current_context_type *view_current_context = 0; +global custom_view_current_context_hook_memory_type *view_current_context_hook_memory = 0; global custom_create_user_managed_scope_type *create_user_managed_scope = 0; global custom_destroy_user_managed_scope_type *destroy_user_managed_scope = 0; global custom_get_global_managed_scope_type *get_global_managed_scope = 0; @@ -792,6 +801,7 @@ global custom_get_current_input_type *get_current_input = 0; global custom_set_current_input_type *set_current_input = 0; global custom_leave_current_input_unhandled_type *leave_current_input_unhandled = 0; global custom_set_custom_hook_type *set_custom_hook = 0; +global custom_set_custom_hook_memory_size_type *set_custom_hook_memory_size = 0; global custom_get_mouse_state_type *get_mouse_state = 0; global custom_get_active_query_bars_type *get_active_query_bars = 0; global custom_start_query_bar_type *start_query_bar = 0; diff --git a/custom/generated/custom_api_master_list.h b/custom/generated/custom_api_master_list.h index 1f6eee70..8a7c906d 100644 --- a/custom/generated/custom_api_master_list.h +++ b/custom/generated/custom_api_master_list.h @@ -82,13 +82,14 @@ api(custom) function Managed_Scope view_get_managed_scope(Application_Links* app api(custom) function Buffer_Cursor buffer_compute_cursor(Application_Links* app, Buffer_ID buffer, Buffer_Seek seek); api(custom) function Buffer_Cursor view_compute_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek); api(custom) function b32 view_set_cursor(Application_Links* app, View_ID view_id, Buffer_Seek seek); -api(custom) function b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll); +api(custom) function b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buffer_Scroll scroll, Set_Buffer_Scroll_Rule rule); api(custom) function b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek); api(custom) function b32 view_set_buffer(Application_Links* app, View_ID view_id, Buffer_ID buffer_id, Set_Buffer_Flag flags); api(custom) function b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, int_color color); api(custom) function b32 view_push_context(Application_Links* app, View_ID view_id, View_Context* ctx); api(custom) function b32 view_pop_context(Application_Links* app, View_ID view_id); api(custom) function View_Context view_current_context(Application_Links* app, View_ID view_id); +api(custom) function Data view_current_context_hook_memory(Application_Links* app, View_ID view_id, Hook_ID hook_id); api(custom) function Managed_Scope create_user_managed_scope(Application_Links* app); api(custom) function b32 destroy_user_managed_scope(Application_Links* app, Managed_Scope scope); api(custom) function Managed_Scope get_global_managed_scope(Application_Links* app); @@ -115,6 +116,7 @@ api(custom) function User_Input get_current_input(Application_Links* app); api(custom) function void set_current_input(Application_Links* app, User_Input* input); api(custom) function void leave_current_input_unhandled(Application_Links* app); api(custom) function void set_custom_hook(Application_Links* app, Hook_ID hook_id, Void_Func* func_ptr); +api(custom) function b32 set_custom_hook_memory_size(Application_Links* app, Hook_ID hook_id, umem size); api(custom) function Mouse_State get_mouse_state(Application_Links* app); api(custom) function b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); api(custom) function b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags);