package core import "core:fmt" import ts "../tree_sitter" import "../theme" GlyphBuffer :: struct { buffer: []Glyph, width: int, height: int, } Glyph :: struct { codepoint: u8, color: theme.PaletteColor, } make_glyph_buffer :: proc(width, height: int, allocator := context.allocator) -> GlyphBuffer { context.allocator = allocator return GlyphBuffer { width = width, height = height, buffer = make([]Glyph, width*height) } } update_glyph_buffer_from_file_buffer :: proc(buffer: ^FileBuffer) { for &glyph in buffer.glyphs.buffer { glyph = Glyph {} glyph.color = .Foreground } outer: for highlight in buffer.tree.highlights { for line in highlight.start.row..=highlight.end.row { if int(line) < buffer.top_line { continue; } screen_line := int(line) - buffer.top_line if screen_line >= buffer.glyphs.height { break outer; } for col in highlight.start.column..= begin && screen_line >= buffer.glyphs.height { break; } // render INSERT mode text into glyph buffer if len(buffer.input_buffer) > 0 && rendered_line == buffer.history.cursor.line && rendered_col >= buffer.history.cursor.col && rendered_col < buffer.history.cursor.col + len(buffer.input_buffer) { for k in 0..= begin && rendered_col < buffer.glyphs.width { buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].color = .Foreground; buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].codepoint = buffer.input_buffer[k]; rendered_col += 1; } } } screen_line = rendered_line - begin; if character == '\n' { rendered_col = 0; rendered_line += 1; continue; } if rendered_line >= begin && rendered_col < buffer.glyphs.width { buffer.glyphs.buffer[rendered_col + screen_line * buffer.glyphs.width].codepoint = character } rendered_col += 1; } } update_glyph_buffer_from_bytes :: proc(glyphs: ^GlyphBuffer, data: []u8, top_line: int) { for &glyph in glyphs.buffer { glyph = Glyph{}; } begin := top_line; rendered_col: int; rendered_line: int; for character in data { if character == '\r' { continue; } screen_line := rendered_line - begin; // don't render past the screen if rendered_line >= begin && screen_line >= glyphs.height { break; } screen_line = rendered_line - begin; if character == '\n' { rendered_col = 0; rendered_line += 1; continue; } if rendered_line >= begin && rendered_col < glyphs.width { glyphs.buffer[rendered_col + screen_line * glyphs.width] = Glyph { codepoint = character, color = .Foreground }; } rendered_col += 1; } } update_glyph_buffer :: proc{update_glyph_buffer_from_file_buffer, update_glyph_buffer_from_bytes} draw_glyph_buffer :: proc(state: ^State, glyphs: ^GlyphBuffer, x: int, y: int, top_line: int, show_line_numbers: bool = true) { padding := 0; if show_line_numbers { padding = state.source_font_width * 5; } for j in 0..