Monosize: Vector2; Scroll: Vector2; Vec2I :: struct { x: int; y: int; } MoveLeft :: proc(buffer: *Buffer, pos: int): int { pos -= 1; pos = AdjustUTF8Pos(buffer, pos, direction = -1); return pos; } MoveRight :: proc(buffer: *Buffer, pos: int): int { pos += 1; pos = AdjustUTF8Pos(buffer, pos, direction = +1); return pos; } CalculateVisualPos :: proc(buffer: *Buffer, pos: int): Vec2I { line: LineInfo = FindLineOfPos(buffer, pos); iter := Iterate(buffer, line.range.min, line.range.max); for IsValid(iter); Advance(&iter) { if iter.pos == pos { break; } } result: Vec2I = {iter.codepoint_index, line.number}; return result; } CalculatePosFromVisualPos :: proc(buffer: *Buffer, vpos: Vec2I): int { line := GetLine(buffer, vpos.y); iter := Iterate(buffer, line.range.min, line.range.max); for IsValid(iter); Advance(&iter) { if iter.codepoint_index == vpos.x { break; } } return iter.pos; } CalculateWorldPosUnscrolled :: proc(vpos: Vec2I): Vector2 { result: Vector2 = {Monosize.x * :f32(vpos.x), Monosize.y * :f32(vpos.y)}; return result; } CalculateWorldPos :: proc(vpos: Vec2I): Vector2 { result: Vector2 = {Monosize.x * :f32(vpos.x) - Scroll.x, Monosize.y * :f32(vpos.y) - Scroll.y}; return result; } MoveDown :: proc(buffer: *Buffer, pos: int): int { vpos := CalculateVisualPos(buffer, pos); if !IsLineValid(buffer, vpos.y + 1) return pos; result := CalculatePosFromVisualPos(buffer, {vpos.x, vpos.y + 1}); return result; } MoveUp :: proc(buffer: *Buffer, pos: int): int { vpos := CalculateVisualPos(buffer, pos); if !IsLineValid(buffer, vpos.y - 1) return pos; result := CalculatePosFromVisualPos(buffer, {vpos.x, vpos.y - 1}); return result; } DrawRect :: proc(rec: Rect2P, color: Color) { rectangle := Rect2PToRectangle(rec); DrawRectangleRec(rectangle, color); }