fix some stuff that breaks on windows

memory-refactor
Patrick Cleavelin 2025-02-08 14:03:48 -06:00
parent 111f2f8a70
commit f0eae25439
9 changed files with 143 additions and 103 deletions

1
build.bat Normal file
View File

@ -0,0 +1 @@
..\odin\odin.exe build src/ -out:bin\editor.exe -debug

View File

@ -1,6 +1,7 @@
use std::{ use std::{
borrow::Cow, borrow::Cow,
ffi::{c_char, c_void, CStr}, ffi::{c_char, c_void, CStr, CString},
fmt::write,
path::Path, path::Path,
}; };
@ -133,8 +134,11 @@ impl BufferVTable {
} }
} }
pub fn open_buffer(&self, path: impl AsRef<Path>, line: i32, col: i32) { pub fn open_buffer(&self, path: impl AsRef<Path>, line: i32, col: i32) {
let c_str = path.as_ref().to_string_lossy().as_ptr(); let Ok(c_str) = CString::new(path.as_ref().as_os_str().as_encoded_bytes()) else {
(self.open_buffer)(c_str, line as isize, col as isize); eprintln!("grep plugin failed to open buffer");
return;
};
(self.open_buffer)(c_str.as_ptr() as *const u8, line as isize, col as isize);
} }
pub fn open_virtual_buffer(&self) -> Buffer { pub fn open_virtual_buffer(&self) -> Buffer {
Buffer { Buffer {

View File

@ -1,7 +1,7 @@
// The default syntax highlighter plugin for Odin & Rust // The default syntax highlighter plugin for Odin & Rust
package highlighter; package highlighter;
import "core:runtime" import "base:runtime"
import "core:fmt" import "core:fmt"
import p "../../../src/plugin" import p "../../../src/plugin"

View File

@ -1,6 +1,6 @@
package core package core
import "core:runtime" import "base:runtime"
import "core:reflect" import "core:reflect"
import "core:fmt" import "core:fmt"
import "core:log" import "core:log"
@ -97,6 +97,10 @@ current_buffer :: proc(state: ^State) -> ^FileBuffer {
return &state.log_buffer; return &state.log_buffer;
} }
if len(state.buffers) < 1 {
return nil
}
return &state.buffers[state.current_buffer]; return &state.buffers[state.current_buffer];
} }
@ -167,7 +171,7 @@ new_input_actions :: proc() -> InputActions {
return input_actions; return input_actions;
} }
delete_input_map :: proc(input_map: ^InputMap) { delete_input_map :: proc(input_map: ^InputMap) {
for _, &actions in &input_map.mode { for _, &actions in input_map.mode {
delete_input_actions(&actions); delete_input_actions(&actions);
} }
delete(input_map.mode); delete(input_map.mode);

View File

@ -1,6 +1,6 @@
package core; package core;
import "core:runtime" import "base:runtime"
ErrorType :: enum { ErrorType :: enum {
None, None,

View File

@ -6,7 +6,7 @@ import "core:mem"
import "core:fmt" import "core:fmt"
import "core:math" import "core:math"
import "core:slice" import "core:slice"
import "core:runtime" import "base:runtime"
import "core:strings" import "core:strings"
import "../theme" import "../theme"
@ -672,8 +672,10 @@ new_virtual_file_buffer :: proc(allocator: mem.Allocator) -> FileBuffer {
new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: string = "") -> (FileBuffer, Error) { new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: string = "") -> (FileBuffer, Error) {
context.allocator = allocator; context.allocator = allocator;
fmt.eprintln("attempting to open", file_path);
fd, err := os.open(file_path); fd, err := os.open(file_path);
if err != os.ERROR_NONE { if err != nil {
return FileBuffer{}, make_error(ErrorType.FileIOError, fmt.aprintf("failed to open file: errno=%x", err)); return FileBuffer{}, make_error(ErrorType.FileIOError, fmt.aprintf("failed to open file: errno=%x", err));
} }
defer os.close(fd); defer os.close(fd);
@ -696,10 +698,12 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string, base_dir: s
width := 256; width := 256;
height := 256; height := 256;
fmt.eprintln("file path", fi.fullpath[4:]);
buffer := FileBuffer { buffer := FileBuffer {
allocator = allocator, allocator = allocator,
directory = dir, directory = dir,
file_path = fi.fullpath, file_path = fi.fullpath[4:],
extension = extension, extension = extension,
original_content = slice.clone_to_dynamic(original_content), original_content = slice.clone_to_dynamic(original_content),
@ -951,7 +955,6 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, sho
draw_rect(state, sel_x, text_y, width, state.source_font_height, .Green); draw_rect(state, sel_x, text_y, width, state.source_font_height, .Green);
} }
} }
} }

View File

@ -26,6 +26,7 @@ gen_font_atlas :: proc(state: ^State, path: cstring) -> FontAtlas {
// FIXME: check if this failed // FIXME: check if this failed
font = ttf.OpenFont(path, font_height), font = ttf.OpenFont(path, font_height),
} }
assert(atlas.font != nil);
ttf.SetFontStyle(atlas.font, ttf.STYLE_NORMAL); ttf.SetFontStyle(atlas.font, ttf.STYLE_NORMAL);
// NOTE: not sure if I like the look of this or not yet // NOTE: not sure if I like the look of this or not yet

View File

@ -1,10 +1,11 @@
package main package main
import "core:c"
import "core:os" import "core:os"
import "core:path/filepath" import "core:path/filepath"
import "core:math" import "core:math"
import "core:strings" import "core:strings"
import "core:runtime" import "base:runtime"
import "core:fmt" import "core:fmt"
import "core:log" import "core:log"
import "core:mem" import "core:mem"
@ -18,6 +19,8 @@ import "theme"
import "ui" import "ui"
import "plugin" import "plugin"
HardcodedFontPath :: "bin/BerkeleyMono-Regular.ttf";
State :: core.State; State :: core.State;
FileBuffer :: core.FileBuffer; FileBuffer :: core.FileBuffer;
@ -146,7 +149,7 @@ register_default_input_actions :: proc(input_map: ^core.InputActions) {
state.source_font_height -= 2; state.source_font_height -= 2;
state.source_font_width = state.source_font_height / 2; state.source_font_width = state.source_font_height / 2;
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); state.font_atlas = core.gen_font_atlas(state, HardcodedFontPath);
} }
log.debug(state.source_font_height); log.debug(state.source_font_height);
}, "increase font size"); }, "increase font size");
@ -154,7 +157,7 @@ register_default_input_actions :: proc(input_map: ^core.InputActions) {
state.source_font_height += 2; state.source_font_height += 2;
state.source_font_width = state.source_font_height / 2; state.source_font_width = state.source_font_height / 2;
state.font_atlas = core.gen_font_atlas(state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); state.font_atlas = core.gen_font_atlas(state, HardcodedFontPath);
}, "decrease font size"); }, "decrease font size");
} }
@ -286,10 +289,10 @@ ui_font_height :: proc() -> i32 {
} }
draw :: proc(state_with_ui: ^StateWithUi) { draw :: proc(state_with_ui: ^StateWithUi) {
buffer := core.current_buffer(state_with_ui.state); if buffer := core.current_buffer(state_with_ui.state); buffer != nil {
buffer.glyph_buffer_height = math.min(256, int((state_with_ui.state.screen_height - state_with_ui.state.source_font_height*2) / state_with_ui.state.source_font_height)) + 1;
buffer.glyph_buffer_height = math.min(256, int((state_with_ui.state.screen_height - state_with_ui.state.source_font_height*2) / state_with_ui.state.source_font_height)) + 1; buffer.glyph_buffer_width = math.min(256, int((state_with_ui.state.screen_width - state_with_ui.state.source_font_width) / state_with_ui.state.source_font_width));
buffer.glyph_buffer_width = math.min(256, int((state_with_ui.state.screen_width - state_with_ui.state.source_font_width) / state_with_ui.state.source_font_width)); }
render_color := theme.get_palette_color(.Background); render_color := theme.get_palette_color(.Background);
sdl2.SetRenderDrawColor(state_with_ui.state.sdl_renderer, render_color.r, render_color.g, render_color.b, render_color.a); sdl2.SetRenderDrawColor(state_with_ui.state.sdl_renderer, render_color.r, render_color.g, render_color.b, render_color.a);
@ -832,6 +835,8 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
open_buffer = proc "c" (path: cstring, line: int, col: int) { open_buffer = proc "c" (path: cstring, line: int, col: int) {
context = state.ctx; context = state.ctx;
fmt.eprintln("opening file from dll", path)
path := string(path); path := string(path);
should_create_buffer := true; should_create_buffer := true;
for buffer, index in state.buffers { for buffer, index in state.buffers {
@ -1106,7 +1111,7 @@ main :: proc() {
sdl_window := sdl2.CreateWindow( sdl_window := sdl2.CreateWindow(
"odin_editor - [now with more ui]", "odin_editor - [now with more ui]",
sdl2.WINDOWPOS_UNDEFINED, sdl2.WINDOWPOS_UNDEFINED,
0, sdl2.WINDOWPOS_UNDEFINED,
640, 640,
480, 480,
{.SHOWN, .RESIZABLE, .ALLOW_HIGHDPI} {.SHOWN, .RESIZABLE, .ALLOW_HIGHDPI}
@ -1129,7 +1134,7 @@ main :: proc() {
log.error("Failed to create renderer:", sdl2.GetError()); log.error("Failed to create renderer:", sdl2.GetError());
return; return;
} }
state.font_atlas = core.gen_font_atlas(&state, "/System/Library/Fonts/Supplemental/Andale Mono.ttf"); state.font_atlas = core.gen_font_atlas(&state, HardcodedFontPath);
defer { defer {
if state.font_atlas.font != nil { if state.font_atlas.font != nil {
ttf.CloseFont(state.font_atlas.font); ttf.CloseFont(state.font_atlas.font);
@ -1170,9 +1175,29 @@ main :: proc() {
} }
// ********************************************************************** // **********************************************************************
L := lua.L_newstate(); lua_allocator :: proc "c" (ud: rawptr, ptr: rawptr, osize, nsize: c.size_t) -> (buf: rawptr) {
state.L = L; old_size := int(osize)
lua.L_openlibs(L); new_size := int(nsize)
context = (^runtime.Context)(ud)^
if ptr == nil {
data, err := runtime.mem_alloc(new_size)
return raw_data(data) if err == .None else nil
} else {
if nsize > 0 {
data, err := runtime.mem_resize(ptr, old_size, new_size)
return raw_data(data) if err == .None else nil
} else {
runtime.mem_free(ptr)
return
}
}
}
_context := context;
// L := lua.newstate(lua_allocator, &_context);
// L := lua.L_newstate();
state.L = lua.L_newstate();
lua.L_openlibs(state.L);
bbb: [^]lua.L_Reg; bbb: [^]lua.L_Reg;
editor_lib := [?]lua.L_Reg { editor_lib := [?]lua.L_Reg {
@ -1780,93 +1805,93 @@ main :: proc() {
}; };
// TODO: generate this from the plugin.Key enum // TODO: generate this from the plugin.Key enum
lua.newtable(L); lua.newtable(state.L);
{ {
lua.newtable(L); lua.newtable(state.L);
lua.pushinteger(L, lua.Integer(plugin.Key.B)); lua.pushinteger(state.L, lua.Integer(plugin.Key.B));
lua.setfield(L, -2, "B"); lua.setfield(state.L, -2, "B");
lua.pushinteger(L, lua.Integer(plugin.Key.T)); lua.pushinteger(state.L, lua.Integer(plugin.Key.T));
lua.setfield(L, -2, "T"); lua.setfield(state.L, -2, "T");
lua.pushinteger(L, lua.Integer(plugin.Key.Y)); lua.pushinteger(state.L, lua.Integer(plugin.Key.Y));
lua.setfield(L, -2, "Y"); lua.setfield(state.L, -2, "Y");
lua.pushinteger(L, lua.Integer(plugin.Key.P)); lua.pushinteger(state.L, lua.Integer(plugin.Key.P));
lua.setfield(L, -2, "P"); lua.setfield(state.L, -2, "P");
lua.pushinteger(L, lua.Integer(plugin.Key.M)); lua.pushinteger(state.L, lua.Integer(plugin.Key.M));
lua.setfield(L, -2, "M"); lua.setfield(state.L, -2, "M");
lua.pushinteger(L, lua.Integer(plugin.Key.K)); lua.pushinteger(state.L, lua.Integer(plugin.Key.K));
lua.setfield(L, -2, "K"); lua.setfield(state.L, -2, "K");
lua.pushinteger(L, lua.Integer(plugin.Key.J)); lua.pushinteger(state.L, lua.Integer(plugin.Key.J));
lua.setfield(L, -2, "J"); lua.setfield(state.L, -2, "J");
lua.pushinteger(L, lua.Integer(plugin.Key.Q)); lua.pushinteger(state.L, lua.Integer(plugin.Key.Q));
lua.setfield(L, -2, "Q"); lua.setfield(state.L, -2, "Q");
lua.pushinteger(L, lua.Integer(plugin.Key.BACKQUOTE)); lua.pushinteger(state.L, lua.Integer(plugin.Key.BACKQUOTE));
lua.setfield(L, -2, "Backtick"); lua.setfield(state.L, -2, "Backtick");
lua.pushinteger(L, lua.Integer(plugin.Key.ESCAPE)); lua.pushinteger(state.L, lua.Integer(plugin.Key.ESCAPE));
lua.setfield(L, -2, "Escape"); lua.setfield(state.L, -2, "Escape");
lua.pushinteger(L, lua.Integer(plugin.Key.ENTER)); lua.pushinteger(state.L, lua.Integer(plugin.Key.ENTER));
lua.setfield(L, -2, "Enter"); lua.setfield(state.L, -2, "Enter");
lua.pushinteger(L, lua.Integer(plugin.Key.SPACE)); lua.pushinteger(state.L, lua.Integer(plugin.Key.SPACE));
lua.setfield(L, -2, "Space"); lua.setfield(state.L, -2, "Space");
} }
lua.setfield(L, -2, "Key"); lua.setfield(state.L, -2, "Key");
{ {
lua.newtable(L); lua.newtable(state.L);
lua.pushinteger(L, lua.Integer(plugin.Hook.BufferInput)); lua.pushinteger(state.L, lua.Integer(plugin.Hook.BufferInput));
lua.setfield(L, -2, "OnBufferInput"); lua.setfield(state.L, -2, "OnBufferInput");
lua.pushinteger(L, lua.Integer(plugin.Hook.Draw)); lua.pushinteger(state.L, lua.Integer(plugin.Hook.Draw));
lua.setfield(L, -2, "OnDraw"); lua.setfield(state.L, -2, "OnDraw");
} }
lua.setfield(L, -2, "Hook"); lua.setfield(state.L, -2, "Hook");
lua.L_setfuncs(L, bbb, 0); lua.L_setfuncs(state.L, bbb, 0);
lua.setglobal(L, "Editor"); lua.setglobal(state.L, "Editor");
lua.newtable(L); lua.newtable(state.L);
{ {
lua.pushinteger(L, lua.Integer(ui.Axis.Horizontal)); lua.pushinteger(state.L, lua.Integer(ui.Axis.Horizontal));
lua.setfield(L, -2, "Horizontal"); lua.setfield(state.L, -2, "Horizontal");
lua.pushinteger(L, lua.Integer(ui.Axis.Vertical)); lua.pushinteger(state.L, lua.Integer(ui.Axis.Vertical));
lua.setfield(L, -2, "Vertical"); lua.setfield(state.L, -2, "Vertical");
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.Fill, 0 }); push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.Fill, 0 });
lua.setfield(L, -2, "Fill"); lua.setfield(state.L, -2, "Fill");
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.ChildrenSum, 0 }); push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.ChildrenSum, 0 });
lua.setfield(L, -2, "ChildrenSum"); lua.setfield(state.L, -2, "ChildrenSum");
push_lua_semantic_size_table(L, { ui.SemanticSizeKind.FitText, 0 }); push_lua_semantic_size_table(state.L, { ui.SemanticSizeKind.FitText, 0 });
lua.setfield(L, -2, "FitText"); lua.setfield(state.L, -2, "FitText");
lua.L_setfuncs(L, raw_data(&ui_lib), 0); lua.L_setfuncs(state.L, raw_data(&ui_lib), 0);
lua.setglobal(L, "UI"); lua.setglobal(state.L, "UI");
} }
if lua.L_dofile(L, "plugins/lua/view.lua") == i32(lua.OK) { if lua.L_dofile(state.L, "plugins/lua/view.lua") == i32(lua.OK) {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} else { } else {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} }
// Initialize Lua Plugins // Initialize Lua Plugins
{ {
lua.getglobal(L, "OnInit"); lua.getglobal(state.L, "OnInit");
if lua.pcall(L, 0, 0, 0) == i32(lua.OK) { if lua.pcall(state.L, 0, 0, 0) == i32(lua.OK) {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} else { } else {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error("failed to initialize plugin (OnInit):", err); log.error("failed to initialize plugin (OnInit):", err);
} }
@ -1989,16 +2014,18 @@ main :: proc() {
// } // }
for hook_ref in state.lua_hooks[plugin.Hook.Draw] { if draw_hooks, ok := state.lua_hooks[plugin.Hook.Draw]; ok {
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); for hook_ref in draw_hooks {
lua.pushlightuserdata(state.L, &ui_context); lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) { lua.pushlightuserdata(state.L, &ui_context);
err := lua.tostring(L, lua.gettop(L)); if lua.pcall(state.L, 1, 0, 0) != i32(lua.OK) {
lua.pop(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} else { } else {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
}
} }
} }
@ -2053,12 +2080,12 @@ main :: proc() {
case core.LuaEditorAction: case core.LuaEditorAction:
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref)); lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} else { } else {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} }
if value.maybe_input_map.ctrl_key_actions != nil { if value.maybe_input_map.ctrl_key_actions != nil {
@ -2078,12 +2105,12 @@ main :: proc() {
case core.LuaEditorAction: case core.LuaEditorAction:
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref)); lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(value.fn_ref));
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} else { } else {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} }
if value.maybe_input_map.key_actions != nil { if value.maybe_input_map.key_actions != nil {
@ -2138,12 +2165,12 @@ main :: proc() {
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] { for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} else { } else {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} }
} }
} }
@ -2168,12 +2195,12 @@ main :: proc() {
for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] { for hook_ref in state.lua_hooks[plugin.Hook.BufferInput] {
lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref)); lua.rawgeti(state.L, lua.REGISTRYINDEX, lua.Integer(hook_ref));
if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) { if lua.pcall(state.L, 0, 0, 0) != i32(lua.OK) {
err := lua.tostring(L, lua.gettop(L)); err := lua.tostring(state.L, lua.gettop(state.L));
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
log.error(err); log.error(err);
} else { } else {
lua.pop(L, lua.gettop(L)); lua.pop(state.L, lua.gettop(state.L));
} }
} }
} }
@ -2227,7 +2254,7 @@ main :: proc() {
plugin.on_exit(); plugin.on_exit();
} }
} }
lua.close(L); lua.close(state.L);
sdl2.Quit(); sdl2.Quit();
} }

View File

@ -1,6 +1,6 @@
package plugin; package plugin;
import "core:intrinsics" import "base:intrinsics"
import "core:dynlib" import "core:dynlib"
import "core:fmt" import "core:fmt"
import "core:log" import "core:log"