2025-07-10 14:08:27 +00:00
///////////////////////////////////////////////////////////////////////////
// Begin Buffer
///////////////////////////////////////////////////////////////////////////
BUFFER_HOOK_SIG ( custom_begin_buffer ) {
ProfileScope ( app , " begin buffer " ) ;
Scratch_Block scratch ( app ) ;
2025-07-10 15:53:54 +00:00
Tree_Sitter_Language_Definition * language = tree_sitter_language_for_buffer ( app , buffer_id ) ;
bool treat_as_code = language ! = 0 ;
if ( treat_as_code ) tree_sitter_begin_buffer ( app , buffer_id ) ;
2025-07-10 14:08:27 +00:00
String_ID file_map_id = vars_save_string_lit ( " keys_file " ) ;
String_ID code_map_id = vars_save_string_lit ( " keys_code " ) ;
2025-07-10 15:53:54 +00:00
Command_Map_ID map_id = ( treat_as_code ) ? ( code_map_id ) : ( file_map_id ) ;
2025-07-10 14:08:27 +00:00
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_lexer = false ;
2025-07-10 15:53:54 +00:00
if ( treat_as_code ) {
2025-07-10 14:08:27 +00:00
wrap_lines = def_get_config_b32 ( vars_save_string_lit ( " enable_code_wrapping " ) ) ;
// TODO(PS): @Remove - consider removing the lexer for now? later, replace in favor of tree-sitter
use_lexer = true ;
}
2025-07-10 15:53:54 +00:00
if ( treat_as_code )
2025-07-10 14:08:27 +00:00
{
Async_Task * parse_task = scope_attachment ( app , scope , buffer_tree_sitter_parse_task_id , Async_Task ) ;
* parse_task = async_task_no_dep ( & global_async_system , tree_sitter_parse_async , make_data_struct ( & buffer_id ) ) ;
}
String_Const_u8 buffer_name = push_buffer_base_name ( app , scratch , buffer_id ) ;
if ( buffer_name . size > 0 & & buffer_name . str [ 0 ] = = ' * ' & & buffer_name . str [ buffer_name . size - 1 ] = = ' * ' ) {
wrap_lines = def_get_config_b32 ( vars_save_string_lit ( " enable_output_wrapping " ) ) ;
}
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_lexer ) {
buffer_set_layout ( app , buffer_id , layout_virt_indent_index_generic ) ;
}
else {
2025-07-10 15:53:54 +00:00
if ( treat_as_code ) {
2025-07-10 14:08:27 +00:00
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 ) ;
}
///////////////////////////////////////////////////////////////////////////
// End Buffer
///////////////////////////////////////////////////////////////////////////
BUFFER_HOOK_SIG ( custom_end_buffer ) {
Marker_List * list = get_marker_list_for_buffer ( buffer_id ) ;
if ( list ! = 0 ) delete_marker_list ( list ) ;
tree_sitter_end_buffer ( app , buffer_id ) ;
default_end_buffer ( app , buffer_id ) ;
return ( 0 ) ;
}
2025-07-10 15:53:54 +00:00
///////////////////////////////////////////////////////////////////////////
// Render Buffer
///////////////////////////////////////////////////////////////////////////
function void custom_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 " ) ;
Scratch_Block scratch ( app ) ;
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 ) ;
Range_i64 visible_range = text_layout_get_visible_range ( app , text_layout_id ) ;
// NOTE(allen): Cursor shape
Face_Metrics metrics = get_face_metrics ( app , face_id ) ;
u64 cursor_roundness_100 = def_get_config_u64 ( app , vars_save_string_lit ( " cursor_roundness " ) ) ;
f32 cursor_roundness = metrics . normal_advance * cursor_roundness_100 * 0.01f ;
f32 mark_thickness = ( f32 ) def_get_config_u64 ( app , vars_save_string_lit ( " mark_thickness " ) ) ;
// NOTE(allen): Token colorizing
Managed_Scope buffer_scope = buffer_get_managed_scope ( app , buffer ) ;
Buffer_Tree_Sitter_Data * tree_data = scope_attachment ( app , buffer_scope , buffer_tree_sitter_data_id , Buffer_Tree_Sitter_Data ) ;
TSTree * tree = tree_sitter_buffer_get_tree_copy ( tree_data ) ;
Token_Array token_array = get_token_array_from_buffer ( app , buffer ) ;
paint_text_color_fcolor ( app , text_layout_id , visible_range , fcolor_id ( defcolor_text_default ) ) ; // will get overridden by lang-specific token coloring below
if ( token_array . tokens ! = 0 & & tree )
{
if ( use_tree_sitter_token_coloring )
{
draw_tree_sitter_node_colors ( app , text_layout_id , buffer ) ;
}
else
{
draw_cpp_token_colors ( app , text_layout_id , & token_array ) ;
}
}
i64 cursor_pos = view_correct_cursor ( app , view_id ) ;
view_correct_mark ( app , view_id ) ;
// NOTE(allen): Scope highlight
b32 use_scope_highlight = def_get_config_b32 ( vars_save_string_lit ( " use_scope_highlight " ) ) ;
if ( 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 ) ;
}
// NOTE(PS): QOL Column
if ( qol_col_cursor . pos > = 0 ) {
Buffer_Seek seek = seek_line_col ( qol_col_cursor . line , qol_col_cursor . col ) ;
Buffer_Cursor cursor = buffer_compute_cursor ( app , buffer , seek ) ;
Rect_f32 col_rect = text_layout_character_on_screen ( app , text_layout_id , cursor . pos ) ;
if ( col_rect . x1 > 0.f ) {
col_rect . y0 = rect . y0 ;
col_rect . y1 = rect . y1 ;
draw_rectangle_fcolor ( app , col_rect , 0.f , fcolor_id ( defcolor_highlight_cursor_line ) ) ;
}
}
b32 use_error_highlight = def_get_config_b32 ( vars_save_string_lit ( " use_error_highlight " ) ) ;
b32 use_jump_highlight = def_get_config_b32 ( vars_save_string_lit ( " use_jump_highlight " ) ) ;
if ( use_error_highlight | | 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 ( use_error_highlight ) {
draw_jump_highlights ( app , buffer , text_layout_id , compilation_buffer ,
fcolor_id ( defcolor_highlight_junk ) ) ;
}
// NOTE(allen): Search highlight
if ( 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
b32 use_paren_helper = def_get_config_b32 ( vars_save_string_lit ( " use_paren_helper " ) ) ;
if ( 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
b32 highlight_line_at_cursor = def_get_config_b32 ( vars_save_string_lit ( " highlight_line_at_cursor " ) ) ;
if ( 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): Whitespace highlight
b64 show_whitespace = false ;
view_get_setting ( app , view_id , ViewSetting_ShowWhitespace , & show_whitespace ) ;
if ( show_whitespace ) {
if ( token_array . tokens = = 0 ) {
draw_whitespace_highlight ( app , buffer , text_layout_id , cursor_roundness ) ;
}
else {
draw_whitespace_highlight ( app , text_layout_id , & token_array , cursor_roundness ) ;
}
}
// 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): Fade ranges
paint_fade_ranges ( app , text_layout_id , buffer ) ;
// 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
custom_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
region = default_draw_query_bars ( app , region , view_id , face_id ) ;
// 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
b32 show_line_number_margins = def_get_config_b32 ( vars_save_string_lit ( " show_line_number_margins " ) ) ;
Rect_f32 line_number_rect = { } ;
if ( 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 ( 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
custom_render_buffer ( app , view_id , face_id , buffer , text_layout_id , region ) ;
loco_render_buffer ( app , view_id , face_id , buffer , text_layout_id , region , frame_info ) ;
text_layout_free ( app , text_layout_id ) ;
draw_set_clip ( app , prev_clip ) ;
}