package plugin; import "base:intrinsics" import "core:dynlib" import "core:fmt" import "core:log" import "../theme" OnInitializeProc :: proc "c" (plugin: Plugin); OnExitProc :: proc "c" (/* probably needs some state eventually */); OnDrawProc :: proc "c" (plugin: Plugin); Interface :: struct { on_initialize: OnInitializeProc, on_exit: OnExitProc, on_draw: OnDrawProc, } NewInterface :: struct { name: string, version: string, namespace: string, } BufferIndex :: struct { slice_index: int, content_index: int, } Cursor :: struct { col: int, line: int, index: BufferIndex, } BufferIter :: struct { cursor: Cursor, buffer: rawptr, hit_end: bool, } IterateResult :: struct { char: u8, should_continue: bool, } BufferInput :: struct { bytes: [^]u8, length: int, } BufferInfo :: struct { buffer: rawptr, file_path: cstring, input: BufferInput, cursor: Cursor, glyph_buffer_width: int, glyph_buffer_height: int, top_line: int, } Buffer :: struct { get_num_buffers: proc "c" () -> int, get_buffer_info: proc "c" (buffer: rawptr) -> BufferInfo, get_buffer_info_from_index: proc "c" (buffer_index: int) -> BufferInfo, color_char_at: proc "c" (buffer: rawptr, start_cursor: Cursor, end_cursor: Cursor, palette_index: i32), set_current_buffer: proc "c" (buffer_index: int), open_buffer: proc "c" (path: cstring, line: int, col: int), open_virtual_buffer: proc "c" () -> rawptr, free_virtual_buffer: proc "c" (buffer: rawptr), } Iterator :: struct { get_current_buffer_iterator: proc "c" () -> BufferIter, get_buffer_iterator: proc "c" (buffer: rawptr) -> BufferIter, get_char_at_iter: proc "c" (it: ^BufferIter) -> u8, get_buffer_list_iter: proc "c" (prev_buffer: ^int) -> int, iterate_buffer: proc "c" (it: ^BufferIter) -> IterateResult, iterate_buffer_reverse: proc "c" (it: ^BufferIter) -> IterateResult, iterate_buffer_until: proc "c" (it: ^BufferIter, until_proc: rawptr), iterate_buffer_until_reverse: proc "c" (it: ^BufferIter, until_proc: rawptr), iterate_buffer_peek: proc "c" (it: ^BufferIter) -> IterateResult, until_line_break: rawptr, until_single_quote: rawptr, until_double_quote: rawptr, until_end_of_word: rawptr, } UiInteraction :: struct { hovering: bool, clicked: bool } UiAxis :: enum { Horizontal = 0, Vertical, } UiSemanticSize :: struct { kind: int, value: int, } UiBox :: rawptr; UiPushParentProc :: proc "c" (ui_context: rawptr, box: UiBox); UiPopParentProc :: proc "c" (ui_context: rawptr); UiFloatingProc :: proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> UiBox; UiCreateBoxProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiBox; UiRectProc :: proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: UiAxis, size: [2]UiSemanticSize) -> UiBox; UiSimpleProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiInteraction; UiBufferProc :: proc "c" (ui_context: rawptr, buffer: rawptr, show_line_numbers: bool); UiBufferIndexProc :: proc "c" (ui_context: rawptr, buffer: int, show_line_numbers: bool); Ui :: struct { ui_context: rawptr, push_parent: UiPushParentProc, pop_parent: UiPopParentProc, spacer: UiSimpleProc, floating: UiFloatingProc, rect: UiRectProc, button: UiSimpleProc, label: UiSimpleProc, buffer: UiBufferProc, buffer_from_index: UiBufferIndexProc, } OnColorBufferProc :: proc "c" (plugin: Plugin, buffer: rawptr); InputGroupProc :: proc "c" (plugin: Plugin, input_map: rawptr); InputActionProc :: proc "c" (plugin: Plugin); OnHookProc :: proc "c" (plugin: Plugin, buffer: rawptr); WindowInputProc :: proc "c" (plugin: Plugin, window: rawptr); WindowDrawProc :: proc "c" (plugin: Plugin, window: rawptr); WindowGetBufferProc :: proc(plugin: Plugin, window: rawptr) -> rawptr; WindowFreeProc :: proc "c" (plugin: Plugin, window: rawptr); Plugin :: struct { state: rawptr, iter: Iterator, buffer: Buffer, ui: Ui, register_hook: proc "c" (hook: Hook, on_hook: OnHookProc), register_highlighter: proc "c" (extension: cstring, on_color_buffer: OnColorBufferProc), register_input_group: proc "c" (input_map: rawptr, key: Key, register_group: InputGroupProc), register_input: proc "c" (input_map: rawptr, key: Key, input_action: InputActionProc, description: cstring), create_window: proc "c" (user_data: rawptr, register_group: InputGroupProc, draw_proc: WindowDrawProc, free_window_proc: WindowFreeProc, get_buffer_proc: WindowGetBufferProc) -> rawptr, get_window: proc "c" () -> rawptr, request_window_close: proc "c" (), get_screen_width: proc "c" () -> int, get_screen_height: proc "c" () -> int, get_font_width: proc "c" () -> int, get_font_height: proc "c" () -> int, get_current_directory: proc "c" () -> cstring, enter_insert_mode: proc "c" (), draw_rect: proc "c" (x: i32, y: i32, width: i32, height: i32, color: theme.PaletteColor), draw_text: proc "c" (text: cstring, x: f32, y: f32, color: theme.PaletteColor), draw_buffer_from_index: proc "c" (buffer_index: int, x: int, y: int, glyph_buffer_width: int, glyph_buffer_height: int, show_line_numbers: bool), draw_buffer: proc "c" (buffer: rawptr, x: int, y: int, glyph_buffer_width: int, glyph_buffer_height: int, show_line_numbers: bool), } Hook :: enum { BufferInput = 0, Draw = 1, } Key :: enum { UNKNOWN = 0, ENTER = 13, ESCAPE = 27, BACKSPACE = 8, TAB = 9, SPACE = 32, EXCLAIM = 33, QUOTEDBL = 34, HASH = 35, PERCENT = 37, DOLLAR = 36, AMPERSAND = 38, QUOTE = 39, LEFTPAREN = 40, RIGHTPAREN = 41, ASTERISK = 42, PLUS = 43, COMMA = 44, MINUS = 45, PERIOD = 46, SLASH = 47, NUM0 = 48, NUM1 = 49, NUM2 = 50, NUM3 = 51, NUM4 = 52, NUM5 = 53, NUM6 = 54, NUM7 = 55, NUM8 = 56, NUM9 = 57, COLON = 58, SEMICOLON = 59, LESS = 60, EQUAL = 61, GREATER = 62, QUESTION = 63, AT = 64, LEFTBRACKET = 91, BACKSLASH = 92, RIGHTBRACKET = 93, CARET = 94, UNDERSCORE = 95, BACKQUOTE = 96, A = 97, B = 98, C = 99, D = 100, E = 101, F = 102, G = 103, H = 104, I = 105, J = 106, K = 107, L = 108, M = 109, N = 110, O = 111, P = 112, Q = 113, R = 114, S = 115, T = 116, U = 117, V = 118, W = 119, X = 120, Y = 121, Z = 122, CAPSLOCK = 1073741881, F1 = 1073741882, F2 = 1073741883, F3 = 1073741884, F4 = 1073741885, F5 = 1073741886, F6 = 1073741887, F7 = 1073741888, F8 = 1073741889, F9 = 1073741890, F10 = 1073741891, F11 = 1073741892, F12 = 1073741893, PRINTSCREEN = 1073741894, SCROLLLOCK = 1073741895, PAUSE = 1073741896, INSERT = 1073741897, HOME = 1073741898, PAGEUP = 1073741899, DELETE = 127, END = 1073741901, PAGEDOWN = 1073741902, RIGHT = 1073741903, LEFT = 1073741904, DOWN = 1073741905, UP = 1073741906, NUMLOCKCLEAR = 1073741907, KP_DIVIDE = 1073741908, KP_MULTIPLY = 1073741909, KP_MINUS = 1073741910, KP_PLUS = 1073741911, KP_ENTER = 1073741912, KP_1 = 1073741913, KP_2 = 1073741914, KP_3 = 1073741915, KP_4 = 1073741916, KP_5 = 1073741917, KP_6 = 1073741918, KP_7 = 1073741919, KP_8 = 1073741920, KP_9 = 1073741921, KP_0 = 1073741922, KP_PERIOD = 1073741923, APPLICATION = 1073741925, POWER = 1073741926, KP_EQUALS = 1073741927, F13 = 1073741928, F14 = 1073741929, F15 = 1073741930, F16 = 1073741931, F17 = 1073741932, F18 = 1073741933, F19 = 1073741934, F20 = 1073741935, F21 = 1073741936, F22 = 1073741937, F23 = 1073741938, F24 = 1073741939, EXECUTE = 1073741940, HELP = 1073741941, MENU = 1073741942, SELECT = 1073741943, STOP = 1073741944, AGAIN = 1073741945, UNDO = 1073741946, CUT = 1073741947, COPY = 1073741948, PASTE = 1073741949, FIND = 1073741950, MUTE = 1073741951, VOLUMEUP = 1073741952, VOLUMEDOWN = 1073741953, KP_COMMA = 1073741957, KP_EQUALSAS400 = 1073741958, ALTERASE = 1073741977, SYSREQ = 1073741978, CANCEL = 1073741979, CLEAR = 1073741980, PRIOR = 1073741981, RETURN2 = 1073741982, SEPARATOR = 1073741983, OUT = 1073741984, OPER = 1073741985, CLEARAGAIN = 1073741986, CRSEL = 1073741987, EXSEL = 1073741988, KP_00 = 1073742000, KP_000 = 1073742001, THOUSANDSSEPARATOR = 1073742002, DECIMALSEPARATOR = 1073742003, CURRENCYUNIT = 1073742004, CURRENCYSUBUNIT = 1073742005, KP_LEFTPAREN = 1073742006, KP_RIGHTPAREN = 1073742007, KP_LEFTBRACE = 1073742008, KP_RIGHTBRACE = 1073742009, KP_TAB = 1073742010, KP_BACKSPACE = 1073742011, KP_A = 1073742012, KP_B = 1073742013, KP_C = 1073742014, KP_D = 1073742015, KP_E = 1073742016, KP_F = 1073742017, KP_XOR = 1073742018, KP_POWER = 1073742019, KP_PERCENT = 1073742020, KP_LESS = 1073742021, KP_GREATER = 1073742022, KP_AMPERSAND = 1073742023, KP_DBLAMPERSAND = 1073742024, KP_VERTICALBAR = 1073742025, KP_DBLVERTICALBAR = 1073742026, KP_COLON = 1073742027, KP_HASH = 1073742028, KP_SPACE = 1073742029, KP_AT = 1073742030, KP_EXCLAM = 1073742031, KP_MEMSTORE = 1073742032, KP_MEMRECALL = 1073742033, KP_MEMCLEAR = 1073742034, KP_MEMADD = 1073742035, KP_MEMSUBTRACT = 1073742036, KP_MEMMULTIPLY = 1073742037, KP_MEMDIVIDE = 1073742038, KP_PLUSMINUS = 1073742039, KP_CLEAR = 1073742040, KP_CLEARENTRY = 1073742041, KP_BINARY = 1073742042, KP_OCTAL = 1073742043, KP_DECIMAL = 1073742044, KP_HEXADECIMAL = 1073742045, LCTRL = 1073742048, LSHIFT = 1073742049, LALT = 1073742050, LGUI = 1073742051, RCTRL = 1073742052, RSHIFT = 1073742053, RALT = 1073742054, RGUI = 1073742055, MODE = 1073742081, AUDIONEXT = 1073742082, AUDIOPREV = 1073742083, AUDIOSTOP = 1073742084, AUDIOPLAY = 1073742085, AUDIOMUTE = 1073742086, MEDIASELECT = 1073742087, WWW = 1073742088, MAIL = 1073742089, CALCULATOR = 1073742090, COMPUTER = 1073742091, AC_SEARCH = 1073742092, AC_HOME = 1073742093, AC_BACK = 1073742094, AC_FORWARD = 1073742095, AC_STOP = 1073742096, AC_REFRESH = 1073742097, AC_BOOKMARKS = 1073742098, BRIGHTNESSDOWN = 1073742099, BRIGHTNESSUP = 1073742100, DISPLAYSWITCH = 1073742101, KBDILLUMTOGGLE = 1073742102, KBDILLUMDOWN = 1073742103, KBDILLUMUP = 1073742104, EJECT = 1073742105, SLEEP = 1073742106, APP1 = 1073742107, APP2 = 1073742108, AUDIOREWIND = 1073742109, AUDIOFASTFORWARD = 1073742110, } load_proc_address :: proc(lib_path: string, library: dynlib.Library, symbol: string, $ProcType: typeid) -> ProcType where intrinsics.type_is_proc(ProcType) { if address, found := dynlib.symbol_address(library, symbol); found { return transmute(ProcType)address; } else { log.warn("Could not find symbol", symbol, "in library", lib_path); } return nil; } try_load_plugin :: proc(lib_path: string) -> (plugin: Interface, success: bool) { library, ok := dynlib.load_library(lib_path) if !ok { return {}, false; } interface := Interface { on_initialize = load_proc_address(lib_path, library, "OnInitialize", OnInitializeProc), on_exit = load_proc_address(lib_path, library, "OnExit", OnExitProc), on_draw = load_proc_address(lib_path, library, "OnDraw", OnDrawProc), }; if interface.on_initialize == nil do return interface, false; if interface.on_exit == nil do return interface, false; return interface, true }