diff --git a/4ed.cpp b/4ed.cpp index 0bc9be89..8059d581 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -9,67 +9,6 @@ // TOP -internal void -fill_hardcode_default_style(Color_Table color_table){ - color_table.vals[Stag_Back] = 0xFF0C0C0C; - color_table.vals[Stag_Margin] = 0xFF181818; - color_table.vals[Stag_Margin_Hover] = 0xFF252525; - color_table.vals[Stag_Margin_Active] = 0xFF323232; - color_table.vals[Stag_List_Item] = color_table.vals[Stag_Margin]; - color_table.vals[Stag_List_Item_Hover] = color_table.vals[Stag_Margin_Hover]; - color_table.vals[Stag_List_Item_Active] = color_table.vals[Stag_Margin_Active]; - color_table.vals[Stag_Cursor] = 0xFF00EE00; - color_table.vals[Stag_Highlight] = 0xFFDDEE00; - color_table.vals[Stag_Mark] = 0xFF494949; - color_table.vals[Stag_Default] = 0xFF90B080; - color_table.vals[Stag_At_Cursor] = color_table.vals[Stag_Back]; - color_table.vals[Stag_Highlight_Cursor_Line] = 0xFF1E1E1E; - color_table.vals[Stag_At_Highlight] = 0xFFFF44DD; - color_table.vals[Stag_Comment] = 0xFF2090F0; - color_table.vals[Stag_Keyword] = 0xFFD08F20; - color_table.vals[Stag_Str_Constant] = 0xFF50FF30; - color_table.vals[Stag_Char_Constant] = color_table.vals[Stag_Str_Constant]; - color_table.vals[Stag_Int_Constant] = color_table.vals[Stag_Str_Constant]; - color_table.vals[Stag_Float_Constant] = color_table.vals[Stag_Str_Constant]; - color_table.vals[Stag_Bool_Constant] = color_table.vals[Stag_Str_Constant]; - color_table.vals[Stag_Include] = color_table.vals[Stag_Str_Constant]; - color_table.vals[Stag_Preproc] = color_table.vals[Stag_Default]; - color_table.vals[Stag_Special_Character] = 0xFFFF0000; - color_table.vals[Stag_Ghost_Character] = color_blend(color_table.vals[Stag_Default], 0.5f, color_table.vals[Stag_Back]); - - color_table.vals[Stag_Paste] = 0xFFDDEE00; - color_table.vals[Stag_Undo] = 0xFF00DDEE; - - color_table.vals[Stag_Highlight_Junk] = 0xff3a0000; - color_table.vals[Stag_Highlight_White] = 0xff003a3a; - - color_table.vals[Stag_Bar] = 0xFF888888; - color_table.vals[Stag_Base] = 0xFF000000; - color_table.vals[Stag_Pop1] = 0xFF3C57DC; - color_table.vals[Stag_Pop2] = 0xFFFF0000; - - color_table.vals[Stag_Back_Cycle_1] = 0x10A00000; - color_table.vals[Stag_Back_Cycle_2] = 0x0C00A000; - color_table.vals[Stag_Back_Cycle_3] = 0x0C0000A0; - color_table.vals[Stag_Back_Cycle_4] = 0x0CA0A000; - color_table.vals[Stag_Text_Cycle_1] = 0xFFA00000; - color_table.vals[Stag_Text_Cycle_2] = 0xFF00A000; - color_table.vals[Stag_Text_Cycle_3] = 0xFF0030B0; - color_table.vals[Stag_Text_Cycle_4] = 0xFFA0A000; - - color_table.vals[Stag_Line_Numbers_Back] = 0xFF101010; - color_table.vals[Stag_Line_Numbers_Text] = 0xFF404040; -} - -internal void -app_hardcode_default_style(Models *models){ - Color_Table color_table = {}; - color_table.count = Stag_COUNT; - color_table.vals = push_array(models->arena, u32, color_table.count); - fill_hardcode_default_style(color_table); - models->fallback_color_table = color_table; -} - internal void init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, i32 argc, char **argv){ char *arg = 0; @@ -337,7 +276,6 @@ App_Init_Sig(app_init){ Face *new_face = font_set_new_face(&models->font_set, &description); models->global_face_id = new_face->id; } - app_hardcode_default_style(models); // NOTE(allen): title space models->has_new_title = true; @@ -805,20 +743,6 @@ App_Step_Sig(app_step){ frame.literal_dt = literal_dt; frame.animation_dt = animation_dt; - { - Color_Table color_table = models->fallback_color_table; -#if 0 - if (models->modify_color_table != 0){ - color_table = models->modify_color_table(&models->app_links, frame); - if (color_table.count < models->fallback_color_table.count){ - block_copy(models->fallback_color_table.vals, color_table.vals, color_table.count*sizeof(*color_table.vals)); - color_table = models->fallback_color_table; - } - } -#endif - models->color_table = color_table; - } - Application_Links app = {}; app.tctx = tctx; app.cmd_context = models; diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 8d1a5bcb..7a58ce74 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -1741,16 +1741,14 @@ view_set_buffer(Application_Links *app, View_ID view_id, Buffer_ID buffer_id, Se // TODO(allen): remove this! api(custom) function b32 view_post_fade(Application_Links *app, View_ID view_id, f32 seconds, Range_i64 range, - FColor color){ + ARGB_Color color){ Models *models = (Models*)app->cmd_context; View *view = imp_get_view(models, view_id); b32 result = false; if (api_check_view(view)){ i64 size = range_size(range); if (size > 0){ - Color_Table color_table = models->color_table; - view_post_paste_effect(view, seconds, (i32)range.start, (i32)size, - finalize_color(color_table, color)); + view_post_paste_effect(view, seconds, (i32)range.start, (i32)size, color); result = true; } } @@ -2018,6 +2016,13 @@ managed_scope_allocator(Application_Links *app, Managed_Scope scope) return(result); } +api(custom) function u64 +managed_id_group_highest_id(Application_Links *app, String_Const_u8 group){ + Models *models = (Models*)app->cmd_context; + Managed_ID_Set *set = &models->managed_id_set; + return(managed_ids_group_highest_id(set, group)); +} + api(custom) function Managed_ID managed_id_declare(Application_Links *app, String_Const_u8 group, String_Const_u8 name) { @@ -2772,37 +2777,6 @@ try_release_face(Application_Links *app, Face_ID id, Face_ID replacement_id) return(release_font_and_update(models, face, replacement)); } -api(custom) function void -set_theme_colors(Application_Links *app, Theme_Color *colors, i32 count) -{ - Models *models = (Models*)app->cmd_context; - Color_Table color_table = models->color_table; - Theme_Color *theme_color = colors; - for (i32 i = 0; i < count; ++i, ++theme_color){ - if (theme_color->tag < color_table.count){ - color_table.vals[theme_color->tag] = theme_color->color; - } - } -} - -api(custom) function void -get_theme_colors(Application_Links *app, Theme_Color *colors, i32 count) -{ - Models *models = (Models*)app->cmd_context; - Color_Table color_table = models->color_table; - Theme_Color *theme_color = colors; - for (i32 i = 0; i < count; ++i, ++theme_color){ - theme_color->color = finalize_color(color_table, theme_color->tag); - } -} - -api(custom) function ARGB_Color -finalize_color(Application_Links *app, ID_Color color){ - Models *models = (Models*)app->cmd_context; - Color_Table color_table = models->color_table; - return(finalize_color(color_table, color)); -} - api(custom) function String_Const_u8 push_hot_directory(Application_Links *app, Arena *arena) { @@ -2841,7 +2815,7 @@ set_window_title(Application_Links *app, String_Const_u8 title) } api(custom) function Vec2_f32 -draw_string_oriented(Application_Links *app, Face_ID font_id, FColor color, +draw_string_oriented(Application_Links *app, Face_ID font_id, ARGB_Color color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta) { Vec2_f32 result = point; @@ -2852,9 +2826,7 @@ draw_string_oriented(Application_Links *app, Face_ID font_id, FColor color, result += delta*width; } else{ - Color_Table color_table = models->color_table; - u32 actual_color = finalize_color(color_table, color); - f32 width = draw_string(models->target, face, str, point, actual_color, flags, delta); + f32 width = draw_string(models->target, face, str, point, color, flags, delta); result += delta*width; } return(result); @@ -2869,23 +2841,18 @@ get_string_advance(Application_Links *app, Face_ID font_id, String_Const_u8 str) } api(custom) function void -draw_rectangle(Application_Links *app, Rect_f32 rect, f32 roundness, FColor color){ +draw_rectangle(Application_Links *app, Rect_f32 rect, f32 roundness, ARGB_Color color){ Models *models = (Models*)app->cmd_context; if (models->in_render_mode){ - Color_Table color_table = models->color_table; - u32 actual_color = finalize_color(color_table, color); - draw_rectangle(models->target, rect, roundness, actual_color); + draw_rectangle(models->target, rect, roundness, color); } } api(custom) function void -draw_rectangle_outline(Application_Links *app, Rect_f32 rect, - f32 roundness, f32 thickness, FColor color){ +draw_rectangle_outline(Application_Links *app, Rect_f32 rect, f32 roundness, f32 thickness, ARGB_Color color){ Models *models = (Models*)app->cmd_context; if (models->in_render_mode){ - Color_Table color_table = models->color_table; - u32 actual_color = finalize_color(color_table, color); - draw_rectangle_outline(models->target, rect, roundness, thickness, actual_color); + draw_rectangle_outline(models->target, rect, roundness, thickness, color); } } @@ -2932,11 +2899,7 @@ text_layout_create(Application_Links *app, Buffer_ID buffer_id, Rect_f32 rect, B buffer_get_last_pos_from_line_number(buffer, visible_line_number_range.max)); i64 item_count = range_size_inclusive(visible_range); - FColor *colors_array = push_array(arena, FColor, item_count); - for (i64 i = 0; i < item_count; i += 1){ - colors_array[i].a_byte = 0; - colors_array[i].id = Stag_Default; - } + ARGB_Color *colors_array = push_array_zero(arena, ARGB_Color, item_count); result = text_layout_new(&models->text_layouts, arena, buffer_id, buffer_point, visible_range, visible_line_number_range, rect, colors_array, layout_func); @@ -3086,7 +3049,7 @@ text_layout_character_on_screen(Application_Links *app, Text_Layout_ID layout_id api(custom) function void paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range, - FColor color){ + ARGB_Color color){ Models *models = (Models*)app->cmd_context; Rect_f32 result = {}; Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); @@ -3095,7 +3058,7 @@ paint_text_color(Application_Links *app, Text_Layout_ID layout_id, Interval_i64 range.max = clamp_top(range.max, layout->visible_range.max); range.min -= layout->visible_range.min; range.max -= layout->visible_range.min; - FColor *color_ptr = layout->item_colors + range.min; + ARGB_Color *color_ptr = layout->item_colors + range.min; for (i64 i = range.min; i < range.max; i += 1, color_ptr += 1){ *color_ptr = color; } @@ -3109,11 +3072,11 @@ text_layout_free(Application_Links *app, Text_Layout_ID text_layout_id){ } api(custom) function void -draw_text_layout(Application_Links *app, Text_Layout_ID layout_id){ +draw_text_layout(Application_Links *app, Text_Layout_ID layout_id, ARGB_Color special_color, ARGB_Color ghost_color){ Models *models = (Models*)app->cmd_context; Text_Layout *layout = text_layout_get(&models->text_layouts, layout_id); if (layout != 0 && models->target != 0){ - text_layout_render(app->tctx, models, layout); + text_layout_render(app->tctx, models, layout, special_color, ghost_color); } } diff --git a/4ed_app_models.h b/4ed_app_models.h index dbc239a1..53e7801a 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -76,8 +76,7 @@ struct Models{ Buffer_Region_Function *buffer_region; Layout_Function *layout_func; - Color_Table fallback_color_table; - Color_Table color_table; + Color_Table color_table_; Model_View_Command_Function *free_view_cmd_funcs; Model_View_Command_Function *first_view_cmd_func; diff --git a/4ed_dynamic_variables.cpp b/4ed_dynamic_variables.cpp index a48d502f..4f0e537f 100644 --- a/4ed_dynamic_variables.cpp +++ b/4ed_dynamic_variables.cpp @@ -15,6 +15,20 @@ managed_ids_init(Base_Allocator *allocator, Managed_ID_Set *set){ set->name_to_group_table = make_table_Data_u64(allocator, 20); } +internal Managed_ID +managed_ids_group_highest_id(Managed_ID_Set *set, String_Const_u8 group_name){ + Managed_ID result = 0; + Data data = make_data(group_name.str, group_name.size); + Table_Lookup lookup = table_lookup(&set->name_to_group_table, data); + if (lookup.found_match){ + u64 val = 0; + table_read(&set->name_to_group_table, lookup, &val); + Managed_ID_Group *group = (Managed_ID_Group*)IntAsPtr(val); + result = group->id_counter - 1; + } + return(result); +} + internal Managed_ID managed_ids_declare(Managed_ID_Set *set, String_Const_u8 group_name, String_Const_u8 name){ Managed_ID_Group *group = 0; diff --git a/4ed_text_layout.cpp b/4ed_text_layout.cpp index 41c8889a..e1f60820 100644 --- a/4ed_text_layout.cpp +++ b/4ed_text_layout.cpp @@ -1,136 +1,131 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 31.03.2019 - * - * Text layout representation - * - */ - -// TOP - -internal void -text_layout_init(Thread_Context *tctx, Text_Layout_Container *container){ - block_zero_struct(container); - container->node_arena = reserve_arena(tctx); - container->table = make_table_u64_u64(tctx->allocator, 20); -} - -internal Text_Layout* -text_layout_new__alloc_layout(Text_Layout_Container *container){ - Text_Layout *node = container->free_nodes; - if (node == 0){ - node = push_array(container->node_arena, Text_Layout, 1); - } - else{ - sll_stack_pop(container->free_nodes); - } - return(node); -} - -internal void -text_layout_release(Thread_Context *tctx, Models *models, Text_Layout_Container *container, Text_Layout *layout){ - release_arena(tctx, layout->arena); - sll_stack_push(container->free_nodes, layout); -} - -internal Text_Layout_ID -text_layout_new(Text_Layout_Container *container, Arena *arena, - Buffer_ID buffer_id, Buffer_Point point, - Range_i64 visible_range, Interval_i64 visible_line_number_range, - Rect_f32 rect, FColor *item_colors, Layout_Function *layout_func){ - 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->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; - new_layout_data->layout_func = layout_func; - Text_Layout_ID new_id = ++container->id_counter; - table_insert(&container->table, new_id, (u64)PtrAsInt(new_layout_data)); - return(new_id); -} - -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); -} - -internal b32 -text_layout_erase(Thread_Context *tctx, Models *models, Text_Layout_Container *container, Text_Layout_ID id){ - b32 result = false; - 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(tctx, models, container, ptr); - table_erase(&container->table, lookup); - result = true; - } - return(result); -} - -//////////////////////////////// - -internal void -text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout){ - Editing_File *file = imp_get_file(models, layout->buffer_id); - if (file != 0){ - Render_Target *target = models->target; - Color_Table color_table = models->color_table; - Face *face = file_get_face(models, file); - f32 width = rect_width(layout->rect); - - ARGB_Color special_color = color_table.vals[Stag_Special_Character]; - ARGB_Color 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; - Layout_Function *layout_func = layout->layout_func; - for (;line_number <= line_number_last; line_number += 1){ - Layout_Item_List line = file_get_line_layout(tctx, models, file, - layout_func, width, face, - line_number); - for (Layout_Item_Block *block = line.first; - block != 0; - block = block->next){ - Layout_Item *item = block->items; - i64 count = block->item_count; - FColor *item_colors = layout->item_colors; - for (i32 i = 0; i < count; i += 1, item += 1){ - if (item->codepoint != 0){ - ARGB_Color color = 0; - if (HasFlag(item->flags, LayoutItemFlag_Special_Character)){ - color = special_color; - } - else if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){ - color = ghost_color; - } - else{ - FColor fcolor = item_colors[item->index - first_index]; - color = finalize_color(color_table, fcolor); - } - Vec2_f32 p = item->rect.p0 + shift_p; - draw_font_glyph(target, face, item->codepoint, - p, color, GlyphFlag_None); - } - } - } - shift_p.y += line.height; - } - } -} - -// BOTTOM +/* + * Mr. 4th Dimention - Allen Webster + * + * 31.03.2019 + * + * Text layout representation + * + */ + +// TOP + +internal void +text_layout_init(Thread_Context *tctx, Text_Layout_Container *container){ + block_zero_struct(container); + container->node_arena = reserve_arena(tctx); + container->table = make_table_u64_u64(tctx->allocator, 20); +} + +internal Text_Layout* +text_layout_new__alloc_layout(Text_Layout_Container *container){ + Text_Layout *node = container->free_nodes; + if (node == 0){ + node = push_array(container->node_arena, Text_Layout, 1); + } + else{ + sll_stack_pop(container->free_nodes); + } + return(node); +} + +internal void +text_layout_release(Thread_Context *tctx, Models *models, Text_Layout_Container *container, Text_Layout *layout){ + release_arena(tctx, layout->arena); + sll_stack_push(container->free_nodes, layout); +} + +internal Text_Layout_ID +text_layout_new(Text_Layout_Container *container, Arena *arena, + Buffer_ID buffer_id, Buffer_Point point, + Range_i64 visible_range, Range_i64 visible_line_number_range, + Rect_f32 rect, ARGB_Color *item_colors, Layout_Function *layout_func){ + 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->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; + new_layout_data->layout_func = layout_func; + Text_Layout_ID new_id = ++container->id_counter; + table_insert(&container->table, new_id, (u64)PtrAsInt(new_layout_data)); + return(new_id); +} + +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); +} + +internal b32 +text_layout_erase(Thread_Context *tctx, Models *models, Text_Layout_Container *container, Text_Layout_ID id){ + b32 result = false; + 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(tctx, models, container, ptr); + table_erase(&container->table, lookup); + result = true; + } + return(result); +} + +//////////////////////////////// + +internal void +text_layout_render(Thread_Context *tctx, Models *models, Text_Layout *layout, + ARGB_Color special_color, ARGB_Color ghost_color){ + Editing_File *file = imp_get_file(models, layout->buffer_id); + if (file != 0){ + Render_Target *target = models->target; + Face *face = file_get_face(models, file); + f32 width = rect_width(layout->rect); + + 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; + Layout_Function *layout_func = layout->layout_func; + for (;line_number <= line_number_last; line_number += 1){ + Layout_Item_List line = file_get_line_layout(tctx, models, file, + layout_func, width, face, + line_number); + for (Layout_Item_Block *block = line.first; + block != 0; + block = block->next){ + Layout_Item *item = block->items; + i64 count = block->item_count; + ARGB_Color *item_colors = layout->item_colors; + for (i32 i = 0; i < count; i += 1, item += 1){ + if (item->codepoint != 0){ + ARGB_Color color = 0; + if (HasFlag(item->flags, LayoutItemFlag_Special_Character)){ + color = special_color; + } + else if (HasFlag(item->flags, LayoutItemFlag_Ghost_Character)){ + color = ghost_color; + } + else{ + color = item_colors[item->index - first_index]; + } + Vec2_f32 p = item->rect.p0 + shift_p; + draw_font_glyph(target, face, item->codepoint, p, color, GlyphFlag_None); + } + } + } + shift_p.y += line.height; + } + } +} + +// BOTTOM diff --git a/4ed_text_layout.h b/4ed_text_layout.h index bee66a01..d9a09ead 100644 --- a/4ed_text_layout.h +++ b/4ed_text_layout.h @@ -21,7 +21,7 @@ union Text_Layout{ Interval_i64 visible_range; Interval_i64 visible_line_number_range; Rect_f32 rect; - FColor *item_colors; + ARGB_Color *item_colors; Layout_Function *layout_func; }; }; diff --git a/4ed_view.cpp b/4ed_view.cpp index 26f772de..7377cc4b 100644 --- a/4ed_view.cpp +++ b/4ed_view.cpp @@ -793,22 +793,6 @@ release_font_and_update(Models *models, Face *face, Face *replacement_face){ //////////////////////////////// -function ARGB_Color -finalize_color(Color_Table color_table, ID_Color id){ - return(color_table.vals[id % color_table.count]); -} - -function ARGB_Color -finalize_color(Color_Table color_table, FColor fcolor){ - ARGB_Color result = fcolor.argb; - if (fcolor.a_byte == 0){ - result = finalize_color(color_table, fcolor.id); - } - return(result); -} - -//////////////////////////////// - internal View* imp_get_view(Models *models, View_ID view_id){ Live_Views *view_set = &models->view_set; diff --git a/custom/4coder_base_commands.cpp b/custom/4coder_base_commands.cpp index 27c6da49..ac1011db 100644 --- a/custom/4coder_base_commands.cpp +++ b/custom/4coder_base_commands.cpp @@ -1593,173 +1593,6 @@ CUSTOM_DOC("Reopen the current buffer from the hard drive.") //////////////////////////////// -CUSTOM_COMMAND_SIG(multi_paste){ - Scratch_Block scratch(app); - - i32 count = clipboard_count(app, 0); - if (count > 0){ - View_ID view = get_active_view(app, Access_ReadWriteVisible); - Managed_Scope scope = view_get_managed_scope(app, view); - - Rewrite_Type *rewrite = scope_attachment(app, scope, view_rewrite_loc, Rewrite_Type); - if (*rewrite == Rewrite_Paste){ - Rewrite_Type *next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); - *next_rewrite = Rewrite_Paste; - i32 *paste_index_ptr = scope_attachment(app, scope, view_paste_index_loc, i32); - i32 paste_index = (*paste_index_ptr) + 1; - *paste_index_ptr = paste_index; - - String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); - - String_Const_u8 insert_string = push_u8_stringf(scratch, "\n%.*s", string_expand(string)); - - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); - Range_i64 range = get_view_range(app, view); - buffer_replace_range(app, buffer, Ii64(range.max), insert_string); - view_set_mark(app, view, seek_pos(range.max + 1)); - view_set_cursor_and_preferred_x(app, view, seek_pos(range.max + insert_string.size)); - - view_post_fade(app, view, 0.667f, - Ii64(range.max + 1, range.max + insert_string.size), - fcolor_id(Stag_Paste)); - } - else{ - paste(app); - } - } -} - -function Range_i64 -multi_paste_range(Application_Links *app, View_ID view, Range_i64 range, i32 paste_count, b32 old_to_new){ - Scratch_Block scratch(app); - - Range_i64 finish_range = range; - if (paste_count >= 1){ - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); - if (buffer != 0){ - i64 total_size = 0; - for (i32 paste_index = 0; paste_index < paste_count; ++paste_index){ - Temp_Memory temp = begin_temp(scratch); - String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); - total_size += string.size + 1; - end_temp(temp); - } - total_size -= 1; - - i32 first = paste_count - 1; - i32 one_past_last = -1; - i32 step = -1; - if (!old_to_new){ - first = 0; - one_past_last = paste_count; - step = 1; - } - - List_String_Const_u8 list = {}; - - for (i32 paste_index = first; paste_index != one_past_last; paste_index += step){ - if (paste_index != first){ - string_list_push(scratch, &list, SCu8("\n", 1)); - } - String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); - if (string.size > 0){ - string_list_push(scratch, &list, string); - } - } - - String_Const_u8 flattened = string_list_flatten(scratch, list); - - buffer_replace_range(app, buffer, range, flattened); - i64 pos = range.min; - finish_range.min = pos; - finish_range.max = pos + total_size; - view_set_mark(app, view, seek_pos(finish_range.min)); - view_set_cursor_and_preferred_x(app, view, seek_pos(finish_range.max)); - - // TODO(allen): Send this to all views. - view_post_fade(app, view, 0.667f, finish_range, fcolor_id(Stag_Paste)); - } - } - return(finish_range); -} - -function void -multi_paste_interactive_up_down(Application_Links *app, i32 paste_count, i32 clip_count){ - View_ID view = get_active_view(app, Access_ReadWriteVisible); - i64 pos = view_get_cursor_pos(app, view); - b32 old_to_new = true; - Range_i64 range = multi_paste_range(app, view, Ii64(pos), paste_count, old_to_new); - - Query_Bar_Group group(app); - Query_Bar bar = {}; - bar.prompt = string_u8_litexpr("Up and Down to condense and expand paste stages; R to reverse order; Return to finish; Escape to abort."); - if (start_query_bar(app, &bar, 0) == 0) return; - - User_Input in = {}; - for (;;){ - in = get_next_input(app, EventProperty_AnyKey, EventProperty_Escape); - if (in.abort) break; - - b32 did_modify = false; - if (match_key_code(&in, KeyCode_Up)){ - if (paste_count > 1){ - --paste_count; - did_modify = true; - } - } - else if (match_key_code(&in, KeyCode_Down)){ - if (paste_count < clip_count){ - ++paste_count; - did_modify = true; - } - } - else if (match_key_code(&in, KeyCode_R)){ - old_to_new = !old_to_new; - did_modify = true; - } - else if (match_key_code(&in, KeyCode_Return)){ - break; - } - - if (did_modify){ - range = multi_paste_range(app, view, range, paste_count, old_to_new); - } - } - - if (in.abort){ - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); - buffer_replace_range(app, buffer, range, SCu8("")); - } -} - -CUSTOM_COMMAND_SIG(multi_paste_interactive){ - i32 clip_count = clipboard_count(app, 0); - if (clip_count > 0){ - multi_paste_interactive_up_down(app, 1, clip_count); - } -} - -CUSTOM_COMMAND_SIG(multi_paste_interactive_quick){ - i32 clip_count = clipboard_count(app, 0); - if (clip_count > 0){ - u8 string_space[256]; - Query_Bar_Group group(app); - Query_Bar bar = {}; - bar.prompt = string_u8_litexpr("How Many Slots To Paste: "); - bar.string = SCu8(string_space, (umem)0); - bar.string_capacity = sizeof(string_space); - query_user_number(app, &bar); - - i32 initial_paste_count = (i32)string_to_integer(bar.string, 10); - initial_paste_count = clamp(1, initial_paste_count, clip_count); - end_query_bar(app, &bar, 0); - - multi_paste_interactive_up_down(app, initial_paste_count, clip_count); - } -} - -//////////////////////////////// - internal i32 record_get_new_cursor_position_undo(Application_Links *app, Buffer_ID buffer_id, History_Record_Index index, Record_Info record){ i32 new_edit_position = 0; diff --git a/custom/4coder_clipboard.cpp b/custom/4coder_clipboard.cpp index 6013937f..ed283c2f 100644 --- a/custom/4coder_clipboard.cpp +++ b/custom/4coder_clipboard.cpp @@ -62,7 +62,8 @@ CUSTOM_DOC("At the cursor, insert the text at the top of the clipboard.") view_set_cursor_and_preferred_x(app, view, seek_pos(pos + (i32)string.size)); // TODO(allen): Send this to all views. - view_post_fade(app, view, 0.667f, Ii64_size(pos, string.size), fcolor_id(Stag_Paste)); + ARGB_Color argb = fcolor_resolve(fcolor_id(defcolor_paste)); + view_post_fade(app, view, 0.667f, Ii64_size(pos, string.size), argb); } } } @@ -97,7 +98,8 @@ CUSTOM_DOC("If the previous command was paste or paste_next, replaces the paste buffer_replace_range(app, buffer, range, string); view_set_cursor_and_preferred_x(app, view, seek_pos(pos + string.size)); - view_post_fade(app, view, 0.667f, Ii64_size(pos, string.size), fcolor_id(Stag_Paste)); + ARGB_Color argb = fcolor_resolve(fcolor_id(defcolor_paste)); + view_post_fade(app, view, 0.667f, Ii64_size(pos, string.size), argb); } else{ paste(app); @@ -119,5 +121,174 @@ CUSTOM_DOC("Paste the next item on the clipboard and run auto-indent on the newl auto_indent_range(app); } +//////////////////////////////// + +CUSTOM_COMMAND_SIG(multi_paste){ + Scratch_Block scratch(app); + + i32 count = clipboard_count(app, 0); + if (count > 0){ + View_ID view = get_active_view(app, Access_ReadWriteVisible); + Managed_Scope scope = view_get_managed_scope(app, view); + + Rewrite_Type *rewrite = scope_attachment(app, scope, view_rewrite_loc, Rewrite_Type); + if (*rewrite == Rewrite_Paste){ + Rewrite_Type *next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); + *next_rewrite = Rewrite_Paste; + i32 *paste_index_ptr = scope_attachment(app, scope, view_paste_index_loc, i32); + i32 paste_index = (*paste_index_ptr) + 1; + *paste_index_ptr = paste_index; + + String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); + + String_Const_u8 insert_string = push_u8_stringf(scratch, "\n%.*s", string_expand(string)); + + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); + Range_i64 range = get_view_range(app, view); + buffer_replace_range(app, buffer, Ii64(range.max), insert_string); + view_set_mark(app, view, seek_pos(range.max + 1)); + view_set_cursor_and_preferred_x(app, view, seek_pos(range.max + insert_string.size)); + + ARGB_Color argb = fcolor_resolve(fcolor_id(defcolor_paste)); + view_post_fade(app, view, 0.667f, + Ii64(range.max + 1, range.max + insert_string.size), + argb); + } + else{ + paste(app); + } + } +} + +function Range_i64 +multi_paste_range(Application_Links *app, View_ID view, Range_i64 range, i32 paste_count, b32 old_to_new){ + Scratch_Block scratch(app); + + Range_i64 finish_range = range; + if (paste_count >= 1){ + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); + if (buffer != 0){ + i64 total_size = 0; + for (i32 paste_index = 0; paste_index < paste_count; ++paste_index){ + Temp_Memory temp = begin_temp(scratch); + String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); + total_size += string.size + 1; + end_temp(temp); + } + total_size -= 1; + + i32 first = paste_count - 1; + i32 one_past_last = -1; + i32 step = -1; + if (!old_to_new){ + first = 0; + one_past_last = paste_count; + step = 1; + } + + List_String_Const_u8 list = {}; + + for (i32 paste_index = first; paste_index != one_past_last; paste_index += step){ + if (paste_index != first){ + string_list_push(scratch, &list, SCu8("\n", 1)); + } + String_Const_u8 string = push_clipboard_index(app, scratch, 0, paste_index); + if (string.size > 0){ + string_list_push(scratch, &list, string); + } + } + + String_Const_u8 flattened = string_list_flatten(scratch, list); + + buffer_replace_range(app, buffer, range, flattened); + i64 pos = range.min; + finish_range.min = pos; + finish_range.max = pos + total_size; + view_set_mark(app, view, seek_pos(finish_range.min)); + view_set_cursor_and_preferred_x(app, view, seek_pos(finish_range.max)); + + // TODO(allen): Send this to all views. + ARGB_Color argb = fcolor_resolve(fcolor_id(defcolor_paste)); + view_post_fade(app, view, 0.667f, finish_range, argb); + } + } + return(finish_range); +} + +function void +multi_paste_interactive_up_down(Application_Links *app, i32 paste_count, i32 clip_count){ + View_ID view = get_active_view(app, Access_ReadWriteVisible); + i64 pos = view_get_cursor_pos(app, view); + b32 old_to_new = true; + Range_i64 range = multi_paste_range(app, view, Ii64(pos), paste_count, old_to_new); + + Query_Bar_Group group(app); + Query_Bar bar = {}; + bar.prompt = string_u8_litexpr("Up and Down to condense and expand paste stages; R to reverse order; Return to finish; Escape to abort."); + if (start_query_bar(app, &bar, 0) == 0) return; + + User_Input in = {}; + for (;;){ + in = get_next_input(app, EventProperty_AnyKey, EventProperty_Escape); + if (in.abort) break; + + b32 did_modify = false; + if (match_key_code(&in, KeyCode_Up)){ + if (paste_count > 1){ + --paste_count; + did_modify = true; + } + } + else if (match_key_code(&in, KeyCode_Down)){ + if (paste_count < clip_count){ + ++paste_count; + did_modify = true; + } + } + else if (match_key_code(&in, KeyCode_R)){ + old_to_new = !old_to_new; + did_modify = true; + } + else if (match_key_code(&in, KeyCode_Return)){ + break; + } + + if (did_modify){ + range = multi_paste_range(app, view, range, paste_count, old_to_new); + } + } + + if (in.abort){ + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); + buffer_replace_range(app, buffer, range, SCu8("")); + } +} + +CUSTOM_COMMAND_SIG(multi_paste_interactive){ + i32 clip_count = clipboard_count(app, 0); + if (clip_count > 0){ + multi_paste_interactive_up_down(app, 1, clip_count); + } +} + +CUSTOM_COMMAND_SIG(multi_paste_interactive_quick){ + i32 clip_count = clipboard_count(app, 0); + if (clip_count > 0){ + u8 string_space[256]; + Query_Bar_Group group(app); + Query_Bar bar = {}; + bar.prompt = string_u8_litexpr("How Many Slots To Paste: "); + bar.string = SCu8(string_space, (umem)0); + bar.string_capacity = sizeof(string_space); + query_user_number(app, &bar); + + i32 initial_paste_count = (i32)string_to_integer(bar.string, 10); + initial_paste_count = clamp(1, initial_paste_count, clip_count); + end_query_bar(app, &bar, 0); + + multi_paste_interactive_up_down(app, initial_paste_count, clip_count); + } +} + // BOTTOM diff --git a/custom/4coder_default_bindings.cpp b/custom/4coder_default_bindings.cpp index 8559bd2f..4050b822 100644 --- a/custom/4coder_default_bindings.cpp +++ b/custom/4coder_default_bindings.cpp @@ -26,6 +26,7 @@ custom_layer_init(Application_Links *app){ ProfileThreadName(tctx, list, string_u8_litexpr("main")); initialize_managed_id_metadata(app); + set_default_color_scheme(app); } #endif diff --git a/custom/4coder_default_colors.cpp b/custom/4coder_default_colors.cpp new file mode 100644 index 00000000..c773a60c --- /dev/null +++ b/custom/4coder_default_colors.cpp @@ -0,0 +1,140 @@ +/* +* Default color slots +*/ + +// TOP + +function Color_Array +finalize_color_array(Color_Table table, u64 id){ + return(table.arrays[id % table.count]); +} + +function ARGB_Color +finalize_color(Color_Array array, i32 sub_index){ + ARGB_Color result = 0xFFFFFFFF; + if (array.count > 0){ + result = array.vals[sub_index % array.count]; + } + return(result); +} + +function ARGB_Color +finalize_color(Color_Table color_table, u64 id, i32 sub_index){ + Color_Array array = finalize_color_array(color_table, id); + return(finalize_color(array, sub_index)); +} + +function Color_Array +finalize_color_array(u64 id){ + return(finalize_color_array(active_color_table, id)); +} + +function ARGB_Color +finalize_color(u64 id, i32 sub_index){ + return(finalize_color(active_color_table, id, sub_index)); +} + +//////////////////////////////// + +function Color_Array +make_colors(Arena *arena, ARGB_Color color){ + Color_Array result = {}; + result.count = 1; + result.vals = push_array(arena, ARGB_Color, 1); + result.vals[0] = color; + return(result); +} + +function Color_Array +make_colors(Arena *arena, ARGB_Color c1, ARGB_Color c2){ + Color_Array result = {}; + result.count = 2; + result.vals = push_array(arena, ARGB_Color, 2); + result.vals[0] = c1; + result.vals[1] = c2; + return(result); +} + +function Color_Array +make_colors(Arena *arena, ARGB_Color c1, ARGB_Color c2, ARGB_Color c3){ + Color_Array result = {}; + result.count = 3; + result.vals = push_array(arena, ARGB_Color, 3); + result.vals[0] = c1; + result.vals[1] = c2; + result.vals[2] = c3; + return(result); +} + +function Color_Array +make_colors(Arena *arena, ARGB_Color c1, ARGB_Color c2, ARGB_Color c3, ARGB_Color c4){ + Color_Array result = {}; + result.count = 4; + result.vals = push_array(arena, ARGB_Color, 4); + result.vals[0] = c1; + result.vals[1] = c2; + result.vals[2] = c3; + result.vals[3] = c4; + return(result); +} + +function Color_Array +make_colors(Arena *arena, ARGB_Color *colors, i32 count){ + Color_Array result = {}; + result.count = count; + result.vals = push_array_write(arena, ARGB_Color, count, colors); + return(result); +} + +function void +set_default_color_scheme(Application_Links *app){ + Arena arena = make_arena_system(); + + Managed_ID highest_color_id = managed_id_group_highest_id(app, string_u8_litexpr("colors")); + default_color_table.count = (u32)(clamp_top(highest_color_id + 1, max_u32)); + default_color_table.arrays = push_array_zero(&arena, Color_Array, default_color_table.count); + + default_color_table.arrays[0] = make_colors(&arena, 0xFF90B080); + default_color_table.arrays[defcolor_bar] = make_colors(&arena, 0xFF888888); + default_color_table.arrays[defcolor_base] = make_colors(&arena, 0xFF000000); + default_color_table.arrays[defcolor_pop1] = make_colors(&arena, 0xFF3C57DC); + default_color_table.arrays[defcolor_pop2] = make_colors(&arena, 0xFFFF0000); + default_color_table.arrays[defcolor_back] = make_colors(&arena, 0xFF0C0C0C); + default_color_table.arrays[defcolor_margin] = make_colors(&arena, 0xFF181818); + default_color_table.arrays[defcolor_margin_hover] = make_colors(&arena, 0xFF252525); + default_color_table.arrays[defcolor_margin_active] = make_colors(&arena, 0xFF323232); + default_color_table.arrays[defcolor_list_item] = make_colors(&arena, 0xFF181818); + default_color_table.arrays[defcolor_list_item_hover] = make_colors(&arena, 0xFF252525); + default_color_table.arrays[defcolor_list_item_active] = make_colors(&arena, 0xFF323232); + default_color_table.arrays[defcolor_cursor] = make_colors(&arena, 0xFF00EE00); + default_color_table.arrays[defcolor_at_cursor] = make_colors(&arena, 0xFF0C0C0C); + default_color_table.arrays[defcolor_highlight_cursor_line] = make_colors(&arena, 0xFF1E1E1E); + default_color_table.arrays[defcolor_highlight] = make_colors(&arena, 0xFFDDEE00); + default_color_table.arrays[defcolor_at_highlight] = make_colors(&arena, 0xFFFF44DD); + default_color_table.arrays[defcolor_mark] = make_colors(&arena, 0xFF494949); + default_color_table.arrays[defcolor_text_default] = make_colors(&arena, 0xFF90B080); + default_color_table.arrays[defcolor_comment] = make_colors(&arena, 0xFF2090F0); + default_color_table.arrays[defcolor_comment_pop] = make_colors(&arena, 0xFF00A000, 0xFFA00000); + default_color_table.arrays[defcolor_keyword] = make_colors(&arena, 0xFFD08F20); + default_color_table.arrays[defcolor_str_constant] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_char_constant] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_int_constant] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_float_constant] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_bool_constant] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_preproc] = make_colors(&arena, 0xFFA0B8A0); + default_color_table.arrays[defcolor_include] = make_colors(&arena, 0xFF50FF30); + default_color_table.arrays[defcolor_special_character] = make_colors(&arena, 0xFFFF0000); + default_color_table.arrays[defcolor_ghost_character] = make_colors(&arena, 0xFF4E5E46); + default_color_table.arrays[defcolor_highlight_junk] = make_colors(&arena, 0xFF3A0000); + default_color_table.arrays[defcolor_highlight_white] = make_colors(&arena, 0xFF003A3A); + default_color_table.arrays[defcolor_paste] = make_colors(&arena, 0xFFDDEE00); + default_color_table.arrays[defcolor_undo] = make_colors(&arena, 0xFF00DDEE); + default_color_table.arrays[defcolor_back_cycle] = make_colors(&arena, 0xFF130707, 0xFF071307, 0xFF070713, 0xFF131307); + default_color_table.arrays[defcolor_text_cycle] = make_colors(&arena, 0xFFA00000, 0xFF00A000, 0xFF0030B0, 0xFFA0A000); + default_color_table.arrays[defcolor_line_numbers_back] = make_colors(&arena, 0xFF101010); + default_color_table.arrays[defcolor_line_numbers_text] = make_colors(&arena, 0xFF404040); + + active_color_table = default_color_table; +} + +// BOTTOM diff --git a/custom/4coder_default_colors.h b/custom/4coder_default_colors.h index fcc9eee4..c2877b9d 100644 --- a/custom/4coder_default_colors.h +++ b/custom/4coder_default_colors.h @@ -1,59 +1,55 @@ /* -* Colors with meanings built into the core. +* Default color slots */ // TOP -enum Style_Tag{ - Stag_NOOP = 0, - - Stag_Bar = 1, - Stag_Base = 2, - Stag_Pop1 = 3, - Stag_Pop2 = 4, - Stag_Back = 5, - Stag_Margin = 6, - Stag_Margin_Hover = 7, - Stag_Margin_Active = 8, - Stag_List_Item = 9, - Stag_List_Item_Hover = 10, - Stag_List_Item_Active = 11, - Stag_Cursor = 12, - Stag_At_Cursor = 13, - Stag_Highlight_Cursor_Line = 14, - Stag_Highlight = 15, - Stag_At_Highlight = 16, - Stag_Mark = 17, - Stag_Default = 18, - Stag_Comment = 19, - Stag_Keyword = 20, - Stag_Str_Constant = 21, - Stag_Char_Constant = 22, - Stag_Int_Constant = 23, - Stag_Float_Constant = 24, - Stag_Bool_Constant = 25, - Stag_Preproc = 26, - Stag_Include = 27, - Stag_Special_Character = 28, - Stag_Ghost_Character = 29, - Stag_Highlight_Junk = 30, - Stag_Highlight_White = 31, - Stag_Paste = 32, - Stag_Undo = 33, - Stag_Back_Cycle_1 = 34, - Stag_Back_Cycle_2 = 35, - Stag_Back_Cycle_3 = 36, - Stag_Back_Cycle_4 = 37, - Stag_Text_Cycle_1 = 38, - Stag_Text_Cycle_2 = 39, - Stag_Text_Cycle_3 = 40, - Stag_Text_Cycle_4 = 41, - Stag_Line_Numbers_Back = 42, - Stag_Line_Numbers_Text = 43, - Stag_COUNT = 44 -}; +#if !defined(FCODER_DEFAULT_COLORS_H) +#define FCODER_DEFAULT_COLORS_H -#define FirstCustomColor Stag_COUNT +CUSTOM_ID(colors, defcolor_bar); +CUSTOM_ID(colors, defcolor_base); +CUSTOM_ID(colors, defcolor_pop1); +CUSTOM_ID(colors, defcolor_pop2); +CUSTOM_ID(colors, defcolor_back); +CUSTOM_ID(colors, defcolor_margin); +CUSTOM_ID(colors, defcolor_margin_hover); +CUSTOM_ID(colors, defcolor_margin_active); +CUSTOM_ID(colors, defcolor_list_item); +CUSTOM_ID(colors, defcolor_list_item_hover); +CUSTOM_ID(colors, defcolor_list_item_active); +CUSTOM_ID(colors, defcolor_cursor); +CUSTOM_ID(colors, defcolor_at_cursor); +CUSTOM_ID(colors, defcolor_highlight_cursor_line); +CUSTOM_ID(colors, defcolor_highlight); +CUSTOM_ID(colors, defcolor_at_highlight); +CUSTOM_ID(colors, defcolor_mark); +CUSTOM_ID(colors, defcolor_text_default); +CUSTOM_ID(colors, defcolor_comment); +CUSTOM_ID(colors, defcolor_comment_pop); +CUSTOM_ID(colors, defcolor_keyword); +CUSTOM_ID(colors, defcolor_str_constant); +CUSTOM_ID(colors, defcolor_char_constant); +CUSTOM_ID(colors, defcolor_int_constant); +CUSTOM_ID(colors, defcolor_float_constant); +CUSTOM_ID(colors, defcolor_bool_constant); +CUSTOM_ID(colors, defcolor_preproc); +CUSTOM_ID(colors, defcolor_include); +CUSTOM_ID(colors, defcolor_special_character); +CUSTOM_ID(colors, defcolor_ghost_character); +CUSTOM_ID(colors, defcolor_highlight_junk); +CUSTOM_ID(colors, defcolor_highlight_white); +CUSTOM_ID(colors, defcolor_paste); +CUSTOM_ID(colors, defcolor_undo); +CUSTOM_ID(colors, defcolor_back_cycle); +CUSTOM_ID(colors, defcolor_text_cycle); +CUSTOM_ID(colors, defcolor_line_numbers_back); +CUSTOM_ID(colors, defcolor_line_numbers_text); + +global Color_Table active_color_table = {}; +global Color_Table default_color_table = {}; + +#endif // BOTTOM diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index 651de150..2ba8bdca 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -1,1189 +1,1182 @@ -/* -4coder_default_hooks.cpp - Sets up the hooks for the default framework. -*/ - -// TOP - -CUSTOM_COMMAND_SIG(default_startup) -CUSTOM_DOC("Default command for responding to a startup event") -{ - ProfileScope(app, "default startup"); - User_Input input = get_current_input(app); - if (match_core_code(&input, CoreCode_Startup)){ - String_Const_u8_Array file_names = input.event.core.file_names; - default_4coder_initialize(app, file_names); - default_4coder_side_by_side_panels(app, file_names); - if (global_config.automatically_load_project){ - load_project(app); - } - } -} - -CUSTOM_COMMAND_SIG(default_try_exit) -CUSTOM_DOC("Default command for responding to a try-exit event") -{ - User_Input input = get_current_input(app); - if (match_core_code(&input, CoreCode_TryExit)){ - b32 do_exit = true; - if (!allow_immediate_close_without_checking_for_changes){ - b32 has_unsaved_changes = false; - for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); - buffer != 0; - buffer = get_buffer_next(app, buffer, Access_Always)){ - Dirty_State dirty = buffer_get_dirty_state(app, buffer); - if (HasFlag(dirty, DirtyState_UnsavedChanges)){ - has_unsaved_changes = true; - break; - } - } - if (has_unsaved_changes){ - View_ID view = get_active_view(app, Access_Always); - do_exit = do_4coder_close_user_check(app, view); - } - } - if (do_exit){ - // NOTE(allen): By leaving try exit unhandled we indicate - // that the core should take responsibility for handling this, - // and it will handle it by exiting 4coder. If we leave this - // event marked as handled on the other hand (for instance by - // running a confirmation GUI that cancels the exit) then 4coder - // will not exit. - leave_current_input_unhandled(app); - } - } -} - -CUSTOM_COMMAND_SIG(default_view_input_handler) -CUSTOM_DOC("Input consumption loop for default view behavior") -{ - Thread_Context *tctx = get_thread_context(app); - Scratch_Block scratch(tctx); - - { - - View_ID view = get_this_ctx_view(app, Access_Always); - String_Const_u8 name = push_u8_stringf(scratch, "view %d", view); - - Profile_Global_List *list = get_core_profile_list(app); - ProfileThreadName(tctx, list, name); - - View_Context ctx = view_current_context(app, view); - ctx.mapping = &framework_mapping; - ctx.map_id = mapid_global; - view_alter_context(app, view, &ctx); - } - - for (;;){ - // NOTE(allen): Get the binding from the buffer's current map - User_Input input = get_next_input(app, EventPropertyGroup_Any, 0); - ProfileScopeNamed(app, "before view input", view_input_profile); - if (input.abort){ - break; - } - - Event_Property event_properties = get_event_properties(&input.event); - - if (suppressing_mouse && (event_properties & EventPropertyGroup_AnyMouseEvent) != 0){ - continue; - } - - View_ID view = get_this_ctx_view(app, Access_Always); - - Buffer_ID buffer = view_get_buffer(app, view, Access_Always); - Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer); - Command_Map_ID *map_id_ptr = scope_attachment(app, buffer_scope, buffer_map_id, Command_Map_ID); - if (*map_id_ptr == 0){ - *map_id_ptr = mapid_file; - } - Command_Map_ID map_id = *map_id_ptr; - - Command_Binding binding = map_get_binding_recursive(&framework_mapping, map_id, &input.event); - - Managed_Scope scope = view_get_managed_scope(app, view); - - if (binding.custom == 0){ - // NOTE(allen): we don't have anything to do with this input, - // leave it marked unhandled so that if there's a follow up - // event it is not blocked. - leave_current_input_unhandled(app); - } - else{ - // NOTE(allen): before the command is called do some book keeping - Rewrite_Type *next_rewrite = - scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); - *next_rewrite = Rewrite_None; - if (fcoder_mode == FCoderMode_NotepadLike){ - for (View_ID view_it = get_view_next(app, 0, Access_Always); - view_it != 0; - view_it = get_view_next(app, view_it, Access_Always)){ - Managed_Scope scope_it = view_get_managed_scope(app, view_it); - b32 *snap_mark_to_cursor = - scope_attachment(app, scope_it, view_snap_mark_to_cursor, - b32); - *snap_mark_to_cursor = true; - } - } - - ProfileCloseNow(view_input_profile); - - // NOTE(allen): call the command - binding.custom(app); - - // NOTE(allen): after the command is called do some book keeping - ProfileScope(app, "after view input"); - - next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); - if (next_rewrite != 0){ - Rewrite_Type *rewrite = - scope_attachment(app, scope, view_rewrite_loc, Rewrite_Type); - *rewrite = *next_rewrite; - if (fcoder_mode == FCoderMode_NotepadLike){ - for (View_ID view_it = get_view_next(app, 0, Access_Always); - view_it != 0; - view_it = get_view_next(app, view_it, Access_Always)){ - Managed_Scope scope_it = view_get_managed_scope(app, view_it); - b32 *snap_mark_to_cursor = - scope_attachment(app, scope_it, view_snap_mark_to_cursor, b32); - if (*snap_mark_to_cursor){ - i64 pos = view_get_cursor_pos(app, view_it); - view_set_mark(app, view_it, seek_pos(pos)); - } - } - } - } - } - } -} - -#if 0 -static argb_color default_colors[Stag_COUNT] = {}; -MODIFY_COLOR_TABLE_SIG(default_modify_color_table){ - if (default_colors[Stag_NOOP] == 0){ - default_colors[Stag_NOOP] = 0xFFFF00FF; - - default_colors[Stag_Back] = 0xFF0C0C0C; - default_colors[Stag_Margin] = 0xFF181818; - default_colors[Stag_Margin_Hover] = 0xFF252525; - default_colors[Stag_Margin_Active] = 0xFF323232; - default_colors[Stag_List_Item] = default_colors[Stag_Margin]; - default_colors[Stag_List_Item_Hover] = default_colors[Stag_Margin_Hover]; - default_colors[Stag_List_Item_Active] = default_colors[Stag_Margin_Active]; - default_colors[Stag_Cursor] = 0xFF00EE00; - default_colors[Stag_Highlight] = 0xFFDDEE00; - default_colors[Stag_Mark] = 0xFF494949; - default_colors[Stag_Default] = 0xFF90B080; - default_colors[Stag_At_Cursor] = default_colors[Stag_Back]; - default_colors[Stag_Highlight_Cursor_Line] = 0xFF1E1E1E; - default_colors[Stag_At_Highlight] = 0xFFFF44DD; - default_colors[Stag_Comment] = 0xFF2090F0; - default_colors[Stag_Keyword] = 0xFFD08F20; - default_colors[Stag_Str_Constant] = 0xFF50FF30; - default_colors[Stag_Char_Constant] = default_colors[Stag_Str_Constant]; - default_colors[Stag_Int_Constant] = default_colors[Stag_Str_Constant]; - default_colors[Stag_Float_Constant] = default_colors[Stag_Str_Constant]; - default_colors[Stag_Bool_Constant] = default_colors[Stag_Str_Constant]; - default_colors[Stag_Include] = default_colors[Stag_Str_Constant]; - default_colors[Stag_Preproc] = default_colors[Stag_Default]; - default_colors[Stag_Special_Character] = 0xFFFF0000; - default_colors[Stag_Ghost_Character] = 0xFF4E5E46; - - default_colors[Stag_Paste] = 0xFFDDEE00; - default_colors[Stag_Undo] = 0xFF00DDEE; - - default_colors[Stag_Highlight_Junk] = 0xFF3A0000; - default_colors[Stag_Highlight_White] = 0xFF003A3A; - - default_colors[Stag_Bar] = 0xFF888888; - default_colors[Stag_Base] = 0xFF000000; - default_colors[Stag_Pop1] = 0xFF3C57DC; - default_colors[Stag_Pop2] = 0xFFFF0000; - - default_colors[Stag_Back_Cycle_1] = 0x10A00000; - default_colors[Stag_Back_Cycle_2] = 0x0C00A000; - default_colors[Stag_Back_Cycle_3] = 0x0C0000A0; - default_colors[Stag_Back_Cycle_4] = 0x0CA0A000; - default_colors[Stag_Text_Cycle_1] = 0xFFA00000; - default_colors[Stag_Text_Cycle_2] = 0xFF00A000; - default_colors[Stag_Text_Cycle_3] = 0xFF0030B0; - default_colors[Stag_Text_Cycle_4] = 0xFFA0A000; - - default_colors[Stag_Line_Numbers_Back] = 0xFF101010; - default_colors[Stag_Line_Numbers_Text] = 0xFF404040; - } - - Color_Table color_table = {}; - color_table.vals = default_colors; - color_table.count = ArrayCount(default_colors); - return(color_table); -} -#endif - -function void -default_tick(Application_Links *app, Frame_Info frame_info){ - Scratch_Block scratch(app); - - for (Buffer_Modified_Node *node = global_buffer_modified_set.first; - node != 0; - node = node->next){ - Temp_Memory_Block temp(scratch); - Buffer_ID buffer_id = node->buffer; - - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - - String_Const_u8 contents = push_whole_buffer(app, scratch, buffer_id); - Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, Token_Array); - if (tokens_ptr == 0){ - continue; - } - if (tokens_ptr->count == 0){ - continue; - } - Token_Array tokens = *tokens_ptr; - - Arena arena = make_arena_system(KB(16)); - Code_Index_File *index = push_array_zero(&arena, Code_Index_File, 1); - index->buffer = buffer_id; - - Generic_Parse_State state = {}; - generic_parse_init(app, &arena, contents, &tokens, &state); - generic_parse_full_input_breaks(index, &state, max_i32); - - code_index_lock(); - code_index_set_file(buffer_id, arena, index); - code_index_unlock(); - buffer_clear_layout_cache(app, buffer_id); - } - - buffer_modified_set_clear(); -} - -function Rect_f32 -default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){ - Buffer_ID buffer = view_get_buffer(app, view_id, Access_Always); - Face_ID face_id = get_face_id(app, buffer); - Face_Metrics metrics = get_face_metrics(app, face_id); - f32 line_height = metrics.line_height; - f32 digit_advance = metrics.decimal_digit_advance; - - // NOTE(allen): margins - region = rect_inner(region, 3.f); - - // NOTE(allen): file bar - 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.max; - } - - // NOTE(allen): query bars - { - Query_Bar *space[32]; - Query_Bar_Ptr_Array query_bars = {}; - query_bars.ptrs = space; - if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){ - Rect_f32_Pair pair = layout_query_bar_on_top(region, line_height, query_bars.count); - region = pair.max; - } - } - - // NOTE(allen): FPS hud - if (show_fps_hud){ - Rect_f32_Pair pair = layout_fps_hud_on_bottom(region, line_height); - region = pair.min; - } - - // NOTE(allen): line numbers - if (global_config.show_line_number_margins){ - Rect_f32_Pair pair = layout_line_number_margin(app, buffer, region, digit_advance); - region = pair.max; - } - - return(region); -} - -function void -recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, - Code_Index_Nest_Ptr_Array *array, i32 counter){ - Code_Index_Nest **ptr = array->ptrs; - Code_Index_Nest **ptr_end = ptr + array->count; - - for (;ptr < ptr_end; ptr += 1){ - Code_Index_Nest *nest = *ptr; - if (!nest->is_closed){ - break; - } - if (range.first <= nest->close.max){ - break; - } - } - - FColor t_colors[] = { - fcolor_id(Stag_Text_Cycle_1), fcolor_id(Stag_Text_Cycle_2), - fcolor_id(Stag_Text_Cycle_3), fcolor_id(Stag_Text_Cycle_4), - }; - FColor t_color = t_colors[counter%ArrayCount(t_colors)]; - - for (;ptr < ptr_end; ptr += 1){ - Code_Index_Nest *nest = *ptr; - if (range.max <= nest->open.min){ - break; - } - - paint_text_color(app, layout_id, nest->open, t_color); - if (nest->is_closed){ - paint_text_color(app, layout_id, nest->close, t_color); - } - recursive_nest_highlight(app, layout_id, range, &nest->nest_array, counter + 1); - } -} - -function void -recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, - Code_Index_File *file){ - recursive_nest_highlight(app, layout_id, range, &file->nest_array, 0); -} - -function void -default_render_buffer(Application_Links *app, View_ID view_id, Face_ID face_id, - Buffer_ID buffer, Text_Layout_ID text_layout_id, - Rect_f32 rect){ - ProfileScope(app, "render buffer"); - - View_ID active_view = get_active_view(app, Access_Always); - b32 is_active_view = (active_view == view_id); - Rect_f32 prev_clip = draw_set_clip(app, rect); - - // NOTE(allen): Token colorizing - Token_Array token_array = get_token_array_from_buffer(app, buffer); - if (token_array.tokens != 0){ - draw_cpp_token_colors(app, text_layout_id, &token_array); - - // NOTE(allen): Scan for TODOs and NOTEs - if (global_config.use_comment_keyword){ - Comment_Highlight_Pair pairs[] = { - {string_u8_litexpr("NOTE"), Stag_Text_Cycle_2}, - {string_u8_litexpr("TODO"), Stag_Text_Cycle_1}, - }; - draw_comment_highlights(app, buffer, text_layout_id, - &token_array, pairs, ArrayCount(pairs)); - } - } - - i64 cursor_pos = view_correct_cursor(app, view_id); - view_correct_mark(app, view_id); - - // NOTE(allen): Scope highlight - if (global_config.use_scope_highlight){ - FColor colors[] = { - fcolor_id(Stag_Back_Cycle_1), fcolor_id(Stag_Back_Cycle_2), - fcolor_id(Stag_Back_Cycle_3), fcolor_id(Stag_Back_Cycle_4), - }; - draw_scope_highlight(app, buffer, text_layout_id, cursor_pos, colors, ArrayCount(colors)); - } - - if (global_config.use_error_highlight || global_config.use_jump_highlight){ - // NOTE(allen): Error highlight - String_Const_u8 name = string_u8_litexpr("*compilation*"); - Buffer_ID compilation_buffer = get_buffer_by_name(app, name, Access_Always); - if (global_config.use_error_highlight){ - draw_jump_highlights(app, buffer, text_layout_id, compilation_buffer, - fcolor_id(Stag_Highlight_Junk)); - } - - // NOTE(allen): Search highlight - if (global_config.use_jump_highlight){ - Buffer_ID jump_buffer = get_locked_jump_buffer(app); - if (jump_buffer != compilation_buffer){ - draw_jump_highlights(app, buffer, text_layout_id, jump_buffer, - fcolor_id(Stag_Highlight_White)); - } - } - } - - // NOTE(allen): Color parens - if (global_config.use_paren_helper){ - FColor colors[] = { - fcolor_id(Stag_Text_Cycle_1), fcolor_id(Stag_Text_Cycle_2), - fcolor_id(Stag_Text_Cycle_3), fcolor_id(Stag_Text_Cycle_4), - }; - draw_paren_highlight(app, buffer, text_layout_id, cursor_pos, - colors, ArrayCount(colors)); - } - - // NOTE(allen): Line highlight - if (global_config.highlight_line_at_cursor && is_active_view){ - i64 line_number = get_line_number_from_pos(app, buffer, cursor_pos); - draw_line_highlight(app, text_layout_id, line_number, - fcolor_id(Stag_Highlight_Cursor_Line)); - } - - // NOTE(allen): Cursor shape - Face_Metrics metrics = get_face_metrics(app, face_id); - f32 cursor_roundness = (metrics.normal_advance*0.5f)*0.9f; - f32 mark_thickness = 2.f; - - // NOTE(allen): Cursor - switch (fcoder_mode){ - case FCoderMode_Original: - { - draw_original_4coder_style_cursor_mark_highlight(app, view_id, is_active_view, buffer, text_layout_id, cursor_roundness, mark_thickness); - }break; - case FCoderMode_NotepadLike: - { - draw_notepad_style_cursor_highlight(app, view_id, buffer, text_layout_id, cursor_roundness); - }break; - } - - // NOTE(allen): put the actual text on the actual screen - draw_text_layout(app, text_layout_id); - - draw_set_clip(app, prev_clip); -} - -function void -default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID view_id){ - ProfileScope(app, "default render caller"); - View_ID active_view = get_active_view(app, Access_Always); - b32 is_active_view = (active_view == view_id); - - Rect_f32 region = draw_background_and_margin(app, view_id, is_active_view); - Rect_f32 prev_clip = draw_set_clip(app, region); - - Buffer_ID buffer = view_get_buffer(app, view_id, Access_Always); - Face_ID face_id = get_face_id(app, buffer); - Face_Metrics face_metrics = get_face_metrics(app, face_id); - f32 line_height = face_metrics.line_height; - f32 digit_advance = face_metrics.decimal_digit_advance; - - // NOTE(allen): file bar - 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); - draw_file_bar(app, view_id, buffer, face_id, pair.min); - region = pair.max; - } - - 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); - } - - // NOTE(allen): query bars - { - Query_Bar *space[32]; - Query_Bar_Ptr_Array query_bars = {}; - query_bars.ptrs = space; - if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){ - for (i32 i = 0; i < query_bars.count; i += 1){ - Rect_f32_Pair pair = layout_query_bar_on_top(region, line_height, 1); - draw_query_bar(app, query_bars.ptrs[i], face_id, pair.min); - region = pair.max; - } - } - } - - // NOTE(allen): FPS hud - if (show_fps_hud){ - Rect_f32_Pair pair = layout_fps_hud_on_bottom(region, line_height); - draw_fps_hud(app, frame_info, face_id, pair.max); - region = pair.min; - animate_in_n_milliseconds(app, 1000); - } - - // NOTE(allen): layout line numbers - Rect_f32 line_number_rect = {}; - if (global_config.show_line_number_margins){ - Rect_f32_Pair pair = layout_line_number_margin(app, buffer, region, digit_advance); - line_number_rect = pair.min; - region = pair.max; - } - - // NOTE(allen): begin buffer render - Buffer_Point buffer_point = scroll.position; - Text_Layout_ID text_layout_id = text_layout_create(app, buffer, region, buffer_point); - - // NOTE(allen): draw line numbers - if (global_config.show_line_number_margins){ - draw_line_number_margin(app, view_id, buffer, face_id, text_layout_id, line_number_rect); - } - - // NOTE(allen): draw the buffer - default_render_buffer(app, view_id, face_id, buffer, text_layout_id, region); - - text_layout_free(app, text_layout_id); - draw_set_clip(app, prev_clip); -} - -HOOK_SIG(default_view_adjust){ - // NOTE(allen): Called whenever the view layout/sizes have been modified, - // including by full window resize. - return(0); -} - -BUFFER_NAME_RESOLVER_SIG(default_buffer_name_resolution){ - ProfileScope(app, "default buffer name resolution"); - if (conflict_count > 1){ - // List of unresolved conflicts - Scratch_Block scratch(app); - - i32 *unresolved = push_array(scratch, i32, conflict_count); - i32 unresolved_count = conflict_count; - for (i32 i = 0; i < conflict_count; ++i){ - unresolved[i] = i; - } - - // Resolution Loop - i32 x = 0; - for (;;){ - // Resolution Pass - ++x; - for (i32 i = 0; i < unresolved_count; ++i){ - i32 conflict_index = unresolved[i]; - Buffer_Name_Conflict_Entry *conflict = &conflicts[conflict_index]; - - umem size = conflict->base_name.size; - size = clamp_top(size, conflict->unique_name_capacity); - conflict->unique_name_len_in_out = size; - block_copy(conflict->unique_name_in_out, conflict->base_name.str, size); - - if (conflict->file_name.str != 0){ - Temp_Memory_Block temp(scratch); - String_Const_u8 uniqueifier = {}; - - String_Const_u8 file_name = string_remove_last_folder(conflict->file_name); - if (file_name.size > 0){ - file_name = string_chop(file_name, 1); - u8 *end = file_name.str + file_name.size; - b32 past_the_end = false; - for (i32 j = 0; j < x; ++j){ - file_name = string_remove_last_folder(file_name); - if (j + 1 < x){ - file_name = string_chop(file_name, 1); - } - if (file_name.size == 0){ - if (j + 1 < x){ - past_the_end = true; - } - break; - } - } - u8 *start = file_name.str + file_name.size; - - uniqueifier = SCu8(start, end); - if (past_the_end){ - uniqueifier = push_u8_stringf(scratch, "%.*s~%d", - string_expand(uniqueifier), i); - } - } - else{ - uniqueifier = push_u8_stringf(scratch, "%d", i); - } - - String_u8 builder = Su8(conflict->unique_name_in_out, - conflict->unique_name_len_in_out, - conflict->unique_name_capacity); - string_append(&builder, string_u8_litexpr(" <")); - string_append(&builder, uniqueifier); - string_append(&builder, string_u8_litexpr(">")); - conflict->unique_name_len_in_out = builder.size; - } - } - - // Conflict Check Pass - b32 has_conflicts = false; - for (i32 i = 0; i < unresolved_count; ++i){ - i32 conflict_index = unresolved[i]; - Buffer_Name_Conflict_Entry *conflict = &conflicts[conflict_index]; - String_Const_u8 conflict_name = SCu8(conflict->unique_name_in_out, - conflict->unique_name_len_in_out); - - b32 hit_conflict = false; - if (conflict->file_name.str != 0){ - for (i32 j = 0; j < unresolved_count; ++j){ - if (i == j) continue; - - i32 conflict_j_index = unresolved[j]; - Buffer_Name_Conflict_Entry *conflict_j = &conflicts[conflict_j_index]; - - String_Const_u8 conflict_name_j = SCu8(conflict_j->unique_name_in_out, - conflict_j->unique_name_len_in_out); - - if (string_match(conflict_name, conflict_name_j)){ - hit_conflict = true; - break; - } - } - } - - if (hit_conflict){ - has_conflicts = true; - } - else{ - --unresolved_count; - unresolved[i] = unresolved[unresolved_count]; - --i; - } - } - - if (!has_conflicts){ - break; - } - } - } -} - -function void -parse_async__inner(Async_Context *actx, Buffer_ID buffer_id, - String_Const_u8 contents, Token_Array *tokens, i32 limit_factor){ - Application_Links *app = actx->app; - ProfileBlock(app, "async parse"); - - Arena arena = make_arena_system(KB(16)); - Code_Index_File *index = push_array_zero(&arena, Code_Index_File, 1); - index->buffer = buffer_id; - - Generic_Parse_State state = {}; - generic_parse_init(app, &arena, contents, tokens, &state); - - b32 canceled = false; - - for (;;){ - if (generic_parse_full_input_breaks(index, &state, limit_factor)){ - break; - } - if (async_check_canceled(actx)){ - canceled = true; - break; - } - } - - if (!canceled){ - Thread_Context *tctx = get_thread_context(app); - system_acquire_global_frame_mutex(tctx); - code_index_lock(); - code_index_set_file(buffer_id, arena, index); - code_index_unlock(); - buffer_clear_layout_cache(app, buffer_id); - system_release_global_frame_mutex(tctx); - } - else{ - linalloc_clear(&arena); - } -} - -function void -do_full_lex_async__inner(Async_Context *actx, Buffer_ID buffer_id){ - Application_Links *app = actx->app; - ProfileScope(app, "async lex"); - Thread_Context *tctx = get_thread_context(app); - Scratch_Block scratch(tctx); - - String_Const_u8 contents = {}; - { - ProfileBlock(app, "async lex contents (before mutex)"); - system_acquire_global_frame_mutex(tctx); - ProfileBlock(app, "async lex contents (after mutex)"); - contents = push_whole_buffer(app, scratch, buffer_id); - system_release_global_frame_mutex(tctx); - } - - i32 limit_factor = 10000; - - Token_List list = {}; - b32 canceled = false; - - Lex_State_Cpp state = {}; - lex_full_input_cpp_init(&state, contents); - for (;;){ - ProfileBlock(app, "async lex block"); - if (lex_full_input_cpp_breaks(scratch, &list, &state, limit_factor)){ - break; - } - if (async_check_canceled(actx)){ - canceled = true; - break; - } - } - - if (!canceled){ - ProfileBlock(app, "async lex save results (before mutex)"); - system_acquire_global_frame_mutex(tctx); - ProfileBlock(app, "async lex save results (after mutex)"); - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - if (scope != 0){ - Base_Allocator *allocator = managed_scope_allocator(app, scope); - Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, - Token_Array); - base_free(allocator, tokens_ptr->tokens); - Token_Array tokens = {}; - tokens.tokens = base_array(allocator, Token, list.total_count); - tokens.count = list.total_count; - tokens.max = list.total_count; - token_fill_memory_from_list(tokens.tokens, &list); - block_copy_struct(tokens_ptr, &tokens); - } - buffer_mark_as_modified(buffer_id); - system_release_global_frame_mutex(tctx); - } -} - -function void -do_full_lex_async(Async_Context *actx, Data data){ - if (data.size == sizeof(Buffer_ID)){ - Buffer_ID buffer = *(Buffer_ID*)data.data; - do_full_lex_async__inner(actx, buffer); - } -} - -#if 0 -function void -do_full_lex_and_parse_async__inner(Async_Context *actx, Buffer_ID buffer_id){ - Application_Links *app = actx->app; - ProfileScope(app, "async lex"); - Thread_Context *tctx = get_thread_context(app); - Scratch_Block scratch(tctx); - - String_Const_u8 contents = {}; - { - ProfileBlock(app, "async lex contents (before mutex)"); - system_acquire_global_frame_mutex(tctx); - ProfileBlock(app, "async lex contents (after mutex)"); - - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - if (scope != 0){ - Base_Allocator *allocator = managed_scope_allocator(app, scope); - Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, - Token_Array); - base_free(allocator, tokens_ptr->tokens); - block_zero_struct(tokens_ptr); - } - - contents = push_whole_buffer(app, scratch, buffer_id); - system_release_global_frame_mutex(tctx); - } - - i32 limit_factor = 10000; - - Token_List list = {}; - b32 canceled = false; - - { - Lex_State_Cpp state = {}; - lex_full_input_cpp_init(&state, contents); - for (;;){ - ProfileBlock(app, "async lex block"); - if (lex_full_input_cpp_breaks(scratch, &list, &state, limit_factor)){ - break; - } - if (async_check_canceled(actx)){ - canceled = true; - break; - } - } - } - - Token_Array tokens = {}; - if (!canceled){ - ProfileBlock(app, "async lex save results (before mutex)"); - system_acquire_global_frame_mutex(tctx); - ProfileBlock(app, "async lex save results (after mutex)"); - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - if (scope != 0){ - Base_Allocator *allocator = managed_scope_allocator(app, scope); - Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, - Token_Array); - base_free(allocator, tokens_ptr->tokens); - tokens.tokens = base_array(allocator, Token, list.total_count); - tokens.count = list.total_count; - tokens.max = list.total_count; - token_fill_memory_from_list(tokens.tokens, &list); - block_copy_struct(tokens_ptr, &tokens); - } - system_release_global_frame_mutex(tctx); - } - - if (tokens.count > 0){ - parse_async__inner(actx, buffer_id, contents, &tokens, limit_factor); - } -} - -function void -do_full_lex_and_parse_async(Async_Context *actx, Data data){ - if (data.size == sizeof(Buffer_ID)){ - Buffer_ID buffer = *(Buffer_ID*)data.data; - do_full_lex_and_parse_async__inner(actx, buffer); - } -} -#endif - -#if 0 -function void -do_parse_async__inner(Async_Context *actx, Buffer_ID buffer_id){ - Application_Links *app = actx->app; - ProfileScope(app, "async lex"); - Thread_Context *tctx = get_thread_context(app); - Scratch_Block scratch(tctx); - - String_Const_u8 contents = {}; - Token_Array tokens = {}; - { - ProfileBlock(app, "async parse contents (before mutex)"); - system_acquire_global_frame_mutex(tctx); - ProfileBlock(app, "async parse contents (after mutex)"); - - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - if (scope != 0){ - Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, - Token_Array); - tokens.count = tokens_ptr->count; - tokens.tokens = push_array_write(scratch, Token, tokens.count, tokens_ptr->tokens); - if (tokens.count > 0){ - contents = push_whole_buffer(app, scratch, buffer_id); - } - } - - system_release_global_frame_mutex(tctx); - } - - i32 limit_factor = 10000; - - if (tokens.count > 0){ - parse_async__inner(actx, buffer_id, contents, &tokens, limit_factor); - } -} - -function void -do_parse_async(Async_Context *actx, Data data){ - if (data.size == sizeof(Buffer_ID)){ - Buffer_ID buffer = *(Buffer_ID*)data.data; - do_parse_async__inner(actx, buffer); - } -} -#endif - -BUFFER_HOOK_SIG(default_begin_buffer){ - ProfileScope(app, "begin buffer"); - - Scratch_Block scratch(app); - - b32 treat_as_code = false; - String_Const_u8 file_name = push_buffer_file_name(app, scratch, buffer_id); - if (file_name.size > 0){ - String_Const_u8_Array extensions = global_config.code_exts; - String_Const_u8 ext = string_file_extension(file_name); - for (i32 i = 0; i < extensions.count; ++i){ - if (string_match(ext, extensions.strings[i])){ - - if (string_match(ext, string_u8_litexpr("cpp")) || - string_match(ext, string_u8_litexpr("h")) || - string_match(ext, string_u8_litexpr("c")) || - string_match(ext, string_u8_litexpr("hpp")) || - string_match(ext, string_u8_litexpr("cc"))){ - treat_as_code = true; - } - -#if 0 - treat_as_code = true; - - if (string_match(ext, string_u8_litexpr("cs"))){ - if (parse_context_language_cs == 0){ - init_language_cs(app); - } - parse_context_id = parse_context_language_cs; - } - - if (string_match(ext, string_u8_litexpr("java"))){ - if (parse_context_language_java == 0){ - init_language_java(app); - } - parse_context_id = parse_context_language_java; - } - - if (string_match(ext, string_u8_litexpr("rs"))){ - if (parse_context_language_rust == 0){ - init_language_rust(app); - } - parse_context_id = parse_context_language_rust; - } - - if (string_match(ext, string_u8_litexpr("cpp")) || - string_match(ext, string_u8_litexpr("h")) || - string_match(ext, string_u8_litexpr("c")) || - string_match(ext, string_u8_litexpr("hpp")) || - string_match(ext, string_u8_litexpr("cc"))){ - if (parse_context_language_cpp == 0){ - init_language_cpp(app); - } - parse_context_id = parse_context_language_cpp; - } - - // TODO(NAME): Real GLSL highlighting - if (string_match(ext, string_u8_litexpr("glsl"))){ - if (parse_context_language_cpp == 0){ - init_language_cpp(app); - } - parse_context_id = parse_context_language_cpp; - } - - // TODO(NAME): Real Objective-C highlighting - if (string_match(ext, string_u8_litexpr("m"))){ - if (parse_context_language_cpp == 0){ - init_language_cpp(app); - } - parse_context_id = parse_context_language_cpp; - } -#endif - - break; - } - } - } - - Command_Map_ID map_id = (treat_as_code)?(default_code_map):(mapid_file); - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - Command_Map_ID *map_id_ptr = scope_attachment(app, scope, buffer_map_id, Command_Map_ID); - *map_id_ptr = map_id; - - Line_Ending_Kind setting = guess_line_ending_kind_from_buffer(app, buffer_id); - Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, Line_Ending_Kind); - *eol_setting = setting; - - // NOTE(allen): Decide buffer settings - b32 wrap_lines = true; - b32 use_virtual_whitespace = false; - b32 use_lexer = false; - if (treat_as_code){ - wrap_lines = global_config.enable_code_wrapping; - use_virtual_whitespace = global_config.enable_virtual_whitespace; - use_lexer = true; - } - - String_Const_u8 buffer_name = push_buffer_base_name(app, scratch, buffer_id); - if (string_match(buffer_name, string_u8_litexpr("*compilation*"))){ - wrap_lines = false; - } - - if (use_lexer){ - ProfileBlock(app, "begin buffer kick off lexer"); - Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); - *lex_task_ptr = async_task_no_dep(&global_async_system, do_full_lex_async, make_data_struct(&buffer_id)); - } - - { - b32 *wrap_lines_ptr = scope_attachment(app, scope, buffer_wrap_lines, b32); - *wrap_lines_ptr = wrap_lines; - } - - if (use_virtual_whitespace){ - if (use_lexer){ - buffer_set_layout(app, buffer_id, layout_virt_indent_index_generic); - } - else{ - buffer_set_layout(app, buffer_id, layout_virt_indent_literal_generic); - } - } - else{ - buffer_set_layout(app, buffer_id, layout_generic); - } - - // no meaning for return - return(0); -} - -BUFFER_HOOK_SIG(default_new_file){ - // buffer_id - // no meaning for return - return(0); -} - -BUFFER_HOOK_SIG(default_file_save){ - // buffer_id - ProfileScope(app, "default file save"); - b32 is_virtual = false; - if (global_config.automatically_indent_text_on_save && is_virtual){ - auto_indent_buffer(app, buffer_id, buffer_range(app, buffer_id)); - } - - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - Line_Ending_Kind *eol = scope_attachment(app, scope, buffer_eol_setting, - Line_Ending_Kind); - switch (*eol){ - case LineEndingKind_LF: - { - rewrite_lines_to_lf(app, buffer_id); - }break; - case LineEndingKind_CRLF: - { - rewrite_lines_to_crlf(app, buffer_id); - }break; - } - - // no meaning for return - return(0); -} - -BUFFER_EDIT_RANGE_SIG(default_buffer_edit_range){ - // buffer_id, new_range, original_size - ProfileScope(app, "default edit range"); - - Range_i64 old_range = Ii64(new_range.first, new_range.first + original_size); - - { - code_index_lock(); - Code_Index_File *file = code_index_get_file(buffer_id); - if (file != 0){ - code_index_shift(file, old_range, range_size(new_range)); - } - code_index_unlock(); - } - - i64 insert_size = range_size(new_range); - i64 text_shift = replace_range_shift(old_range, insert_size); - - Scratch_Block scratch(app); - - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); - - Base_Allocator *allocator = managed_scope_allocator(app, scope); - b32 do_full_relex = false; - - if (async_task_is_running_or_pending(&global_async_system, *lex_task_ptr)){ - async_task_cancel(&global_async_system, *lex_task_ptr); - buffer_unmark_as_modified(buffer_id); - do_full_relex = true; - *lex_task_ptr = 0; - } - - Token_Array *ptr = scope_attachment(app, scope, attachment_tokens, Token_Array); - if (ptr != 0 && ptr->tokens != 0){ - ProfileBlockNamed(app, "attempt resync", profile_attempt_resync); - - i64 token_index_first = token_relex_first(ptr, old_range.first, 1); - i64 token_index_resync_guess = - token_relex_resync(ptr, old_range.one_past_last, 16); - - if (token_index_resync_guess - token_index_first >= 4000){ - do_full_relex = true; - } - else{ - Token *token_first = ptr->tokens + token_index_first; - Token *token_resync = ptr->tokens + token_index_resync_guess; - - Range_i64 relex_range = Ii64(token_first->pos, token_resync->pos + token_resync->size + text_shift); - String_Const_u8 partial_text = push_buffer_range(app, scratch, buffer_id, relex_range); - - Token_List relex_list = lex_full_input_cpp(scratch, partial_text); - if (relex_range.one_past_last < buffer_get_size(app, buffer_id)){ - token_drop_eof(&relex_list); - } - - Token_Relex relex = token_relex(relex_list, relex_range.first - text_shift, ptr->tokens, token_index_first, token_index_resync_guess); - - ProfileCloseNow(profile_attempt_resync); - - if (!relex.successful_resync){ - do_full_relex = true; - } - else{ - ProfileBlock(app, "apply resync"); - - i64 token_index_resync = relex.first_resync_index; - - Interval_i64 head = Ii64(0, token_index_first); - Interval_i64 replaced = Ii64(token_index_first, token_index_resync); - Interval_i64 tail = Ii64(token_index_resync, ptr->count); - i64 resynced_count = (token_index_resync_guess + 1) - token_index_resync; - i64 relexed_count = relex_list.total_count - resynced_count; - i64 tail_shift = relexed_count - (token_index_resync - token_index_first); - - i64 new_tokens_count = ptr->count + tail_shift; - Token *new_tokens = base_array(allocator, Token, new_tokens_count); - - Token *old_tokens = ptr->tokens; - block_copy_array_shift(new_tokens, old_tokens, head, 0); - token_fill_memory_from_list(new_tokens + replaced.first, &relex_list, relexed_count); - for (i64 i = 0, index = replaced.first; i < relexed_count; i += 1, index += 1){ - new_tokens[index].pos += relex_range.first; - } - for (i64 i = tail.first; i < tail.one_past_last; i += 1){ - old_tokens[i].pos += text_shift; - } - block_copy_array_shift(new_tokens, ptr->tokens, tail, tail_shift); - - base_free(allocator, ptr->tokens); - - ptr->tokens = new_tokens; - ptr->count = new_tokens_count; - ptr->max = new_tokens_count; - - buffer_mark_as_modified(buffer_id); - } - } - } - - if (do_full_relex){ - *lex_task_ptr = async_task_no_dep(&global_async_system, do_full_lex_async, - make_data_struct(&buffer_id)); - } - - // no meaning for return - return(0); -} - -BUFFER_HOOK_SIG(default_end_buffer){ - Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); - Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); - if (lex_task_ptr != 0){ - async_task_cancel(&global_async_system, *lex_task_ptr); - } - buffer_unmark_as_modified(buffer_id); - code_index_lock(); - code_index_erase_file(buffer_id); - code_index_unlock(); - // no meaning for return - return(0); -} - -internal void -set_all_default_hooks(Application_Links *app){ - set_custom_hook(app, HookID_BufferViewerUpdate, default_view_adjust); - - set_custom_hook(app, HookID_ViewEventHandler, default_view_input_handler); - set_custom_hook(app, HookID_Tick, default_tick); - set_custom_hook(app, HookID_RenderCaller, default_render_caller); -#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_begin_buffer); - set_custom_hook(app, HookID_EndBuffer, end_buffer_close_jump_list); - 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_buffer_region); - - set_custom_hook(app, HookID_Layout, layout_unwrapped); - //set_custom_hook(app, HookID_Layout, layout_wrap_anywhere); - //set_custom_hook(app, HookID_Layout, layout_wrap_whitespace); - //set_custom_hook(app, HookID_Layout, layout_virt_indent_unwrapped); - //set_custom_hook(app, HookID_Layout, layout_unwrapped_small_blank_lines); -} - -// BOTTOM - +/* +4coder_default_hooks.cpp - Sets up the hooks for the default framework. +*/ + +// TOP + +CUSTOM_COMMAND_SIG(default_startup) +CUSTOM_DOC("Default command for responding to a startup event") +{ + ProfileScope(app, "default startup"); + User_Input input = get_current_input(app); + if (match_core_code(&input, CoreCode_Startup)){ + String_Const_u8_Array file_names = input.event.core.file_names; + default_4coder_initialize(app, file_names); + default_4coder_side_by_side_panels(app, file_names); + if (global_config.automatically_load_project){ + load_project(app); + } + } +} + +CUSTOM_COMMAND_SIG(default_try_exit) +CUSTOM_DOC("Default command for responding to a try-exit event") +{ + User_Input input = get_current_input(app); + if (match_core_code(&input, CoreCode_TryExit)){ + b32 do_exit = true; + if (!allow_immediate_close_without_checking_for_changes){ + b32 has_unsaved_changes = false; + for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); + buffer != 0; + buffer = get_buffer_next(app, buffer, Access_Always)){ + Dirty_State dirty = buffer_get_dirty_state(app, buffer); + if (HasFlag(dirty, DirtyState_UnsavedChanges)){ + has_unsaved_changes = true; + break; + } + } + if (has_unsaved_changes){ + View_ID view = get_active_view(app, Access_Always); + do_exit = do_4coder_close_user_check(app, view); + } + } + if (do_exit){ + // NOTE(allen): By leaving try exit unhandled we indicate + // that the core should take responsibility for handling this, + // and it will handle it by exiting 4coder. If we leave this + // event marked as handled on the other hand (for instance by + // running a confirmation GUI that cancels the exit) then 4coder + // will not exit. + leave_current_input_unhandled(app); + } + } +} + +CUSTOM_COMMAND_SIG(default_view_input_handler) +CUSTOM_DOC("Input consumption loop for default view behavior") +{ + Thread_Context *tctx = get_thread_context(app); + Scratch_Block scratch(tctx); + + { + + View_ID view = get_this_ctx_view(app, Access_Always); + String_Const_u8 name = push_u8_stringf(scratch, "view %d", view); + + Profile_Global_List *list = get_core_profile_list(app); + ProfileThreadName(tctx, list, name); + + View_Context ctx = view_current_context(app, view); + ctx.mapping = &framework_mapping; + ctx.map_id = mapid_global; + view_alter_context(app, view, &ctx); + } + + for (;;){ + // NOTE(allen): Get the binding from the buffer's current map + User_Input input = get_next_input(app, EventPropertyGroup_Any, 0); + ProfileScopeNamed(app, "before view input", view_input_profile); + if (input.abort){ + break; + } + + Event_Property event_properties = get_event_properties(&input.event); + + if (suppressing_mouse && (event_properties & EventPropertyGroup_AnyMouseEvent) != 0){ + continue; + } + + View_ID view = get_this_ctx_view(app, Access_Always); + + Buffer_ID buffer = view_get_buffer(app, view, Access_Always); + Managed_Scope buffer_scope = buffer_get_managed_scope(app, buffer); + Command_Map_ID *map_id_ptr = scope_attachment(app, buffer_scope, buffer_map_id, Command_Map_ID); + if (*map_id_ptr == 0){ + *map_id_ptr = mapid_file; + } + Command_Map_ID map_id = *map_id_ptr; + + Command_Binding binding = map_get_binding_recursive(&framework_mapping, map_id, &input.event); + + Managed_Scope scope = view_get_managed_scope(app, view); + + if (binding.custom == 0){ + // NOTE(allen): we don't have anything to do with this input, + // leave it marked unhandled so that if there's a follow up + // event it is not blocked. + leave_current_input_unhandled(app); + } + else{ + // NOTE(allen): before the command is called do some book keeping + Rewrite_Type *next_rewrite = + scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); + *next_rewrite = Rewrite_None; + if (fcoder_mode == FCoderMode_NotepadLike){ + for (View_ID view_it = get_view_next(app, 0, Access_Always); + view_it != 0; + view_it = get_view_next(app, view_it, Access_Always)){ + Managed_Scope scope_it = view_get_managed_scope(app, view_it); + b32 *snap_mark_to_cursor = + scope_attachment(app, scope_it, view_snap_mark_to_cursor, + b32); + *snap_mark_to_cursor = true; + } + } + + ProfileCloseNow(view_input_profile); + + // NOTE(allen): call the command + binding.custom(app); + + // NOTE(allen): after the command is called do some book keeping + ProfileScope(app, "after view input"); + + next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type); + if (next_rewrite != 0){ + Rewrite_Type *rewrite = + scope_attachment(app, scope, view_rewrite_loc, Rewrite_Type); + *rewrite = *next_rewrite; + if (fcoder_mode == FCoderMode_NotepadLike){ + for (View_ID view_it = get_view_next(app, 0, Access_Always); + view_it != 0; + view_it = get_view_next(app, view_it, Access_Always)){ + Managed_Scope scope_it = view_get_managed_scope(app, view_it); + b32 *snap_mark_to_cursor = + scope_attachment(app, scope_it, view_snap_mark_to_cursor, b32); + if (*snap_mark_to_cursor){ + i64 pos = view_get_cursor_pos(app, view_it); + view_set_mark(app, view_it, seek_pos(pos)); + } + } + } + } + } + } +} + +#if 0 +static argb_color default_colors[Stag_COUNT] = {}; +MODIFY_COLOR_TABLE_SIG(default_modify_color_table){ + if (default_colors[Stag_NOOP] == 0){ + default_colors[Stag_NOOP] = 0xFFFF00FF; + + default_colors[Stag_Back] = 0xFF0C0C0C; + default_colors[Stag_Margin] = 0xFF181818; + default_colors[Stag_Margin_Hover] = 0xFF252525; + default_colors[Stag_Margin_Active] = 0xFF323232; + default_colors[Stag_List_Item] = default_colors[Stag_Margin]; + default_colors[Stag_List_Item_Hover] = default_colors[Stag_Margin_Hover]; + default_colors[Stag_List_Item_Active] = default_colors[Stag_Margin_Active]; + default_colors[Stag_Cursor] = 0xFF00EE00; + default_colors[Stag_Highlight] = 0xFFDDEE00; + default_colors[Stag_Mark] = 0xFF494949; + default_colors[Stag_Default] = 0xFF90B080; + default_colors[Stag_At_Cursor] = default_colors[Stag_Back]; + default_colors[Stag_Highlight_Cursor_Line] = 0xFF1E1E1E; + default_colors[Stag_At_Highlight] = 0xFFFF44DD; + default_colors[Stag_Comment] = 0xFF2090F0; + default_colors[Stag_Keyword] = 0xFFD08F20; + default_colors[Stag_Str_Constant] = 0xFF50FF30; + default_colors[Stag_Char_Constant] = default_colors[Stag_Str_Constant]; + default_colors[Stag_Int_Constant] = default_colors[Stag_Str_Constant]; + default_colors[Stag_Float_Constant] = default_colors[Stag_Str_Constant]; + default_colors[Stag_Bool_Constant] = default_colors[Stag_Str_Constant]; + default_colors[Stag_Include] = default_colors[Stag_Str_Constant]; + default_colors[Stag_Preproc] = default_colors[Stag_Default]; + default_colors[Stag_Special_Character] = 0xFFFF0000; + default_colors[Stag_Ghost_Character] = 0xFF4E5E46; + + default_colors[Stag_Paste] = 0xFFDDEE00; + default_colors[Stag_Undo] = 0xFF00DDEE; + + default_colors[Stag_Highlight_Junk] = 0xFF3A0000; + default_colors[Stag_Highlight_White] = 0xFF003A3A; + + default_colors[Stag_Bar] = 0xFF888888; + default_colors[Stag_Base] = 0xFF000000; + default_colors[Stag_Pop1] = 0xFF3C57DC; + default_colors[Stag_Pop2] = 0xFFFF0000; + + default_colors[Stag_Back_Cycle_1] = 0x10A00000; + default_colors[Stag_Back_Cycle_2] = 0x0C00A000; + default_colors[Stag_Back_Cycle_3] = 0x0C0000A0; + default_colors[Stag_Back_Cycle_4] = 0x0CA0A000; + default_colors[Stag_Text_Cycle_1] = 0xFFA00000; + default_colors[Stag_Text_Cycle_2] = 0xFF00A000; + default_colors[Stag_Text_Cycle_3] = 0xFF0030B0; + default_colors[Stag_Text_Cycle_4] = 0xFFA0A000; + + default_colors[Stag_Line_Numbers_Back] = 0xFF101010; + default_colors[Stag_Line_Numbers_Text] = 0xFF404040; + } + + Color_Table color_table = {}; + color_table.vals = default_colors; + color_table.count = ArrayCount(default_colors); + return(color_table); +} +#endif + +function void +default_tick(Application_Links *app, Frame_Info frame_info){ + Scratch_Block scratch(app); + + for (Buffer_Modified_Node *node = global_buffer_modified_set.first; + node != 0; + node = node->next){ + Temp_Memory_Block temp(scratch); + Buffer_ID buffer_id = node->buffer; + + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + + String_Const_u8 contents = push_whole_buffer(app, scratch, buffer_id); + Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, Token_Array); + if (tokens_ptr == 0){ + continue; + } + if (tokens_ptr->count == 0){ + continue; + } + Token_Array tokens = *tokens_ptr; + + Arena arena = make_arena_system(KB(16)); + Code_Index_File *index = push_array_zero(&arena, Code_Index_File, 1); + index->buffer = buffer_id; + + Generic_Parse_State state = {}; + generic_parse_init(app, &arena, contents, &tokens, &state); + generic_parse_full_input_breaks(index, &state, max_i32); + + code_index_lock(); + code_index_set_file(buffer_id, arena, index); + code_index_unlock(); + buffer_clear_layout_cache(app, buffer_id); + } + + buffer_modified_set_clear(); +} + +function Rect_f32 +default_buffer_region(Application_Links *app, View_ID view_id, Rect_f32 region){ + Buffer_ID buffer = view_get_buffer(app, view_id, Access_Always); + Face_ID face_id = get_face_id(app, buffer); + Face_Metrics metrics = get_face_metrics(app, face_id); + f32 line_height = metrics.line_height; + f32 digit_advance = metrics.decimal_digit_advance; + + // NOTE(allen): margins + region = rect_inner(region, 3.f); + + // NOTE(allen): file bar + 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.max; + } + + // NOTE(allen): query bars + { + Query_Bar *space[32]; + Query_Bar_Ptr_Array query_bars = {}; + query_bars.ptrs = space; + if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){ + Rect_f32_Pair pair = layout_query_bar_on_top(region, line_height, query_bars.count); + region = pair.max; + } + } + + // NOTE(allen): FPS hud + if (show_fps_hud){ + Rect_f32_Pair pair = layout_fps_hud_on_bottom(region, line_height); + region = pair.min; + } + + // NOTE(allen): line numbers + if (global_config.show_line_number_margins){ + Rect_f32_Pair pair = layout_line_number_margin(app, buffer, region, digit_advance); + region = pair.max; + } + + return(region); +} + +function void +recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, + Code_Index_Nest_Ptr_Array *array, i32 counter){ + Code_Index_Nest **ptr = array->ptrs; + Code_Index_Nest **ptr_end = ptr + array->count; + + for (;ptr < ptr_end; ptr += 1){ + Code_Index_Nest *nest = *ptr; + if (!nest->is_closed){ + break; + } + if (range.first <= nest->close.max){ + break; + } + } + + ARGB_Color argb = finalize_color(defcolor_text_cycle, counter); + + for (;ptr < ptr_end; ptr += 1){ + Code_Index_Nest *nest = *ptr; + if (range.max <= nest->open.min){ + break; + } + + paint_text_color(app, layout_id, nest->open, argb); + if (nest->is_closed){ + paint_text_color(app, layout_id, nest->close, argb); + } + recursive_nest_highlight(app, layout_id, range, &nest->nest_array, counter + 1); + } +} + +function void +recursive_nest_highlight(Application_Links *app, Text_Layout_ID layout_id, Range_i64 range, + Code_Index_File *file){ + recursive_nest_highlight(app, layout_id, range, &file->nest_array, 0); +} + +function void +default_render_buffer(Application_Links *app, View_ID view_id, Face_ID face_id, + Buffer_ID buffer, Text_Layout_ID text_layout_id, + Rect_f32 rect){ + ProfileScope(app, "render buffer"); + + View_ID active_view = get_active_view(app, Access_Always); + b32 is_active_view = (active_view == view_id); + Rect_f32 prev_clip = draw_set_clip(app, rect); + + // NOTE(allen): Token colorizing + Token_Array token_array = get_token_array_from_buffer(app, buffer); + if (token_array.tokens != 0){ + draw_cpp_token_colors(app, text_layout_id, &token_array); + + // NOTE(allen): Scan for TODOs and NOTEs + if (global_config.use_comment_keyword){ + Comment_Highlight_Pair pairs[] = { + {string_u8_litexpr("NOTE"), finalize_color(defcolor_comment_pop, 0)}, + {string_u8_litexpr("TODO"), finalize_color(defcolor_comment_pop, 1)}, + }; + draw_comment_highlights(app, buffer, text_layout_id, + &token_array, pairs, ArrayCount(pairs)); + } + } + else{ + Range_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); + paint_text_color_fcolor(app, text_layout_id, visible_range, fcolor_id(defcolor_text_default)); + } + + i64 cursor_pos = view_correct_cursor(app, view_id); + view_correct_mark(app, view_id); + + // NOTE(allen): Scope highlight + if (global_config.use_scope_highlight){ + Color_Array colors = finalize_color_array(defcolor_back_cycle); + draw_scope_highlight(app, buffer, text_layout_id, cursor_pos, colors.vals, colors.count); + } + + if (global_config.use_error_highlight || global_config.use_jump_highlight){ + // NOTE(allen): Error highlight + String_Const_u8 name = string_u8_litexpr("*compilation*"); + Buffer_ID compilation_buffer = get_buffer_by_name(app, name, Access_Always); + if (global_config.use_error_highlight){ + draw_jump_highlights(app, buffer, text_layout_id, compilation_buffer, + fcolor_id(defcolor_highlight_junk)); + } + + // NOTE(allen): Search highlight + if (global_config.use_jump_highlight){ + Buffer_ID jump_buffer = get_locked_jump_buffer(app); + if (jump_buffer != compilation_buffer){ + draw_jump_highlights(app, buffer, text_layout_id, jump_buffer, + fcolor_id(defcolor_highlight_white)); + } + } + } + + // NOTE(allen): Color parens + if (global_config.use_paren_helper){ + Color_Array colors = finalize_color_array(defcolor_text_cycle); + draw_paren_highlight(app, buffer, text_layout_id, cursor_pos, colors.vals, colors.count); + } + + // NOTE(allen): Line highlight + if (global_config.highlight_line_at_cursor && is_active_view){ + i64 line_number = get_line_number_from_pos(app, buffer, cursor_pos); + draw_line_highlight(app, text_layout_id, line_number, + fcolor_id(defcolor_highlight_cursor_line)); + } + + // NOTE(allen): Cursor shape + Face_Metrics metrics = get_face_metrics(app, face_id); + f32 cursor_roundness = (metrics.normal_advance*0.5f)*0.9f; + f32 mark_thickness = 2.f; + + // NOTE(allen): Cursor + switch (fcoder_mode){ + case FCoderMode_Original: + { + draw_original_4coder_style_cursor_mark_highlight(app, view_id, is_active_view, buffer, text_layout_id, cursor_roundness, mark_thickness); + }break; + case FCoderMode_NotepadLike: + { + draw_notepad_style_cursor_highlight(app, view_id, buffer, text_layout_id, cursor_roundness); + }break; + } + + // NOTE(allen): put the actual text on the actual screen + draw_text_layout_default(app, text_layout_id); + + draw_set_clip(app, prev_clip); +} + +function void +default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID view_id){ + ProfileScope(app, "default render caller"); + View_ID active_view = get_active_view(app, Access_Always); + b32 is_active_view = (active_view == view_id); + + Rect_f32 region = draw_background_and_margin(app, view_id, is_active_view); + Rect_f32 prev_clip = draw_set_clip(app, region); + + Buffer_ID buffer = view_get_buffer(app, view_id, Access_Always); + Face_ID face_id = get_face_id(app, buffer); + Face_Metrics face_metrics = get_face_metrics(app, face_id); + f32 line_height = face_metrics.line_height; + f32 digit_advance = face_metrics.decimal_digit_advance; + + // NOTE(allen): file bar + 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); + draw_file_bar(app, view_id, buffer, face_id, pair.min); + region = pair.max; + } + + 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); + } + + // NOTE(allen): query bars + { + Query_Bar *space[32]; + Query_Bar_Ptr_Array query_bars = {}; + query_bars.ptrs = space; + if (get_active_query_bars(app, view_id, ArrayCount(space), &query_bars)){ + for (i32 i = 0; i < query_bars.count; i += 1){ + Rect_f32_Pair pair = layout_query_bar_on_top(region, line_height, 1); + draw_query_bar(app, query_bars.ptrs[i], face_id, pair.min); + region = pair.max; + } + } + } + + // NOTE(allen): FPS hud + if (show_fps_hud){ + Rect_f32_Pair pair = layout_fps_hud_on_bottom(region, line_height); + draw_fps_hud(app, frame_info, face_id, pair.max); + region = pair.min; + animate_in_n_milliseconds(app, 1000); + } + + // NOTE(allen): layout line numbers + Rect_f32 line_number_rect = {}; + if (global_config.show_line_number_margins){ + Rect_f32_Pair pair = layout_line_number_margin(app, buffer, region, digit_advance); + line_number_rect = pair.min; + region = pair.max; + } + + // NOTE(allen): begin buffer render + Buffer_Point buffer_point = scroll.position; + Text_Layout_ID text_layout_id = text_layout_create(app, buffer, region, buffer_point); + + // NOTE(allen): draw line numbers + if (global_config.show_line_number_margins){ + draw_line_number_margin(app, view_id, buffer, face_id, text_layout_id, line_number_rect); + } + + // NOTE(allen): draw the buffer + default_render_buffer(app, view_id, face_id, buffer, text_layout_id, region); + + text_layout_free(app, text_layout_id); + draw_set_clip(app, prev_clip); +} + +HOOK_SIG(default_view_adjust){ + // NOTE(allen): Called whenever the view layout/sizes have been modified, + // including by full window resize. + return(0); +} + +BUFFER_NAME_RESOLVER_SIG(default_buffer_name_resolution){ + ProfileScope(app, "default buffer name resolution"); + if (conflict_count > 1){ + // List of unresolved conflicts + Scratch_Block scratch(app); + + i32 *unresolved = push_array(scratch, i32, conflict_count); + i32 unresolved_count = conflict_count; + for (i32 i = 0; i < conflict_count; ++i){ + unresolved[i] = i; + } + + // Resolution Loop + i32 x = 0; + for (;;){ + // Resolution Pass + ++x; + for (i32 i = 0; i < unresolved_count; ++i){ + i32 conflict_index = unresolved[i]; + Buffer_Name_Conflict_Entry *conflict = &conflicts[conflict_index]; + + umem size = conflict->base_name.size; + size = clamp_top(size, conflict->unique_name_capacity); + conflict->unique_name_len_in_out = size; + block_copy(conflict->unique_name_in_out, conflict->base_name.str, size); + + if (conflict->file_name.str != 0){ + Temp_Memory_Block temp(scratch); + String_Const_u8 uniqueifier = {}; + + String_Const_u8 file_name = string_remove_last_folder(conflict->file_name); + if (file_name.size > 0){ + file_name = string_chop(file_name, 1); + u8 *end = file_name.str + file_name.size; + b32 past_the_end = false; + for (i32 j = 0; j < x; ++j){ + file_name = string_remove_last_folder(file_name); + if (j + 1 < x){ + file_name = string_chop(file_name, 1); + } + if (file_name.size == 0){ + if (j + 1 < x){ + past_the_end = true; + } + break; + } + } + u8 *start = file_name.str + file_name.size; + + uniqueifier = SCu8(start, end); + if (past_the_end){ + uniqueifier = push_u8_stringf(scratch, "%.*s~%d", + string_expand(uniqueifier), i); + } + } + else{ + uniqueifier = push_u8_stringf(scratch, "%d", i); + } + + String_u8 builder = Su8(conflict->unique_name_in_out, + conflict->unique_name_len_in_out, + conflict->unique_name_capacity); + string_append(&builder, string_u8_litexpr(" <")); + string_append(&builder, uniqueifier); + string_append(&builder, string_u8_litexpr(">")); + conflict->unique_name_len_in_out = builder.size; + } + } + + // Conflict Check Pass + b32 has_conflicts = false; + for (i32 i = 0; i < unresolved_count; ++i){ + i32 conflict_index = unresolved[i]; + Buffer_Name_Conflict_Entry *conflict = &conflicts[conflict_index]; + String_Const_u8 conflict_name = SCu8(conflict->unique_name_in_out, + conflict->unique_name_len_in_out); + + b32 hit_conflict = false; + if (conflict->file_name.str != 0){ + for (i32 j = 0; j < unresolved_count; ++j){ + if (i == j) continue; + + i32 conflict_j_index = unresolved[j]; + Buffer_Name_Conflict_Entry *conflict_j = &conflicts[conflict_j_index]; + + String_Const_u8 conflict_name_j = SCu8(conflict_j->unique_name_in_out, + conflict_j->unique_name_len_in_out); + + if (string_match(conflict_name, conflict_name_j)){ + hit_conflict = true; + break; + } + } + } + + if (hit_conflict){ + has_conflicts = true; + } + else{ + --unresolved_count; + unresolved[i] = unresolved[unresolved_count]; + --i; + } + } + + if (!has_conflicts){ + break; + } + } + } +} + +function void +parse_async__inner(Async_Context *actx, Buffer_ID buffer_id, + String_Const_u8 contents, Token_Array *tokens, i32 limit_factor){ + Application_Links *app = actx->app; + ProfileBlock(app, "async parse"); + + Arena arena = make_arena_system(KB(16)); + Code_Index_File *index = push_array_zero(&arena, Code_Index_File, 1); + index->buffer = buffer_id; + + Generic_Parse_State state = {}; + generic_parse_init(app, &arena, contents, tokens, &state); + + b32 canceled = false; + + for (;;){ + if (generic_parse_full_input_breaks(index, &state, limit_factor)){ + break; + } + if (async_check_canceled(actx)){ + canceled = true; + break; + } + } + + if (!canceled){ + Thread_Context *tctx = get_thread_context(app); + system_acquire_global_frame_mutex(tctx); + code_index_lock(); + code_index_set_file(buffer_id, arena, index); + code_index_unlock(); + buffer_clear_layout_cache(app, buffer_id); + system_release_global_frame_mutex(tctx); + } + else{ + linalloc_clear(&arena); + } +} + +function void +do_full_lex_async__inner(Async_Context *actx, Buffer_ID buffer_id){ + Application_Links *app = actx->app; + ProfileScope(app, "async lex"); + Thread_Context *tctx = get_thread_context(app); + Scratch_Block scratch(tctx); + + String_Const_u8 contents = {}; + { + ProfileBlock(app, "async lex contents (before mutex)"); + system_acquire_global_frame_mutex(tctx); + ProfileBlock(app, "async lex contents (after mutex)"); + contents = push_whole_buffer(app, scratch, buffer_id); + system_release_global_frame_mutex(tctx); + } + + i32 limit_factor = 10000; + + Token_List list = {}; + b32 canceled = false; + + Lex_State_Cpp state = {}; + lex_full_input_cpp_init(&state, contents); + for (;;){ + ProfileBlock(app, "async lex block"); + if (lex_full_input_cpp_breaks(scratch, &list, &state, limit_factor)){ + break; + } + if (async_check_canceled(actx)){ + canceled = true; + break; + } + } + + if (!canceled){ + ProfileBlock(app, "async lex save results (before mutex)"); + system_acquire_global_frame_mutex(tctx); + ProfileBlock(app, "async lex save results (after mutex)"); + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + if (scope != 0){ + Base_Allocator *allocator = managed_scope_allocator(app, scope); + Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, + Token_Array); + base_free(allocator, tokens_ptr->tokens); + Token_Array tokens = {}; + tokens.tokens = base_array(allocator, Token, list.total_count); + tokens.count = list.total_count; + tokens.max = list.total_count; + token_fill_memory_from_list(tokens.tokens, &list); + block_copy_struct(tokens_ptr, &tokens); + } + buffer_mark_as_modified(buffer_id); + system_release_global_frame_mutex(tctx); + } +} + +function void +do_full_lex_async(Async_Context *actx, Data data){ + if (data.size == sizeof(Buffer_ID)){ + Buffer_ID buffer = *(Buffer_ID*)data.data; + do_full_lex_async__inner(actx, buffer); + } +} + +#if 0 +function void +do_full_lex_and_parse_async__inner(Async_Context *actx, Buffer_ID buffer_id){ + Application_Links *app = actx->app; + ProfileScope(app, "async lex"); + Thread_Context *tctx = get_thread_context(app); + Scratch_Block scratch(tctx); + + String_Const_u8 contents = {}; + { + ProfileBlock(app, "async lex contents (before mutex)"); + system_acquire_global_frame_mutex(tctx); + ProfileBlock(app, "async lex contents (after mutex)"); + + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + if (scope != 0){ + Base_Allocator *allocator = managed_scope_allocator(app, scope); + Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, + Token_Array); + base_free(allocator, tokens_ptr->tokens); + block_zero_struct(tokens_ptr); + } + + contents = push_whole_buffer(app, scratch, buffer_id); + system_release_global_frame_mutex(tctx); + } + + i32 limit_factor = 10000; + + Token_List list = {}; + b32 canceled = false; + + { + Lex_State_Cpp state = {}; + lex_full_input_cpp_init(&state, contents); + for (;;){ + ProfileBlock(app, "async lex block"); + if (lex_full_input_cpp_breaks(scratch, &list, &state, limit_factor)){ + break; + } + if (async_check_canceled(actx)){ + canceled = true; + break; + } + } + } + + Token_Array tokens = {}; + if (!canceled){ + ProfileBlock(app, "async lex save results (before mutex)"); + system_acquire_global_frame_mutex(tctx); + ProfileBlock(app, "async lex save results (after mutex)"); + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + if (scope != 0){ + Base_Allocator *allocator = managed_scope_allocator(app, scope); + Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, + Token_Array); + base_free(allocator, tokens_ptr->tokens); + tokens.tokens = base_array(allocator, Token, list.total_count); + tokens.count = list.total_count; + tokens.max = list.total_count; + token_fill_memory_from_list(tokens.tokens, &list); + block_copy_struct(tokens_ptr, &tokens); + } + system_release_global_frame_mutex(tctx); + } + + if (tokens.count > 0){ + parse_async__inner(actx, buffer_id, contents, &tokens, limit_factor); + } +} + +function void +do_full_lex_and_parse_async(Async_Context *actx, Data data){ + if (data.size == sizeof(Buffer_ID)){ + Buffer_ID buffer = *(Buffer_ID*)data.data; + do_full_lex_and_parse_async__inner(actx, buffer); + } +} +#endif + +#if 0 +function void +do_parse_async__inner(Async_Context *actx, Buffer_ID buffer_id){ + Application_Links *app = actx->app; + ProfileScope(app, "async lex"); + Thread_Context *tctx = get_thread_context(app); + Scratch_Block scratch(tctx); + + String_Const_u8 contents = {}; + Token_Array tokens = {}; + { + ProfileBlock(app, "async parse contents (before mutex)"); + system_acquire_global_frame_mutex(tctx); + ProfileBlock(app, "async parse contents (after mutex)"); + + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + if (scope != 0){ + Token_Array *tokens_ptr = scope_attachment(app, scope, attachment_tokens, + Token_Array); + tokens.count = tokens_ptr->count; + tokens.tokens = push_array_write(scratch, Token, tokens.count, tokens_ptr->tokens); + if (tokens.count > 0){ + contents = push_whole_buffer(app, scratch, buffer_id); + } + } + + system_release_global_frame_mutex(tctx); + } + + i32 limit_factor = 10000; + + if (tokens.count > 0){ + parse_async__inner(actx, buffer_id, contents, &tokens, limit_factor); + } +} + +function void +do_parse_async(Async_Context *actx, Data data){ + if (data.size == sizeof(Buffer_ID)){ + Buffer_ID buffer = *(Buffer_ID*)data.data; + do_parse_async__inner(actx, buffer); + } +} +#endif + +BUFFER_HOOK_SIG(default_begin_buffer){ + ProfileScope(app, "begin buffer"); + + Scratch_Block scratch(app); + + b32 treat_as_code = false; + String_Const_u8 file_name = push_buffer_file_name(app, scratch, buffer_id); + if (file_name.size > 0){ + String_Const_u8_Array extensions = global_config.code_exts; + String_Const_u8 ext = string_file_extension(file_name); + for (i32 i = 0; i < extensions.count; ++i){ + if (string_match(ext, extensions.strings[i])){ + + if (string_match(ext, string_u8_litexpr("cpp")) || + string_match(ext, string_u8_litexpr("h")) || + string_match(ext, string_u8_litexpr("c")) || + string_match(ext, string_u8_litexpr("hpp")) || + string_match(ext, string_u8_litexpr("cc"))){ + treat_as_code = true; + } + +#if 0 + treat_as_code = true; + + if (string_match(ext, string_u8_litexpr("cs"))){ + if (parse_context_language_cs == 0){ + init_language_cs(app); + } + parse_context_id = parse_context_language_cs; + } + + if (string_match(ext, string_u8_litexpr("java"))){ + if (parse_context_language_java == 0){ + init_language_java(app); + } + parse_context_id = parse_context_language_java; + } + + if (string_match(ext, string_u8_litexpr("rs"))){ + if (parse_context_language_rust == 0){ + init_language_rust(app); + } + parse_context_id = parse_context_language_rust; + } + + if (string_match(ext, string_u8_litexpr("cpp")) || + string_match(ext, string_u8_litexpr("h")) || + string_match(ext, string_u8_litexpr("c")) || + string_match(ext, string_u8_litexpr("hpp")) || + string_match(ext, string_u8_litexpr("cc"))){ + if (parse_context_language_cpp == 0){ + init_language_cpp(app); + } + parse_context_id = parse_context_language_cpp; + } + + // TODO(NAME): Real GLSL highlighting + if (string_match(ext, string_u8_litexpr("glsl"))){ + if (parse_context_language_cpp == 0){ + init_language_cpp(app); + } + parse_context_id = parse_context_language_cpp; + } + + // TODO(NAME): Real Objective-C highlighting + if (string_match(ext, string_u8_litexpr("m"))){ + if (parse_context_language_cpp == 0){ + init_language_cpp(app); + } + parse_context_id = parse_context_language_cpp; + } +#endif + + break; + } + } + } + + Command_Map_ID map_id = (treat_as_code)?(default_code_map):(mapid_file); + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + Command_Map_ID *map_id_ptr = scope_attachment(app, scope, buffer_map_id, Command_Map_ID); + *map_id_ptr = map_id; + + Line_Ending_Kind setting = guess_line_ending_kind_from_buffer(app, buffer_id); + Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, Line_Ending_Kind); + *eol_setting = setting; + + // NOTE(allen): Decide buffer settings + b32 wrap_lines = true; + b32 use_virtual_whitespace = false; + b32 use_lexer = false; + if (treat_as_code){ + wrap_lines = global_config.enable_code_wrapping; + use_virtual_whitespace = global_config.enable_virtual_whitespace; + use_lexer = true; + } + + String_Const_u8 buffer_name = push_buffer_base_name(app, scratch, buffer_id); + if (string_match(buffer_name, string_u8_litexpr("*compilation*"))){ + wrap_lines = false; + } + + if (use_lexer){ + ProfileBlock(app, "begin buffer kick off lexer"); + Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); + *lex_task_ptr = async_task_no_dep(&global_async_system, do_full_lex_async, make_data_struct(&buffer_id)); + } + + { + b32 *wrap_lines_ptr = scope_attachment(app, scope, buffer_wrap_lines, b32); + *wrap_lines_ptr = wrap_lines; + } + + if (use_virtual_whitespace){ + if (use_lexer){ + buffer_set_layout(app, buffer_id, layout_virt_indent_index_generic); + } + else{ + buffer_set_layout(app, buffer_id, layout_virt_indent_literal_generic); + } + } + else{ + buffer_set_layout(app, buffer_id, layout_generic); + } + + // no meaning for return + return(0); +} + +BUFFER_HOOK_SIG(default_new_file){ + // buffer_id + // no meaning for return + return(0); +} + +BUFFER_HOOK_SIG(default_file_save){ + // buffer_id + ProfileScope(app, "default file save"); + b32 is_virtual = false; + if (global_config.automatically_indent_text_on_save && is_virtual){ + auto_indent_buffer(app, buffer_id, buffer_range(app, buffer_id)); + } + + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + Line_Ending_Kind *eol = scope_attachment(app, scope, buffer_eol_setting, + Line_Ending_Kind); + switch (*eol){ + case LineEndingKind_LF: + { + rewrite_lines_to_lf(app, buffer_id); + }break; + case LineEndingKind_CRLF: + { + rewrite_lines_to_crlf(app, buffer_id); + }break; + } + + // no meaning for return + return(0); +} + +BUFFER_EDIT_RANGE_SIG(default_buffer_edit_range){ + // buffer_id, new_range, original_size + ProfileScope(app, "default edit range"); + + Range_i64 old_range = Ii64(new_range.first, new_range.first + original_size); + + { + code_index_lock(); + Code_Index_File *file = code_index_get_file(buffer_id); + if (file != 0){ + code_index_shift(file, old_range, range_size(new_range)); + } + code_index_unlock(); + } + + i64 insert_size = range_size(new_range); + i64 text_shift = replace_range_shift(old_range, insert_size); + + Scratch_Block scratch(app); + + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); + + Base_Allocator *allocator = managed_scope_allocator(app, scope); + b32 do_full_relex = false; + + if (async_task_is_running_or_pending(&global_async_system, *lex_task_ptr)){ + async_task_cancel(&global_async_system, *lex_task_ptr); + buffer_unmark_as_modified(buffer_id); + do_full_relex = true; + *lex_task_ptr = 0; + } + + Token_Array *ptr = scope_attachment(app, scope, attachment_tokens, Token_Array); + if (ptr != 0 && ptr->tokens != 0){ + ProfileBlockNamed(app, "attempt resync", profile_attempt_resync); + + i64 token_index_first = token_relex_first(ptr, old_range.first, 1); + i64 token_index_resync_guess = + token_relex_resync(ptr, old_range.one_past_last, 16); + + if (token_index_resync_guess - token_index_first >= 4000){ + do_full_relex = true; + } + else{ + Token *token_first = ptr->tokens + token_index_first; + Token *token_resync = ptr->tokens + token_index_resync_guess; + + Range_i64 relex_range = Ii64(token_first->pos, token_resync->pos + token_resync->size + text_shift); + String_Const_u8 partial_text = push_buffer_range(app, scratch, buffer_id, relex_range); + + Token_List relex_list = lex_full_input_cpp(scratch, partial_text); + if (relex_range.one_past_last < buffer_get_size(app, buffer_id)){ + token_drop_eof(&relex_list); + } + + Token_Relex relex = token_relex(relex_list, relex_range.first - text_shift, ptr->tokens, token_index_first, token_index_resync_guess); + + ProfileCloseNow(profile_attempt_resync); + + if (!relex.successful_resync){ + do_full_relex = true; + } + else{ + ProfileBlock(app, "apply resync"); + + i64 token_index_resync = relex.first_resync_index; + + Interval_i64 head = Ii64(0, token_index_first); + Interval_i64 replaced = Ii64(token_index_first, token_index_resync); + Interval_i64 tail = Ii64(token_index_resync, ptr->count); + i64 resynced_count = (token_index_resync_guess + 1) - token_index_resync; + i64 relexed_count = relex_list.total_count - resynced_count; + i64 tail_shift = relexed_count - (token_index_resync - token_index_first); + + i64 new_tokens_count = ptr->count + tail_shift; + Token *new_tokens = base_array(allocator, Token, new_tokens_count); + + Token *old_tokens = ptr->tokens; + block_copy_array_shift(new_tokens, old_tokens, head, 0); + token_fill_memory_from_list(new_tokens + replaced.first, &relex_list, relexed_count); + for (i64 i = 0, index = replaced.first; i < relexed_count; i += 1, index += 1){ + new_tokens[index].pos += relex_range.first; + } + for (i64 i = tail.first; i < tail.one_past_last; i += 1){ + old_tokens[i].pos += text_shift; + } + block_copy_array_shift(new_tokens, ptr->tokens, tail, tail_shift); + + base_free(allocator, ptr->tokens); + + ptr->tokens = new_tokens; + ptr->count = new_tokens_count; + ptr->max = new_tokens_count; + + buffer_mark_as_modified(buffer_id); + } + } + } + + if (do_full_relex){ + *lex_task_ptr = async_task_no_dep(&global_async_system, do_full_lex_async, + make_data_struct(&buffer_id)); + } + + // no meaning for return + return(0); +} + +BUFFER_HOOK_SIG(default_end_buffer){ + Managed_Scope scope = buffer_get_managed_scope(app, buffer_id); + Async_Task *lex_task_ptr = scope_attachment(app, scope, buffer_lex_task, Async_Task); + if (lex_task_ptr != 0){ + async_task_cancel(&global_async_system, *lex_task_ptr); + } + buffer_unmark_as_modified(buffer_id); + code_index_lock(); + code_index_erase_file(buffer_id); + code_index_unlock(); + // no meaning for return + return(0); +} + +internal void +set_all_default_hooks(Application_Links *app){ + set_custom_hook(app, HookID_BufferViewerUpdate, default_view_adjust); + + set_custom_hook(app, HookID_ViewEventHandler, default_view_input_handler); + set_custom_hook(app, HookID_Tick, default_tick); + set_custom_hook(app, HookID_RenderCaller, default_render_caller); +#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_begin_buffer); + set_custom_hook(app, HookID_EndBuffer, end_buffer_close_jump_list); + 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_buffer_region); + + set_custom_hook(app, HookID_Layout, layout_unwrapped); + //set_custom_hook(app, HookID_Layout, layout_wrap_anywhere); + //set_custom_hook(app, HookID_Layout, layout_wrap_whitespace); + //set_custom_hook(app, HookID_Layout, layout_virt_indent_unwrapped); + //set_custom_hook(app, HookID_Layout, layout_unwrapped_small_blank_lines); +} + +// BOTTOM + diff --git a/custom/4coder_default_include.cpp b/custom/4coder_default_include.cpp index 94d71592..f7cd09a0 100644 --- a/custom/4coder_default_include.cpp +++ b/custom/4coder_default_include.cpp @@ -77,6 +77,7 @@ #include "generated/lexer_cpp.cpp" #include "4coder_command_map.cpp" #include "4coder_default_framework_variables.cpp" +#include "4coder_default_colors.cpp" #include "4coder_helper.cpp" #include "4coder_delta_rule.cpp" #include "4coder_layout_rule.cpp" diff --git a/custom/4coder_draw.cpp b/custom/4coder_draw.cpp index 707a8011..46252e76 100644 --- a/custom/4coder_draw.cpp +++ b/custom/4coder_draw.cpp @@ -1,763 +1,843 @@ -/* -4coder_draw.cpp - Layout and rendering implementation of standard UI pieces (including buffers) -*/ - -// TOP - -function FColor -get_margin_color(i32 level){ - FColor margin = fcolor_zero(); - switch (level){ - default: - case UIHighlight_None: - { - margin = fcolor_id(Stag_List_Item); - }break; - case UIHighlight_Hover: - { - margin = fcolor_id(Stag_List_Item_Hover); - }break; - case UIHighlight_Active: - { - margin = fcolor_id(Stag_List_Item_Active); - }break; - } - return(margin); -} - -function Vec2_f32 -draw_string(Application_Links *app, Face_ID font_id, String_Const_u8 string, - Vec2_f32 p, FColor color){ - return(draw_string_oriented(app, font_id, color, string, p, 0, V2(1.f, 0.f))); -} - -function void -draw_margin(Application_Links *app, Rect_f32 outer, Rect_f32 inner, FColor color){ - draw_rectangle(app, Rf32(outer.x0, outer.y0, outer.x1, inner.y0), 0.f, color); - draw_rectangle(app, Rf32(outer.x0, inner.y1, outer.x1, outer.y1), 0.f, color); - draw_rectangle(app, Rf32(outer.x0, inner.y0, inner.x0, inner.y1), 0.f, color); - draw_rectangle(app, Rf32(inner.x1, inner.y0, outer.x1, inner.y1), 0.f, color); -} - -function void -draw_character_block(Application_Links *app, Text_Layout_ID layout, i64 pos, - f32 roundness, FColor color){ - Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); - draw_rectangle(app, rect, roundness, color); -} - -function void -draw_character_block(Application_Links *app, Text_Layout_ID layout, Range_i64 range, - f32 roundness, FColor color){ - if (range.first < range.one_past_last){ - i64 i = range.first; - Rect_f32 first_rect = text_layout_character_on_screen(app, layout, i); - i += 1; - Range_f32 y = rect_range_y(first_rect); - Range_f32 x = rect_range_x(first_rect); - for (;i < range.one_past_last; i += 1){ - Rect_f32 rect = text_layout_character_on_screen(app, layout, i); - if (rect.x0 < rect.x1 && rect.y0 < rect.y1){ - Range_f32 new_y = rect_range_y(rect); - Range_f32 new_x = rect_range_x(rect); - b32 joinable = false; - if (new_y == y && (range_overlap(x, new_x) || x.max == new_x.min || new_x.max == x.min)){ - joinable = true; - } - - if (!joinable){ - draw_rectangle(app, Rf32(x, y), roundness, color); - y = new_y; - x = new_x; - } - else{ - x = range_union(x, new_x); - } - } - } - draw_rectangle(app, Rf32(x, y), roundness, color); - } - for (i64 i = range.first; i < range.one_past_last; i += 1){ - draw_character_block(app, layout, i, roundness, color); - } -} - -function void -draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, i64 pos, - f32 roundness, f32 thickness, FColor color){ - Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); - draw_rectangle_outline(app, rect, roundness, thickness, color); -} - -function void -draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, - Range_i64 range, f32 roundness, f32 thickness, - FColor color){ - for (i64 i = range.first; i < range.one_past_last; i += 1){ - draw_character_wire_frame(app, layout, i, roundness, thickness, color); - } -} - -function void -draw_character_i_bar(Application_Links *app, Text_Layout_ID layout, i64 pos, - FColor color){ - Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); - rect.x1 = rect.x0 + 1.f; - draw_rectangle(app, rect, 0.f, color); -} - -function void -draw_line_highlight(Application_Links *app, Text_Layout_ID layout, - Range_i64 line_range, FColor color){ - Range_f32 y1 = text_layout_line_on_screen(app, layout, line_range.min); - Range_f32 y2 = text_layout_line_on_screen(app, layout, line_range.max); - Range_f32 y = range_union(y1, y2); - if (range_size(y) > 0.f){ - Rect_f32 region = text_layout_region(app, layout); - draw_rectangle(app, Rf32(rect_range_x(region), y), 0.f, color); - } -} - -function void -draw_line_highlight(Application_Links *app, Text_Layout_ID layout, i64 line, - FColor color){ - draw_line_highlight(app, layout, Ii64(line), color); -} - -function void -paint_text_color_pos(Application_Links *app, Text_Layout_ID layout, i64 pos, - FColor color){ - paint_text_color(app, layout, Ii64(pos, pos + 1), color); -} - -//////////////////////////////// - -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_Pair -layout_query_bar_on_top(Rect_f32 rect, f32 line_height, i32 bar_count){ - return(rect_split_top_bottom(rect, (line_height + 2.f)*bar_count)); -} - -function Rect_f32_Pair -layout_query_bar_on_bot(Rect_f32 rect, f32 line_height, i32 bar_count){ - return(rect_split_top_bottom_neg(rect, (line_height + 2.f)*bar_count)); -} - -function Rect_f32_Pair -layout_line_number_margin(Rect_f32 rect, f32 digit_advance, i64 digit_count){ - f32 margin_width = (f32)digit_count*digit_advance + 2.f; - return(rect_split_left_right(rect, margin_width)); -} - -function Rect_f32_Pair -layout_line_number_margin(Application_Links *app, Buffer_ID buffer, Rect_f32 rect, f32 digit_advance){ - i64 line_count = buffer_get_line_count(app, buffer); - i64 line_count_digit_count = digit_count_from_integer(line_count, 10); - return(layout_line_number_margin(rect, digit_advance, line_count_digit_count)); -} - -global_const i32 fps_history_depth = 10; -function Rect_f32_Pair -layout_fps_hud_on_bottom(Rect_f32 rect, f32 line_height){ - return(rect_split_top_bottom_neg(rect, line_height*fps_history_depth)); -} - -function Rect_f32 -draw_background_and_margin(Application_Links *app, View_ID view, FColor margin, FColor back){ - Rect_f32 view_rect = view_get_screen_rect(app, view); - Rect_f32 inner = rect_inner(view_rect, 3.f); - draw_rectangle(app, inner, 0.f, back); - draw_margin(app, view_rect, inner, margin); - return(inner); -} - -function Rect_f32 -draw_background_and_margin(Application_Links *app, View_ID view, b32 is_active_view){ - FColor margin_color = get_margin_color(is_active_view?UIHighlight_Active:UIHighlight_None); - return(draw_background_and_margin(app, view, margin_color, fcolor_id(Stag_Back))); -} - -function Rect_f32 -draw_background_and_margin(Application_Links *app, View_ID view){ - View_ID active_view = get_active_view(app, Access_Always); - b32 is_active_view = (active_view == view); - return(draw_background_and_margin(app, view, is_active_view)); -} - -function void -draw_file_bar(Application_Links *app, View_ID view_id, Buffer_ID buffer, Face_ID face_id, Rect_f32 bar){ - Scratch_Block scratch(app); - - draw_rectangle(app, bar, 0.f, fcolor_id(Stag_Bar)); - - FColor base_color = fcolor_id(Stag_Base); - FColor pop2_color = fcolor_id(Stag_Pop2); - - i64 cursor_position = view_get_cursor_pos(app, view_id); - Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(cursor_position)); - - Fancy_Line 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.col); - - Managed_Scope scope = buffer_get_managed_scope(app, buffer); - Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, - Line_Ending_Kind); - switch (*eol_setting){ - case LineEndingKind_Binary: - { - push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" bin")); - }break; - - case LineEndingKind_LF: - { - push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" lf")); - }break; - - case LineEndingKind_CRLF: - { - push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" crlf")); - }break; - } - - { - Dirty_State dirty = buffer_get_dirty_state(app, buffer); - u8 space[3]; - String_u8 str = Su8(space, 0, 3); - if (dirty != 0){ - string_append(&str, string_u8_litexpr(" ")); - } - if (HasFlag(dirty, DirtyState_UnsavedChanges)){ - string_append(&str, string_u8_litexpr("*")); - } - if (HasFlag(dirty, DirtyState_UnloadedChanges)){ - string_append(&str, string_u8_litexpr("!")); - } - push_fancy_string(scratch, &list, pop2_color, str.string); - } - - Vec2 p = bar.p0 + V2(2.f, 2.f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); -} - -function void -draw_query_bar(Application_Links *app, Query_Bar *query_bar, Face_ID face_id, Rect_f32 bar){ - Scratch_Block scratch(app); - Fancy_Line list = {}; - push_fancy_string(scratch, &list, fcolor_id(Stag_Pop1) , query_bar->prompt); - push_fancy_string(scratch, &list, fcolor_id(Stag_Default), query_bar->string); - Vec2_f32 p = bar.p0 + V2(2.f, 2.f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); -} - -function void -draw_line_number_margin(Application_Links *app, View_ID view_id, Buffer_ID buffer, Face_ID face_id, Text_Layout_ID text_layout_id, Rect_f32 margin){ - Rect_f32 prev_clip = draw_set_clip(app, margin); - draw_rectangle(app, margin, 0.f, fcolor_id(Stag_Line_Numbers_Back)); - - Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); - - FColor line_color = fcolor_id(Stag_Line_Numbers_Text); - - i64 line_count = buffer_get_line_count(app, buffer); - i64 line_count_digit_count = digit_count_from_integer(line_count, 10); - - Scratch_Block scratch(app, Scratch_Share); - - Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(visible_range.first)); - i64 line_number = cursor.line; - for (;cursor.pos <= visible_range.one_past_last;){ - if (line_number > line_count){ - break; - } - Range_f32 line_y = text_layout_line_on_screen(app, text_layout_id, line_number); - Vec2_f32 p = V2f32(margin.x0, line_y.min); - Temp_Memory_Block temp(scratch); - Fancy_String *string = push_fancy_stringf(scratch, 0, line_color, - "%*lld", - line_count_digit_count, - line_number); - draw_fancy_string(app, face_id, fcolor_zero(), string, p); - line_number += 1; - } - - draw_set_clip(app, prev_clip); -} - -function void -draw_fps_hud(Application_Links *app, Frame_Info frame_info, - Face_ID face_id, Rect_f32 rect){ - Face_Metrics face_metrics = get_face_metrics(app, face_id); - f32 line_height = face_metrics.line_height; - - local_persist f32 history_literal_dt[fps_history_depth] = {}; - local_persist f32 history_animation_dt[fps_history_depth] = {}; - local_persist i32 history_frame_index[fps_history_depth] = {}; - - i32 wrapped_index = frame_info.index%fps_history_depth; - history_literal_dt[wrapped_index] = frame_info.literal_dt; - history_animation_dt[wrapped_index] = frame_info.animation_dt; - history_frame_index[wrapped_index] = frame_info.index; - - draw_rectangle(app, rect, 0.f, f_black); - draw_rectangle_outline(app, rect, 0.f, 1.f, f_white); - - Vec2_f32 p = rect.p0; - - Scratch_Block scratch(app); - - Range ranges[2]; - ranges[0].first = wrapped_index; - ranges[0].one_past_last = -1; - ranges[1].first = fps_history_depth - 1; - ranges[1].one_past_last = wrapped_index; - for (i32 i = 0; i < 2; i += 1){ - Range r = ranges[i]; - for (i32 j = r.first; j > r.one_past_last; j -= 1, p.y += line_height){ - f32 dts[2]; - dts[0] = history_literal_dt[j]; - dts[1] = history_animation_dt[j]; - i32 frame_index = history_frame_index[j]; - - Fancy_Line list = {}; - push_fancy_stringf(scratch, &list, f_pink , "FPS: "); - push_fancy_stringf(scratch, &list, f_green, "["); - push_fancy_stringf(scratch, &list, f_white, "%5d", frame_index); - push_fancy_stringf(scratch, &list, f_green, "]: "); - - for (i32 k = 0; k < 2; k += 1){ - f32 dt = dts[k]; - if (dt == 0.f){ - push_fancy_stringf(scratch, &list, f_white, "----------"); - } - else{ - push_fancy_stringf(scratch, &list, f_white, "%10.6f", dt); - } - push_fancy_stringf(scratch, &list, f_green, " | "); - } - - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); - } - } -} - -function FColor -get_token_color_cpp(Token token){ - ID_Color color = Stag_Default; - switch (token.kind){ - case TokenBaseKind_Preprocessor: - { - color = Stag_Preproc; - }break; - case TokenBaseKind_Keyword: - { - color = Stag_Keyword; - }break; - case TokenBaseKind_Comment: - { - color = Stag_Comment; - }break; - case TokenBaseKind_LiteralString: - { - color = Stag_Str_Constant; - }break; - case TokenBaseKind_LiteralInteger: - { - color = Stag_Int_Constant; - }break; - case TokenBaseKind_LiteralFloat: - { - color = Stag_Float_Constant; - }break; - default: - { - switch (token.sub_kind){ - case TokenCppKind_LiteralTrue: - case TokenCppKind_LiteralFalse: - { - color = Stag_Bool_Constant; - }break; - case TokenCppKind_LiteralCharacter: - case TokenCppKind_LiteralCharacterWide: - case TokenCppKind_LiteralCharacterUTF8: - case TokenCppKind_LiteralCharacterUTF16: - case TokenCppKind_LiteralCharacterUTF32: - { - color = Stag_Char_Constant; - }break; - case TokenCppKind_PPIncludeFile: - { - color = Stag_Include; - }break; - } - }break; - } - return(fcolor_id(color)); -} - -function void -draw_cpp_token_colors(Application_Links *app, Text_Layout_ID text_layout_id, Token_Array *array){ - Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); - i64 first_index = token_index_from_pos(array, visible_range.first); - Token_Iterator_Array it = token_iterator_index(0, array, first_index); - for (;;){ - Token *token = token_it_read(&it); - if (token->pos >= visible_range.one_past_last){ - break; - } - FColor color = get_token_color_cpp(*token); - paint_text_color(app, text_layout_id, Ii64_size(token->pos, token->size), color); - if (!token_it_inc_non_whitespace(&it)){ - break; - } - } -} - -function void -draw_comment_highlights(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, - Token_Array *array, Comment_Highlight_Pair *pairs, i32 pair_count){ - Scratch_Block scratch(app); - Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); - i64 first_index = token_index_from_pos(array, visible_range.first); - Token_Iterator_Array it = token_iterator_index(buffer, array, first_index); - for (;;){ - Temp_Memory_Block temp(scratch); - Token *token = token_it_read(&it); - if (token->pos >= visible_range.one_past_last){ - break; - } - String_Const_u8 tail = {}; - if (token_it_check_and_get_lexeme(app, scratch, &it, TokenBaseKind_Comment, &tail)){ - for (i64 index = token->pos; - tail.size > 0; - tail = string_skip(tail, 1), index += 1){ - Comment_Highlight_Pair *pair = pairs; - for (i32 i = 0; i < pair_count; i += 1, pair += 1){ - umem needle_size = pair->needle.size; - if (needle_size == 0){ - continue; - } - String_Const_u8 prefix = string_prefix(tail, needle_size); - if (string_match(prefix, pair->needle)){ - Range_i64 range = Ii64_size(index, needle_size); - paint_text_color(app, text_layout_id, range, pair->color); - tail = string_skip(tail, needle_size - 1); - index += needle_size - 1; - break; - } - } - } - } - if (!token_it_inc_non_whitespace(&it)){ - break; - } - } -} - -function 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; - array.ranges = push_array(arena, Range_i64, max); - for (;;){ - Range_i64 range = {}; - if (find_surrounding_nest(app, buffer, pos, flags, &range)){ - array.ranges[array.count] = range; - array.count += 1; - pos = range.first; - if (array.count >= max){ - break; - } - } - else{ - break; - } - } - return(array); -} - -function void -draw_enclosures(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID buffer, - i64 pos, u32 flags, Range_Highlight_Kind kind, - FColor *back_colors, FColor *fore_colors, i32 color_count){ - Scratch_Block scratch(app); - Range_i64_Array ranges = get_enclosure_ranges(app, scratch, buffer, pos, flags); - - i32 color_index = 0; - for (i32 i = ranges.count - 1; i >= 0; i -= 1){ - Range_i64 range = ranges.ranges[i]; - if (kind == RangeHighlightKind_LineHighlight){ - Range_i64 r[2] = {}; - if (i > 0){ - Range_i64 inner_range = ranges.ranges[i - 1]; - Range_i64 lines = get_line_range_from_pos_range(app, buffer, range); - Range_i64 inner_lines = get_line_range_from_pos_range(app, buffer, inner_range); - inner_lines.min = clamp_bot(lines.min, inner_lines.min); - inner_lines.max = clamp_top(inner_lines.max, lines.max); - inner_lines.min -= 1; - inner_lines.max += 1; - if (lines.min <= inner_lines.min){ - r[0] = Ii64(lines.min, inner_lines.min); - } - if (inner_lines.max <= lines.max){ - r[1] = Ii64(inner_lines.max, lines.max); - } - } - else{ - r[0] = get_line_range_from_pos_range(app, buffer, range); - } - for (i32 j = 0; j < 2; j += 1){ - if (r[j].min == 0){ - continue; - } - Range_i64 line_range = r[j]; - if (back_colors != 0){ - draw_line_highlight(app, text_layout_id, line_range, back_colors[color_index]); - } - if (fore_colors != 0){ - Range_i64 pos_range = get_pos_range_from_line_range(app, buffer, line_range); - paint_text_color(app, text_layout_id, pos_range, fore_colors[color_index]); - } - } - } - else{ - if (back_colors != 0){ - draw_character_block(app, text_layout_id, range.min, 0.f, back_colors[color_index]); - draw_character_block(app, text_layout_id, range.max - 1, 0.f, back_colors[color_index]); - } - if (fore_colors != 0){ - paint_text_color_pos(app, text_layout_id, range.min, fore_colors[color_index]); - paint_text_color_pos(app, text_layout_id, range.max - 1, fore_colors[color_index]); - } - } - color_index += 1; - color_index = (color_index%color_count); - } -} - -function void -draw_scope_highlight(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, - i64 pos, FColor *colors, i32 color_count){ - draw_enclosures(app, text_layout_id, buffer, - pos, FindNest_Scope, RangeHighlightKind_LineHighlight, - colors, 0, color_count); -} - -function void -draw_paren_highlight(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, - i64 pos, FColor *colors, i32 color_count){ - Token_Array token_array = get_token_array_from_buffer(app, buffer); - if (token_array.tokens != 0){ - Token_Iterator_Array it = token_iterator_pos(0, &token_array, pos); - Token *token = token_it_read(&it); - if (token != 0 && token->kind == TokenBaseKind_ParentheticalOpen){ - pos = token->pos + token->size; - } - else{ - if (token_it_dec_all(&it)){ - token = token_it_read(&it); - if (token->kind == TokenBaseKind_ParentheticalClose && - pos == token->pos + token->size){ - pos = token->pos; - } - } - } - } - draw_enclosures(app, text_layout_id, buffer, - pos, FindNest_Paren, RangeHighlightKind_CharacterHighlight, - 0, colors, color_count); -} - -function void -draw_jump_highlights(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, - Buffer_ID jump_buffer, FColor line_color){ - Scratch_Block scratch(app); - if (jump_buffer != 0){ - Managed_Scope scopes[2]; - scopes[0] = buffer_get_managed_scope(app, jump_buffer); - scopes[1] = buffer_get_managed_scope(app, buffer); - Managed_Scope comp_scope = get_managed_scope_with_multiple_dependencies(app, scopes, ArrayCount(scopes)); - Managed_Object *markers_object = scope_attachment(app, comp_scope, sticky_jump_marker_handle, Managed_Object); - - i32 count = managed_object_get_item_count(app, *markers_object); - Marker *markers = push_array(scratch, Marker, count); - managed_object_load_data(app, *markers_object, 0, count, markers); - for (i32 i = 0; i < count; i += 1){ - i64 line_number = get_line_number_from_pos(app, buffer, markers[i].pos); - draw_line_highlight(app, text_layout_id, line_number, line_color); - } - } -} - -function b32 -draw_highlight_range(Application_Links *app, View_ID view_id, - Buffer_ID buffer, Text_Layout_ID text_layout_id, - f32 roundness){ - b32 has_highlight_range = false; - Managed_Scope scope = view_get_managed_scope(app, view_id); - Buffer_ID *highlight_buffer = scope_attachment(app, scope, view_highlight_buffer, Buffer_ID); - if (*highlight_buffer != 0){ - if (*highlight_buffer != buffer){ - view_disable_highlight_range(app, view_id); - } - else{ - has_highlight_range = true; - Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); - Marker marker_range[2]; - if (managed_object_load_data(app, *highlight, 0, 2, marker_range)){ - Range_i64 range = Ii64(marker_range[0].pos, marker_range[1].pos); - draw_character_block(app, text_layout_id, range, roundness, - fcolor_id(Stag_Highlight)); - paint_text_color(app, text_layout_id, range, - fcolor_id(Stag_At_Highlight)); - } - } - } - return(has_highlight_range); -} - -function void -draw_original_4coder_style_cursor_mark_highlight(Application_Links *app, View_ID view_id, b32 is_active_view, - Buffer_ID buffer, Text_Layout_ID text_layout_id, - f32 roundness, f32 outline_thickness){ - b32 has_highlight_range = draw_highlight_range(app, view_id, buffer, text_layout_id, roundness); - if (!has_highlight_range){ - i64 cursor_pos = view_get_cursor_pos(app, view_id); - i64 mark_pos = view_get_mark_pos(app, view_id); - if (is_active_view){ - draw_character_block(app, text_layout_id, cursor_pos, roundness, - fcolor_id(Stag_Cursor)); - paint_text_color_pos(app, text_layout_id, cursor_pos, - fcolor_id(Stag_At_Cursor)); - draw_character_wire_frame(app, text_layout_id, mark_pos, - roundness, outline_thickness, - fcolor_id(Stag_Mark)); - } - else{ - draw_character_wire_frame(app, text_layout_id, mark_pos, - roundness, outline_thickness, - fcolor_id(Stag_Mark)); - draw_character_wire_frame(app, text_layout_id, cursor_pos, - roundness, outline_thickness, - fcolor_id(Stag_Cursor)); - } - } -} - -function void -draw_notepad_style_cursor_highlight(Application_Links *app, View_ID view_id, - Buffer_ID buffer, Text_Layout_ID text_layout_id, - f32 roundness){ - b32 has_highlight_range = draw_highlight_range(app, view_id, buffer, text_layout_id, roundness); - if (!has_highlight_range){ - i64 cursor_pos = view_get_cursor_pos(app, view_id); - i64 mark_pos = view_get_mark_pos(app, view_id); - if (cursor_pos != mark_pos){ - Range_i64 range = Ii64(cursor_pos, mark_pos); - draw_character_block(app, text_layout_id, range, roundness, - fcolor_id(Stag_Highlight)); - paint_text_color(app, text_layout_id, range, - fcolor_id(Stag_At_Highlight)); - } - draw_character_i_bar(app, text_layout_id, cursor_pos, fcolor_id(Stag_Cursor)); - } -} - -//////////////////////////////// - -function Rect_f32 -get_contained_box_near_point(Rect_f32 container, Vec2_f32 p, Vec2_f32 box_dims){ - Vec2_f32 container_dims = rect_dim(container); - box_dims.x = clamp_top(box_dims.x, container_dims.x); - box_dims.y = clamp_top(box_dims.y, container_dims.y); - Vec2_f32 q = p + V2f32(-20.f, 22.f); - if (q.x + box_dims.x > container.x1){ - q.x = container.x1 - box_dims.x; - } - if (q.y + box_dims.y > container.y1){ - q.y = p.y - box_dims.y - 2.f; - if (q.y < container.y0){ - q.y = (container.y0 + container.y1 - box_dims.y)*0.5f; - } - } - return(Rf32_xy_wh(q, box_dims)); -} - -function Rect_f32 -draw_tool_tip(Application_Links *app, Face_ID face, Fancy_Block *block, - Vec2_f32 p, Rect_f32 region, f32 x_padding, f32 x_half_padding, - FColor back_color){ - Rect_f32 box = Rf32(p, p); - if (block->line_count > 0){ - Vec2_f32 dims = get_fancy_block_dim(app, face, block); - dims += V2f32(x_padding, 2.f); - box = get_contained_box_near_point(region, p, dims); - box.x0 = f32_round32(box.x0); - box.y0 = f32_round32(box.y0); - box.x1 = f32_round32(box.x1); - box.y1 = f32_round32(box.y1); - Rect_f32 prev_clip = draw_set_clip(app, box); - draw_rectangle(app, box, 6.f, back_color); - draw_fancy_block(app, face, fcolor_zero(), block, - box.p0 + V2f32(x_half_padding, 1.f)); - draw_set_clip(app, prev_clip); - } - return(box); -} - -function Rect_f32 -draw_drop_down(Application_Links *app, Face_ID face, Fancy_Block *block, - Vec2_f32 p, Rect_f32 region, f32 x_padding, f32 x_half_padding, - FColor outline_color, FColor back_color){ - Rect_f32 box = Rf32(p, p); - if (block->line_count > 0){ - Vec2_f32 dims = get_fancy_block_dim(app, face, block); - dims += V2f32(x_padding, 4.f); - box = get_contained_box_near_point(region, p, dims); - box.x0 = f32_round32(box.x0); - box.y0 = f32_round32(box.y0); - box.x1 = f32_round32(box.x1); - box.y1 = f32_round32(box.y1); - Rect_f32 prev_clip = draw_set_clip(app, box); - draw_rectangle(app, box, 0.f, back_color); - draw_margin(app, box, rect_inner(box, 1.f), outline_color); - draw_fancy_block(app, face, fcolor_zero(), block, - box.p0 + V2f32(x_half_padding, 2.f)); - draw_set_clip(app, prev_clip); - } - return(box); -} - -function b32 -draw_button(Application_Links *app, Rect_f32 rect, Vec2_f32 mouse_p, Face_ID face, String_Const_u8 text){ - b32 hovered = false; - if (rect_contains_point(rect, mouse_p)){ - hovered = true; - } - - FColor margin_color = get_margin_color(hovered?UIHighlight_Active:UIHighlight_None); - draw_rectangle(app, rect, 3.f, margin_color); - rect = rect_inner(rect, 3.f); - draw_rectangle(app, rect, 3.f, fcolor_id(Stag_Back)); - - Scratch_Block scratch(app); - Fancy_String *fancy = push_fancy_string(scratch, 0, face, fcolor_id(Stag_Default), text); - Vec2_f32 dim = get_fancy_string_dim(app, 0, fancy); - Vec2_f32 p = (rect.p0 + rect.p1 - dim)*0.5f; - draw_fancy_string(app, fancy, p); - - return(hovered); -} - -// BOTTOM - +/* +4coder_draw.cpp - Layout and rendering implementation of standard UI pieces (including buffers) +*/ + +// TOP + +function void +draw_text_layout_default(Application_Links *app, Text_Layout_ID layout_id){ + ARGB_Color special_color = finalize_color(defcolor_special_character, 0); + ARGB_Color ghost_color = finalize_color(defcolor_ghost_character, 0); + draw_text_layout(app, layout_id, special_color, ghost_color); +} + +function FColor +get_margin_color(i32 level){ + FColor margin = fcolor_zero(); + switch (level){ + default: + case UIHighlight_None: + { + margin = fcolor_id(defcolor_list_item); + }break; + case UIHighlight_Hover: + { + margin = fcolor_id(defcolor_list_item_hover); + }break; + case UIHighlight_Active: + { + margin = fcolor_id(defcolor_list_item_active); + }break; + } + return(margin); +} + +function Vec2_f32 +draw_string(Application_Links *app, Face_ID font_id, String_Const_u8 string, Vec2_f32 p, ARGB_Color color){ + return(draw_string_oriented(app, font_id, color, string, p, 0, V2(1.f, 0.f))); +} + +function Vec2_f32 +draw_string(Application_Links *app, Face_ID font_id, String_Const_u8 string, Vec2_f32 p, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_string(app, font_id, string, p, argb); +} + +function void +draw_rectangle_fcolor(Application_Links *app, Rect_f32 rect, f32 roundness, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_rectangle(app, rect, roundness, argb); +} + +function void +draw_rectangle_outline_fcolor(Application_Links *app, Rect_f32 rect, f32 roundness, f32 thickness, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_rectangle_outline(app, rect, roundness, thickness, argb); +} + +function void +draw_margin(Application_Links *app, Rect_f32 outer, Rect_f32 inner, ARGB_Color color){ + draw_rectangle(app, Rf32(outer.x0, outer.y0, outer.x1, inner.y0), 0.f, color); + draw_rectangle(app, Rf32(outer.x0, inner.y1, outer.x1, outer.y1), 0.f, color); + draw_rectangle(app, Rf32(outer.x0, inner.y0, inner.x0, inner.y1), 0.f, color); + draw_rectangle(app, Rf32(inner.x1, inner.y0, outer.x1, inner.y1), 0.f, color); +} + +function void +draw_margin(Application_Links *app, Rect_f32 outer, Rect_f32 inner, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_margin(app, outer, inner, argb); +} + +function void +draw_character_block(Application_Links *app, Text_Layout_ID layout, i64 pos, f32 roundness, ARGB_Color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + draw_rectangle(app, rect, roundness, color); +} + +function void +draw_character_block(Application_Links *app, Text_Layout_ID layout, i64 pos, f32 roundness, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_character_block(app, layout, pos, roundness, argb); +} + +function void +draw_character_block(Application_Links *app, Text_Layout_ID layout, Range_i64 range, f32 roundness, ARGB_Color color){ + if (range.first < range.one_past_last){ + i64 i = range.first; + Rect_f32 first_rect = text_layout_character_on_screen(app, layout, i); + i += 1; + Range_f32 y = rect_range_y(first_rect); + Range_f32 x = rect_range_x(first_rect); + for (;i < range.one_past_last; i += 1){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, i); + if (rect.x0 < rect.x1 && rect.y0 < rect.y1){ + Range_f32 new_y = rect_range_y(rect); + Range_f32 new_x = rect_range_x(rect); + b32 joinable = false; + if (new_y == y && (range_overlap(x, new_x) || x.max == new_x.min || new_x.max == x.min)){ + joinable = true; + } + + if (!joinable){ + draw_rectangle(app, Rf32(x, y), roundness, color); + y = new_y; + x = new_x; + } + else{ + x = range_union(x, new_x); + } + } + } + draw_rectangle(app, Rf32(x, y), roundness, color); + } + for (i64 i = range.first; i < range.one_past_last; i += 1){ + draw_character_block(app, layout, i, roundness, color); + } +} + +function void +draw_character_block(Application_Links *app, Text_Layout_ID layout, Range_i64 range, f32 roundness, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_character_block(app, layout, range, roundness, argb); + } + +function void +draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, i64 pos, f32 roundness, f32 thickness, ARGB_Color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + draw_rectangle_outline(app, rect, roundness, thickness, color); +} + +function void +draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, i64 pos, f32 roundness, f32 thickness, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_character_wire_frame(app, layout, pos, roundness, thickness, argb); +} + +function void +draw_character_wire_frame(Application_Links *app, Text_Layout_ID layout, Range_i64 range, f32 roundness, f32 thickness, FColor color){ + for (i64 i = range.first; i < range.one_past_last; i += 1){ + draw_character_wire_frame(app, layout, i, roundness, thickness, color); + } +} + +function void +draw_character_i_bar(Application_Links *app, Text_Layout_ID layout, i64 pos, ARGB_Color color){ + Rect_f32 rect = text_layout_character_on_screen(app, layout, pos); + rect.x1 = rect.x0 + 1.f; + draw_rectangle(app, rect, 0.f, color); +} + +function void +draw_character_i_bar(Application_Links *app, Text_Layout_ID layout, i64 pos, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_character_i_bar(app, layout, pos, argb); +} + +function void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, Range_i64 line_range, ARGB_Color color){ + Range_f32 y1 = text_layout_line_on_screen(app, layout, line_range.min); + Range_f32 y2 = text_layout_line_on_screen(app, layout, line_range.max); + Range_f32 y = range_union(y1, y2); + if (range_size(y) > 0.f){ + Rect_f32 region = text_layout_region(app, layout); + draw_rectangle(app, Rf32(rect_range_x(region), y), 0.f, color); + } +} + +function void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, Range_i64 line_range, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + draw_line_highlight(app, layout, line_range, argb); +} + +function void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, i64 line, ARGB_Color color){ + draw_line_highlight(app, layout, Ii64(line), color); +} + +function void +draw_line_highlight(Application_Links *app, Text_Layout_ID layout, i64 line, FColor color){ + draw_line_highlight(app, layout, Ii64(line), color); +} + +function void +paint_text_color_fcolor(Application_Links *app, Text_Layout_ID layout, Range_i64 pos, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + paint_text_color(app, layout, pos, argb); +} + +function void +paint_text_color_pos(Application_Links *app, Text_Layout_ID layout, i64 pos, ARGB_Color color){ + paint_text_color(app, layout, Ii64(pos, pos + 1), color); +} + +function void +paint_text_color_pos(Application_Links *app, Text_Layout_ID layout, i64 pos, FColor color){ + ARGB_Color argb = fcolor_resolve(color); + paint_text_color_pos(app, layout, pos, argb); +} + +//////////////////////////////// + +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_Pair +layout_query_bar_on_top(Rect_f32 rect, f32 line_height, i32 bar_count){ + return(rect_split_top_bottom(rect, (line_height + 2.f)*bar_count)); +} + +function Rect_f32_Pair +layout_query_bar_on_bot(Rect_f32 rect, f32 line_height, i32 bar_count){ + return(rect_split_top_bottom_neg(rect, (line_height + 2.f)*bar_count)); +} + +function Rect_f32_Pair +layout_line_number_margin(Rect_f32 rect, f32 digit_advance, i64 digit_count){ + f32 margin_width = (f32)digit_count*digit_advance + 2.f; + return(rect_split_left_right(rect, margin_width)); +} + +function Rect_f32_Pair +layout_line_number_margin(Application_Links *app, Buffer_ID buffer, Rect_f32 rect, f32 digit_advance){ + i64 line_count = buffer_get_line_count(app, buffer); + i64 line_count_digit_count = digit_count_from_integer(line_count, 10); + return(layout_line_number_margin(rect, digit_advance, line_count_digit_count)); +} + +global_const i32 fps_history_depth = 10; +function Rect_f32_Pair +layout_fps_hud_on_bottom(Rect_f32 rect, f32 line_height){ + return(rect_split_top_bottom_neg(rect, line_height*fps_history_depth)); +} + +function Rect_f32 +draw_background_and_margin(Application_Links *app, View_ID view, ARGB_Color margin, ARGB_Color back){ + Rect_f32 view_rect = view_get_screen_rect(app, view); + Rect_f32 inner = rect_inner(view_rect, 3.f); + draw_rectangle(app, inner, 0.f, back); + draw_margin(app, view_rect, inner, margin); + return(inner); +} + +function Rect_f32 +draw_background_and_margin(Application_Links *app, View_ID view, FColor margin, FColor back){ + ARGB_Color margin_argb = fcolor_resolve(margin); + ARGB_Color back_argb = fcolor_resolve(back); + return(draw_background_and_margin(app, view, margin_argb, back_argb)); +} + +function Rect_f32 +draw_background_and_margin(Application_Links *app, View_ID view, b32 is_active_view){ + FColor margin_color = get_margin_color(is_active_view?UIHighlight_Active:UIHighlight_None); + return(draw_background_and_margin(app, view, margin_color, fcolor_id(defcolor_back))); +} + +function Rect_f32 +draw_background_and_margin(Application_Links *app, View_ID view){ + View_ID active_view = get_active_view(app, Access_Always); + b32 is_active_view = (active_view == view); + return(draw_background_and_margin(app, view, is_active_view)); +} + +function void +draw_file_bar(Application_Links *app, View_ID view_id, Buffer_ID buffer, Face_ID face_id, Rect_f32 bar){ + Scratch_Block scratch(app); + + draw_rectangle_fcolor(app, bar, 0.f, fcolor_id(defcolor_bar)); + + FColor base_color = fcolor_id(defcolor_base); + FColor pop2_color = fcolor_id(defcolor_pop2); + + i64 cursor_position = view_get_cursor_pos(app, view_id); + Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(cursor_position)); + + Fancy_Line 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.col); + + Managed_Scope scope = buffer_get_managed_scope(app, buffer); + Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, + Line_Ending_Kind); + switch (*eol_setting){ + case LineEndingKind_Binary: + { + push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" bin")); + }break; + + case LineEndingKind_LF: + { + push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" lf")); + }break; + + case LineEndingKind_CRLF: + { + push_fancy_string(scratch, &list, base_color, string_u8_litexpr(" crlf")); + }break; + } + + { + Dirty_State dirty = buffer_get_dirty_state(app, buffer); + u8 space[3]; + String_u8 str = Su8(space, 0, 3); + if (dirty != 0){ + string_append(&str, string_u8_litexpr(" ")); + } + if (HasFlag(dirty, DirtyState_UnsavedChanges)){ + string_append(&str, string_u8_litexpr("*")); + } + if (HasFlag(dirty, DirtyState_UnloadedChanges)){ + string_append(&str, string_u8_litexpr("!")); + } + push_fancy_string(scratch, &list, pop2_color, str.string); + } + + Vec2 p = bar.p0 + V2(2.f, 2.f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); +} + +function void +draw_query_bar(Application_Links *app, Query_Bar *query_bar, Face_ID face_id, Rect_f32 bar){ + Scratch_Block scratch(app); + Fancy_Line list = {}; + push_fancy_string(scratch, &list, fcolor_id(defcolor_pop1) , query_bar->prompt); + push_fancy_string(scratch, &list, fcolor_id(defcolor_text_default), query_bar->string); + Vec2_f32 p = bar.p0 + V2(2.f, 2.f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); +} + +function void +draw_line_number_margin(Application_Links *app, View_ID view_id, Buffer_ID buffer, Face_ID face_id, Text_Layout_ID text_layout_id, Rect_f32 margin){ + Rect_f32 prev_clip = draw_set_clip(app, margin); + draw_rectangle_fcolor(app, margin, 0.f, fcolor_id(defcolor_line_numbers_back)); + + Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); + + FColor line_color = fcolor_id(defcolor_line_numbers_text); + + i64 line_count = buffer_get_line_count(app, buffer); + i64 line_count_digit_count = digit_count_from_integer(line_count, 10); + + Scratch_Block scratch(app, Scratch_Share); + + Buffer_Cursor cursor = view_compute_cursor(app, view_id, seek_pos(visible_range.first)); + i64 line_number = cursor.line; + for (;cursor.pos <= visible_range.one_past_last;){ + if (line_number > line_count){ + break; + } + Range_f32 line_y = text_layout_line_on_screen(app, text_layout_id, line_number); + Vec2_f32 p = V2f32(margin.x0, line_y.min); + Temp_Memory_Block temp(scratch); + Fancy_String *string = push_fancy_stringf(scratch, 0, line_color, + "%*lld", + line_count_digit_count, + line_number); + draw_fancy_string(app, face_id, fcolor_zero(), string, p); + line_number += 1; + } + + draw_set_clip(app, prev_clip); +} + +function void +draw_fps_hud(Application_Links *app, Frame_Info frame_info, + Face_ID face_id, Rect_f32 rect){ + Face_Metrics face_metrics = get_face_metrics(app, face_id); + f32 line_height = face_metrics.line_height; + + local_persist f32 history_literal_dt[fps_history_depth] = {}; + local_persist f32 history_animation_dt[fps_history_depth] = {}; + local_persist i32 history_frame_index[fps_history_depth] = {}; + + i32 wrapped_index = frame_info.index%fps_history_depth; + history_literal_dt[wrapped_index] = frame_info.literal_dt; + history_animation_dt[wrapped_index] = frame_info.animation_dt; + history_frame_index[wrapped_index] = frame_info.index; + + draw_rectangle_fcolor(app, rect, 0.f, f_black); + draw_rectangle_outline_fcolor(app, rect, 0.f, 1.f, f_white); + + Vec2_f32 p = rect.p0; + + Scratch_Block scratch(app); + + Range ranges[2]; + ranges[0].first = wrapped_index; + ranges[0].one_past_last = -1; + ranges[1].first = fps_history_depth - 1; + ranges[1].one_past_last = wrapped_index; + for (i32 i = 0; i < 2; i += 1){ + Range r = ranges[i]; + for (i32 j = r.first; j > r.one_past_last; j -= 1, p.y += line_height){ + f32 dts[2]; + dts[0] = history_literal_dt[j]; + dts[1] = history_animation_dt[j]; + i32 frame_index = history_frame_index[j]; + + Fancy_Line list = {}; + push_fancy_stringf(scratch, &list, f_pink , "FPS: "); + push_fancy_stringf(scratch, &list, f_green, "["); + push_fancy_stringf(scratch, &list, f_white, "%5d", frame_index); + push_fancy_stringf(scratch, &list, f_green, "]: "); + + for (i32 k = 0; k < 2; k += 1){ + f32 dt = dts[k]; + if (dt == 0.f){ + push_fancy_stringf(scratch, &list, f_white, "----------"); + } + else{ + push_fancy_stringf(scratch, &list, f_white, "%10.6f", dt); + } + push_fancy_stringf(scratch, &list, f_green, " | "); + } + + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + } + } +} + +function FColor +get_token_color_cpp(Token token){ + Managed_ID color = defcolor_text_default; + switch (token.kind){ + case TokenBaseKind_Preprocessor: + { + color = defcolor_preproc; + }break; + case TokenBaseKind_Keyword: + { + color = defcolor_keyword; + }break; + case TokenBaseKind_Comment: + { + color = defcolor_comment; + }break; + case TokenBaseKind_LiteralString: + { + color = defcolor_str_constant; + }break; + case TokenBaseKind_LiteralInteger: + { + color = defcolor_int_constant; + }break; + case TokenBaseKind_LiteralFloat: + { + color = defcolor_float_constant; + }break; + default: + { + switch (token.sub_kind){ + case TokenCppKind_LiteralTrue: + case TokenCppKind_LiteralFalse: + { + color = defcolor_bool_constant; + }break; + case TokenCppKind_LiteralCharacter: + case TokenCppKind_LiteralCharacterWide: + case TokenCppKind_LiteralCharacterUTF8: + case TokenCppKind_LiteralCharacterUTF16: + case TokenCppKind_LiteralCharacterUTF32: + { + color = defcolor_char_constant; + }break; + case TokenCppKind_PPIncludeFile: + { + color = defcolor_include; + }break; + } + }break; + } + return(fcolor_id(color)); +} + +function void +draw_cpp_token_colors(Application_Links *app, Text_Layout_ID text_layout_id, Token_Array *array){ + Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); + i64 first_index = token_index_from_pos(array, visible_range.first); + Token_Iterator_Array it = token_iterator_index(0, array, first_index); + for (;;){ + Token *token = token_it_read(&it); + if (token->pos >= visible_range.one_past_last){ + break; + } + FColor color = get_token_color_cpp(*token); + ARGB_Color argb = fcolor_resolve(color); + paint_text_color(app, text_layout_id, Ii64_size(token->pos, token->size), argb); + if (!token_it_inc_non_whitespace(&it)){ + break; + } + } +} + +function void +draw_comment_highlights(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, + Token_Array *array, Comment_Highlight_Pair *pairs, i32 pair_count){ + Scratch_Block scratch(app); + Interval_i64 visible_range = text_layout_get_visible_range(app, text_layout_id); + i64 first_index = token_index_from_pos(array, visible_range.first); + Token_Iterator_Array it = token_iterator_index(buffer, array, first_index); + for (;;){ + Temp_Memory_Block temp(scratch); + Token *token = token_it_read(&it); + if (token->pos >= visible_range.one_past_last){ + break; + } + String_Const_u8 tail = {}; + if (token_it_check_and_get_lexeme(app, scratch, &it, TokenBaseKind_Comment, &tail)){ + for (i64 index = token->pos; + tail.size > 0; + tail = string_skip(tail, 1), index += 1){ + Comment_Highlight_Pair *pair = pairs; + for (i32 i = 0; i < pair_count; i += 1, pair += 1){ + umem needle_size = pair->needle.size; + if (needle_size == 0){ + continue; + } + String_Const_u8 prefix = string_prefix(tail, needle_size); + if (string_match(prefix, pair->needle)){ + Range_i64 range = Ii64_size(index, needle_size); + paint_text_color(app, text_layout_id, range, pair->color); + tail = string_skip(tail, needle_size - 1); + index += needle_size - 1; + break; + } + } + } + } + if (!token_it_inc_non_whitespace(&it)){ + break; + } + } +} + +function 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; + array.ranges = push_array(arena, Range_i64, max); + for (;;){ + Range_i64 range = {}; + if (find_surrounding_nest(app, buffer, pos, flags, &range)){ + array.ranges[array.count] = range; + array.count += 1; + pos = range.first; + if (array.count >= max){ + break; + } + } + else{ + break; + } + } + return(array); +} + +function void +draw_enclosures(Application_Links *app, Text_Layout_ID text_layout_id, Buffer_ID buffer, + i64 pos, u32 flags, Range_Highlight_Kind kind, + ARGB_Color *back_colors, i32 back_count, + ARGB_Color *fore_colors, i32 fore_count){ + Scratch_Block scratch(app); + Range_i64_Array ranges = get_enclosure_ranges(app, scratch, buffer, pos, flags); + + i32 color_index = 0; + for (i32 i = ranges.count - 1; i >= 0; i -= 1){ + Range_i64 range = ranges.ranges[i]; + if (kind == RangeHighlightKind_LineHighlight){ + Range_i64 r[2] = {}; + if (i > 0){ + Range_i64 inner_range = ranges.ranges[i - 1]; + Range_i64 lines = get_line_range_from_pos_range(app, buffer, range); + Range_i64 inner_lines = get_line_range_from_pos_range(app, buffer, inner_range); + inner_lines.min = clamp_bot(lines.min, inner_lines.min); + inner_lines.max = clamp_top(inner_lines.max, lines.max); + inner_lines.min -= 1; + inner_lines.max += 1; + if (lines.min <= inner_lines.min){ + r[0] = Ii64(lines.min, inner_lines.min); + } + if (inner_lines.max <= lines.max){ + r[1] = Ii64(inner_lines.max, lines.max); + } + } + else{ + r[0] = get_line_range_from_pos_range(app, buffer, range); + } + for (i32 j = 0; j < 2; j += 1){ + if (r[j].min == 0){ + continue; + } + Range_i64 line_range = r[j]; + if (back_colors != 0){ + i32 back_index = color_index%back_count; + draw_line_highlight(app, text_layout_id, line_range, back_colors[back_index]); + } + if (fore_colors != 0){ + i32 fore_index = color_index%fore_count; + Range_i64 pos_range = get_pos_range_from_line_range(app, buffer, line_range); + paint_text_color(app, text_layout_id, pos_range, fore_colors[fore_index]); + } + } + } + else{ + if (back_colors != 0){ + i32 back_index = color_index%back_count; + draw_character_block(app, text_layout_id, range.min, 0.f, back_colors[back_index]); + draw_character_block(app, text_layout_id, range.max - 1, 0.f, back_colors[back_index]); + } + if (fore_colors != 0){ + i32 fore_index = color_index%fore_count; + paint_text_color_pos(app, text_layout_id, range.min, fore_colors[fore_index]); + paint_text_color_pos(app, text_layout_id, range.max - 1, fore_colors[fore_index]); + } + } + color_index += 1; + } +} + +function void +draw_scope_highlight(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, + i64 pos, ARGB_Color *colors, i32 color_count){ + draw_enclosures(app, text_layout_id, buffer, + pos, FindNest_Scope, RangeHighlightKind_LineHighlight, + colors, color_count, 0, 0); +} + +function void +draw_paren_highlight(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, + i64 pos, ARGB_Color *colors, i32 color_count){ + Token_Array token_array = get_token_array_from_buffer(app, buffer); + if (token_array.tokens != 0){ + Token_Iterator_Array it = token_iterator_pos(0, &token_array, pos); + Token *token = token_it_read(&it); + if (token != 0 && token->kind == TokenBaseKind_ParentheticalOpen){ + pos = token->pos + token->size; + } + else{ + if (token_it_dec_all(&it)){ + token = token_it_read(&it); + if (token->kind == TokenBaseKind_ParentheticalClose && + pos == token->pos + token->size){ + pos = token->pos; + } + } + } + } + draw_enclosures(app, text_layout_id, buffer, + pos, FindNest_Paren, RangeHighlightKind_CharacterHighlight, + 0, 0, colors, color_count); +} + +function void +draw_jump_highlights(Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, + Buffer_ID jump_buffer, FColor line_color){ + Scratch_Block scratch(app); + if (jump_buffer != 0){ + Managed_Scope scopes[2]; + scopes[0] = buffer_get_managed_scope(app, jump_buffer); + scopes[1] = buffer_get_managed_scope(app, buffer); + Managed_Scope comp_scope = get_managed_scope_with_multiple_dependencies(app, scopes, ArrayCount(scopes)); + Managed_Object *markers_object = scope_attachment(app, comp_scope, sticky_jump_marker_handle, Managed_Object); + + i32 count = managed_object_get_item_count(app, *markers_object); + Marker *markers = push_array(scratch, Marker, count); + managed_object_load_data(app, *markers_object, 0, count, markers); + for (i32 i = 0; i < count; i += 1){ + i64 line_number = get_line_number_from_pos(app, buffer, markers[i].pos); + draw_line_highlight(app, text_layout_id, line_number, line_color); + } + } +} + +function b32 +draw_highlight_range(Application_Links *app, View_ID view_id, + Buffer_ID buffer, Text_Layout_ID text_layout_id, + f32 roundness){ + b32 has_highlight_range = false; + Managed_Scope scope = view_get_managed_scope(app, view_id); + Buffer_ID *highlight_buffer = scope_attachment(app, scope, view_highlight_buffer, Buffer_ID); + if (*highlight_buffer != 0){ + if (*highlight_buffer != buffer){ + view_disable_highlight_range(app, view_id); + } + else{ + has_highlight_range = true; + Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); + Marker marker_range[2]; + if (managed_object_load_data(app, *highlight, 0, 2, marker_range)){ + Range_i64 range = Ii64(marker_range[0].pos, marker_range[1].pos); + draw_character_block(app, text_layout_id, range, roundness, + fcolor_id(defcolor_highlight)); + paint_text_color_fcolor(app, text_layout_id, range, + fcolor_id(defcolor_at_highlight)); + } + } + } + return(has_highlight_range); +} + +function void +draw_original_4coder_style_cursor_mark_highlight(Application_Links *app, View_ID view_id, b32 is_active_view, + Buffer_ID buffer, Text_Layout_ID text_layout_id, + f32 roundness, f32 outline_thickness){ + b32 has_highlight_range = draw_highlight_range(app, view_id, buffer, text_layout_id, roundness); + if (!has_highlight_range){ + i64 cursor_pos = view_get_cursor_pos(app, view_id); + i64 mark_pos = view_get_mark_pos(app, view_id); + if (is_active_view){ + draw_character_block(app, text_layout_id, cursor_pos, roundness, + fcolor_id(defcolor_cursor)); + paint_text_color_pos(app, text_layout_id, cursor_pos, + fcolor_id(defcolor_at_cursor)); + draw_character_wire_frame(app, text_layout_id, mark_pos, + roundness, outline_thickness, + fcolor_id(defcolor_mark)); + } + else{ + draw_character_wire_frame(app, text_layout_id, mark_pos, + roundness, outline_thickness, + fcolor_id(defcolor_mark)); + draw_character_wire_frame(app, text_layout_id, cursor_pos, + roundness, outline_thickness, + fcolor_id(defcolor_cursor)); + } + } +} + +function void +draw_notepad_style_cursor_highlight(Application_Links *app, View_ID view_id, + Buffer_ID buffer, Text_Layout_ID text_layout_id, + f32 roundness){ + b32 has_highlight_range = draw_highlight_range(app, view_id, buffer, text_layout_id, roundness); + if (!has_highlight_range){ + i64 cursor_pos = view_get_cursor_pos(app, view_id); + i64 mark_pos = view_get_mark_pos(app, view_id); + if (cursor_pos != mark_pos){ + Range_i64 range = Ii64(cursor_pos, mark_pos); + draw_character_block(app, text_layout_id, range, roundness, + fcolor_id(defcolor_highlight)); + paint_text_color_fcolor(app, text_layout_id, range, + fcolor_id(defcolor_at_highlight)); + } + draw_character_i_bar(app, text_layout_id, cursor_pos, fcolor_id(defcolor_cursor)); + } +} + +//////////////////////////////// + +function Rect_f32 +get_contained_box_near_point(Rect_f32 container, Vec2_f32 p, Vec2_f32 box_dims){ + Vec2_f32 container_dims = rect_dim(container); + box_dims.x = clamp_top(box_dims.x, container_dims.x); + box_dims.y = clamp_top(box_dims.y, container_dims.y); + Vec2_f32 q = p + V2f32(-20.f, 22.f); + if (q.x + box_dims.x > container.x1){ + q.x = container.x1 - box_dims.x; + } + if (q.y + box_dims.y > container.y1){ + q.y = p.y - box_dims.y - 2.f; + if (q.y < container.y0){ + q.y = (container.y0 + container.y1 - box_dims.y)*0.5f; + } + } + return(Rf32_xy_wh(q, box_dims)); +} + +function Rect_f32 +draw_tool_tip(Application_Links *app, Face_ID face, Fancy_Block *block, + Vec2_f32 p, Rect_f32 region, f32 x_padding, f32 x_half_padding, + FColor back_color){ + Rect_f32 box = Rf32(p, p); + if (block->line_count > 0){ + Vec2_f32 dims = get_fancy_block_dim(app, face, block); + dims += V2f32(x_padding, 2.f); + box = get_contained_box_near_point(region, p, dims); + box.x0 = f32_round32(box.x0); + box.y0 = f32_round32(box.y0); + box.x1 = f32_round32(box.x1); + box.y1 = f32_round32(box.y1); + Rect_f32 prev_clip = draw_set_clip(app, box); + draw_rectangle_fcolor(app, box, 6.f, back_color); + draw_fancy_block(app, face, fcolor_zero(), block, + box.p0 + V2f32(x_half_padding, 1.f)); + draw_set_clip(app, prev_clip); + } + return(box); +} + +function Rect_f32 +draw_drop_down(Application_Links *app, Face_ID face, Fancy_Block *block, + Vec2_f32 p, Rect_f32 region, f32 x_padding, f32 x_half_padding, + FColor outline_color, FColor back_color){ + Rect_f32 box = Rf32(p, p); + if (block->line_count > 0){ + Vec2_f32 dims = get_fancy_block_dim(app, face, block); + dims += V2f32(x_padding, 4.f); + box = get_contained_box_near_point(region, p, dims); + box.x0 = f32_round32(box.x0); + box.y0 = f32_round32(box.y0); + box.x1 = f32_round32(box.x1); + box.y1 = f32_round32(box.y1); + Rect_f32 prev_clip = draw_set_clip(app, box); + draw_rectangle_fcolor(app, box, 0.f, back_color); + draw_margin(app, box, rect_inner(box, 1.f), outline_color); + draw_fancy_block(app, face, fcolor_zero(), block, + box.p0 + V2f32(x_half_padding, 2.f)); + draw_set_clip(app, prev_clip); + } + return(box); +} + +function b32 +draw_button(Application_Links *app, Rect_f32 rect, Vec2_f32 mouse_p, Face_ID face, String_Const_u8 text){ + b32 hovered = false; + if (rect_contains_point(rect, mouse_p)){ + hovered = true; + } + + FColor margin_color = get_margin_color(hovered?UIHighlight_Active:UIHighlight_None); + draw_rectangle_fcolor(app, rect, 3.f, margin_color); + rect = rect_inner(rect, 3.f); + draw_rectangle_fcolor(app, rect, 3.f, fcolor_id(defcolor_back)); + + Scratch_Block scratch(app); + Fancy_String *fancy = push_fancy_string(scratch, 0, face, fcolor_id(defcolor_text_default), text); + Vec2_f32 dim = get_fancy_string_dim(app, 0, fancy); + Vec2_f32 p = (rect.p0 + rect.p1 - dim)*0.5f; + draw_fancy_string(app, fancy, p); + + return(hovered); +} + +// BOTTOM + diff --git a/custom/4coder_draw.h b/custom/4coder_draw.h index e0c5542a..db7fa317 100644 --- a/custom/4coder_draw.h +++ b/custom/4coder_draw.h @@ -9,7 +9,7 @@ struct Comment_Highlight_Pair{ String_Const_u8 needle; - FColor color; + ARGB_Color color; }; typedef i32 Range_Highlight_Kind; diff --git a/custom/4coder_fancy.cpp b/custom/4coder_fancy.cpp index b1750d11..68d71568 100644 --- a/custom/4coder_fancy.cpp +++ b/custom/4coder_fancy.cpp @@ -23,9 +23,17 @@ fcolor_argb(f32 r, f32 g, f32 b, f32 a){ } function FColor -fcolor_id(ID_Color id){ +fcolor_id(Managed_ID id){ FColor result = {}; - result.id = id; + result.id = (ID_Color)id; + return(result); +} + +function FColor +fcolor_id(Managed_ID id, u32 sub_index){ + FColor result = {}; + result.id = (ID_Color)id; + result.sub_index = (u8)sub_index; return(result); } @@ -42,11 +50,11 @@ argb_color_blend(ARGB_Color a, f32 t, ARGB_Color b){ } function ARGB_Color -fcolor_resolve_to_argb(Application_Links *app, FColor color){ +fcolor_resolve(FColor color){ ARGB_Color result = 0; if (color.a_byte == 0){ if (color.id != 0){ - result = finalize_color(app, color.id); + result = finalize_color(color.id, color.sub_index); } } else{ @@ -56,20 +64,20 @@ fcolor_resolve_to_argb(Application_Links *app, FColor color){ } function FColor -fcolor_change_alpha(Application_Links *app, FColor color, f32 alpha){ - Vec4_f32 v = unpack_color(fcolor_resolve_to_argb(app, color)); +fcolor_change_alpha(FColor color, f32 alpha){ + Vec4_f32 v = unpack_color(fcolor_resolve(color)); v.a = alpha; return(fcolor_argb(pack_color(v))); } function FColor -fcolor_blend(Application_Links *app, FColor a, f32 at, FColor b, f32 bt){ - ARGB_Color a_argb = fcolor_resolve_to_argb(app, a); - ARGB_Color b_argb = fcolor_resolve_to_argb(app, b); +fcolor_blend(FColor a, f32 at, FColor b, f32 bt){ + ARGB_Color a_argb = fcolor_resolve(a); + ARGB_Color b_argb = fcolor_resolve(b); return(fcolor_argb(argb_color_blend(a_argb, at, b_argb, bt))); } function FColor -fcolor_blend(Application_Links *app, FColor a, f32 t, FColor b){ - return(fcolor_blend(app, a, 1.f - t, b, t)); +fcolor_blend(FColor a, f32 t, FColor b){ + return(fcolor_blend(a, 1.f - t, b, t)); } function FColor @@ -612,6 +620,7 @@ draw_fancy_string__inner(Application_Links *app, Face_ID face, FColor fore, Fanc use_fore = string->fore; } if (use_face != 0){ + ARGB_Color use_argb = fcolor_resolve(use_fore); Face_Metrics metrics = get_face_metrics(app, use_face); f32 down_shift = (base_line - metrics.ascent); down_shift = clamp_bot(0.f, down_shift); @@ -621,7 +630,7 @@ draw_fancy_string__inner(Application_Links *app, Face_ID face, FColor fore, Fanc if (fcolor_is_valid(use_fore)){ Vec2_f32 margin_delta = delta*metrics.normal_advance; p_shifted += margin_delta*string->pre_margin; - p_shifted = draw_string_oriented(app, use_face, use_fore, string->value, p_shifted, flags, delta); + p_shifted = draw_string_oriented(app, use_face, use_argb, string->value, p_shifted, flags, delta); p_shifted += margin_delta*string->post_margin; } else{ diff --git a/custom/4coder_lister_base.cpp b/custom/4coder_lister_base.cpp index 4b492c10..512bbcb9 100644 --- a/custom/4coder_lister_base.cpp +++ b/custom/4coder_lister_base.cpp @@ -182,10 +182,10 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ { Fancy_Line text_field = {}; - push_fancy_string(scratch, &text_field, fcolor_id(Stag_Pop1), + push_fancy_string(scratch, &text_field, fcolor_id(defcolor_pop1), lister->query.string); push_fancy_stringf(scratch, &text_field, " "); - push_fancy_string(scratch, &text_field, fcolor_id(Stag_Default), + push_fancy_string(scratch, &text_field, fcolor_id(defcolor_text_default), lister->text_field.string); draw_fancy_line(app, face_id, fcolor_zero(), &text_field, V2f32(text_field_rect.x0 + 3.f, text_field_rect.y0)); @@ -266,13 +266,13 @@ lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ highlight = UIHighlight_Hover; } - draw_rectangle(app, item_rect, 6.f, get_margin_color(highlight)); - draw_rectangle(app, item_inner, 6.f, fcolor_id(Stag_Back)); + draw_rectangle_fcolor(app, item_rect, 6.f, get_margin_color(highlight)); + draw_rectangle_fcolor(app, item_inner, 6.f, fcolor_id(defcolor_back)); Fancy_Line line = {}; - push_fancy_string(scratch, &line, fcolor_id(Stag_Default), node->string); + push_fancy_string(scratch, &line, fcolor_id(defcolor_text_default), node->string); push_fancy_stringf(scratch, &line, " "); - push_fancy_string(scratch, &line, fcolor_id(Stag_Pop2), node->status); + push_fancy_string(scratch, &line, fcolor_id(defcolor_pop2), node->status); Vec2_f32 p = item_inner.p0 + V2f32(3.f, (block_height - line_height)*0.5f); draw_fancy_line(app, face_id, fcolor_zero(), &line, p); diff --git a/custom/4coder_log_parser.cpp b/custom/4coder_log_parser.cpp index b4dc5d13..d4c52bed 100644 --- a/custom/4coder_log_parser.cpp +++ b/custom/4coder_log_parser.cpp @@ -671,10 +671,9 @@ log_graph_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Rect_f32 view_rect = view_get_screen_rect(app, view); Rect_f32 inner = rect_inner(view_rect, 3); - draw_rectangle(app, view_rect, 0.f, - get_margin_color(is_active_view? - UIHighlight_Active:UIHighlight_None)); - draw_rectangle(app, inner, 0.f, fcolor_id(Stag_Back)); + draw_rectangle_fcolor(app, view_rect, 0.f, + get_margin_color(is_active_view?UIHighlight_Active:UIHighlight_None)); + draw_rectangle_fcolor(app, inner, 0.f, fcolor_id(defcolor_back)); Rect_f32 prev_clip = draw_set_clip(app, inner); //////////////////////////////// @@ -721,8 +720,8 @@ log_graph_render(Application_Links *app, Frame_Info frame_info, View_ID view){ margin_color = f_light_gray; } - draw_rectangle(app, box , 0.f, margin_color); - draw_rectangle(app, box_inner, 0.f, f_black ); + draw_rectangle_fcolor(app, box , 0.f, margin_color); + draw_rectangle_fcolor(app, box_inner, 0.f, f_black ); Log_Event *event = box_node->event; @@ -759,8 +758,8 @@ log_graph_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Log_Graph_List_Tab current_tab = log_graph.tab; Log_Filter_Set *viewing_filter_set = log_filter_set_from_tab(current_tab); - draw_rectangle(app, box , 0.f, f_dark_gray); - draw_rectangle(app, box_inner, 0.f, f_black ); + draw_rectangle_fcolor(app, box , 0.f, f_dark_gray); + draw_rectangle_fcolor(app, box_inner, 0.f, f_black ); { f32 y_cursor = box_inner.y0 + 3.f; diff --git a/custom/4coder_profile_inspect.cpp b/custom/4coder_profile_inspect.cpp index fe110ce1..752f9174 100644 --- a/custom/4coder_profile_inspect.cpp +++ b/custom/4coder_profile_inspect.cpp @@ -1,944 +1,941 @@ -/* - * 4coder_profile_inspect.cpp - Built in self profiling UI. - */ - -// TOP - -function Profile_Slot* -profile_parse_get_slot(Arena *arena, Profile_Inspection *insp, - String_Const_u8 loc, String_Const_u8 name){ - Profile_Slot *result = 0; - for (Profile_Slot *node = insp->first_slot; - node != 0; - node = node->next){ - if (string_match(node->location, loc) && - string_match(node->name, name)){ - result = node; - break; - } - } - if (result == 0){ - result = push_array_zero(arena, Profile_Slot, 1); - sll_queue_push(insp->first_slot, insp->last_slot, result); - insp->slot_count += 1; - result->location = loc; - result->name = name; - } - return(result); -} - -function void -profile_parse_error(Arena *arena, Profile_Inspection *insp, String_Const_u8 message, - String_Const_u8 location){ - Profile_Error *error = push_array(arena, Profile_Error, 1); - sll_queue_push(insp->first_error, insp->last_error, error); - insp->error_count += 1; - error->message = message; - error->location = location; -} - -function Profile_Record* -profile_parse_record(Arena *arena, Profile_Inspection *insp, - Profile_Node *parent, Profile_Record *record, - Range_u64 *total_time_range){ - for (;record != 0;){ - if (record->id <= parent->id){ - break; - } - - Profile_ID id = record->id; - Profile_Node *node = push_array(arena, Profile_Node, 1); - sll_queue_push(parent->first_child, parent->last_child, node); - parent->child_count += 1; - node->parent = parent; - node->thread = parent->thread; - - String_Const_u8 location = record->location; - String_Const_u8 name = record->name; - - node->time.min = record->time; - node->time.max = max_u64; - node->id = id; - node->first_child = 0; - node->last_child = 0; - node->child_count = 0; - node->closed = false; - - record = profile_parse_record(arena, insp, node, record->next, - total_time_range); - - b32 quit_loop = false; - Profile_Slot *slot = 0; - if (record == 0 || record->id < id){ - if (record == 0){ -#define M "List ended before all nodes closed" - profile_parse_error(arena, insp, string_u8_litexpr(M), location); -#undef M - } - else{ -#define M "Node '%.*s' closed by parent ending (or higher priority sibling starting)" - String_Const_u8 str = push_u8_stringf(arena, M, string_expand(name)); - profile_parse_error(arena, insp, str, location); -#undef M - if (parent->id != 0){ - quit_loop = true; - } - } - slot = profile_parse_get_slot(arena, insp, location, name); - } - else if (record->id == id){ - slot = profile_parse_get_slot(arena, insp, location, name); - node->time.max = record->time; - node->closed = true; - total_time_range->min = min(total_time_range->min, node->time.min); - total_time_range->max = max(total_time_range->max, node->time.max); - record = record->next; - } - else{ - // NOTE(allen): This would mean that record exists and it's id - // is greater than id, but then the sub-call should not have returned! - InvalidPath; - } - - node->slot = slot; - if (!slot->corrupted_time){ - if (node->closed){ - slot->total_time += range_size(node->time); - } - else{ - slot->corrupted_time = true; - } - } - { - Profile_Node_Ptr *node_ptr = push_array(arena, Profile_Node_Ptr, 1); - sll_queue_push(slot->first_hit, slot->last_hit, node_ptr); - slot->hit_count += 1; - node_ptr->ptr = node; - node->unique_counter = (u64)slot->hit_count; - } - - if (quit_loop){ - break; - } - } - return(record); -} - -function Profile_Inspection -profile_parse(Arena *arena, Profile_Global_List *src){ - Mutex_Lock lock(src->mutex); - - Profile_Inspection result = {}; - - result.thread_count = src->thread_count; - result.threads = push_array_zero(arena, Profile_Inspection_Thread, - result.thread_count); - - i32 counter = 0; - Profile_Inspection_Thread *insp_thread = result.threads; - for (Profile_Thread *node = src->first_thread; - node != 0; - node = node->next, counter += 1, insp_thread += 1){ - insp_thread->thread_id = node->thread_id; - insp_thread->name = node->name; - - // NOTE(allen): This is the "negative infinity" range. - // We will be "maxing" it against all the ranges durring the parse, - // to get the root range. - Range_u64 time_range = {max_u64, 0}; - insp_thread->root.thread = insp_thread; - profile_parse_record(arena, &result, &insp_thread->root, node->first_record, - &time_range); - insp_thread->root.time = time_range; - insp_thread->root.closed = true; - - for (Profile_Node *prof_node = insp_thread->root.first_child; - prof_node != 0; - prof_node = prof_node->next){ - insp_thread->active_time += range_size(prof_node->time); - } - } - - return(result); -} - -//////////////////////////////// - -struct Tab_State{ - Vec2_f32 p; - Range_f32 tabs_y; - Face_ID face_id; - f32 x_half_padding; - Vec2_f32 m_p; -}; - -function void -profile_draw_tab(Application_Links *app, Tab_State *state, Profile_Inspection *insp, - String_Const_u8 string, Profile_Inspection_Tab tab_id){ - Scratch_Block scratch(app); - - state->p.x += state->x_half_padding; - - Fancy_String *fstring = push_fancy_string(scratch, 0, string); - - b32 hover = false; - f32 width = get_fancy_string_width(app, state->face_id, fstring); - Rect_f32 box = Rf32(If32_size(state->p.x, width), state->tabs_y); - if (rect_contains_point(box, state->m_p)){ - hover = true; - insp->tab_id_hovered = tab_id; - } - - FColor text = fcolor_id(Stag_Default); - if (insp->tab_id == tab_id){ - text = fcolor_id(Stag_Pop2); - } - else if (hover){ - text = fcolor_id(Stag_Pop1); - } - - Vec2_f32 np = draw_fancy_string(app, state->face_id, text, fstring, state->p); - state->p = np; - state->p.x += state->x_half_padding; -} - -function void -profile_select_thread(Profile_Inspection *inspect, Profile_Inspection_Thread *thread){ - inspect->tab_id = ProfileInspectTab_Selection; - inspect->selected_thread = thread; - inspect->selected_slot = 0; - inspect->selected_node = 0; -} - -function void -profile_select_slot(Profile_Inspection *inspect, Profile_Slot *slot){ - inspect->tab_id = ProfileInspectTab_Selection; - inspect->selected_thread = 0; - inspect->selected_slot = slot; - inspect->selected_node = 0; -} - -function void -profile_select_node(Profile_Inspection *inspect, Profile_Node *node){ - inspect->tab_id = ProfileInspectTab_Selection; - inspect->selected_thread = 0; - inspect->selected_slot = 0; - inspect->selected_node = node; -} - -function String_Const_u8 -profile_node_thread_name(Profile_Node *node){ - String_Const_u8 result = {}; - if (node->thread != 0){ - result = node->thread->name; - } - return(result); -} - -function String_Const_u8 -profile_node_name(Profile_Node *node){ - String_Const_u8 result = string_u8_litexpr("*root*"); - if (node->slot != 0){ - result = node->slot->name; - } - return(result); -} - -function String_Const_u8 -profile_node_location(Profile_Node *node){ - String_Const_u8 result = {}; - if (node->slot != 0){ - result = node->slot->location; - } - return(result); -} - -function void -profile_qsort_nodes(Profile_Node **nodes, i32 first, i32 one_past_last){ - if (first + 1 < one_past_last){ - i32 pivot_index = one_past_last - 1; - Profile_Node *pivot = nodes[pivot_index]; - u64 pivot_time = range_size(pivot->time); - i32 j = first; - for (i32 i = first; i < one_past_last; i += 1){ - Profile_Node *node = nodes[i]; - u64 node_time = range_size(node->time); - if (node_time > pivot_time){ - Swap(Profile_Node*, nodes[i], nodes[j]); - j += 1; - } - } - Swap(Profile_Node*, nodes[pivot_index], nodes[j]); - profile_qsort_nodes(nodes, first, j); - profile_qsort_nodes(nodes, j + 1, one_past_last); - } -} - -function void -profile_draw_node(Application_Links *app, View_ID view, Face_ID face_id, - Profile_Node *node, Rect_f32 rect, - Profile_Inspection *insp, Vec2_f32 m_p){ - Range_f32 x = rect_range_x(rect); - Range_f32 y = rect_range_y(rect); - - // TODO(allen): share this shit - Face_Metrics metrics = get_face_metrics(app, face_id); - f32 line_height = metrics.line_height; - f32 normal_advance = metrics.normal_advance; - f32 block_height = line_height*2.f; - f32 x_padding = normal_advance*1.5f; - f32 x_half_padding = x_padding*0.5f; - - FColor colors[] = { - fcolor_id(Stag_Back_Cycle_1), fcolor_id(Stag_Back_Cycle_2), - fcolor_id(Stag_Back_Cycle_3), fcolor_id(Stag_Back_Cycle_4), - }; - - Scratch_Block scratch(app); - - f32 x_pos = x.min + x_half_padding; - f32 nav_bar_w = 0.f; - Range_f32 nav_bar_y = {}; - nav_bar_y.min = y.min; - - String_Const_u8 thread_name = profile_node_thread_name(node); - if (thread_name.size > 0){ - Fancy_String *fstr = - push_fancy_string(scratch, 0, fcolor_id(Stag_Pop1), thread_name); - Vec2_f32 p = V2f32(x_pos, y.min + 1.f); - draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); - f32 w = get_fancy_string_width(app, face_id, fstr); - nav_bar_w = max(nav_bar_w, w); - } - y.min += line_height + 2.f; - - String_Const_u8 name = profile_node_name(node); - if (name.size > 0){ - Fancy_String *fstr = - push_fancy_string(scratch, 0, fcolor_id(Stag_Default), name); - Vec2_f32 p = V2f32(x_pos, y.min + 1.f); - draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); - f32 w = get_fancy_string_width(app, face_id, fstr); - nav_bar_w = max(nav_bar_w, w); - } - y.min += line_height + 2.f; - - nav_bar_y.max = y.min; - - x_pos += nav_bar_w + x_half_padding; - if (node->parent != 0){ - Fancy_String *fstr = push_fancy_string(scratch, 0, fcolor_zero(), - string_u8_litexpr("to parent")); - f32 w = get_fancy_string_width(app, face_id, fstr) + x_padding; - Range_f32 btn_x = If32_size(x_pos, w); - Rect_f32 box = Rf32(btn_x, nav_bar_y); - - FColor color = fcolor_id(Stag_Default); - if (rect_contains_point(box, m_p)){ - draw_rectangle(app, box, 0.f, fcolor_id(Stag_Margin)); - color = fcolor_id(Stag_Pop1); - insp->hover_node = node->parent; - } - - Vec2_f32 p = V2f32(box.x0 + x_half_padding, - (box.y0 + box.y1 - line_height)*0.5f); - draw_fancy_string(app, face_id, color, fstr, p); - - x_pos = btn_x.max; - } - - Range_u64 top_time = node->time; - - Rect_f32_Pair side_by_side = rect_split_left_right_lerp(Rf32(x, y), 0.5f); - - Rect_f32 time_slice_box = side_by_side.min; - time_slice_box = rect_inner(time_slice_box, 3.f); - draw_rectangle_outline(app, time_slice_box, 0.f, 3.f, f_white); - time_slice_box = rect_inner(time_slice_box, 3.f); - - if (node->closed){ - draw_set_clip(app, time_slice_box); - - x = rect_range_x(time_slice_box); - y = rect_range_y(time_slice_box); - - i32 cycle_counter = 0; - i32 count = ArrayCount(colors); - for (Profile_Node *child = node->first_child; - child != 0; - child = child->next){ - if (!child->closed){ - continue; - } - - Range_u64 child_time = child->time; - Range_f32 child_y = {}; - child_y.min = unlerp(top_time.min, child_time.min, top_time.max); - child_y.max = unlerp(top_time.min, child_time.max, top_time.max); - child_y.min = lerp(y.min, child_y.min, y.max); - child_y.max = lerp(y.min, child_y.max, y.max); - - Rect_f32 box = Rf32(x, child_y); - draw_rectangle(app, box, 0.f, colors[cycle_counter%count]); - cycle_counter += 1; - - if (rect_contains_point(box, m_p)){ - insp->full_name_hovered = profile_node_name(child); - insp->unique_counter_hovered = child->unique_counter; - insp->location_jump_hovered = profile_node_location(child); - insp->hover_node = child; - } - - if (range_size(child_y) >= line_height){ - String_Const_u8 child_name = profile_node_name(child); - Fancy_Line line = {}; - push_fancy_string(scratch, &line, fcolor_id(Stag_Pop1), - child_name); - push_fancy_stringf(scratch, &line, fcolor_id(Stag_Default), - 0.5f, 0.f, "#%4llu", child->unique_counter); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - child_y.min); - draw_fancy_line(app, face_id, fcolor_zero(), - &line, p); - } - } - } - - Rect_f32 info_box = side_by_side.max; - - { - draw_set_clip(app, info_box); - - x = rect_range_x(info_box); - - x_pos = x.min + x_half_padding; - f32 y_pos = info_box.y0; - - // NOTE(allen): duration - { - f32 duration = ((f32)range_size(node->time))/1000000.f; - Fancy_Line list = {}; - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Default), - "time: %11.9f", duration); - draw_fancy_line(app, face_id, fcolor_zero(), - &list, V2f32(x_pos, y_pos + 1.f)); - y_pos += line_height + 2.f; - } - - i32 child_count = node->child_count; - Profile_Node **children_array = push_array(scratch, Profile_Node*, child_count); - i32 counter = 0; - for (Profile_Node *child = node->first_child; - child != 0; - child = child->next){ - children_array[counter] = child; - counter += 1; - } - - profile_qsort_nodes(children_array, 0, child_count); - - Profile_Node **child_ptr = children_array; - for (i32 i = 0; i < child_count; i += 1, child_ptr += 1){ - Profile_Node *child = *child_ptr; - y = If32_size(y_pos, block_height); - - f32 child_duration = ((f32)range_size(child->time))/1000000.f; - - String_Const_u8 child_name = profile_node_name(child); - Fancy_Line line = {}; - push_fancy_string_trunc(scratch, &line, child_name, 20); - push_fancy_stringf(scratch, &line, fcolor_id(Stag_Default), 0.5f, 0.f, - "#%4llu", child->unique_counter); - push_fancy_stringf(scratch, &line, fcolor_id(Stag_Pop2), - 0.5f, 0.f, "%6.4f", child_duration); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - (y.min + y.max - line_height)*0.5f); - draw_fancy_line(app, face_id, fcolor_id(Stag_Pop1), &line, p); - - Rect_f32 box = Rf32(x, y); - FColor margin = fcolor_id(Stag_Margin); - if (rect_contains_point(box, m_p)){ - insp->full_name_hovered = child_name; - insp->unique_counter_hovered = child->unique_counter; - insp->location_jump_hovered = profile_node_location(child); - insp->hover_node = child; - margin = fcolor_id(Stag_Margin_Hover); - } - draw_rectangle_outline(app, box, 6.f, 3.f, margin); - - y_pos = y.max; - if (y_pos >= info_box.y1){ - break; - } - } - } -} - -function void -profile_memory_sort_by_count(Memory_Bucket **buckets, i32 first, i32 one_past_last){ - if (first + 1 < one_past_last){ - i32 pivot = one_past_last - 1; - i32 pivot_key = buckets[pivot]->annotation.count; - i32 j = first; - for (i32 i = first; i < pivot; i += 1){ - i32 key = buckets[i]->annotation.count; - if (key <= pivot_key){ - Swap(Memory_Bucket*, buckets[j], buckets[i]); - j += 1; - } - } - Swap(Memory_Bucket*, buckets[j], buckets[pivot]); - profile_memory_sort_by_count(buckets, first, j); - profile_memory_sort_by_count(buckets, j + 1, one_past_last); - } -} - -function void -profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ - Scratch_Block scratch(app); - - Rect_f32 region = draw_background_and_margin(app, view); - Rect_f32 prev_clip = draw_set_clip(app, region); - - Face_ID face_id = get_face_id(app, 0); - // TODO(allen): share this shit - Face_Metrics metrics = get_face_metrics(app, face_id); - f32 line_height = metrics.line_height; - f32 normal_advance = metrics.normal_advance; - f32 block_height = line_height*2.f; - f32 x_padding = normal_advance*1.5f; - f32 x_half_padding = x_padding*0.5f; - - Mouse_State mouse = get_mouse_state(app); - Vec2_f32 m_p = V2f32(mouse.p); - - Profile_Inspection *inspect = &global_profile_inspection; - - if (inspect->thread_count == 0){ - Fancy_String *fstr = push_fancy_string(scratch, 0, fcolor_id(Stag_Pop2), - string_u8_litexpr("no profile data")); - f32 width = get_fancy_string_width(app, face_id, fstr); - Vec2_f32 view_center = (region.p0 + region.p1)*0.5f; - Vec2_f32 half_dim = V2f32(width, line_height)*0.5f; - Vec2_f32 p = view_center - half_dim; - draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); - } - else{ - Rect_f32_Pair tabs_body = rect_split_top_bottom(region, line_height + 2.f); - Range_f32 tabs_y = rect_range_y(tabs_body.min); - - inspect->tab_id_hovered = ProfileInspectTab_None; - block_zero_struct(&inspect->full_name_hovered); - inspect->unique_counter_hovered = 0; - block_zero_struct(&inspect->location_jump_hovered); - inspect->hover_thread = 0; - inspect->hover_slot = 0; - inspect->hover_node = 0; - - // NOTE(allen): tabs - { - f32 y = (tabs_y.min + tabs_y.max - line_height)*0.5f; - f32 x = region.x0; - - Tab_State tab_state = {}; - tab_state.p = V2f32(x, y); - tab_state.tabs_y = tabs_y; - tab_state.face_id = face_id; - tab_state.x_half_padding = x_half_padding; - tab_state.m_p = m_p; - - draw_rectangle(app, tabs_body.min, 0.f, fcolor_id(Stag_Margin_Hover)); - - if (inspect->tab_id == ProfileInspectTab_None){ - inspect->tab_id = ProfileInspectTab_Threads; - } - - profile_draw_tab(app, &tab_state, inspect, - string_u8_litexpr("threads"), - ProfileInspectTab_Threads); - - if (inspect->slot_count > 0){ - profile_draw_tab(app, &tab_state, inspect, - string_u8_litexpr("blocks"), - ProfileInspectTab_Blocks); - } - - if (inspect->error_count > 0){ - profile_draw_tab(app, &tab_state, inspect, - string_u8_litexpr("errors"), - ProfileInspectTab_Errors); - } - - profile_draw_tab(app, &tab_state, inspect, - string_u8_litexpr("memory"), - ProfileInspectTab_Memory); - - if (inspect->tab_id == ProfileInspectTab_Selection){ - String_Const_u8 string = {}; - if (inspect->selected_thread != 0){ - String_Const_u8 name = inspect->selected_thread->name; - string = push_u8_stringf(scratch, "%.*s (%d)", - string_expand(name), - inspect->selected_thread->thread_id); - } - else if (inspect->selected_slot != 0){ - String_Const_u8 name = inspect->selected_slot->name; - string = push_u8_stringf(scratch, "block %.*s", - string_expand(name)); - } - else if (inspect->selected_node != 0){ - String_Const_u8 name = profile_node_name(inspect->selected_node); - string = push_u8_stringf(scratch, "node %.*s", - string_expand(name)); - } - else{ - inspect->tab_id = ProfileInspectTab_Threads; - } - if (string.str != 0){ - profile_draw_tab(app, &tab_state, inspect, - string, ProfileInspectTab_Selection); - } - } - } - - draw_set_clip(app, tabs_body.max); - switch (inspect->tab_id){ - case ProfileInspectTab_Threads: - { - Range_f32 x = rect_range_x(tabs_body.max); - f32 y_pos = tabs_body.max.y0; - i32 count = inspect->thread_count; - Profile_Inspection_Thread *thread = inspect->threads; - for (i32 i = 0; i < count; i += 1, thread += 1){ - Range_f32 y = If32_size(y_pos, block_height); - - Fancy_Line list = {}; - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop1), - "%-20.*s (%6d) ", - string_expand(thread->name), - thread->thread_id); - - f32 active_time = ((f32)thread->active_time)/1000000.f; - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop2), - "active time %11.9f", - active_time); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - (y.min + y.max - line_height)*0.5f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); - - Rect_f32 box = Rf32(x, y); - FColor margin = fcolor_id(Stag_Margin); - if (rect_contains_point(box, m_p)){ - inspect->hover_thread = thread; - margin = fcolor_id(Stag_Margin_Hover); - } - draw_rectangle_outline(app, box, 6.f, 3.f, margin); - - y_pos = y.max; - if (y_pos >= tabs_body.max.y1){ - break; - } - } - }break; - - case ProfileInspectTab_Blocks: - { - Range_f32 x = rect_range_x(tabs_body.max); - f32 y_pos = tabs_body.max.y0; - for (Profile_Slot *node = inspect->first_slot; - node != 0; - node = node->next){ - Range_f32 y = If32_size(y_pos, block_height); - - u32 name_width = 45; - b32 name_too_long = (node->name.size > name_width); - Fancy_Line list = {}; - push_fancy_string_fixed(scratch, &list, fcolor_id(Stag_Pop1), - node->name, name_width); - - if (node->corrupted_time){ - push_fancy_string(scratch, &list, fcolor_id(Stag_Pop2), - string_u8_litexpr("timing error ")); - } - else{ - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop2), - "%11.9fs ", - ((f32)node->total_time)/1000000.f); - } - - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Keyword), - "hit # %5d", node->hit_count); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - (y.min + y.max - line_height)*0.5f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); - - Rect_f32 box = Rf32(x, y); - FColor margin = fcolor_id(Stag_Margin); - if (rect_contains_point(box, m_p)){ - if (name_too_long){ - inspect->full_name_hovered = node->name; - } - inspect->location_jump_hovered = node->location; - inspect->hover_slot = node; - margin = fcolor_id(Stag_Margin_Hover); - } - draw_rectangle_outline(app, box, 6.f, 3.f, margin); - - y_pos = y.max; - if (y_pos >= tabs_body.max.y1){ - break; - } - } - }break; - - case ProfileInspectTab_Errors: - { - draw_set_clip(app, tabs_body.max); - Range_f32 x = rect_range_x(tabs_body.max); - f32 y_pos = tabs_body.max.y0; - for (Profile_Error *node = inspect->first_error; - node != 0; - node = node->next){ - Range_f32 y = If32_size(y_pos, block_height); - - Fancy_Line list = {}; - push_fancy_string(scratch, &list, fcolor_id(Stag_Pop2), - node->message); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - (y.min + y.max - line_height)*0.5f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); - - Rect_f32 box = Rf32(x, y); - FColor margin = fcolor_id(Stag_Margin); - if (rect_contains_point(box, m_p)){ - inspect->location_jump_hovered = node->location; - margin = fcolor_id(Stag_Margin_Hover); - } - draw_rectangle_outline(app, box, 6.f, 3.f, margin); - - y_pos = y.max; - if (y_pos >= tabs_body.max.y1){ - break; - } - } - }break; - - case ProfileInspectTab_Memory: - { - draw_set_clip(app, tabs_body.max); - Range_f32 x = rect_range_x(tabs_body.max); - f32 y_pos = tabs_body.max.y0; - Memory_Annotation annotation = system_memory_annotation(scratch); - - Base_Allocator *allocator = get_base_allocator_system(); - - Memory_Bucket *first_bucket = 0; - Memory_Bucket *last_bucket = 0; - i32 bucket_count = 0; - Table_Data_u64 table = make_table_Data_u64(allocator, 100); - - for (Memory_Annotation_Node *node = annotation.first, *next = 0; - node != 0; - node = next){ - next = node->next; - Data key = make_data(node->location.str, node->location.size); - Table_Lookup lookup = table_lookup(&table, key); - Memory_Bucket *bucket = 0; - if (lookup.found_match){ - u64 val = 0; - table_read(&table, lookup, &val); - bucket = (Memory_Bucket*)IntAsPtr(val); - } - else{ - bucket = push_array_zero(scratch, Memory_Bucket, 1); - sll_queue_push(first_bucket, last_bucket, bucket); - bucket_count += 1; - bucket->location = node->location; - table_insert(&table, key, PtrAsInt(bucket)); - } - sll_queue_push(bucket->annotation.first, bucket->annotation.last, node); - bucket->annotation.count += 1; - bucket->total_memory += node->size; - } - - Memory_Bucket **buckets = push_array(scratch, Memory_Bucket*, bucket_count); - i32 counter = 0; - for (Memory_Bucket *node = first_bucket; - node != 0; - node = node->next){ - buckets[counter] = node; - counter += 1; - } - - profile_memory_sort_by_count(buckets, 0, bucket_count); - - for (i32 i = bucket_count - 1; i >= 0; i -= 1){ - Memory_Bucket *node = buckets[i]; - Range_f32 y = If32_size(y_pos, block_height); - - Fancy_Line list = {}; - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop2), "[%12llu] / %6d ", - node->total_memory, node->annotation.count); - push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop1), "%.*s", - string_expand(node->location)); - - Vec2_f32 p = V2f32(x.min + x_half_padding, - (y.min + y.max - line_height)*0.5f); - draw_fancy_line(app, face_id, fcolor_zero(), &list, p); - - Rect_f32 box = Rf32(x, y); - FColor margin = fcolor_id(Stag_Margin); - if (rect_contains_point(box, m_p)){ - inspect->location_jump_hovered = node->location; - margin = fcolor_id(Stag_Margin_Hover); - } - - y_pos = y.max; - if (y_pos >= tabs_body.max.y1){ - break; - } - } - - table_free(&table); - }break; - - case ProfileInspectTab_Selection: - { - if (inspect->selected_thread != 0){ - profile_draw_node(app, view, face_id, - &inspect->selected_thread->root, tabs_body.max, - inspect, m_p); - } - else if (inspect->selected_slot != 0){ - - } - else if (inspect->selected_node != 0){ - profile_draw_node(app, view, face_id, - inspect->selected_node, tabs_body.max, - inspect, m_p); - } - }break; - } - - if (!rect_contains_point(region, m_p)){ - // NOTE(allen): don't draw tool tip when the mouse doesn't hover in our view - } - else if (inspect->tab_id_hovered != ProfileInspectTab_None){ - // NOTE(allen): no tool tip for tabs - } - else{ - Fancy_Block block = {}; - FColor text_color = fcolor_change_alpha(app, f_white, 0.5f); - FColor back_color = fcolor_change_alpha(app, f_black, 0.5f); - - if (inspect->full_name_hovered.size > 0){ - Fancy_Line *line = push_fancy_line(scratch, &block, text_color); - push_fancy_stringf(scratch, line, "%.*s", - string_expand(inspect->full_name_hovered)); - if (inspect->unique_counter_hovered > 0){ - push_fancy_stringf(scratch, line, text_color, 0.5f, 0.f, - "#%4llu", inspect->unique_counter_hovered); - } - } - if (inspect->location_jump_hovered.size > 0){ - Fancy_Line *line = push_fancy_line(scratch, &block, text_color); - push_fancy_stringf(scratch, line, "[shift] '%.*s'", - string_expand(inspect->location_jump_hovered)); - } - - draw_tool_tip(app, face_id, &block, m_p, region, - x_padding, x_half_padding, back_color); - } - } - - draw_set_clip(app, prev_clip); -} - -function void -profile_inspect__left_click(Application_Links *app, View_ID view, - Profile_Inspection *insp, Input_Event *event){ - if (has_modifier(event, KeyCode_Shift)){ - if (insp->location_jump_hovered.size != 0){ - View_ID target_view = view; - target_view = get_next_view_looped_primary_panels(app, target_view, - Access_Always); - String_Const_u8 location = insp->location_jump_hovered; - jump_to_location(app, target_view, location); - } - } - else{ - if (insp->tab_id_hovered != ProfileInspectTab_None){ - insp->tab_id = insp->tab_id_hovered; - } - else if (insp->hover_thread != 0){ - profile_select_thread(insp, insp->hover_thread); - } - else if (insp->hover_slot != 0){ - profile_select_slot(insp, insp->hover_slot); - } - else if (insp->hover_node != 0){ - profile_select_node(insp, insp->hover_node); - } - } -} - -CUSTOM_UI_COMMAND_SIG(profile_inspect) -CUSTOM_DOC("Inspect all currently collected profiling information in 4coder's self profiler.") -{ - Profile_Global_List *list = get_core_profile_list(app); - if (HasFlag(list->disable_bits, ProfileEnable_InspectBit)){ - return; - } - - profile_set_enabled(list, false, ProfileEnable_InspectBit); - - Scratch_Block scratch(app); - global_profile_inspection = profile_parse(scratch, list); - Profile_Inspection *insp = &global_profile_inspection; - - View_ID view = get_active_view(app, Access_Always); - View_Context ctx = view_current_context(app, view); - ctx.render_caller = profile_render; - ctx.hides_buffer = true; - View_Context_Block ctx_block(app, view, &ctx); - - for (;;){ - User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); - if (in.abort){ - break; - } - - b32 handled = true; - switch (in.event.kind){ - case InputEventKind_MouseButton: - { - switch (in.event.mouse.code){ - case MouseCode_Left: - { - profile_inspect__left_click(app, view, insp, &in.event); - }break; - } - }break; - - default: - { - handled = false; - }break; - } - - if (!handled){ - if (ui_fallback_command_dispatch(app, view, &in)){ - break; - } - } - } - - profile_set_enabled(list, true, ProfileEnable_InspectBit); -} - -// BOTTOM +/* + * 4coder_profile_inspect.cpp - Built in self profiling UI. + */ + +// TOP + +function Profile_Slot* +profile_parse_get_slot(Arena *arena, Profile_Inspection *insp, + String_Const_u8 loc, String_Const_u8 name){ + Profile_Slot *result = 0; + for (Profile_Slot *node = insp->first_slot; + node != 0; + node = node->next){ + if (string_match(node->location, loc) && + string_match(node->name, name)){ + result = node; + break; + } + } + if (result == 0){ + result = push_array_zero(arena, Profile_Slot, 1); + sll_queue_push(insp->first_slot, insp->last_slot, result); + insp->slot_count += 1; + result->location = loc; + result->name = name; + } + return(result); +} + +function void +profile_parse_error(Arena *arena, Profile_Inspection *insp, String_Const_u8 message, + String_Const_u8 location){ + Profile_Error *error = push_array(arena, Profile_Error, 1); + sll_queue_push(insp->first_error, insp->last_error, error); + insp->error_count += 1; + error->message = message; + error->location = location; +} + +function Profile_Record* +profile_parse_record(Arena *arena, Profile_Inspection *insp, + Profile_Node *parent, Profile_Record *record, + Range_u64 *total_time_range){ + for (;record != 0;){ + if (record->id <= parent->id){ + break; + } + + Profile_ID id = record->id; + Profile_Node *node = push_array(arena, Profile_Node, 1); + sll_queue_push(parent->first_child, parent->last_child, node); + parent->child_count += 1; + node->parent = parent; + node->thread = parent->thread; + + String_Const_u8 location = record->location; + String_Const_u8 name = record->name; + + node->time.min = record->time; + node->time.max = max_u64; + node->id = id; + node->first_child = 0; + node->last_child = 0; + node->child_count = 0; + node->closed = false; + + record = profile_parse_record(arena, insp, node, record->next, + total_time_range); + + b32 quit_loop = false; + Profile_Slot *slot = 0; + if (record == 0 || record->id < id){ + if (record == 0){ +#define M "List ended before all nodes closed" + profile_parse_error(arena, insp, string_u8_litexpr(M), location); +#undef M + } + else{ +#define M "Node '%.*s' closed by parent ending (or higher priority sibling starting)" + String_Const_u8 str = push_u8_stringf(arena, M, string_expand(name)); + profile_parse_error(arena, insp, str, location); +#undef M + if (parent->id != 0){ + quit_loop = true; + } + } + slot = profile_parse_get_slot(arena, insp, location, name); + } + else if (record->id == id){ + slot = profile_parse_get_slot(arena, insp, location, name); + node->time.max = record->time; + node->closed = true; + total_time_range->min = min(total_time_range->min, node->time.min); + total_time_range->max = max(total_time_range->max, node->time.max); + record = record->next; + } + else{ + // NOTE(allen): This would mean that record exists and it's id + // is greater than id, but then the sub-call should not have returned! + InvalidPath; + } + + node->slot = slot; + if (!slot->corrupted_time){ + if (node->closed){ + slot->total_time += range_size(node->time); + } + else{ + slot->corrupted_time = true; + } + } + { + Profile_Node_Ptr *node_ptr = push_array(arena, Profile_Node_Ptr, 1); + sll_queue_push(slot->first_hit, slot->last_hit, node_ptr); + slot->hit_count += 1; + node_ptr->ptr = node; + node->unique_counter = (u64)slot->hit_count; + } + + if (quit_loop){ + break; + } + } + return(record); +} + +function Profile_Inspection +profile_parse(Arena *arena, Profile_Global_List *src){ + Mutex_Lock lock(src->mutex); + + Profile_Inspection result = {}; + + result.thread_count = src->thread_count; + result.threads = push_array_zero(arena, Profile_Inspection_Thread, + result.thread_count); + + i32 counter = 0; + Profile_Inspection_Thread *insp_thread = result.threads; + for (Profile_Thread *node = src->first_thread; + node != 0; + node = node->next, counter += 1, insp_thread += 1){ + insp_thread->thread_id = node->thread_id; + insp_thread->name = node->name; + + // NOTE(allen): This is the "negative infinity" range. + // We will be "maxing" it against all the ranges durring the parse, + // to get the root range. + Range_u64 time_range = {max_u64, 0}; + insp_thread->root.thread = insp_thread; + profile_parse_record(arena, &result, &insp_thread->root, node->first_record, + &time_range); + insp_thread->root.time = time_range; + insp_thread->root.closed = true; + + for (Profile_Node *prof_node = insp_thread->root.first_child; + prof_node != 0; + prof_node = prof_node->next){ + insp_thread->active_time += range_size(prof_node->time); + } + } + + return(result); +} + +//////////////////////////////// + +struct Tab_State{ + Vec2_f32 p; + Range_f32 tabs_y; + Face_ID face_id; + f32 x_half_padding; + Vec2_f32 m_p; +}; + +function void +profile_draw_tab(Application_Links *app, Tab_State *state, Profile_Inspection *insp, + String_Const_u8 string, Profile_Inspection_Tab tab_id){ + Scratch_Block scratch(app); + + state->p.x += state->x_half_padding; + + Fancy_String *fstring = push_fancy_string(scratch, 0, string); + + b32 hover = false; + f32 width = get_fancy_string_width(app, state->face_id, fstring); + Rect_f32 box = Rf32(If32_size(state->p.x, width), state->tabs_y); + if (rect_contains_point(box, state->m_p)){ + hover = true; + insp->tab_id_hovered = tab_id; + } + + FColor text = fcolor_id(defcolor_text_default); + if (insp->tab_id == tab_id){ + text = fcolor_id(defcolor_pop2); + } + else if (hover){ + text = fcolor_id(defcolor_pop1); + } + + Vec2_f32 np = draw_fancy_string(app, state->face_id, text, fstring, state->p); + state->p = np; + state->p.x += state->x_half_padding; +} + +function void +profile_select_thread(Profile_Inspection *inspect, Profile_Inspection_Thread *thread){ + inspect->tab_id = ProfileInspectTab_Selection; + inspect->selected_thread = thread; + inspect->selected_slot = 0; + inspect->selected_node = 0; +} + +function void +profile_select_slot(Profile_Inspection *inspect, Profile_Slot *slot){ + inspect->tab_id = ProfileInspectTab_Selection; + inspect->selected_thread = 0; + inspect->selected_slot = slot; + inspect->selected_node = 0; +} + +function void +profile_select_node(Profile_Inspection *inspect, Profile_Node *node){ + inspect->tab_id = ProfileInspectTab_Selection; + inspect->selected_thread = 0; + inspect->selected_slot = 0; + inspect->selected_node = node; +} + +function String_Const_u8 +profile_node_thread_name(Profile_Node *node){ + String_Const_u8 result = {}; + if (node->thread != 0){ + result = node->thread->name; + } + return(result); +} + +function String_Const_u8 +profile_node_name(Profile_Node *node){ + String_Const_u8 result = string_u8_litexpr("*root*"); + if (node->slot != 0){ + result = node->slot->name; + } + return(result); +} + +function String_Const_u8 +profile_node_location(Profile_Node *node){ + String_Const_u8 result = {}; + if (node->slot != 0){ + result = node->slot->location; + } + return(result); +} + +function void +profile_qsort_nodes(Profile_Node **nodes, i32 first, i32 one_past_last){ + if (first + 1 < one_past_last){ + i32 pivot_index = one_past_last - 1; + Profile_Node *pivot = nodes[pivot_index]; + u64 pivot_time = range_size(pivot->time); + i32 j = first; + for (i32 i = first; i < one_past_last; i += 1){ + Profile_Node *node = nodes[i]; + u64 node_time = range_size(node->time); + if (node_time > pivot_time){ + Swap(Profile_Node*, nodes[i], nodes[j]); + j += 1; + } + } + Swap(Profile_Node*, nodes[pivot_index], nodes[j]); + profile_qsort_nodes(nodes, first, j); + profile_qsort_nodes(nodes, j + 1, one_past_last); + } +} + +function void +profile_draw_node(Application_Links *app, View_ID view, Face_ID face_id, + Profile_Node *node, Rect_f32 rect, + Profile_Inspection *insp, Vec2_f32 m_p){ + Range_f32 x = rect_range_x(rect); + Range_f32 y = rect_range_y(rect); + + // TODO(allen): share this shit + Face_Metrics metrics = get_face_metrics(app, face_id); + f32 line_height = metrics.line_height; + f32 normal_advance = metrics.normal_advance; + f32 block_height = line_height*2.f; + f32 x_padding = normal_advance*1.5f; + f32 x_half_padding = x_padding*0.5f; + + Color_Array colors = finalize_color_array(defcolor_back_cycle); + + Scratch_Block scratch(app); + + f32 x_pos = x.min + x_half_padding; + f32 nav_bar_w = 0.f; + Range_f32 nav_bar_y = {}; + nav_bar_y.min = y.min; + + String_Const_u8 thread_name = profile_node_thread_name(node); + if (thread_name.size > 0){ + Fancy_String *fstr = + push_fancy_string(scratch, 0, fcolor_id(defcolor_pop1), thread_name); + Vec2_f32 p = V2f32(x_pos, y.min + 1.f); + draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); + f32 w = get_fancy_string_width(app, face_id, fstr); + nav_bar_w = max(nav_bar_w, w); + } + y.min += line_height + 2.f; + + String_Const_u8 name = profile_node_name(node); + if (name.size > 0){ + Fancy_String *fstr = + push_fancy_string(scratch, 0, fcolor_id(defcolor_text_default), name); + Vec2_f32 p = V2f32(x_pos, y.min + 1.f); + draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); + f32 w = get_fancy_string_width(app, face_id, fstr); + nav_bar_w = max(nav_bar_w, w); + } + y.min += line_height + 2.f; + + nav_bar_y.max = y.min; + + x_pos += nav_bar_w + x_half_padding; + if (node->parent != 0){ + Fancy_String *fstr = push_fancy_string(scratch, 0, fcolor_zero(), + string_u8_litexpr("to parent")); + f32 w = get_fancy_string_width(app, face_id, fstr) + x_padding; + Range_f32 btn_x = If32_size(x_pos, w); + Rect_f32 box = Rf32(btn_x, nav_bar_y); + + FColor color = fcolor_id(defcolor_text_default); + if (rect_contains_point(box, m_p)){ + draw_rectangle_fcolor(app, box, 0.f, fcolor_id(defcolor_margin)); + color = fcolor_id(defcolor_pop1); + insp->hover_node = node->parent; + } + + Vec2_f32 p = V2f32(box.x0 + x_half_padding, + (box.y0 + box.y1 - line_height)*0.5f); + draw_fancy_string(app, face_id, color, fstr, p); + + x_pos = btn_x.max; + } + + Range_u64 top_time = node->time; + + Rect_f32_Pair side_by_side = rect_split_left_right_lerp(Rf32(x, y), 0.5f); + + Rect_f32 time_slice_box = side_by_side.min; + time_slice_box = rect_inner(time_slice_box, 3.f); + draw_rectangle_outline_fcolor(app, time_slice_box, 0.f, 3.f, f_white); + time_slice_box = rect_inner(time_slice_box, 3.f); + + if (node->closed){ + draw_set_clip(app, time_slice_box); + + x = rect_range_x(time_slice_box); + y = rect_range_y(time_slice_box); + + i32 cycle_counter = 0; + for (Profile_Node *child = node->first_child; + child != 0; + child = child->next){ + if (!child->closed){ + continue; + } + + Range_u64 child_time = child->time; + Range_f32 child_y = {}; + child_y.min = unlerp(top_time.min, child_time.min, top_time.max); + child_y.max = unlerp(top_time.min, child_time.max, top_time.max); + child_y.min = lerp(y.min, child_y.min, y.max); + child_y.max = lerp(y.min, child_y.max, y.max); + + Rect_f32 box = Rf32(x, child_y); + ARGB_Color argb = finalize_color(colors, cycle_counter); + draw_rectangle(app, box, 0.f, argb); + cycle_counter += 1; + + if (rect_contains_point(box, m_p)){ + insp->full_name_hovered = profile_node_name(child); + insp->unique_counter_hovered = child->unique_counter; + insp->location_jump_hovered = profile_node_location(child); + insp->hover_node = child; + } + + if (range_size(child_y) >= line_height){ + String_Const_u8 child_name = profile_node_name(child); + Fancy_Line line = {}; + push_fancy_string(scratch, &line, fcolor_id(defcolor_pop1), + child_name); + push_fancy_stringf(scratch, &line, fcolor_id(defcolor_text_default), + 0.5f, 0.f, "#%4llu", child->unique_counter); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + child_y.min); + draw_fancy_line(app, face_id, fcolor_zero(), + &line, p); + } + } + } + + Rect_f32 info_box = side_by_side.max; + + { + draw_set_clip(app, info_box); + + x = rect_range_x(info_box); + + x_pos = x.min + x_half_padding; + f32 y_pos = info_box.y0; + + // NOTE(allen): duration + { + f32 duration = ((f32)range_size(node->time))/1000000.f; + Fancy_Line list = {}; + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_text_default), + "time: %11.9f", duration); + draw_fancy_line(app, face_id, fcolor_zero(), + &list, V2f32(x_pos, y_pos + 1.f)); + y_pos += line_height + 2.f; + } + + i32 child_count = node->child_count; + Profile_Node **children_array = push_array(scratch, Profile_Node*, child_count); + i32 counter = 0; + for (Profile_Node *child = node->first_child; + child != 0; + child = child->next){ + children_array[counter] = child; + counter += 1; + } + + profile_qsort_nodes(children_array, 0, child_count); + + Profile_Node **child_ptr = children_array; + for (i32 i = 0; i < child_count; i += 1, child_ptr += 1){ + Profile_Node *child = *child_ptr; + y = If32_size(y_pos, block_height); + + f32 child_duration = ((f32)range_size(child->time))/1000000.f; + + String_Const_u8 child_name = profile_node_name(child); + Fancy_Line line = {}; + push_fancy_string_trunc(scratch, &line, child_name, 20); + push_fancy_stringf(scratch, &line, fcolor_id(defcolor_text_default), 0.5f, 0.f, + "#%4llu", child->unique_counter); + push_fancy_stringf(scratch, &line, fcolor_id(defcolor_pop2), + 0.5f, 0.f, "%6.4f", child_duration); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_id(defcolor_pop1), &line, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(defcolor_margin); + if (rect_contains_point(box, m_p)){ + insp->full_name_hovered = child_name; + insp->unique_counter_hovered = child->unique_counter; + insp->location_jump_hovered = profile_node_location(child); + insp->hover_node = child; + margin = fcolor_id(defcolor_margin_hover); + } + draw_rectangle_outline_fcolor(app, box, 6.f, 3.f, margin); + + y_pos = y.max; + if (y_pos >= info_box.y1){ + break; + } + } + } +} + +function void +profile_memory_sort_by_count(Memory_Bucket **buckets, i32 first, i32 one_past_last){ + if (first + 1 < one_past_last){ + i32 pivot = one_past_last - 1; + i32 pivot_key = buckets[pivot]->annotation.count; + i32 j = first; + for (i32 i = first; i < pivot; i += 1){ + i32 key = buckets[i]->annotation.count; + if (key <= pivot_key){ + Swap(Memory_Bucket*, buckets[j], buckets[i]); + j += 1; + } + } + Swap(Memory_Bucket*, buckets[j], buckets[pivot]); + profile_memory_sort_by_count(buckets, first, j); + profile_memory_sort_by_count(buckets, j + 1, one_past_last); + } +} + +function void +profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ + Scratch_Block scratch(app); + + Rect_f32 region = draw_background_and_margin(app, view); + Rect_f32 prev_clip = draw_set_clip(app, region); + + Face_ID face_id = get_face_id(app, 0); + // TODO(allen): share this shit + Face_Metrics metrics = get_face_metrics(app, face_id); + f32 line_height = metrics.line_height; + f32 normal_advance = metrics.normal_advance; + f32 block_height = line_height*2.f; + f32 x_padding = normal_advance*1.5f; + f32 x_half_padding = x_padding*0.5f; + + Mouse_State mouse = get_mouse_state(app); + Vec2_f32 m_p = V2f32(mouse.p); + + Profile_Inspection *inspect = &global_profile_inspection; + + if (inspect->thread_count == 0){ + Fancy_String *fstr = push_fancy_string(scratch, 0, fcolor_id(defcolor_pop2), + string_u8_litexpr("no profile data")); + f32 width = get_fancy_string_width(app, face_id, fstr); + Vec2_f32 view_center = (region.p0 + region.p1)*0.5f; + Vec2_f32 half_dim = V2f32(width, line_height)*0.5f; + Vec2_f32 p = view_center - half_dim; + draw_fancy_string(app, face_id, fcolor_zero(), fstr, p); + } + else{ + Rect_f32_Pair tabs_body = rect_split_top_bottom(region, line_height + 2.f); + Range_f32 tabs_y = rect_range_y(tabs_body.min); + + inspect->tab_id_hovered = ProfileInspectTab_None; + block_zero_struct(&inspect->full_name_hovered); + inspect->unique_counter_hovered = 0; + block_zero_struct(&inspect->location_jump_hovered); + inspect->hover_thread = 0; + inspect->hover_slot = 0; + inspect->hover_node = 0; + + // NOTE(allen): tabs + { + f32 y = (tabs_y.min + tabs_y.max - line_height)*0.5f; + f32 x = region.x0; + + Tab_State tab_state = {}; + tab_state.p = V2f32(x, y); + tab_state.tabs_y = tabs_y; + tab_state.face_id = face_id; + tab_state.x_half_padding = x_half_padding; + tab_state.m_p = m_p; + + draw_rectangle_fcolor(app, tabs_body.min, 0.f, fcolor_id(defcolor_margin_hover)); + + if (inspect->tab_id == ProfileInspectTab_None){ + inspect->tab_id = ProfileInspectTab_Threads; + } + + profile_draw_tab(app, &tab_state, inspect, + string_u8_litexpr("threads"), + ProfileInspectTab_Threads); + + if (inspect->slot_count > 0){ + profile_draw_tab(app, &tab_state, inspect, + string_u8_litexpr("blocks"), + ProfileInspectTab_Blocks); + } + + if (inspect->error_count > 0){ + profile_draw_tab(app, &tab_state, inspect, + string_u8_litexpr("errors"), + ProfileInspectTab_Errors); + } + + profile_draw_tab(app, &tab_state, inspect, + string_u8_litexpr("memory"), + ProfileInspectTab_Memory); + + if (inspect->tab_id == ProfileInspectTab_Selection){ + String_Const_u8 string = {}; + if (inspect->selected_thread != 0){ + String_Const_u8 name = inspect->selected_thread->name; + string = push_u8_stringf(scratch, "%.*s (%d)", + string_expand(name), + inspect->selected_thread->thread_id); + } + else if (inspect->selected_slot != 0){ + String_Const_u8 name = inspect->selected_slot->name; + string = push_u8_stringf(scratch, "block %.*s", + string_expand(name)); + } + else if (inspect->selected_node != 0){ + String_Const_u8 name = profile_node_name(inspect->selected_node); + string = push_u8_stringf(scratch, "node %.*s", + string_expand(name)); + } + else{ + inspect->tab_id = ProfileInspectTab_Threads; + } + if (string.str != 0){ + profile_draw_tab(app, &tab_state, inspect, + string, ProfileInspectTab_Selection); + } + } + } + + draw_set_clip(app, tabs_body.max); + switch (inspect->tab_id){ + case ProfileInspectTab_Threads: + { + Range_f32 x = rect_range_x(tabs_body.max); + f32 y_pos = tabs_body.max.y0; + i32 count = inspect->thread_count; + Profile_Inspection_Thread *thread = inspect->threads; + for (i32 i = 0; i < count; i += 1, thread += 1){ + Range_f32 y = If32_size(y_pos, block_height); + + Fancy_Line list = {}; + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_pop1), + "%-20.*s (%6d) ", + string_expand(thread->name), + thread->thread_id); + + f32 active_time = ((f32)thread->active_time)/1000000.f; + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_pop2), + "active time %11.9f", + active_time); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(defcolor_margin); + if (rect_contains_point(box, m_p)){ + inspect->hover_thread = thread; + margin = fcolor_id(defcolor_margin_hover); + } + draw_rectangle_outline_fcolor(app, box, 6.f, 3.f, margin); + + y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } + } + }break; + + case ProfileInspectTab_Blocks: + { + Range_f32 x = rect_range_x(tabs_body.max); + f32 y_pos = tabs_body.max.y0; + for (Profile_Slot *node = inspect->first_slot; + node != 0; + node = node->next){ + Range_f32 y = If32_size(y_pos, block_height); + + u32 name_width = 45; + b32 name_too_long = (node->name.size > name_width); + Fancy_Line list = {}; + push_fancy_string_fixed(scratch, &list, fcolor_id(defcolor_pop1), + node->name, name_width); + + if (node->corrupted_time){ + push_fancy_string(scratch, &list, fcolor_id(defcolor_pop2), + string_u8_litexpr("timing error ")); + } + else{ + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_pop2), + "%11.9fs ", + ((f32)node->total_time)/1000000.f); + } + + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_keyword), + "hit # %5d", node->hit_count); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(defcolor_margin); + if (rect_contains_point(box, m_p)){ + if (name_too_long){ + inspect->full_name_hovered = node->name; + } + inspect->location_jump_hovered = node->location; + inspect->hover_slot = node; + margin = fcolor_id(defcolor_margin_hover); + } + draw_rectangle_outline_fcolor(app, box, 6.f, 3.f, margin); + + y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } + } + }break; + + case ProfileInspectTab_Errors: + { + draw_set_clip(app, tabs_body.max); + Range_f32 x = rect_range_x(tabs_body.max); + f32 y_pos = tabs_body.max.y0; + for (Profile_Error *node = inspect->first_error; + node != 0; + node = node->next){ + Range_f32 y = If32_size(y_pos, block_height); + + Fancy_Line list = {}; + push_fancy_string(scratch, &list, fcolor_id(defcolor_pop2), + node->message); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(defcolor_margin); + if (rect_contains_point(box, m_p)){ + inspect->location_jump_hovered = node->location; + margin = fcolor_id(defcolor_margin_hover); + } + draw_rectangle_outline_fcolor(app, box, 6.f, 3.f, margin); + + y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } + } + }break; + + case ProfileInspectTab_Memory: + { + draw_set_clip(app, tabs_body.max); + Range_f32 x = rect_range_x(tabs_body.max); + f32 y_pos = tabs_body.max.y0; + Memory_Annotation annotation = system_memory_annotation(scratch); + + Base_Allocator *allocator = get_base_allocator_system(); + + Memory_Bucket *first_bucket = 0; + Memory_Bucket *last_bucket = 0; + i32 bucket_count = 0; + Table_Data_u64 table = make_table_Data_u64(allocator, 100); + + for (Memory_Annotation_Node *node = annotation.first, *next = 0; + node != 0; + node = next){ + next = node->next; + Data key = make_data(node->location.str, node->location.size); + Table_Lookup lookup = table_lookup(&table, key); + Memory_Bucket *bucket = 0; + if (lookup.found_match){ + u64 val = 0; + table_read(&table, lookup, &val); + bucket = (Memory_Bucket*)IntAsPtr(val); + } + else{ + bucket = push_array_zero(scratch, Memory_Bucket, 1); + sll_queue_push(first_bucket, last_bucket, bucket); + bucket_count += 1; + bucket->location = node->location; + table_insert(&table, key, PtrAsInt(bucket)); + } + sll_queue_push(bucket->annotation.first, bucket->annotation.last, node); + bucket->annotation.count += 1; + bucket->total_memory += node->size; + } + + Memory_Bucket **buckets = push_array(scratch, Memory_Bucket*, bucket_count); + i32 counter = 0; + for (Memory_Bucket *node = first_bucket; + node != 0; + node = node->next){ + buckets[counter] = node; + counter += 1; + } + + profile_memory_sort_by_count(buckets, 0, bucket_count); + + for (i32 i = bucket_count - 1; i >= 0; i -= 1){ + Memory_Bucket *node = buckets[i]; + Range_f32 y = If32_size(y_pos, block_height); + + Fancy_Line list = {}; + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_pop2), "[%12llu] / %6d ", + node->total_memory, node->annotation.count); + push_fancy_stringf(scratch, &list, fcolor_id(defcolor_pop1), "%.*s", + string_expand(node->location)); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(defcolor_margin); + if (rect_contains_point(box, m_p)){ + inspect->location_jump_hovered = node->location; + margin = fcolor_id(defcolor_margin_hover); + } + + y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } + } + + table_free(&table); + }break; + + case ProfileInspectTab_Selection: + { + if (inspect->selected_thread != 0){ + profile_draw_node(app, view, face_id, + &inspect->selected_thread->root, tabs_body.max, + inspect, m_p); + } + else if (inspect->selected_slot != 0){ + + } + else if (inspect->selected_node != 0){ + profile_draw_node(app, view, face_id, + inspect->selected_node, tabs_body.max, + inspect, m_p); + } + }break; + } + + if (!rect_contains_point(region, m_p)){ + // NOTE(allen): don't draw tool tip when the mouse doesn't hover in our view + } + else if (inspect->tab_id_hovered != ProfileInspectTab_None){ + // NOTE(allen): no tool tip for tabs + } + else{ + Fancy_Block block = {}; + FColor text_color = fcolor_change_alpha(f_white, 0.5f); + FColor back_color = fcolor_change_alpha(f_black, 0.5f); + + if (inspect->full_name_hovered.size > 0){ + Fancy_Line *line = push_fancy_line(scratch, &block, text_color); + push_fancy_stringf(scratch, line, "%.*s", + string_expand(inspect->full_name_hovered)); + if (inspect->unique_counter_hovered > 0){ + push_fancy_stringf(scratch, line, text_color, 0.5f, 0.f, + "#%4llu", inspect->unique_counter_hovered); + } + } + if (inspect->location_jump_hovered.size > 0){ + Fancy_Line *line = push_fancy_line(scratch, &block, text_color); + push_fancy_stringf(scratch, line, "[shift] '%.*s'", + string_expand(inspect->location_jump_hovered)); + } + + draw_tool_tip(app, face_id, &block, m_p, region, + x_padding, x_half_padding, back_color); + } + } + + draw_set_clip(app, prev_clip); +} + +function void +profile_inspect__left_click(Application_Links *app, View_ID view, + Profile_Inspection *insp, Input_Event *event){ + if (has_modifier(event, KeyCode_Shift)){ + if (insp->location_jump_hovered.size != 0){ + View_ID target_view = view; + target_view = get_next_view_looped_primary_panels(app, target_view, + Access_Always); + String_Const_u8 location = insp->location_jump_hovered; + jump_to_location(app, target_view, location); + } + } + else{ + if (insp->tab_id_hovered != ProfileInspectTab_None){ + insp->tab_id = insp->tab_id_hovered; + } + else if (insp->hover_thread != 0){ + profile_select_thread(insp, insp->hover_thread); + } + else if (insp->hover_slot != 0){ + profile_select_slot(insp, insp->hover_slot); + } + else if (insp->hover_node != 0){ + profile_select_node(insp, insp->hover_node); + } + } +} + +CUSTOM_UI_COMMAND_SIG(profile_inspect) +CUSTOM_DOC("Inspect all currently collected profiling information in 4coder's self profiler.") +{ + Profile_Global_List *list = get_core_profile_list(app); + if (HasFlag(list->disable_bits, ProfileEnable_InspectBit)){ + return; + } + + profile_set_enabled(list, false, ProfileEnable_InspectBit); + + Scratch_Block scratch(app); + global_profile_inspection = profile_parse(scratch, list); + Profile_Inspection *insp = &global_profile_inspection; + + View_ID view = get_active_view(app, Access_Always); + View_Context ctx = view_current_context(app, view); + ctx.render_caller = profile_render; + ctx.hides_buffer = true; + View_Context_Block ctx_block(app, view, &ctx); + + for (;;){ + User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); + if (in.abort){ + break; + } + + b32 handled = true; + switch (in.event.kind){ + case InputEventKind_MouseButton: + { + switch (in.event.mouse.code){ + case MouseCode_Left: + { + profile_inspect__left_click(app, view, insp, &in.event); + }break; + } + }break; + + default: + { + handled = false; + }break; + } + + if (!handled){ + if (ui_fallback_command_dispatch(app, view, &in)){ + break; + } + } + } + + profile_set_enabled(list, true, ProfileEnable_InspectBit); +} + +// BOTTOM diff --git a/custom/4coder_search.cpp b/custom/4coder_search.cpp index 56b313a5..0b35787d 100644 --- a/custom/4coder_search.cpp +++ b/custom/4coder_search.cpp @@ -230,7 +230,7 @@ get_word_complete_needle_range(Application_Links *app, Buffer_ID buffer, i64 pos needle_range.max = pos; needle_range.min = scan(app, boundary_alpha_numeric_underscore_utf8, buffer, Scan_Backward, pos); i64 e = scan(app, boundary_alpha_numeric_underscore_utf8, buffer, Scan_Forward, needle_range.min); - if (needle_range.max > e){ + if (pos > e){ needle_range = Ii64(pos); } return(needle_range); @@ -414,11 +414,9 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with if (first_completion || !initialized){ ProfileBlock(app, "word complete state init"); - + initialized = false; i64 pos = view_get_cursor_pos(app, view); - Range_i64 needle_range = get_word_complete_needle_range(app, buffer, pos); - if (range_size(needle_range) > 0){ initialized = true; range = needle_range; @@ -482,8 +480,8 @@ word_complete_menu_render(Application_Links *app, Frame_Info frame_info, View_ID for (i32 i = 0; i < menu->count; i += 1){ if (menu->options[i].size > 0){ Fancy_Line *line = push_fancy_line(scratch, &block, face); - push_fancy_stringf(scratch, line, fcolor_id(Stag_Pop1), "F%d:", i + 1); - push_fancy_string(scratch, line, fcolor_id(Stag_Default), menu->options[i]); + push_fancy_stringf(scratch, line, fcolor_id(defcolor_pop1), "F%d:", i + 1); + push_fancy_string(scratch, line, fcolor_id(defcolor_text_default), menu->options[i]); } } @@ -501,7 +499,7 @@ word_complete_menu_render(Application_Links *app, Frame_Info frame_info, View_ID f32 x_half_padding = x_padding*0.5f; draw_drop_down(app, face, &block, cursor_p, region, x_padding, x_half_padding, - fcolor_id(Stag_Margin_Hover), fcolor_id(Stag_Back)); + fcolor_id(defcolor_margin_hover), fcolor_id(defcolor_back)); } } diff --git a/custom/4coder_tutorial.cpp b/custom/4coder_tutorial.cpp index 7302c298..3f0e82fa 100644 --- a/custom/4coder_tutorial.cpp +++ b/custom/4coder_tutorial.cpp @@ -128,7 +128,7 @@ tutorial_render(Application_Links *app, Frame_Info frame_info, View_ID view_id){ f32 panel_y0 = region.y0 - 3.f; region = rect_inner(region, 3.f); - draw_rectangle(app, region, 20.f, fcolor_id(Stag_Back)); + draw_rectangle_fcolor(app, region, 20.f, fcolor_id(defcolor_back)); region = rect_inner(region, 10.f); Vec2_f32 title_p = V2f32(region.x0, panel_y0 + (metrics.line_height*2.f) - title_height*0.5f); @@ -302,25 +302,25 @@ global String_Const_u8 hms_title = string_u8_litexpr("Handmade Seattle Demo"); function void hms_demo_tutorial_short_details(Application_Links *app, Arena *arena, Fancy_Line *short_details){ Face_ID face = get_face_id(app, 0); - push_fancy_string(arena, short_details, tutorial.face, fcolor_id(Stag_Pop1), hms_title); - push_fancy_string(arena, short_details, face, fcolor_id(Stag_Default), 8.f, 8.f, string_u8_litexpr("Welcome to Handmade Seattle and to this 4coder demo!")); - push_fancy_string(arena, short_details, face, fcolor_id(Stag_Pop2), string_u8_litexpr("Click here to see more.")); + push_fancy_string(arena, short_details, tutorial.face, fcolor_id(defcolor_pop1), hms_title); + push_fancy_string(arena, short_details, face, fcolor_id(defcolor_text_default), 8.f, 8.f, string_u8_litexpr("Welcome to Handmade Seattle and to this 4coder demo!")); + push_fancy_string(arena, short_details, face, fcolor_id(defcolor_pop2), string_u8_litexpr("Click here to see more.")); } function void hms_demo_tutorial_long_start(Application_Links *app, Arena *arena, Fancy_Block *long_details){ - Fancy_Line *line = push_fancy_line(arena, long_details, tutorial.face, fcolor_id(Stag_Pop1), hms_title); + Fancy_Line *line = push_fancy_line(arena, long_details, tutorial.face, fcolor_id(defcolor_pop1), hms_title); Face_ID face = get_face_id(app, 0); // - line = push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default)); + line = push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default)); #define M "If you want more information than what you can find here, please " push_fancy_string(arena, line, string_u8_litexpr(M)); #undef M - push_fancy_string(arena, line, fcolor_id(Stag_Pop2), string_u8_litexpr("ask!")); + push_fancy_string(arena, line, fcolor_id(defcolor_pop2), string_u8_litexpr("ask!")); // - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("")); } function void @@ -337,12 +337,12 @@ hms_demo_tutorial_binding_line(Application_Links *app, Arena *arena, Fancy_Block pad_size = 40.f - fill_size; } - Fancy_Line *line = line = push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default)); + Fancy_Line *line = line = push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default)); push_fancy_stringf(arena, line, pad_size, 0.5f, "<"); if (m.size > 0){ - push_fancy_stringf(arena, line, fcolor_id(Stag_Keyword), 0.f, 0.5f, "%s", modifiers); + push_fancy_stringf(arena, line, fcolor_id(defcolor_keyword), 0.f, 0.5f, "%s", modifiers); } - push_fancy_stringf(arena, line, fcolor_id(Stag_Pop2), "%s", key); + push_fancy_stringf(arena, line, fcolor_id(defcolor_pop2), "%s", key); push_fancy_stringf(arena, line, 0.5f, 1.f, ">"); push_fancy_stringf(arena, line, "%s", description); } @@ -359,7 +359,7 @@ hms_demo_tutorial_slide_1(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Let's start with a few navigation commands:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Let's start with a few navigation commands:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "Comma", "change active panel"); @@ -376,7 +376,7 @@ hms_demo_tutorial_slide_1(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "PageUp/PageDown", "move cursor by full pages up/down"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Available in code files:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Available in code files:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -409,7 +409,7 @@ hms_demo_tutorial_slide_2(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Now a look at basic editing:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Now a look at basic editing:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "TextInsert", "non-modal text insertion works in any user-writable buffers at the cursor"); @@ -429,7 +429,7 @@ hms_demo_tutorial_slide_2(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "Up/Down", "move the current line"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Range commands based on a cursor and mark (emacs style):")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Range commands based on a cursor and mark (emacs style):")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "Space", "moves the mark to the cursor"); @@ -443,7 +443,7 @@ hms_demo_tutorial_slide_2(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "X", "cut the range"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Paste options with a multi-stage clipboard:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Paste options with a multi-stage clipboard:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "V", "paste the clipboard to the buffer"); @@ -466,7 +466,7 @@ hms_demo_tutorial_slide_3(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Now try beginning a file lister:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Now try beginning a file lister:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "N", "begin a file lister for exploring the file system - always creating a new file"); @@ -477,7 +477,7 @@ hms_demo_tutorial_slide_3(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "O", "same as previous option but opens in the other panel"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Inside a file lister:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Inside a file lister:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "TextInsert", "narrows the lister down to options with substrings matching the text field"); @@ -497,7 +497,7 @@ hms_demo_tutorial_slide_3(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "Escape", "cancel the operation"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("There are also buffer listers for operations on buffers that are already open:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("There are also buffer listers for operations on buffers that are already open:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "I", "begin a buffer lister and switch to the selected buffer"); @@ -520,12 +520,12 @@ hms_demo_tutorial_slide_4(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("The command lister makes all commands available in one place:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("The command lister makes all commands available in one place:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "X", "a lister of all commands"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Try some of these commands from the command lister:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Try some of these commands from the command lister:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "toggle_filebar", "toggle the panel's filebar"); @@ -560,7 +560,7 @@ hms_demo_tutorial_slide_5(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Fast navigation by jump lists:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Fast navigation by jump lists:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "F", "after the user answers a query for a string generate a jump list of matches"); @@ -571,7 +571,7 @@ hms_demo_tutorial_slide_5(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control Shift", "I", "parse the current buffer as a C/C++ source and generate a jump list of functions"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("After generating a jump list it is bound as the active jump list enabling these commands:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("After generating a jump list it is bound as the active jump list enabling these commands:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "N", "jump to the next jump location"); @@ -597,43 +597,43 @@ hms_demo_tutorial_slide_6(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Virtual whitespace:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Virtual whitespace:")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\tBuffers that are indexed with information about nest structures can be equiped with the virtual whitespace layout algorithm.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\tThe on screen layout of text is independent of the actual whitespace contents of the underlying text.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), string_u8_litexpr("")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Keyword), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_keyword), string_u8_litexpr("\tTry inserting new scopes and parenthetical sections in a code file.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\t\tObserve that indentation is updated automatically.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Keyword), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_keyword), string_u8_litexpr("\tTry creating a line that is long enough to wrap around the edge.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\t\tObserve that wrapped lines obey the same indentation rules as literal lines.")); { - Fancy_Line *line = push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default)); + Fancy_Line *line = push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default)); push_fancy_stringf(arena, line, "\tUse the command "); - push_fancy_stringf(arena, line, fcolor_id(Stag_Pop2), "toggle_virtual_whitespace"); + push_fancy_stringf(arena, line, fcolor_id(defcolor_pop2), "toggle_virtual_whitespace"); push_fancy_stringf(arena, line, " to turn this feature on and off"); } { - Fancy_Line *line = push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default)); + Fancy_Line *line = push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default)); push_fancy_stringf(arena, line, "\tUse the command "); - push_fancy_stringf(arena, line, fcolor_id(Stag_Pop2), "toggle_line_wrap"); + push_fancy_stringf(arena, line, fcolor_id(defcolor_pop2), "toggle_line_wrap"); push_fancy_stringf(arena, line, " to see how layout changes with line wrapping on and off"); } - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Auto Indentation:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Auto Indentation:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Control", "Tab", "auto indent the lines marked by the range; the effect is only visible with virtual whitespace off."); @@ -653,7 +653,7 @@ hms_demo_tutorial_slide_7(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("Builds, scripts, and projects:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Builds, scripts, and projects:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "M", "searches for and runs a build script (windows -> 'build.bat'; unix -> 'build.sh')"); @@ -664,7 +664,7 @@ hms_demo_tutorial_slide_7(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "execute_previous_cli", "repeats an execute_any_cli command with the same command and ouptut buffer"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("If a script/command generates output that can be parsed as jumps (e.g. compilation errors) then it becomes the active jump buffer:")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("If a script/command generates output that can be parsed as jumps (e.g. compilation errors) then it becomes the active jump buffer:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "N", "jump to the next jump location"); @@ -675,7 +675,7 @@ hms_demo_tutorial_slide_7(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt Shift", "M", "jump to the first jump"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("The project system enables rich bindings of arbitrary system scripts (when a project is loaded):")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("The project system enables rich bindings of arbitrary system scripts (when a project is loaded):")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "F#", "run a script bound to the corresponding index in the loaded project"); @@ -689,7 +689,7 @@ hms_demo_tutorial_slide_7(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "setup_new_project", "command to generate a new 'project.4coder' file and build scripts"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\tCheckout 'project.4coder' to see more about what is in a project.")); return(result); @@ -707,16 +707,16 @@ hms_demo_tutorial_slide_8(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("Probably the biggest feature in 4coder is that so many things about it can be customized.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("The project loaded for this demo is the 'default custom layer' everything here could be done differently, as you see fit.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Search for these commands to see some of the features available to customization:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -740,11 +740,11 @@ hms_demo_tutorial_slide_8(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "setup_default_mapping", "defines the mapping of commands to bindings"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), string_u8_litexpr("")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), string_u8_litexpr("\tThe macros CUSTOM_COMMAND_SIG and CUSTOM_DOC markup the commands to create the list of all available commands.")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\tThe macros CUSTOM_COMMAND_SIG and CUSTOM_DOC markup the commands to create the list of all available commands.")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), string_u8_litexpr("\tThis means that user written commands that use the same markup automatically appear in the command_lister along side built in commands!")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("\tThis means that user written commands that use the same markup automatically appear in the command_lister along side built in commands!")); return(result); } @@ -761,13 +761,13 @@ hms_demo_tutorial_slide_9(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Default), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_text_default), string_u8_litexpr("The customization system exposes much more than just commands to be customized...")); hms_demo_tutorial_binding_line(app, arena, long_details, face, "Alt", "F", "(hint!) this is the default binding for search, use it to find these functions"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Write completely custom GUIs:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -776,7 +776,7 @@ hms_demo_tutorial_slide_9(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "tutorial_run_loop/tutorial_render", "underlying implementation for the tutorial system powering this demo!"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Write custom text coloring and highlighting in buffers:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -788,7 +788,7 @@ hms_demo_tutorial_slide_9(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "default_render_buffer", "puts together all the default markup in buffer rendering"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Write custom line layout rules:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -797,7 +797,7 @@ hms_demo_tutorial_slide_9(Application_Links *app, Arena *arena){ hms_demo_tutorial_binding_line(app, arena, long_details, face, "", "layout_index_unwrapped__inner", "the unwrapped version of the virtual whitespace layout logic"); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Write custom smoothing rules that interact with buffer and UI scrolling:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -821,7 +821,7 @@ hms_demo_tutorial_slide_10(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("Some miscellaneous things to try:")); hms_demo_tutorial_binding_line(app, arena, long_details, face, @@ -857,11 +857,11 @@ hms_demo_tutorial_slide_11(Application_Links *app, Arena *arena){ Fancy_Block *long_details = &result.long_details; hms_demo_tutorial_long_start(app, arena, long_details); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("")); - push_fancy_line(arena, long_details, face, fcolor_id(Stag_Pop1), string_u8_litexpr("\t\tThanks for checking out the demo!")); + push_fancy_line(arena, long_details, face, fcolor_id(defcolor_pop1), string_u8_litexpr("\t\tThanks for checking out the demo!")); return(result); } diff --git a/custom/4coder_types.h b/custom/4coder_types.h index 22d742f0..184fa6f5 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -27,7 +27,8 @@ union FColor{ ARGB_Color argb; struct{ ID_Color id; - u16 padding_; + u8 sub_index; + u8 padding_; }; }; @@ -36,12 +37,13 @@ struct Theme_Color{ ARGB_Color color; }; -//struct Theme{ -//ARGB_Color colors[Stag_COUNT]; -//}; +struct Color_Array{ + ARGB_Color *vals; + i32 count; +}; struct Color_Table{ - ARGB_Color *vals; + Color_Array *arrays; u32 count; }; diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 4528ecea..73220e4a 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -358,12 +358,12 @@ static Command_Metadata fcoder_metacmd_table[222] = { { PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1568 }, { PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1576 }, { PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 }, -{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1811 }, -{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1824 }, -{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1838 }, -{ PROC_LINKS(redo_all_buffers, 0), false, "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, 1909 }, -{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2010 }, -{ PROC_LINKS(default_file_externally_modified, 0), false, "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, 2016 }, +{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1644 }, +{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1657 }, +{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1671 }, +{ PROC_LINKS(redo_all_buffers, 0), false, "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, 1742 }, +{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1843 }, +{ PROC_LINKS(default_file_externally_modified, 0), false, "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, 1849 }, { PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 86 }, { PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 99 }, { PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 112 }, @@ -389,7 +389,7 @@ static Command_Metadata fcoder_metacmd_table[222] = { { PROC_LINKS(list_all_locations_of_type_definition, 0), false, "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\\custom\\4coder_search.cpp", 36, 210 }, { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "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\\custom\\4coder_search.cpp", 36, 218 }, { PROC_LINKS(word_complete, 0), false, "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\\custom\\4coder_search.cpp", 36, 392 }, -{ PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 641 }, +{ PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 639 }, { PROC_LINKS(goto_jump_at_cursor, 0), false, "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\\custom\\4coder_jump_sticky.cpp", 41, 346 }, { PROC_LINKS(goto_jump_at_cursor_same_panel, 0), false, "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\\custom\\4coder_jump_sticky.cpp", 41, 373 }, { PROC_LINKS(goto_next_jump, 0), false, "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\\custom\\4coder_jump_sticky.cpp", 41, 462 }, @@ -401,13 +401,13 @@ static Command_Metadata fcoder_metacmd_table[222] = { { PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 }, { PROC_LINKS(if_read_only_goto_position_same_panel, 0), false, "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 }, { PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 }, -{ PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 995 }, +{ PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 994 }, { PROC_LINKS(copy, 0), false, "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 }, { PROC_LINKS(cut, 0), false, "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 }, { PROC_LINKS(paste, 0), false, "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 }, -{ PROC_LINKS(paste_next, 0), false, "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 70 }, -{ PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 108 }, -{ PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 115 }, +{ PROC_LINKS(paste_next, 0), false, "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 71 }, +{ PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 110 }, +{ PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 117 }, { PROC_LINKS(keyboard_macro_start_recording, 0), false, "keyboard_macro_start_recording", 30, "Start macro recording, do nothing if macro recording is already started", 71, "w:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 44 }, { PROC_LINKS(keyboard_macro_finish_recording, 0), false, "keyboard_macro_finish_recording", 31, "Stop macro recording, do nothing if macro recording is not already started", 74, "w:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 57 }, { PROC_LINKS(keyboard_macro_replay, 0), false, "keyboard_macro_replay", 21, "Replay the most recently recorded keyboard macro", 48, "w:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 80 }, @@ -459,7 +459,7 @@ static Command_Metadata fcoder_metacmd_table[222] = { { PROC_LINKS(miblo_decrement_time_stamp, 0), false, "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\\custom\\4coder_miblo_numbers.cpp", 43, 237 }, { PROC_LINKS(miblo_increment_time_stamp_minute, 0), false, "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\\custom\\4coder_miblo_numbers.cpp", 43, 243 }, { PROC_LINKS(miblo_decrement_time_stamp_minute, 0), false, "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\\custom\\4coder_miblo_numbers.cpp", 43, 249 }, -{ PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 890 }, +{ PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 887 }, { PROC_LINKS(kill_tutorial, 0), false, "kill_tutorial", 13, "If there is an active tutorial, kill it.", 40, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 9 }, { PROC_LINKS(tutorial_maximize, 0), false, "tutorial_maximize", 17, "Expand the tutorial window", 26, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 20 }, { PROC_LINKS(tutorial_minimize, 0), false, "tutorial_minimize", 17, "Shrink the tutorial window", 26, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 34 }, diff --git a/custom/generated/custom_api.cpp b/custom/generated/custom_api.cpp index 9f2d4720..fa55a258 100644 --- a/custom/generated/custom_api.cpp +++ b/custom/generated/custom_api.cpp @@ -108,6 +108,7 @@ vtable->get_managed_scope_with_multiple_dependencies = get_managed_scope_with_mu vtable->managed_scope_clear_contents = managed_scope_clear_contents; vtable->managed_scope_clear_self_all_dependent_scopes = managed_scope_clear_self_all_dependent_scopes; vtable->managed_scope_allocator = managed_scope_allocator; +vtable->managed_id_group_highest_id = managed_id_group_highest_id; vtable->managed_id_declare = managed_id_declare; vtable->managed_scope_get_attachment = managed_scope_get_attachment; vtable->managed_scope_attachment_erase = managed_scope_attachment_erase; @@ -155,9 +156,6 @@ vtable->get_face_id = get_face_id; vtable->try_create_new_face = try_create_new_face; vtable->try_modify_face = try_modify_face; vtable->try_release_face = try_release_face; -vtable->set_theme_colors = set_theme_colors; -vtable->get_theme_colors = get_theme_colors; -vtable->finalize_color = finalize_color; vtable->push_hot_directory = push_hot_directory; vtable->set_hot_directory = set_hot_directory; vtable->send_exit_signal = send_exit_signal; @@ -292,6 +290,7 @@ get_managed_scope_with_multiple_dependencies = vtable->get_managed_scope_with_mu managed_scope_clear_contents = vtable->managed_scope_clear_contents; managed_scope_clear_self_all_dependent_scopes = vtable->managed_scope_clear_self_all_dependent_scopes; managed_scope_allocator = vtable->managed_scope_allocator; +managed_id_group_highest_id = vtable->managed_id_group_highest_id; managed_id_declare = vtable->managed_id_declare; managed_scope_get_attachment = vtable->managed_scope_get_attachment; managed_scope_attachment_erase = vtable->managed_scope_attachment_erase; @@ -339,9 +338,6 @@ get_face_id = vtable->get_face_id; try_create_new_face = vtable->try_create_new_face; try_modify_face = vtable->try_modify_face; try_release_face = vtable->try_release_face; -set_theme_colors = vtable->set_theme_colors; -get_theme_colors = vtable->get_theme_colors; -finalize_color = vtable->finalize_color; push_hot_directory = vtable->push_hot_directory; set_hot_directory = vtable->set_hot_directory; send_exit_signal = vtable->send_exit_signal; diff --git a/custom/generated/custom_api.h b/custom/generated/custom_api.h index caea61aa..ebe13f2f 100644 --- a/custom/generated/custom_api.h +++ b/custom/generated/custom_api.h @@ -93,7 +93,7 @@ #define custom_view_set_mark_sig() b32 custom_view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek) #define custom_view_quit_ui_sig() b32 custom_view_quit_ui(Application_Links* app, View_ID view_id) #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, FColor color) +#define custom_view_post_fade_sig() b32 custom_view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, ARGB_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_alter_context_sig() b32 custom_view_alter_context(Application_Links* app, View_ID view_id, View_Context* ctx) @@ -106,6 +106,7 @@ #define custom_managed_scope_clear_contents_sig() b32 custom_managed_scope_clear_contents(Application_Links* app, Managed_Scope scope) #define custom_managed_scope_clear_self_all_dependent_scopes_sig() b32 custom_managed_scope_clear_self_all_dependent_scopes(Application_Links* app, Managed_Scope scope) #define custom_managed_scope_allocator_sig() Base_Allocator* custom_managed_scope_allocator(Application_Links* app, Managed_Scope scope) +#define custom_managed_id_group_highest_id_sig() u64 custom_managed_id_group_highest_id(Application_Links* app, String_Const_u8 group) #define custom_managed_id_declare_sig() Managed_ID custom_managed_id_declare(Application_Links* app, String_Const_u8 group, String_Const_u8 name) #define custom_managed_scope_get_attachment_sig() void* custom_managed_scope_get_attachment(Application_Links* app, Managed_Scope scope, Managed_ID id, umem size) #define custom_managed_scope_attachment_erase_sig() void* custom_managed_scope_attachment_erase(Application_Links* app, Managed_Scope scope, Managed_ID id) @@ -153,17 +154,14 @@ #define custom_try_create_new_face_sig() Face_ID custom_try_create_new_face(Application_Links* app, Face_Description* description) #define custom_try_modify_face_sig() b32 custom_try_modify_face(Application_Links* app, Face_ID id, Face_Description* description) #define custom_try_release_face_sig() b32 custom_try_release_face(Application_Links* app, Face_ID id, Face_ID replacement_id) -#define custom_set_theme_colors_sig() void custom_set_theme_colors(Application_Links* app, Theme_Color* colors, i32 count) -#define custom_get_theme_colors_sig() void custom_get_theme_colors(Application_Links* app, Theme_Color* colors, i32 count) -#define custom_finalize_color_sig() ARGB_Color custom_finalize_color(Application_Links* app, ID_Color color) #define custom_push_hot_directory_sig() String_Const_u8 custom_push_hot_directory(Application_Links* app, Arena* arena) #define custom_set_hot_directory_sig() b32 custom_set_hot_directory(Application_Links* app, String_Const_u8 string) #define custom_send_exit_signal_sig() void custom_send_exit_signal(Application_Links* app) #define custom_set_window_title_sig() b32 custom_set_window_title(Application_Links* app, String_Const_u8 title) -#define custom_draw_string_oriented_sig() Vec2_f32 custom_draw_string_oriented(Application_Links* app, Face_ID font_id, FColor color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta) +#define custom_draw_string_oriented_sig() Vec2_f32 custom_draw_string_oriented(Application_Links* app, Face_ID font_id, ARGB_Color color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta) #define custom_get_string_advance_sig() f32 custom_get_string_advance(Application_Links* app, Face_ID font_id, String_Const_u8 str) -#define custom_draw_rectangle_sig() void custom_draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, FColor color) -#define custom_draw_rectangle_outline_sig() void custom_draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, FColor color) +#define custom_draw_rectangle_sig() void custom_draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, ARGB_Color color) +#define custom_draw_rectangle_outline_sig() void custom_draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, ARGB_Color color) #define custom_draw_set_clip_sig() Rect_f32 custom_draw_set_clip(Application_Links* app, Rect_f32 new_clip) #define custom_text_layout_create_sig() Text_Layout_ID custom_text_layout_create(Application_Links* app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point) #define custom_text_layout_region_sig() Rect_f32 custom_text_layout_region(Application_Links* app, Text_Layout_ID text_layout_id) @@ -171,9 +169,9 @@ #define custom_text_layout_get_visible_range_sig() Range_i64 custom_text_layout_get_visible_range(Application_Links* app, Text_Layout_ID text_layout_id) #define custom_text_layout_line_on_screen_sig() Range_f32 custom_text_layout_line_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 line_number) #define custom_text_layout_character_on_screen_sig() Rect_f32 custom_text_layout_character_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 pos) -#define custom_paint_text_color_sig() void custom_paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, FColor color) +#define custom_paint_text_color_sig() void custom_paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, ARGB_Color color) #define custom_text_layout_free_sig() b32 custom_text_layout_free(Application_Links* app, Text_Layout_ID text_layout_id) -#define custom_draw_text_layout_sig() void custom_draw_text_layout(Application_Links* app, Text_Layout_ID layout_id) +#define custom_draw_text_layout_sig() void custom_draw_text_layout(Application_Links* app, Text_Layout_ID layout_id, ARGB_Color special_color, ARGB_Color ghost_color) #define custom_open_color_picker_sig() void custom_open_color_picker(Application_Links* app, Color_Picker* picker) #define custom_animate_in_n_milliseconds_sig() void custom_animate_in_n_milliseconds(Application_Links* app, u32 n) #define custom_buffer_find_all_matches_sig() String_Match_List custom_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) @@ -273,7 +271,7 @@ typedef b32 custom_view_set_buffer_scroll_type(Application_Links* app, View_ID v typedef b32 custom_view_set_mark_type(Application_Links* app, View_ID view_id, Buffer_Seek seek); typedef b32 custom_view_quit_ui_type(Application_Links* app, View_ID view_id); 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, FColor color); +typedef b32 custom_view_post_fade_type(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, ARGB_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 b32 custom_view_alter_context_type(Application_Links* app, View_ID view_id, View_Context* ctx); @@ -286,6 +284,7 @@ typedef Managed_Scope custom_get_managed_scope_with_multiple_dependencies_type(A typedef b32 custom_managed_scope_clear_contents_type(Application_Links* app, Managed_Scope scope); typedef b32 custom_managed_scope_clear_self_all_dependent_scopes_type(Application_Links* app, Managed_Scope scope); typedef Base_Allocator* custom_managed_scope_allocator_type(Application_Links* app, Managed_Scope scope); +typedef u64 custom_managed_id_group_highest_id_type(Application_Links* app, String_Const_u8 group); typedef Managed_ID custom_managed_id_declare_type(Application_Links* app, String_Const_u8 group, String_Const_u8 name); typedef void* custom_managed_scope_get_attachment_type(Application_Links* app, Managed_Scope scope, Managed_ID id, umem size); typedef void* custom_managed_scope_attachment_erase_type(Application_Links* app, Managed_Scope scope, Managed_ID id); @@ -333,17 +332,14 @@ typedef Face_ID custom_get_face_id_type(Application_Links* app, Buffer_ID buffer typedef Face_ID custom_try_create_new_face_type(Application_Links* app, Face_Description* description); typedef b32 custom_try_modify_face_type(Application_Links* app, Face_ID id, Face_Description* description); typedef b32 custom_try_release_face_type(Application_Links* app, Face_ID id, Face_ID replacement_id); -typedef void custom_set_theme_colors_type(Application_Links* app, Theme_Color* colors, i32 count); -typedef void custom_get_theme_colors_type(Application_Links* app, Theme_Color* colors, i32 count); -typedef ARGB_Color custom_finalize_color_type(Application_Links* app, ID_Color color); typedef String_Const_u8 custom_push_hot_directory_type(Application_Links* app, Arena* arena); typedef b32 custom_set_hot_directory_type(Application_Links* app, String_Const_u8 string); typedef void custom_send_exit_signal_type(Application_Links* app); typedef b32 custom_set_window_title_type(Application_Links* app, String_Const_u8 title); -typedef Vec2_f32 custom_draw_string_oriented_type(Application_Links* app, Face_ID font_id, FColor color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); +typedef Vec2_f32 custom_draw_string_oriented_type(Application_Links* app, Face_ID font_id, ARGB_Color color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); typedef f32 custom_get_string_advance_type(Application_Links* app, Face_ID font_id, String_Const_u8 str); -typedef void custom_draw_rectangle_type(Application_Links* app, Rect_f32 rect, f32 roundness, FColor color); -typedef void custom_draw_rectangle_outline_type(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, FColor color); +typedef void custom_draw_rectangle_type(Application_Links* app, Rect_f32 rect, f32 roundness, ARGB_Color color); +typedef void custom_draw_rectangle_outline_type(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, ARGB_Color color); typedef Rect_f32 custom_draw_set_clip_type(Application_Links* app, Rect_f32 new_clip); typedef Text_Layout_ID custom_text_layout_create_type(Application_Links* app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point); typedef Rect_f32 custom_text_layout_region_type(Application_Links* app, Text_Layout_ID text_layout_id); @@ -351,9 +347,9 @@ typedef Buffer_ID custom_text_layout_get_buffer_type(Application_Links* app, Tex typedef Range_i64 custom_text_layout_get_visible_range_type(Application_Links* app, Text_Layout_ID text_layout_id); typedef Range_f32 custom_text_layout_line_on_screen_type(Application_Links* app, Text_Layout_ID layout_id, i64 line_number); typedef Rect_f32 custom_text_layout_character_on_screen_type(Application_Links* app, Text_Layout_ID layout_id, i64 pos); -typedef void custom_paint_text_color_type(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, FColor color); +typedef void custom_paint_text_color_type(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, ARGB_Color color); typedef b32 custom_text_layout_free_type(Application_Links* app, Text_Layout_ID text_layout_id); -typedef void custom_draw_text_layout_type(Application_Links* app, Text_Layout_ID layout_id); +typedef void custom_draw_text_layout_type(Application_Links* app, Text_Layout_ID layout_id, ARGB_Color special_color, ARGB_Color ghost_color); typedef void custom_open_color_picker_type(Application_Links* app, Color_Picker* picker); typedef void custom_animate_in_n_milliseconds_type(Application_Links* app, u32 n); typedef String_Match_List custom_buffer_find_all_matches_type(Application_Links* app, Arena* arena, Buffer_ID buffer, i32 string_id, Range_i64 range, String_Const_u8 needle, Character_Predicate* predicate, Scan_Direction direction); @@ -467,6 +463,7 @@ custom_get_managed_scope_with_multiple_dependencies_type *get_managed_scope_with custom_managed_scope_clear_contents_type *managed_scope_clear_contents; custom_managed_scope_clear_self_all_dependent_scopes_type *managed_scope_clear_self_all_dependent_scopes; custom_managed_scope_allocator_type *managed_scope_allocator; +custom_managed_id_group_highest_id_type *managed_id_group_highest_id; custom_managed_id_declare_type *managed_id_declare; custom_managed_scope_get_attachment_type *managed_scope_get_attachment; custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase; @@ -514,9 +511,6 @@ custom_get_face_id_type *get_face_id; custom_try_create_new_face_type *try_create_new_face; custom_try_modify_face_type *try_modify_face; custom_try_release_face_type *try_release_face; -custom_set_theme_colors_type *set_theme_colors; -custom_get_theme_colors_type *get_theme_colors; -custom_finalize_color_type *finalize_color; custom_push_hot_directory_type *push_hot_directory; custom_set_hot_directory_type *set_hot_directory; custom_send_exit_signal_type *send_exit_signal; @@ -636,7 +630,7 @@ internal b32 view_set_buffer_scroll(Application_Links* app, View_ID view_id, Buf internal b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek); internal b32 view_quit_ui(Application_Links* app, View_ID view_id); 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, FColor color); +internal b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, ARGB_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 b32 view_alter_context(Application_Links* app, View_ID view_id, View_Context* ctx); @@ -649,6 +643,7 @@ internal Managed_Scope get_managed_scope_with_multiple_dependencies(Application_ internal b32 managed_scope_clear_contents(Application_Links* app, Managed_Scope scope); internal b32 managed_scope_clear_self_all_dependent_scopes(Application_Links* app, Managed_Scope scope); internal Base_Allocator* managed_scope_allocator(Application_Links* app, Managed_Scope scope); +internal u64 managed_id_group_highest_id(Application_Links* app, String_Const_u8 group); internal Managed_ID managed_id_declare(Application_Links* app, String_Const_u8 group, String_Const_u8 name); internal void* managed_scope_get_attachment(Application_Links* app, Managed_Scope scope, Managed_ID id, umem size); internal void* managed_scope_attachment_erase(Application_Links* app, Managed_Scope scope, Managed_ID id); @@ -696,17 +691,14 @@ internal Face_ID get_face_id(Application_Links* app, Buffer_ID buffer_id); internal Face_ID try_create_new_face(Application_Links* app, Face_Description* description); internal b32 try_modify_face(Application_Links* app, Face_ID id, Face_Description* description); internal b32 try_release_face(Application_Links* app, Face_ID id, Face_ID replacement_id); -internal void set_theme_colors(Application_Links* app, Theme_Color* colors, i32 count); -internal void get_theme_colors(Application_Links* app, Theme_Color* colors, i32 count); -internal ARGB_Color finalize_color(Application_Links* app, ID_Color color); internal String_Const_u8 push_hot_directory(Application_Links* app, Arena* arena); internal b32 set_hot_directory(Application_Links* app, String_Const_u8 string); internal void send_exit_signal(Application_Links* app); internal b32 set_window_title(Application_Links* app, String_Const_u8 title); -internal Vec2_f32 draw_string_oriented(Application_Links* app, Face_ID font_id, FColor color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); +internal Vec2_f32 draw_string_oriented(Application_Links* app, Face_ID font_id, ARGB_Color color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); internal f32 get_string_advance(Application_Links* app, Face_ID font_id, String_Const_u8 str); -internal void draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, FColor color); -internal void draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, FColor color); +internal void draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, ARGB_Color color); +internal void draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, ARGB_Color color); internal Rect_f32 draw_set_clip(Application_Links* app, Rect_f32 new_clip); internal Text_Layout_ID text_layout_create(Application_Links* app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point); internal Rect_f32 text_layout_region(Application_Links* app, Text_Layout_ID text_layout_id); @@ -714,9 +706,9 @@ internal Buffer_ID text_layout_get_buffer(Application_Links* app, Text_Layout_ID internal Range_i64 text_layout_get_visible_range(Application_Links* app, Text_Layout_ID text_layout_id); internal Range_f32 text_layout_line_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 line_number); internal Rect_f32 text_layout_character_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 pos); -internal void paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, FColor color); +internal void paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, ARGB_Color color); internal b32 text_layout_free(Application_Links* app, Text_Layout_ID text_layout_id); -internal void draw_text_layout(Application_Links* app, Text_Layout_ID layout_id); +internal void draw_text_layout(Application_Links* app, Text_Layout_ID layout_id, ARGB_Color special_color, ARGB_Color ghost_color); internal void open_color_picker(Application_Links* app, Color_Picker* picker); internal void animate_in_n_milliseconds(Application_Links* app, u32 n); internal 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); @@ -831,6 +823,7 @@ global custom_get_managed_scope_with_multiple_dependencies_type *get_managed_sco global custom_managed_scope_clear_contents_type *managed_scope_clear_contents = 0; global custom_managed_scope_clear_self_all_dependent_scopes_type *managed_scope_clear_self_all_dependent_scopes = 0; global custom_managed_scope_allocator_type *managed_scope_allocator = 0; +global custom_managed_id_group_highest_id_type *managed_id_group_highest_id = 0; global custom_managed_id_declare_type *managed_id_declare = 0; global custom_managed_scope_get_attachment_type *managed_scope_get_attachment = 0; global custom_managed_scope_attachment_erase_type *managed_scope_attachment_erase = 0; @@ -878,9 +871,6 @@ global custom_get_face_id_type *get_face_id = 0; global custom_try_create_new_face_type *try_create_new_face = 0; global custom_try_modify_face_type *try_modify_face = 0; global custom_try_release_face_type *try_release_face = 0; -global custom_set_theme_colors_type *set_theme_colors = 0; -global custom_get_theme_colors_type *get_theme_colors = 0; -global custom_finalize_color_type *finalize_color = 0; global custom_push_hot_directory_type *push_hot_directory = 0; global custom_set_hot_directory_type *set_hot_directory = 0; global custom_send_exit_signal_type *send_exit_signal = 0; diff --git a/custom/generated/custom_api_master_list.h b/custom/generated/custom_api_master_list.h index 54b254da..94a247f5 100644 --- a/custom/generated/custom_api_master_list.h +++ b/custom/generated/custom_api_master_list.h @@ -93,7 +93,7 @@ api(custom) function b32 view_set_buffer_scroll(Application_Links* app, View_ID api(custom) function b32 view_set_mark(Application_Links* app, View_ID view_id, Buffer_Seek seek); api(custom) function b32 view_quit_ui(Application_Links* app, View_ID view_id); 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, FColor color); +api(custom) function b32 view_post_fade(Application_Links* app, View_ID view_id, f32 seconds, Range_i64 range, ARGB_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 b32 view_alter_context(Application_Links* app, View_ID view_id, View_Context* ctx); @@ -106,6 +106,7 @@ api(custom) function Managed_Scope get_managed_scope_with_multiple_dependencies( api(custom) function b32 managed_scope_clear_contents(Application_Links* app, Managed_Scope scope); api(custom) function b32 managed_scope_clear_self_all_dependent_scopes(Application_Links* app, Managed_Scope scope); api(custom) function Base_Allocator* managed_scope_allocator(Application_Links* app, Managed_Scope scope); +api(custom) function u64 managed_id_group_highest_id(Application_Links* app, String_Const_u8 group); api(custom) function Managed_ID managed_id_declare(Application_Links* app, String_Const_u8 group, String_Const_u8 name); api(custom) function void* managed_scope_get_attachment(Application_Links* app, Managed_Scope scope, Managed_ID id, umem size); api(custom) function void* managed_scope_attachment_erase(Application_Links* app, Managed_Scope scope, Managed_ID id); @@ -153,17 +154,14 @@ api(custom) function Face_ID get_face_id(Application_Links* app, Buffer_ID buffe api(custom) function Face_ID try_create_new_face(Application_Links* app, Face_Description* description); api(custom) function b32 try_modify_face(Application_Links* app, Face_ID id, Face_Description* description); api(custom) function b32 try_release_face(Application_Links* app, Face_ID id, Face_ID replacement_id); -api(custom) function void set_theme_colors(Application_Links* app, Theme_Color* colors, i32 count); -api(custom) function void get_theme_colors(Application_Links* app, Theme_Color* colors, i32 count); -api(custom) function ARGB_Color finalize_color(Application_Links* app, ID_Color color); api(custom) function String_Const_u8 push_hot_directory(Application_Links* app, Arena* arena); api(custom) function b32 set_hot_directory(Application_Links* app, String_Const_u8 string); api(custom) function void send_exit_signal(Application_Links* app); api(custom) function b32 set_window_title(Application_Links* app, String_Const_u8 title); -api(custom) function Vec2_f32 draw_string_oriented(Application_Links* app, Face_ID font_id, FColor color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); +api(custom) function Vec2_f32 draw_string_oriented(Application_Links* app, Face_ID font_id, ARGB_Color color, String_Const_u8 str, Vec2_f32 point, u32 flags, Vec2_f32 delta); api(custom) function f32 get_string_advance(Application_Links* app, Face_ID font_id, String_Const_u8 str); -api(custom) function void draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, FColor color); -api(custom) function void draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, FColor color); +api(custom) function void draw_rectangle(Application_Links* app, Rect_f32 rect, f32 roundness, ARGB_Color color); +api(custom) function void draw_rectangle_outline(Application_Links* app, Rect_f32 rect, f32 roundness, f32 thickness, ARGB_Color color); api(custom) function Rect_f32 draw_set_clip(Application_Links* app, Rect_f32 new_clip); api(custom) function Text_Layout_ID text_layout_create(Application_Links* app, Buffer_ID buffer_id, Rect_f32 rect, Buffer_Point buffer_point); api(custom) function Rect_f32 text_layout_region(Application_Links* app, Text_Layout_ID text_layout_id); @@ -171,9 +169,9 @@ api(custom) function Buffer_ID text_layout_get_buffer(Application_Links* app, Te api(custom) function Range_i64 text_layout_get_visible_range(Application_Links* app, Text_Layout_ID text_layout_id); api(custom) function Range_f32 text_layout_line_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 line_number); api(custom) function Rect_f32 text_layout_character_on_screen(Application_Links* app, Text_Layout_ID layout_id, i64 pos); -api(custom) function void paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, FColor color); +api(custom) function void paint_text_color(Application_Links* app, Text_Layout_ID layout_id, Interval_i64 range, ARGB_Color color); api(custom) function b32 text_layout_free(Application_Links* app, Text_Layout_ID text_layout_id); -api(custom) function void draw_text_layout(Application_Links* app, Text_Layout_ID layout_id); +api(custom) function void draw_text_layout(Application_Links* app, Text_Layout_ID layout_id, ARGB_Color special_color, ARGB_Color ghost_color); api(custom) function void open_color_picker(Application_Links* app, Color_Picker* picker); api(custom) function void animate_in_n_milliseconds(Application_Links* app, u32 n); api(custom) function 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); diff --git a/custom/generated/managed_id_metadata.cpp b/custom/generated/managed_id_metadata.cpp index 046d9bbf..79b9b4ef 100644 --- a/custom/generated/managed_id_metadata.cpp +++ b/custom/generated/managed_id_metadata.cpp @@ -1,5 +1,43 @@ function void initialize_managed_id_metadata(Application_Links *app){ +defcolor_bar = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_bar")); +defcolor_base = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_base")); +defcolor_pop1 = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_pop1")); +defcolor_pop2 = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_pop2")); +defcolor_back = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_back")); +defcolor_margin = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_margin")); +defcolor_margin_hover = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_margin_hover")); +defcolor_margin_active = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_margin_active")); +defcolor_list_item = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_list_item")); +defcolor_list_item_hover = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_list_item_hover")); +defcolor_list_item_active = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_list_item_active")); +defcolor_cursor = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_cursor")); +defcolor_at_cursor = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_at_cursor")); +defcolor_highlight_cursor_line = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_highlight_cursor_line")); +defcolor_highlight = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_highlight")); +defcolor_at_highlight = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_at_highlight")); +defcolor_mark = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_mark")); +defcolor_text_default = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_text_default")); +defcolor_comment = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_comment")); +defcolor_comment_pop = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_comment_pop")); +defcolor_keyword = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_keyword")); +defcolor_str_constant = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_str_constant")); +defcolor_char_constant = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_char_constant")); +defcolor_int_constant = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_int_constant")); +defcolor_float_constant = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_float_constant")); +defcolor_bool_constant = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_bool_constant")); +defcolor_preproc = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_preproc")); +defcolor_include = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_include")); +defcolor_special_character = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_special_character")); +defcolor_ghost_character = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_ghost_character")); +defcolor_highlight_junk = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_highlight_junk")); +defcolor_highlight_white = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_highlight_white")); +defcolor_paste = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_paste")); +defcolor_undo = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_undo")); +defcolor_back_cycle = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_back_cycle")); +defcolor_text_cycle = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_text_cycle")); +defcolor_line_numbers_back = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_line_numbers_back")); +defcolor_line_numbers_text = managed_id_declare(app, string_u8_litexpr("colors"), string_u8_litexpr("defcolor_line_numbers_text")); view_rewrite_loc = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_rewrite_loc")); view_next_rewrite_loc = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_next_rewrite_loc")); view_paste_index_loc = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_paste_index_loc"));