From 3edd53a835f28f1234db943015761b958044b9c6 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Tue, 10 Jan 2023 05:50:26 +0800 Subject: [PATCH 001/176] Reorganize resources/ + wasm target (#1244) * add README.md to resources directory * add cross/ directory for meson cross files * fix readme list syntax error * fix reflink * disable ASYNCIFY_ADVISE by default * use executable names instead of hardcoding paths --- resources/README.md | 23 ++++++++++ .../macos_arm64.txt} | 3 ++ resources/cross/wasm.txt | 46 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 resources/README.md rename resources/{macos/macos_arm64.conf => cross/macos_arm64.txt} (78%) create mode 100644 resources/cross/wasm.txt diff --git a/resources/README.md b/resources/README.md new file mode 100644 index 00000000..975881c4 --- /dev/null +++ b/resources/README.md @@ -0,0 +1,23 @@ +# Resources + +This folder contains resources that is used for building or packaging the project. + +### Build + +- `cross/*.txt`: Meson [cross files][1] for cross-compiling lite-xl on other platforms. + +### Packaging + +- `icons/icon.{icns,ico,inl,rc,svg}`: lite-xl icon in various formats. +- `linux/org.lite_xl.lite_xl.appdata.xml`: AppStream metadata. +- `linux/org.lite_xl.lite_xl.desktop`: Desktop file for Linux desktops. +- `macos/appdmg.png`: Background image for packaging MacOS DMGs. +- `macos/Info.plist.in`: Template for generating `info.plist` on MacOS. See `macos/macos-retina-display.md` for details. +- `windows/001-lua-unicode.diff`: Patch for allowing Lua to load files with UTF-8 filenames on Windows. + +### Development + +- `lite_xl_plugin_api.h`: Native plugin API header. See the contents of `lite_xl_plugin_api.h` for more details. + + +[1]: https://mesonbuild.com/Cross-compilation.html \ No newline at end of file diff --git a/resources/macos/macos_arm64.conf b/resources/cross/macos_arm64.txt similarity index 78% rename from resources/macos/macos_arm64.conf rename to resources/cross/macos_arm64.txt index b1371b3b..3ccc6aa5 100644 --- a/resources/macos/macos_arm64.conf +++ b/resources/cross/macos_arm64.txt @@ -1,3 +1,6 @@ +# cross file for compiling on MacOS ARM (Apple Sillicon). +# use this file by running meson setup --cross-file resources/cross/macos_arm64.txt + [host_machine] system = 'darwin' cpu_family = 'aarch64' diff --git a/resources/cross/wasm.txt b/resources/cross/wasm.txt new file mode 100644 index 00000000..a6e87a06 --- /dev/null +++ b/resources/cross/wasm.txt @@ -0,0 +1,46 @@ +# cross file for WASM. +# use this file by running meson setup --cross-file resources/cross/wasm.txt + +[constants] + +# a list of functions that can run without being asyncified; proceed with caution +asyncify_ignores = '["SDL_BlitScaled","SDL_UpperBlitScaled","SDL_MapRGB*","SDL_FillRect","SDL_FreeSurface","SDL_CreateRGBSurface","SDL_GetWindowSurface","SDL_PollEvent","SDL_CreateSystemCursor","SDL_SetWindowTitle","SDL_SetCursor","SDL_GetWindowSize","SDL_GetWindowPosition","lua_push*","lua_rawget*","luaL_check*","pcre2*","FT_*","Bezier_*","g_*","FT_*","ft_*","TT_*","tt_*","__*","*printf","gray_*","fopen","fclose","fread","fflush","qsort","sift"]' + +# enable advising for optimizing the list above; disable this to prevent flooding logs +asyncify_advise = '0' + +# initial heap size in bytes; make sure it is not too low (around 64mb - 250mb) +initial_heap = '104857600' + + +[binaries] +c = 'emcc' +cpp = 'em++' +ar = 'emar' +strip = 'emstrip' +cmake = ['emmake', 'cmake'] +pkg-config = ['emconfigure', 'pkg-config'] +sdl2-config = ['emconfigure', 'sdl2-config'] + + +[properties] +needs_exe_wrapper = true + + +[built-in options] +c_args = [] +c_link_args = [] +cpp_args = [] +cpp_link_args = [] + + +[project options] +buildtype = 'release' +c_link_args = ['-s', 'ALLOW_MEMORY_GROWTH=1', '-s', 'INITIAL_MEMORY=' + initial_heap, '-s', 'ASYNCIFY=1', '-s', 'ASYNCIFY_ADVISE=' + asyncify_advise, '-s', 'ASYNCIFY_STACK_SIZE=6144', '-s', 'ASYNCIFY_REMOVE=' + asyncify_ignores, '-s', 'FORCE_FILESYSTEM=1'] + + +[host_machine] +system = 'emscripten' +cpu_family = 'wasm32' +cpu = 'wasm32' +endian = 'little' From c44a3cd291df660d86d268d31a4660b67d7f22a2 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 12 Jan 2023 00:25:06 +0100 Subject: [PATCH 002/176] replace uses of SDL_Window with RenWindow (#1319) Since Renwindow contains our instance of SDL_Window we can use this to simplify future logic to create separate window instances --- src/api/system.c | 46 +++++++++++++++++++++++----------------------- src/main.c | 2 +- src/renderer.c | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index 5e55acce..36d9c680 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -7,6 +7,7 @@ #include #include "api.h" #include "../rencache.h" +#include "../renwindow.h" #ifdef _WIN32 #include #include @@ -36,8 +37,7 @@ #endif #endif -extern SDL_Window *window; - +extern RenWindow window_renderer; static const char* button_name(int button) { switch (button) { @@ -76,7 +76,7 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p const int controls_width = hit_info->controls_width; int w, h; - SDL_GetWindowSize(window, &w, &h); + SDL_GetWindowSize(window_renderer.window, &w, &h); if (pt->y < hit_info->title_height && #if RESIZE_FROM_TOP @@ -326,7 +326,7 @@ top: return 3; case SDL_FINGERDOWN: - SDL_GetWindowSize(window, &w, &h); + SDL_GetWindowSize(window_renderer.window, &w, &h); lua_pushstring(L, "touchpressed"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -335,7 +335,7 @@ top: return 4; case SDL_FINGERUP: - SDL_GetWindowSize(window, &w, &h); + SDL_GetWindowSize(window_renderer.window, &w, &h); lua_pushstring(L, "touchreleased"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -351,7 +351,7 @@ top: e.tfinger.dx += event_plus.tfinger.dx; e.tfinger.dy += event_plus.tfinger.dy; } - SDL_GetWindowSize(window, &w, &h); + SDL_GetWindowSize(window_renderer.window, &w, &h); lua_pushstring(L, "touchmoved"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -415,7 +415,7 @@ static int f_set_cursor(lua_State *L) { static int f_set_window_title(lua_State *L) { const char *title = luaL_checkstring(L, 1); - SDL_SetWindowTitle(window, title); + SDL_SetWindowTitle(window_renderer.window, title); return 0; } @@ -425,39 +425,39 @@ enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN }; static int f_set_window_mode(lua_State *L) { int n = luaL_checkoption(L, 1, "normal", window_opts); - SDL_SetWindowFullscreen(window, + SDL_SetWindowFullscreen(window_renderer.window, n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - if (n == WIN_NORMAL) { SDL_RestoreWindow(window); } - if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); } - if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window); } + if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer.window); } + if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window_renderer.window); } + if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window_renderer.window); } return 0; } static int f_set_window_bordered(lua_State *L) { int bordered = lua_toboolean(L, 1); - SDL_SetWindowBordered(window, bordered); + SDL_SetWindowBordered(window_renderer.window, bordered); return 0; } static int f_set_window_hit_test(lua_State *L) { if (lua_gettop(L) == 0) { - SDL_SetWindowHitTest(window, NULL, NULL); + SDL_SetWindowHitTest(window_renderer.window, NULL, NULL); return 0; } window_hit_info->title_height = luaL_checknumber(L, 1); window_hit_info->controls_width = luaL_checknumber(L, 2); window_hit_info->resize_border = luaL_checknumber(L, 3); - SDL_SetWindowHitTest(window, hit_test, window_hit_info); + SDL_SetWindowHitTest(window_renderer.window, hit_test, window_hit_info); return 0; } static int f_get_window_size(lua_State *L) { int x, y, w, h; - SDL_GetWindowSize(window, &w, &h); - SDL_GetWindowPosition(window, &x, &y); + SDL_GetWindowSize(window_renderer.window, &w, &h); + SDL_GetWindowPosition(window_renderer.window, &x, &y); lua_pushinteger(L, w); lua_pushinteger(L, h); lua_pushinteger(L, x); @@ -471,22 +471,22 @@ static int f_set_window_size(lua_State *L) { double h = luaL_checknumber(L, 2); double x = luaL_checknumber(L, 3); double y = luaL_checknumber(L, 4); - SDL_SetWindowSize(window, w, h); - SDL_SetWindowPosition(window, x, y); + SDL_SetWindowSize(window_renderer.window, w, h); + SDL_SetWindowPosition(window_renderer.window, x, y); ren_resize_window(); return 0; } static int f_window_has_focus(lua_State *L) { - unsigned flags = SDL_GetWindowFlags(window); + unsigned flags = SDL_GetWindowFlags(window_renderer.window); lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS); return 1; } static int f_get_window_mode(lua_State *L) { - unsigned flags = SDL_GetWindowFlags(window); + unsigned flags = SDL_GetWindowFlags(window_renderer.window); if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { lua_pushstring(L, "fullscreen"); } else if (flags & SDL_WINDOW_MINIMIZED) { @@ -524,8 +524,8 @@ static int f_raise_window(lua_State *L) { to allow the window to be focused. Also on wayland the raise window event may not always be obeyed. */ - SDL_SetWindowInputFocus(window); - SDL_RaiseWindow(window); + SDL_SetWindowInputFocus(window_renderer.window); + SDL_RaiseWindow(window_renderer.window); return 0; } @@ -901,7 +901,7 @@ static int f_fuzzy_match(lua_State *L) { static int f_set_window_opacity(lua_State *L) { double n = luaL_checknumber(L, 1); - int r = SDL_SetWindowOpacity(window, n); + int r = SDL_SetWindowOpacity(window_renderer.window, n); lua_pushboolean(L, r > -1); return 1; } diff --git a/src/main.c b/src/main.c index 19b7d40f..3c08a643 100644 --- a/src/main.c +++ b/src/main.c @@ -18,7 +18,7 @@ #endif -SDL_Window *window; +static SDL_Window *window; static double get_scale(void) { #ifndef __APPLE__ diff --git a/src/renderer.c b/src/renderer.c index 4319f042..2932784a 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -20,7 +20,7 @@ #define MAX_LOADABLE_GLYPHSETS 1024 #define SUBPIXEL_BITMAPS_CACHED 3 -static RenWindow window_renderer = {0}; +RenWindow window_renderer = {0}; static FT_Library library; // draw_rect_surface is used as a 1x1 surface to simplify ren_draw_rect with blending From 8c4f093c419da8474d5e212232e2f12f495964ef Mon Sep 17 00:00:00 2001 From: adityaraj <75035219+pegvin@users.noreply.github.com> Date: Thu, 12 Jan 2023 05:23:23 +0530 Subject: [PATCH 003/176] Create Renderer Only When It Doesn't Exist (#1315) --- src/renwindow.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/renwindow.c b/src/renwindow.c index 9356ed21..85fd7a07 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -17,11 +17,12 @@ static int query_surface_scale(RenWindow *ren) { static void setup_renderer(RenWindow *ren, int w, int h) { /* Note that w and h here should always be in pixels and obtained from a call to SDL_GL_GetDrawableSize(). */ - if (ren->renderer) { - SDL_DestroyTexture(ren->texture); - SDL_DestroyRenderer(ren->renderer); + if (!ren->renderer) { + ren->renderer = SDL_CreateRenderer(ren->window, -1, 0); + } + if (ren->texture) { + SDL_DestroyTexture(ren->texture); } - ren->renderer = SDL_CreateRenderer(ren->window, -1, 0); ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); ren->surface_scale = query_surface_scale(ren); } From 75b6173dc99af7b8a7dc408e530c0039eb6c68ef Mon Sep 17 00:00:00 2001 From: Merlin Volkmer <49447733+Meerschwein@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:12:55 +0100 Subject: [PATCH 004/176] language_md: add nix code block highlighting (#1323) --- data/plugins/language_md.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data/plugins/language_md.lua b/data/plugins/language_md.lua index 1046657d..4b6cf0c2 100644 --- a/data/plugins/language_md.lua +++ b/data/plugins/language_md.lua @@ -147,6 +147,7 @@ syntax.add { { pattern = { "```go", "```" }, type = "string", syntax = ".go" }, { pattern = { "```lobster", "```" }, type = "string", syntax = ".lobster" }, { pattern = { "```liquid", "```" }, type = "string", syntax = ".liquid" }, + { pattern = { "```nix", "```" }, type = "string", syntax = ".nix" }, { pattern = { "```", "```" }, type = "string" }, { pattern = { "``", "``" }, type = "string" }, { pattern = { "%f[\\`]%`[%S]", "`" }, type = "string" }, From e4c5fceaf9ee45ae9dd9893b92f82e5d097a29ea Mon Sep 17 00:00:00 2001 From: xwii Date: Sat, 14 Jan 2023 01:33:13 +0700 Subject: [PATCH 005/176] Use `table.move` to implement `common.splice` (#1324) * Use `table.move` to implement `common.splice` * Disallow negative `remove` in `common.splice` --- data/core/common.lua | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index a4ea01f5..b6c9db67 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -82,25 +82,14 @@ end function common.splice(t, at, remove, insert) + assert(remove >= 0, "bad argument #3 to 'splice' (non-negative value expected)") insert = insert or {} - local offset = #insert - remove - local old_len = #t - if offset < 0 then - for i = at - offset, old_len - offset do - t[i + offset] = t[i] - end - elseif offset > 0 then - for i = old_len, at, -1 do - t[i + offset] = t[i] - end - end - for i, item in ipairs(insert) do - t[at + i - 1] = item - end + local len = #insert + if remove ~= len then table.move(t, at + remove, #t + remove, at + len) end + table.move(insert, 1, len, at, t) end - local function compare_score(a, b) return a.score > b.score end From b58ba3fede2452e6d95ac6670595d72cafefa7b2 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 13 Jan 2023 19:34:09 +0100 Subject: [PATCH 006/176] Make empty groups in `regex.gmatch` return their offset (#1325) This makes `regex.gmatch` behave like `string.gmatch`. --- src/api/regex.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/regex.c b/src/api/regex.c index f86e7ff6..bf17d424 100644 --- a/src/api/regex.c +++ b/src/api/regex.c @@ -91,7 +91,10 @@ static int regex_gmatch_iterator(lua_State *L) { int total_results = ovector_count * 2; size_t last_offset = 0; for (int i = index; i < total_results; i+=2) { - lua_pushlstring(L, state->subject+ovector[i], ovector[i+1] - ovector[i]); + if (ovector[i] == ovector[i+1]) + lua_pushinteger(L, ovector[i] + 1); + else + lua_pushlstring(L, state->subject+ovector[i], ovector[i+1] - ovector[i]); last_offset = ovector[i+1]; total++; } From bdd87298d686d80c1ebf70da75f773fdb87f97a9 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Fri, 13 Jan 2023 16:31:28 -0500 Subject: [PATCH 007/176] Updated dummy method signature to match prototypes. --- src/api/dirmonitor/dummy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/dirmonitor/dummy.c b/src/api/dirmonitor/dummy.c index 47aa0990..0690f61d 100644 --- a/src/api/dirmonitor/dummy.c +++ b/src/api/dirmonitor/dummy.c @@ -2,7 +2,7 @@ struct dirmonitor_internal* init_dirmonitor() { return NULL; } void deinit_dirmonitor(struct dirmonitor_internal* monitor) { } -int get_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, size_t len) { return -1; } +int get_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int len) { return -1; } int translate_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buffer, int size, int (*callback)(int, const char*, void*), void* data) { return -1; } int add_dirmonitor(struct dirmonitor_internal* monitor, const char* path) { return -1; } void remove_dirmonitor(struct dirmonitor_internal* monitor, int fd) { } From 64065b98cac3285a64a02502674a6824081d7757 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 19 Jan 2023 02:43:48 +0100 Subject: [PATCH 008/176] remove static libgcc from meson (#1290) --- meson.build | 4 ---- 1 file changed, 4 deletions(-) diff --git a/meson.build b/meson.build index e5fc1fbe..7bbecc68 100644 --- a/meson.build +++ b/meson.build @@ -63,10 +63,6 @@ lite_cargs += '-DLITE_ARCH_TUPLE="@0@"'.format(arch_tuple) # Linker Settings #=============================================================================== lite_link_args = [] -if cc.get_id() == 'gcc' and get_option('buildtype') == 'release' - lite_link_args += ['-static-libgcc'] -endif - if host_machine.system() == 'darwin' lite_link_args += ['-framework', 'CoreServices', '-framework', 'Foundation'] endif From 12bae1ec955316f17e1582209241d94094bc0f84 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 19 Jan 2023 04:15:26 +0100 Subject: [PATCH 009/176] Avoid drawing hidden text in `DocView:draw_line_text` (#1298) * Stop drawing text past the `DocView` edge in `DocView:draw_line_text` * Don't add draw commands if they fall outside the latest clip The check was previously done with the window rect, so this will reduce a bit more the number of commands sent. --- data/core/docview.lua | 1 + src/rencache.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/data/core/docview.lua b/data/core/docview.lua index 6b7913c8..bf222738 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -422,6 +422,7 @@ function DocView:draw_line_text(line, x, y) -- do not render newline, fixes issue #1164 if tidx == last_token then text = text:sub(1, -2) end tx = renderer.draw_text(font, text, tx, ty, color) + if tx > self.position.x + self.size.x then break end end return self:get_line_height() end diff --git a/src/rencache.c b/src/rencache.c index 12c2a33c..f0243f0b 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -54,6 +54,7 @@ uint8_t *command_buf = NULL; static bool resize_issue; static int command_buf_idx; static RenRect screen_rect; +static RenRect last_clip_rect; static bool show_debug; static inline int rencache_min(int a, int b) { return a < b ? a : b; } @@ -156,12 +157,15 @@ void rencache_show_debug(bool enable) { void rencache_set_clip_rect(RenRect rect) { Command *cmd = push_command(SET_CLIP, COMMAND_BARE_SIZE); - if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); } + if (cmd) { + cmd->rect = intersect_rects(rect, screen_rect); + last_clip_rect = cmd->rect; + } } void rencache_draw_rect(RenRect rect, RenColor color) { - if (!rects_overlap(screen_rect, rect) || rect.width == 0 || rect.height == 0) { + if (rect.width == 0 || rect.height == 0 || !rects_overlap(last_clip_rect, rect)) { return; } Command *cmd = push_command(DRAW_RECT, COMMAND_BARE_SIZE); @@ -175,7 +179,7 @@ float rencache_draw_text(RenFont **fonts, const char *text, size_t len, float x, { float width = ren_font_group_get_width(fonts, text, len); RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; - if (rects_overlap(screen_rect, rect)) { + if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; Command *cmd = push_command(DRAW_TEXT, COMMAND_BARE_SIZE + sz); if (cmd) { @@ -207,6 +211,7 @@ void rencache_begin_frame() { screen_rect.height = h; rencache_invalidate(); } + last_clip_rect = screen_rect; } From 4682092b8d76b4e824817880799b65e4e057ba1a Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 19 Jan 2023 10:14:45 -0500 Subject: [PATCH 010/176] Added in Config Postload (#1336) * Added in an `onload` variable to configs which is called by the plugin loader. * Used appropriate parameter. * Fixed tabbing. --- data/core/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/core/init.lua b/data/core/init.lua index 89ac7ec4..d8f77b19 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1010,7 +1010,7 @@ function core.load_plugins() table.insert(list, plugin.file) elseif config.plugins[plugin.name] ~= false then local start = system.get_time() - local ok = core.try(require, "plugins." .. plugin.name) + local ok, loaded_plugin = core.try(require, "plugins." .. plugin.name) if ok then core.log_quiet( "Loaded plugin %q from %s in %.1fms", @@ -1021,6 +1021,8 @@ function core.load_plugins() end if not ok then no_errors = false + elseif config.plugins[plugin.name].onload then + core.try(config.plugins[plugin.name].onload, loaded_plugin) end end end From 9dcdf1f7c91531f0fa835542d276fc79ac8daa6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Thu, 19 Jan 2023 20:27:23 -0400 Subject: [PATCH 011/176] plugin api: allow usage on multiple source files (#1335) As discussed with Adam on discord current Lite XL Lua Plugin API was not working on native plugins with more than 1 source file since imported symbols were not exposed to other unit files. The issue was tackled on #1332 but the solution introduced another issue when Lite XL was dynamically linked to the system lua. So we opted to tackle this by using function wrappers around the function pointers. --- resources/lite_xl_plugin_api.h | 1179 ++++++++++++++++++++------------ 1 file changed, 758 insertions(+), 421 deletions(-) diff --git a/resources/lite_xl_plugin_api.h b/resources/lite_xl_plugin_api.h index 5337d8ae..257791ce 100644 --- a/resources/lite_xl_plugin_api.h +++ b/resources/lite_xl_plugin_api.h @@ -3,12 +3,18 @@ /** The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long as it has an entrypoint that looks like the following, where xxxxx is the plugin name: + +#define LITE_XL_PLUGIN_ENTRYPOINT #include "lite_xl_plugin_api.h" int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) { lite_xl_plugin_init(XL); ... return 1; } + +NOTE: `#define LITE_XL_PLUGIN_ENTRYPOINT` needs to be defined only on the +source file where the lite_xl_plugin_init() initialization function is called. + In linux, to compile this file, you'd do: 'gcc -o xxxxx.so -shared xxxxx.c'. Simple! Due to the way the API is structured, you *should not* link or include lua libraries. This file was automatically generated. DO NOT MODIFY DIRECTLY. @@ -23,6 +29,28 @@ Go figure. #include #include // for BUFSIZ? this is kinda weird +#define SYMBOL_WRAP_DECL(ret, name, ...) \ + ret name(__VA_ARGS__) + +#define SYMBOL_WRAP_CALL(name, ...) \ + return __##name(__VA_ARGS__) + +#define SYMBOL_WRAP_CALL_FB(name, ...) \ + return __lite_xl_fallback_##name(__VA_ARGS__) + +#ifdef LITE_XL_PLUGIN_ENTRYPOINT + #define SYMBOL_DECLARE(ret, name, ...) \ + static ret (*__##name) (__VA_ARGS__); \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); \ + static ret __lite_xl_fallback_##name(__VA_ARGS__) { \ + fputs("warning: " #name " is a stub", stderr); \ + exit(1); \ + } +#else + #define SYMBOL_DECLARE(ret, name, ...) \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); +#endif + /** luaconf.h **/ #ifndef lconfig_h @@ -227,101 +255,103 @@ struct lua_Debug { char short_src[LUA_IDSIZE]; struct CallInfo *i_ci; }; -static lua_State *(*lua_newstate) (lua_Alloc f, void *ud); -static void (*lua_close) (lua_State *L); -static lua_State *(*lua_newthread) (lua_State *L); -static lua_CFunction (*lua_atpanic) (lua_State *L, lua_CFunction panicf); -static const lua_Number *(*lua_version) (lua_State *L); -static int (*lua_absindex) (lua_State *L, int idx); -static int (*lua_gettop) (lua_State *L); -static void (*lua_settop) (lua_State *L, int idx); -static void (*lua_pushvalue) (lua_State *L, int idx); -static void (*lua_copy) (lua_State *L, int fromidx, int toidx); -static int (*lua_checkstack) (lua_State *L, int sz); -static void (*lua_xmove) (lua_State *from, lua_State *to, int n); -static int (*lua_isnumber) (lua_State *L, int idx); -static int (*lua_isstring) (lua_State *L, int idx); -static int (*lua_iscfunction) (lua_State *L, int idx); -static int (*lua_isuserdata) (lua_State *L, int idx); -static int (*lua_type) (lua_State *L, int idx); -static const char *(*lua_typename) (lua_State *L, int tp); -static lua_Number (*lua_tonumberx) (lua_State *L, int idx, int *isnum); -static lua_Integer (*lua_tointegerx) (lua_State *L, int idx, int *isnum); -static lua_Unsigned (*lua_tounsignedx) (lua_State *L, int idx, int *isnum); -static int (*lua_toboolean) (lua_State *L, int idx); -static const char *(*lua_tolstring) (lua_State *L, int idx, size_t *len); -static size_t (*lua_rawlen) (lua_State *L, int idx); -static lua_CFunction (*lua_tocfunction) (lua_State *L, int idx); -static void *(*lua_touserdata) (lua_State *L, int idx); -static lua_State *(*lua_tothread) (lua_State *L, int idx); -static const void *(*lua_topointer) (lua_State *L, int idx); -static void (*lua_arith) (lua_State *L, int op); -static int (*lua_rawequal) (lua_State *L, int idx1, int idx2); -static int (*lua_compare) (lua_State *L, int idx1, int idx2, int op); -static void (*lua_pushnil) (lua_State *L); -static void (*lua_pushnumber) (lua_State *L, lua_Number n); -static void (*lua_pushinteger) (lua_State *L, lua_Integer n); -static void (*lua_pushunsigned) (lua_State *L, lua_Unsigned n); -static const char *(*lua_pushlstring) (lua_State *L, const char *s, size_t l); -static const char *(*lua_pushstring) (lua_State *L, const char *s); -static const char *(*lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); -static const char *(*lua_pushfstring) (lua_State *L, const char *fmt, ...); -static void (*lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -static void (*lua_pushboolean) (lua_State *L, int b); -static void (*lua_pushlightuserdata) (lua_State *L, void *p); -static int (*lua_pushthread) (lua_State *L); -static void (*lua_getglobal) (lua_State *L, const char *var); -static void (*lua_gettable) (lua_State *L, int idx); -static void (*lua_getfield) (lua_State *L, int idx, const char *k); -static void (*lua_rawget) (lua_State *L, int idx); -static void (*lua_rawgeti) (lua_State *L, int idx, int n); -static void (*lua_rawgetp) (lua_State *L, int idx, const void *p); -static void (*lua_createtable) (lua_State *L, int narr, int nrec); -static void *(*lua_newuserdata) (lua_State *L, size_t sz); -static void *(*lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); -static int (*lua_getmetatable) (lua_State *L, int objindex); -static void (*lua_getuservalue) (lua_State *L, int idx); -static void (*lua_getiuservalue) (lua_State *L, int idx, int n); -static void (*lua_setglobal) (lua_State *L, const char *var); -static void (*lua_settable) (lua_State *L, int idx); -static void (*lua_setfield) (lua_State *L, int idx, const char *k); -static void (*lua_rawset) (lua_State *L, int idx); -static void (*lua_rawseti) (lua_State *L, int idx, int n); -static void (*lua_rawsetp) (lua_State *L, int idx, const void *p); -static int (*lua_setmetatable) (lua_State *L, int objindex); -static void (*lua_setuservalue) (lua_State *L, int idx); -static void (*lua_setiuservalue) (lua_State *L, int idx, int n); -static void (*lua_callk) (lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); -static int (*lua_getctx) (lua_State *L, int *ctx); -static int (*lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); -static int (*lua_load) (lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); -static int (*lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); -static int (*lua_yieldk) (lua_State *L, int nresults, int ctx, lua_CFunction k); -static int (*lua_resume) (lua_State *L, lua_State *from, int narg); -static int (*lua_status) (lua_State *L); -static int (*lua_gc) (lua_State *L, int what, int data); -static int (*lua_error) (lua_State *L); -static int (*lua_next) (lua_State *L, int idx); -static void (*lua_concat) (lua_State *L, int n); -static void (*lua_len) (lua_State *L, int idx); -static lua_Alloc (*lua_getallocf) (lua_State *L, void **ud); -static void (*lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); -static int (*lua_getstack) (lua_State *L, int level, lua_Debug *ar); -static int (*lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -static const char *(*lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -static const char *(*lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -static const char *(*lua_getupvalue) (lua_State *L, int funcindex, int n); -static const char *(*lua_setupvalue) (lua_State *L, int funcindex, int n); -static void *(*lua_upvalueid) (lua_State *L, int fidx, int n); -static void (*lua_upvaluejoin) (lua_State *L, int fidx1, int n1, int fidx2, int n2); -static int (*lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -static lua_Hook (*lua_gethook) (lua_State *L); -static int (*lua_gethookmask) (lua_State *L); -static int (*lua_gethookcount) (lua_State *L); + +SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) +SYMBOL_DECLARE(void, lua_close, lua_State *L) +SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) +SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) +SYMBOL_DECLARE(const lua_Number *, lua_version, lua_State *L) +SYMBOL_DECLARE(int, lua_absindex, lua_State *L, int idx) +SYMBOL_DECLARE(int, lua_gettop, lua_State *L) +SYMBOL_DECLARE(void, lua_settop, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_pushvalue, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_copy, lua_State *L, int fromidx, int toidx) +SYMBOL_DECLARE(int, lua_checkstack, lua_State *L, int sz) +SYMBOL_DECLARE(void, lua_xmove, lua_State *from, lua_State *to, int n) +SYMBOL_DECLARE(int, lua_isnumber, lua_State *L, int idx) +SYMBOL_DECLARE(int, lua_isstring, lua_State *L, int idx) +SYMBOL_DECLARE(int, lua_iscfunction, lua_State *L, int idx) +SYMBOL_DECLARE(int, lua_isuserdata, lua_State *L, int idx) +SYMBOL_DECLARE(int, lua_type, lua_State *L, int idx) +SYMBOL_DECLARE(const char *, lua_typename, lua_State *L, int tp) +SYMBOL_DECLARE(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum) +SYMBOL_DECLARE(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum) +SYMBOL_DECLARE(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum) +SYMBOL_DECLARE(int, lua_toboolean, lua_State *L, int idx) +SYMBOL_DECLARE(const char *, lua_tolstring, lua_State *L, int idx, size_t *len) +SYMBOL_DECLARE(size_t, lua_rawlen, lua_State *L, int idx) +SYMBOL_DECLARE(lua_CFunction, lua_tocfunction, lua_State *L, int idx) +SYMBOL_DECLARE(void *, lua_touserdata, lua_State *L, int idx) +SYMBOL_DECLARE(lua_State *, lua_tothread, lua_State *L, int idx) +SYMBOL_DECLARE(const void *, lua_topointer, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_arith, lua_State *L, int op) +SYMBOL_DECLARE(int, lua_rawequal, lua_State *L, int idx1, int idx2) +SYMBOL_DECLARE(int, lua_compare, lua_State *L, int idx1, int idx2, int op) +SYMBOL_DECLARE(void, lua_pushnil, lua_State *L) +SYMBOL_DECLARE(void, lua_pushnumber, lua_State *L, lua_Number n) +SYMBOL_DECLARE(void, lua_pushinteger, lua_State *L, lua_Integer n) +SYMBOL_DECLARE(void, lua_pushunsigned, lua_State *L, lua_Unsigned n) +SYMBOL_DECLARE(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l) +SYMBOL_DECLARE(const char *, lua_pushstring, lua_State *L, const char *s) +SYMBOL_DECLARE(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp) +SYMBOL_DECLARE(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...) +SYMBOL_DECLARE(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n) +SYMBOL_DECLARE(void, lua_pushboolean, lua_State *L, int b) +SYMBOL_DECLARE(void, lua_pushlightuserdata, lua_State *L, void *p) +SYMBOL_DECLARE(int, lua_pushthread, lua_State *L) +SYMBOL_DECLARE(void, lua_getglobal, lua_State *L, const char *var) +SYMBOL_DECLARE(void, lua_gettable, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_getfield, lua_State *L, int idx, const char *k) +SYMBOL_DECLARE(void, lua_rawget, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_rawgeti, lua_State *L, int idx, int n) +SYMBOL_DECLARE(void, lua_rawgetp, lua_State *L, int idx, const void *p) +SYMBOL_DECLARE(void, lua_createtable, lua_State *L, int narr, int nrec) +SYMBOL_DECLARE(void *, lua_newuserdata, lua_State *L, size_t sz) +SYMBOL_DECLARE(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue) +SYMBOL_DECLARE(int, lua_getmetatable, lua_State *L, int objindex) +SYMBOL_DECLARE(void, lua_getuservalue, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_getiuservalue, lua_State *L, int idx, int n) +SYMBOL_DECLARE(void, lua_setglobal, lua_State *L, const char *var) +SYMBOL_DECLARE(void, lua_settable, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_setfield, lua_State *L, int idx, const char *k) +SYMBOL_DECLARE(void, lua_rawset, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_rawseti, lua_State *L, int idx, int n) +SYMBOL_DECLARE(void, lua_rawsetp, lua_State *L, int idx, const void *p) +SYMBOL_DECLARE(int, lua_setmetatable, lua_State *L, int objindex) +SYMBOL_DECLARE(void, lua_setuservalue, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_setiuservalue, lua_State *L, int idx, int n) +SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) +SYMBOL_DECLARE(int, lua_getctx, lua_State *L, int *ctx) +SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k) +SYMBOL_DECLARE(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) +SYMBOL_DECLARE(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) +SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k) +SYMBOL_DECLARE(int, lua_resume, lua_State *L, lua_State *from, int narg) +SYMBOL_DECLARE(int, lua_status, lua_State *L) +SYMBOL_DECLARE(int, lua_gc, lua_State *L, int what, int data) +SYMBOL_DECLARE(int, lua_error, lua_State *L) +SYMBOL_DECLARE(int, lua_next, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_concat, lua_State *L, int n) +SYMBOL_DECLARE(void, lua_len, lua_State *L, int idx) +SYMBOL_DECLARE(lua_Alloc, lua_getallocf, lua_State *L, void **ud) +SYMBOL_DECLARE(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud) +SYMBOL_DECLARE(int, lua_getstack, lua_State *L, int level, lua_Debug *ar) +SYMBOL_DECLARE(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar) +SYMBOL_DECLARE(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n) +SYMBOL_DECLARE(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n) +SYMBOL_DECLARE(const char *, lua_getupvalue, lua_State *L, int funcindex, int n) +SYMBOL_DECLARE(const char *, lua_setupvalue, lua_State *L, int funcindex, int n) +SYMBOL_DECLARE(void *, lua_upvalueid, lua_State *L, int fidx, int n) +SYMBOL_DECLARE(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2) +SYMBOL_DECLARE(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count) +SYMBOL_DECLARE(lua_Hook, lua_gethook, lua_State *L) +SYMBOL_DECLARE(int, lua_gethookmask, lua_State *L) +SYMBOL_DECLARE(int, lua_gethookcount, lua_State *L) + #define lua_h #define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "2" -#define LUA_VERSION_NUM 502 +#define LUA_VERSION_MINOR "4" +#define LUA_VERSION_NUM 504 #define LUA_VERSION_RELEASE "4" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE @@ -408,98 +438,6 @@ static int (*lua_gethookcount) (lua_State *L); #define LUA_MASKRET (1 << LUA_HOOKRET) #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -static lua_State * __lite_xl_fallback_lua_newstate (lua_Alloc f, void *ud) { fputs("warning: lua_newstate is a stub", stderr); } -static void __lite_xl_fallback_lua_close (lua_State *L) { fputs("warning: lua_close is a stub", stderr); } -static lua_State * __lite_xl_fallback_lua_newthread (lua_State *L) { fputs("warning: lua_newthread is a stub", stderr); } -static lua_CFunction __lite_xl_fallback_lua_atpanic (lua_State *L, lua_CFunction panicf) { fputs("warning: lua_atpanic is a stub", stderr); } -static const lua_Number * __lite_xl_fallback_lua_version (lua_State *L) { fputs("warning: lua_version is a stub", stderr); } -static int __lite_xl_fallback_lua_absindex (lua_State *L, int idx) { fputs("warning: lua_absindex is a stub", stderr); } -static int __lite_xl_fallback_lua_gettop (lua_State *L) { fputs("warning: lua_gettop is a stub", stderr); } -static void __lite_xl_fallback_lua_settop (lua_State *L, int idx) { fputs("warning: lua_settop is a stub", stderr); } -static void __lite_xl_fallback_lua_pushvalue (lua_State *L, int idx) { fputs("warning: lua_pushvalue is a stub", stderr); } -static void __lite_xl_fallback_lua_copy (lua_State *L, int fromidx, int toidx) { fputs("warning: lua_copy is a stub", stderr); } -static int __lite_xl_fallback_lua_checkstack (lua_State *L, int sz) { fputs("warning: lua_checkstack is a stub", stderr); } -static void __lite_xl_fallback_lua_xmove (lua_State *from, lua_State *to, int n) { fputs("warning: lua_xmove is a stub", stderr); } -static int __lite_xl_fallback_lua_isnumber (lua_State *L, int idx) { fputs("warning: lua_isnumber is a stub", stderr); } -static int __lite_xl_fallback_lua_isstring (lua_State *L, int idx) { fputs("warning: lua_isstring is a stub", stderr); } -static int __lite_xl_fallback_lua_iscfunction (lua_State *L, int idx) { fputs("warning: lua_iscfunction is a stub", stderr); } -static int __lite_xl_fallback_lua_isuserdata (lua_State *L, int idx) { fputs("warning: lua_isuserdata is a stub", stderr); } -static int __lite_xl_fallback_lua_type (lua_State *L, int idx) { fputs("warning: lua_type is a stub", stderr); } -static const char * __lite_xl_fallback_lua_typename (lua_State *L, int tp) { fputs("warning: lua_typename is a stub", stderr); } -static lua_Number __lite_xl_fallback_lua_tonumberx (lua_State *L, int idx, int *isnum) { fputs("warning: lua_tonumberx is a stub", stderr); } -static lua_Integer __lite_xl_fallback_lua_tointegerx (lua_State *L, int idx, int *isnum) { fputs("warning: lua_tointegerx is a stub", stderr); } -static lua_Unsigned __lite_xl_fallback_lua_tounsignedx (lua_State *L, int idx, int *isnum) { fputs("warning: lua_tounsignedx is a stub", stderr); } -static int __lite_xl_fallback_lua_toboolean (lua_State *L, int idx) { fputs("warning: lua_toboolean is a stub", stderr); } -static const char * __lite_xl_fallback_lua_tolstring (lua_State *L, int idx, size_t *len) { fputs("warning: lua_tolstring is a stub", stderr); } -static size_t __lite_xl_fallback_lua_rawlen (lua_State *L, int idx) { fputs("warning: lua_rawlen is a stub", stderr); } -static lua_CFunction __lite_xl_fallback_lua_tocfunction (lua_State *L, int idx) { fputs("warning: lua_tocfunction is a stub", stderr); } -static void * __lite_xl_fallback_lua_touserdata (lua_State *L, int idx) { fputs("warning: lua_touserdata is a stub", stderr); } -static lua_State * __lite_xl_fallback_lua_tothread (lua_State *L, int idx) { fputs("warning: lua_tothread is a stub", stderr); } -static const void * __lite_xl_fallback_lua_topointer (lua_State *L, int idx) { fputs("warning: lua_topointer is a stub", stderr); } -static void __lite_xl_fallback_lua_arith (lua_State *L, int op) { fputs("warning: lua_arith is a stub", stderr); } -static int __lite_xl_fallback_lua_rawequal (lua_State *L, int idx1, int idx2) { fputs("warning: lua_rawequal is a stub", stderr); } -static int __lite_xl_fallback_lua_compare (lua_State *L, int idx1, int idx2, int op) { fputs("warning: lua_compare is a stub", stderr); } -static void __lite_xl_fallback_lua_pushnil (lua_State *L) { fputs("warning: lua_pushnil is a stub", stderr); } -static void __lite_xl_fallback_lua_pushnumber (lua_State *L, lua_Number n) { fputs("warning: lua_pushnumber is a stub", stderr); } -static void __lite_xl_fallback_lua_pushinteger (lua_State *L, lua_Integer n) { fputs("warning: lua_pushinteger is a stub", stderr); } -static void __lite_xl_fallback_lua_pushunsigned (lua_State *L, lua_Unsigned n) { fputs("warning: lua_pushunsigned is a stub", stderr); } -static const char * __lite_xl_fallback_lua_pushlstring (lua_State *L, const char *s, size_t l) { fputs("warning: lua_pushlstring is a stub", stderr); } -static const char * __lite_xl_fallback_lua_pushstring (lua_State *L, const char *s) { fputs("warning: lua_pushstring is a stub", stderr); } -static const char * __lite_xl_fallback_lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { fputs("warning: lua_pushvfstring is a stub", stderr); } -static const char * __lite_xl_fallback_lua_pushfstring (lua_State *L, const char *fmt, ...) { fputs("warning: lua_pushfstring is a stub", stderr); } -static void __lite_xl_fallback_lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { fputs("warning: lua_pushcclosure is a stub", stderr); } -static void __lite_xl_fallback_lua_pushboolean (lua_State *L, int b) { fputs("warning: lua_pushboolean is a stub", stderr); } -static void __lite_xl_fallback_lua_pushlightuserdata (lua_State *L, void *p) { fputs("warning: lua_pushlightuserdata is a stub", stderr); } -static int __lite_xl_fallback_lua_pushthread (lua_State *L) { fputs("warning: lua_pushthread is a stub", stderr); } -static void __lite_xl_fallback_lua_getglobal (lua_State *L, const char *var) { fputs("warning: lua_getglobal is a stub", stderr); } -static void __lite_xl_fallback_lua_gettable (lua_State *L, int idx) { fputs("warning: lua_gettable is a stub", stderr); } -static void __lite_xl_fallback_lua_getfield (lua_State *L, int idx, const char *k) { fputs("warning: lua_getfield is a stub", stderr); } -static void __lite_xl_fallback_lua_rawget (lua_State *L, int idx) { fputs("warning: lua_rawget is a stub", stderr); } -static void __lite_xl_fallback_lua_rawgeti (lua_State *L, int idx, int n) { fputs("warning: lua_rawgeti is a stub", stderr); } -static void __lite_xl_fallback_lua_rawgetp (lua_State *L, int idx, const void *p) { fputs("warning: lua_rawgetp is a stub", stderr); } -static void __lite_xl_fallback_lua_createtable (lua_State *L, int narr, int nrec) { fputs("warning: lua_createtable is a stub", stderr); } -static void * __lite_xl_fallback_lua_newuserdata (lua_State *L, size_t sz) { fputs("warning: lua_newuserdata is a stub", stderr); } -static void * __lite_xl_fallback_lua_newuserdatauv (lua_State *L, size_t sz, int nuvalue) { fputs("warning: lua_newuserdatauv is a stub", stderr); } -static int __lite_xl_fallback_lua_getmetatable (lua_State *L, int objindex) { fputs("warning: lua_getmetatable is a stub", stderr); } -static void __lite_xl_fallback_lua_getuservalue (lua_State *L, int idx) { fputs("warning: lua_getuservalue is a stub", stderr); } -static void __lite_xl_fallback_lua_getiuservalue (lua_State *L, int idx, int n) { fputs("warning: lua_getiuservalue is a stub", stderr); } -static void __lite_xl_fallback_lua_setglobal (lua_State *L, const char *var) { fputs("warning: lua_setglobal is a stub", stderr); } -static void __lite_xl_fallback_lua_settable (lua_State *L, int idx) { fputs("warning: lua_settable is a stub", stderr); } -static void __lite_xl_fallback_lua_setfield (lua_State *L, int idx, const char *k) { fputs("warning: lua_setfield is a stub", stderr); } -static void __lite_xl_fallback_lua_rawset (lua_State *L, int idx) { fputs("warning: lua_rawset is a stub", stderr); } -static void __lite_xl_fallback_lua_rawseti (lua_State *L, int idx, int n) { fputs("warning: lua_rawseti is a stub", stderr); } -static void __lite_xl_fallback_lua_rawsetp (lua_State *L, int idx, const void *p) { fputs("warning: lua_rawsetp is a stub", stderr); } -static int __lite_xl_fallback_lua_setmetatable (lua_State *L, int objindex) { fputs("warning: lua_setmetatable is a stub", stderr); } -static void __lite_xl_fallback_lua_setuservalue (lua_State *L, int idx) { fputs("warning: lua_setuservalue is a stub", stderr); } -static void __lite_xl_fallback_lua_setiuservalue (lua_State *L, int idx, int n) { fputs("warning: lua_setiuservalue is a stub", stderr); } -static void __lite_xl_fallback_lua_callk (lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) { fputs("warning: lua_callk is a stub", stderr); } -static int __lite_xl_fallback_lua_getctx (lua_State *L, int *ctx) { fputs("warning: lua_getctx is a stub", stderr); } -static int __lite_xl_fallback_lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k) { fputs("warning: lua_pcallk is a stub", stderr); } -static int __lite_xl_fallback_lua_load (lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) { fputs("warning: lua_load is a stub", stderr); } -static int __lite_xl_fallback_lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { fputs("warning: lua_dump is a stub", stderr); } -static int __lite_xl_fallback_lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { fputs("warning: lua_yieldk is a stub", stderr); } -static int __lite_xl_fallback_lua_resume (lua_State *L, lua_State *from, int narg) { fputs("warning: lua_resume is a stub", stderr); } -static int __lite_xl_fallback_lua_status (lua_State *L) { fputs("warning: lua_status is a stub", stderr); } -static int __lite_xl_fallback_lua_gc (lua_State *L, int what, int data) { fputs("warning: lua_gc is a stub", stderr); } -static int __lite_xl_fallback_lua_error (lua_State *L) { fputs("warning: lua_error is a stub", stderr); } -static int __lite_xl_fallback_lua_next (lua_State *L, int idx) { fputs("warning: lua_next is a stub", stderr); } -static void __lite_xl_fallback_lua_concat (lua_State *L, int n) { fputs("warning: lua_concat is a stub", stderr); } -static void __lite_xl_fallback_lua_len (lua_State *L, int idx) { fputs("warning: lua_len is a stub", stderr); } -static lua_Alloc __lite_xl_fallback_lua_getallocf (lua_State *L, void **ud) { fputs("warning: lua_getallocf is a stub", stderr); } -static void __lite_xl_fallback_lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { fputs("warning: lua_setallocf is a stub", stderr); } -static int __lite_xl_fallback_lua_getstack (lua_State *L, int level, lua_Debug *ar) { fputs("warning: lua_getstack is a stub", stderr); } -static int __lite_xl_fallback_lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { fputs("warning: lua_getinfo is a stub", stderr); } -static const char * __lite_xl_fallback_lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { fputs("warning: lua_getlocal is a stub", stderr); } -static const char * __lite_xl_fallback_lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { fputs("warning: lua_setlocal is a stub", stderr); } -static const char * __lite_xl_fallback_lua_getupvalue (lua_State *L, int funcindex, int n) { fputs("warning: lua_getupvalue is a stub", stderr); } -static const char * __lite_xl_fallback_lua_setupvalue (lua_State *L, int funcindex, int n) { fputs("warning: lua_setupvalue is a stub", stderr); } -static void * __lite_xl_fallback_lua_upvalueid (lua_State *L, int fidx, int n) { fputs("warning: lua_upvalueid is a stub", stderr); } -static void __lite_xl_fallback_lua_upvaluejoin (lua_State *L, int fidx1, int n1, int fidx2, int n2) { fputs("warning: lua_upvaluejoin is a stub", stderr); } -static int __lite_xl_fallback_lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { fputs("warning: lua_sethook is a stub", stderr); } -static lua_Hook __lite_xl_fallback_lua_gethook (lua_State *L) { fputs("warning: lua_gethook is a stub", stderr); } -static int __lite_xl_fallback_lua_gethookmask (lua_State *L) { fputs("warning: lua_gethookmask is a stub", stderr); } -static int __lite_xl_fallback_lua_gethookcount (lua_State *L) { fputs("warning: lua_gethookcount is a stub", stderr); } - /** lauxlib.h **/ @@ -518,53 +456,54 @@ typedef struct luaL_Stream { FILE *f; lua_CFunction closef; } luaL_Stream; -static void (*luaL_checkversion_) (lua_State *L, lua_Number ver); -static int (*luaL_getmetafield) (lua_State *L, int obj, const char *e); -static int (*luaL_callmeta) (lua_State *L, int obj, const char *e); -static const char *(*luaL_tolstring) (lua_State *L, int idx, size_t *len); -static int (*luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -static const char *(*luaL_checklstring) (lua_State *L, int numArg, size_t *l); -static const char *(*luaL_optlstring) (lua_State *L, int numArg, const char *def, size_t *l); -static lua_Number (*luaL_checknumber) (lua_State *L, int numArg); -static lua_Number (*luaL_optnumber) (lua_State *L, int nArg, lua_Number def); -static lua_Integer (*luaL_checkinteger) (lua_State *L, int numArg); -static lua_Integer (*luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); -static lua_Unsigned (*luaL_checkunsigned) (lua_State *L, int numArg); -static lua_Unsigned (*luaL_optunsigned) (lua_State *L, int numArg, lua_Unsigned def); -static void (*luaL_checkstack) (lua_State *L, int sz, const char *msg); -static void (*luaL_checktype) (lua_State *L, int narg, int t); -static void (*luaL_checkany) (lua_State *L, int narg); -static int (*luaL_newmetatable) (lua_State *L, const char *tname); -static void (*luaL_setmetatable) (lua_State *L, const char *tname); -static void *(*luaL_testudata) (lua_State *L, int ud, const char *tname); -static void *(*luaL_checkudata) (lua_State *L, int ud, const char *tname); -static void (*luaL_where) (lua_State *L, int lvl); -static int (*luaL_error) (lua_State *L, const char *fmt, ...); -static int (*luaL_typeerror) (lua_State *L, int narg, const char *tname); -static int (*luaL_checkoption) (lua_State *L, int narg, const char *def, const char *const lst[]); -static int (*luaL_fileresult) (lua_State *L, int stat, const char *fname); -static int (*luaL_execresult) (lua_State *L, int stat); -static int (*luaL_ref) (lua_State *L, int t); -static void (*luaL_unref) (lua_State *L, int t, int ref); -static int (*luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); -static int (*luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); -static int (*luaL_loadstring) (lua_State *L, const char *s); -static lua_State *(*luaL_newstate) (void); -static int (*luaL_len) (lua_State *L, int idx); -static const char *(*luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); -static void (*luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); -static int (*luaL_getsubtable) (lua_State *L, int idx, const char *fname); -static void (*luaL_traceback) (lua_State *L, lua_State *L1, const char *msg, int level); -static void (*luaL_requiref) (lua_State *L, const char *modname, lua_CFunction openf, int glb); -static void (*luaL_buffinit) (lua_State *L, luaL_Buffer *B); -static char *(*luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -static void (*luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -static void (*luaL_addstring) (luaL_Buffer *B, const char *s); -static void (*luaL_addvalue) (luaL_Buffer *B); -static void (*luaL_pushresult) (luaL_Buffer *B); -static void (*luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -static char *(*luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); -static void (*luaL_openlibs) (lua_State *L); + +SYMBOL_DECLARE(void, luaL_checkversion_, lua_State *L, lua_Number ver) +SYMBOL_DECLARE(int, luaL_getmetafield, lua_State *L, int obj, const char *e) +SYMBOL_DECLARE(int, luaL_callmeta, lua_State *L, int obj, const char *e) +SYMBOL_DECLARE(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len) +SYMBOL_DECLARE(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg) +SYMBOL_DECLARE(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l) +SYMBOL_DECLARE(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l) +SYMBOL_DECLARE(lua_Number, luaL_checknumber, lua_State *L, int numArg) +SYMBOL_DECLARE(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def) +SYMBOL_DECLARE(lua_Integer, luaL_checkinteger, lua_State *L, int numArg) +SYMBOL_DECLARE(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def) +SYMBOL_DECLARE(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg) +SYMBOL_DECLARE(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def) +SYMBOL_DECLARE(void, luaL_checkstack, lua_State *L, int sz, const char *msg) +SYMBOL_DECLARE(void, luaL_checktype, lua_State *L, int narg, int t) +SYMBOL_DECLARE(void, luaL_checkany, lua_State *L, int narg) +SYMBOL_DECLARE(int, luaL_newmetatable, lua_State *L, const char *tname) +SYMBOL_DECLARE(void, luaL_setmetatable, lua_State *L, const char *tname) +SYMBOL_DECLARE(void *, luaL_testudata, lua_State *L, int ud, const char *tname) +SYMBOL_DECLARE(void *, luaL_checkudata, lua_State *L, int ud, const char *tname) +SYMBOL_DECLARE(void, luaL_where, lua_State *L, int lvl) +SYMBOL_DECLARE(int, luaL_error, lua_State *L, const char *fmt, ...) +SYMBOL_DECLARE(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]) +SYMBOL_DECLARE(int, luaL_fileresult, lua_State *L, int stat, const char *fname) +SYMBOL_DECLARE(int, luaL_execresult, lua_State *L, int stat) +SYMBOL_DECLARE(int, luaL_ref, lua_State *L, int t) +SYMBOL_DECLARE(void, luaL_unref, lua_State *L, int t, int ref) +SYMBOL_DECLARE(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode) +SYMBOL_DECLARE(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) +SYMBOL_DECLARE(int, luaL_loadstring, lua_State *L, const char *s) +SYMBOL_DECLARE(lua_State *, luaL_newstate, void) +SYMBOL_DECLARE(int, luaL_len, lua_State *L, int idx) +SYMBOL_DECLARE(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r) +SYMBOL_DECLARE(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup) +SYMBOL_DECLARE(int, luaL_getsubtable, lua_State *L, int idx, const char *fname) +SYMBOL_DECLARE(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level) +SYMBOL_DECLARE(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb) +SYMBOL_DECLARE(void, luaL_buffinit, lua_State *L, luaL_Buffer *B) +SYMBOL_DECLARE(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz) +SYMBOL_DECLARE(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l) +SYMBOL_DECLARE(void, luaL_addstring, luaL_Buffer *B, const char *s) +SYMBOL_DECLARE(void, luaL_addvalue, luaL_Buffer *B) +SYMBOL_DECLARE(void, luaL_pushresult, luaL_Buffer *B) +SYMBOL_DECLARE(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz) +SYMBOL_DECLARE(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz) +SYMBOL_DECLARE(void, luaL_openlibs, lua_State *L) + #define lauxlib_h #define LUA_ERRFILE (LUA_ERRERR+1) #define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) @@ -590,194 +529,592 @@ static void (*luaL_openlibs) (lua_State *L); #define luaL_addsize(B,s) ((B)->n += (s)) #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) #define LUA_FILEHANDLE "FILE*" -static void __lite_xl_fallback_luaL_checkversion_ (lua_State *L, lua_Number ver) { fputs("warning: luaL_checkversion_ is a stub", stderr); } -static int __lite_xl_fallback_luaL_getmetafield (lua_State *L, int obj, const char *e) { fputs("warning: luaL_getmetafield is a stub", stderr); } -static int __lite_xl_fallback_luaL_callmeta (lua_State *L, int obj, const char *e) { fputs("warning: luaL_callmeta is a stub", stderr); } -static const char * __lite_xl_fallback_luaL_tolstring (lua_State *L, int idx, size_t *len) { fputs("warning: luaL_tolstring is a stub", stderr); } -static int __lite_xl_fallback_luaL_argerror (lua_State *L, int numarg, const char *extramsg) { fputs("warning: luaL_argerror is a stub", stderr); } -static const char * __lite_xl_fallback_luaL_checklstring (lua_State *L, int numArg, size_t *l) { fputs("warning: luaL_checklstring is a stub", stderr); } -static const char * __lite_xl_fallback_luaL_optlstring (lua_State *L, int numArg, const char *def, size_t *l) { fputs("warning: luaL_optlstring is a stub", stderr); } -static lua_Number __lite_xl_fallback_luaL_checknumber (lua_State *L, int numArg) { fputs("warning: luaL_checknumber is a stub", stderr); } -static lua_Number __lite_xl_fallback_luaL_optnumber (lua_State *L, int nArg, lua_Number def) { fputs("warning: luaL_optnumber is a stub", stderr); } -static lua_Integer __lite_xl_fallback_luaL_checkinteger (lua_State *L, int numArg) { fputs("warning: luaL_checkinteger is a stub", stderr); } -static lua_Integer __lite_xl_fallback_luaL_optinteger (lua_State *L, int nArg, lua_Integer def) { fputs("warning: luaL_optinteger is a stub", stderr); } -static lua_Unsigned __lite_xl_fallback_luaL_checkunsigned (lua_State *L, int numArg) { fputs("warning: luaL_checkunsigned is a stub", stderr); } -static lua_Unsigned __lite_xl_fallback_luaL_optunsigned (lua_State *L, int numArg, lua_Unsigned def) { fputs("warning: luaL_optunsigned is a stub", stderr); } -static void __lite_xl_fallback_luaL_checkstack (lua_State *L, int sz, const char *msg) { fputs("warning: luaL_checkstack is a stub", stderr); } -static void __lite_xl_fallback_luaL_checktype (lua_State *L, int narg, int t) { fputs("warning: luaL_checktype is a stub", stderr); } -static void __lite_xl_fallback_luaL_checkany (lua_State *L, int narg) { fputs("warning: luaL_checkany is a stub", stderr); } -static int __lite_xl_fallback_luaL_newmetatable (lua_State *L, const char *tname) { fputs("warning: luaL_newmetatable is a stub", stderr); } -static void __lite_xl_fallback_luaL_setmetatable (lua_State *L, const char *tname) { fputs("warning: luaL_setmetatable is a stub", stderr); } -static void * __lite_xl_fallback_luaL_testudata (lua_State *L, int ud, const char *tname) { fputs("warning: luaL_testudata is a stub", stderr); } -static void * __lite_xl_fallback_luaL_checkudata (lua_State *L, int ud, const char *tname) { fputs("warning: luaL_checkudata is a stub", stderr); } -static void __lite_xl_fallback_luaL_where (lua_State *L, int lvl) { fputs("warning: luaL_where is a stub", stderr); } -static int __lite_xl_fallback_luaL_error (lua_State *L, const char *fmt, ...) { fputs("warning: luaL_error is a stub", stderr); } -static int __lite_xl_fallback_luaL_typeerror (lua_State *L, int narg, const char *tname) { fputs("warning: luaL_typeerror is a stub", stderr); } -static int __lite_xl_fallback_luaL_checkoption (lua_State *L, int narg, const char *def, const char *const lst[]) { fputs("warning: luaL_checkoption is a stub", stderr); } -static int __lite_xl_fallback_luaL_fileresult (lua_State *L, int stat, const char *fname) { fputs("warning: luaL_fileresult is a stub", stderr); } -static int __lite_xl_fallback_luaL_execresult (lua_State *L, int stat) { fputs("warning: luaL_execresult is a stub", stderr); } -static int __lite_xl_fallback_luaL_ref (lua_State *L, int t) { fputs("warning: luaL_ref is a stub", stderr); } -static void __lite_xl_fallback_luaL_unref (lua_State *L, int t, int ref) { fputs("warning: luaL_unref is a stub", stderr); } -static int __lite_xl_fallback_luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { fputs("warning: luaL_loadfilex is a stub", stderr); } -static int __lite_xl_fallback_luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { fputs("warning: luaL_loadbufferx is a stub", stderr); } -static int __lite_xl_fallback_luaL_loadstring (lua_State *L, const char *s) { fputs("warning: luaL_loadstring is a stub", stderr); } -static lua_State * __lite_xl_fallback_luaL_newstate (void) { fputs("warning: luaL_newstate is a stub", stderr); } -static int __lite_xl_fallback_luaL_len (lua_State *L, int idx) { fputs("warning: luaL_len is a stub", stderr); } -static const char * __lite_xl_fallback_luaL_gsub (lua_State *L, const char *s, const char *p, const char *r) { fputs("warning: luaL_gsub is a stub", stderr); } -static void __lite_xl_fallback_luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { fputs("warning: luaL_setfuncs is a stub", stderr); } -static int __lite_xl_fallback_luaL_getsubtable (lua_State *L, int idx, const char *fname) { fputs("warning: luaL_getsubtable is a stub", stderr); } -static void __lite_xl_fallback_luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level) { fputs("warning: luaL_traceback is a stub", stderr); } -static void __lite_xl_fallback_luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb) { fputs("warning: luaL_requiref is a stub", stderr); } -static void __lite_xl_fallback_luaL_buffinit (lua_State *L, luaL_Buffer *B) { fputs("warning: luaL_buffinit is a stub", stderr); } -static char * __lite_xl_fallback_luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { fputs("warning: luaL_prepbuffsize is a stub", stderr); } -static void __lite_xl_fallback_luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { fputs("warning: luaL_addlstring is a stub", stderr); } -static void __lite_xl_fallback_luaL_addstring (luaL_Buffer *B, const char *s) { fputs("warning: luaL_addstring is a stub", stderr); } -static void __lite_xl_fallback_luaL_addvalue (luaL_Buffer *B) { fputs("warning: luaL_addvalue is a stub", stderr); } -static void __lite_xl_fallback_luaL_pushresult (luaL_Buffer *B) { fputs("warning: luaL_pushresult is a stub", stderr); } -static void __lite_xl_fallback_luaL_pushresultsize (luaL_Buffer *B, size_t sz) { fputs("warning: luaL_pushresultsize is a stub", stderr); } -static char * __lite_xl_fallback_luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { fputs("warning: luaL_buffinitsize is a stub", stderr); } -static void __lite_xl_fallback_luaL_openlibs (lua_State *L) { fputs("warning: luaL_openlibs is a stub", stderr); } -#define IMPORT_SYMBOL(name, ret, ...) name = (name = (ret (*) (__VA_ARGS__)) symbol(#name), name == NULL ? &__lite_xl_fallback_##name : name) -static void lite_xl_plugin_init(void *XL) { - void* (*symbol)(const char *) = (void* (*) (const char *)) XL; - IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); - IMPORT_SYMBOL(lua_close, void , lua_State *L); - IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); - IMPORT_SYMBOL(lua_atpanic, lua_CFunction , lua_State *L, lua_CFunction panicf); - IMPORT_SYMBOL(lua_version, const lua_Number *, lua_State *L); - IMPORT_SYMBOL(lua_absindex, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_gettop, int , lua_State *L); - IMPORT_SYMBOL(lua_settop, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_pushvalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_copy, void , lua_State *L, int fromidx, int toidx); - IMPORT_SYMBOL(lua_checkstack, int , lua_State *L, int sz); - IMPORT_SYMBOL(lua_xmove, void , lua_State *from, lua_State *to, int n); - IMPORT_SYMBOL(lua_isnumber, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_isstring, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_iscfunction, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_isuserdata, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_type, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_typename, const char *, lua_State *L, int tp); - IMPORT_SYMBOL(lua_tonumberx, lua_Number , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_tointegerx, lua_Integer , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_tounsignedx, lua_Unsigned , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_toboolean, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_tolstring, const char *, lua_State *L, int idx, size_t *len); - IMPORT_SYMBOL(lua_rawlen, size_t , lua_State *L, int idx); - IMPORT_SYMBOL(lua_tocfunction, lua_CFunction , lua_State *L, int idx); - IMPORT_SYMBOL(lua_touserdata, void *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_tothread, lua_State *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_topointer, const void *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_arith, void , lua_State *L, int op); - IMPORT_SYMBOL(lua_rawequal, int , lua_State *L, int idx1, int idx2); - IMPORT_SYMBOL(lua_compare, int , lua_State *L, int idx1, int idx2, int op); - IMPORT_SYMBOL(lua_pushnil, void , lua_State *L); - IMPORT_SYMBOL(lua_pushnumber, void , lua_State *L, lua_Number n); - IMPORT_SYMBOL(lua_pushinteger, void , lua_State *L, lua_Integer n); - IMPORT_SYMBOL(lua_pushunsigned, void , lua_State *L, lua_Unsigned n); - IMPORT_SYMBOL(lua_pushlstring, const char *, lua_State *L, const char *s, size_t l); - IMPORT_SYMBOL(lua_pushstring, const char *, lua_State *L, const char *s); - IMPORT_SYMBOL(lua_pushvfstring, const char *, lua_State *L, const char *fmt, va_list argp); - IMPORT_SYMBOL(lua_pushfstring, const char *, lua_State *L, const char *fmt, ...); - IMPORT_SYMBOL(lua_pushcclosure, void , lua_State *L, lua_CFunction fn, int n); - IMPORT_SYMBOL(lua_pushboolean, void , lua_State *L, int b); - IMPORT_SYMBOL(lua_pushlightuserdata, void , lua_State *L, void *p); - IMPORT_SYMBOL(lua_pushthread, int , lua_State *L); - IMPORT_SYMBOL(lua_getglobal, void , lua_State *L, const char *var); - IMPORT_SYMBOL(lua_gettable, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getfield, void , lua_State *L, int idx, const char *k); - IMPORT_SYMBOL(lua_rawget, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_rawgeti, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_rawgetp, void , lua_State *L, int idx, const void *p); - IMPORT_SYMBOL(lua_createtable, void , lua_State *L, int narr, int nrec); - IMPORT_SYMBOL(lua_newuserdata, void *, lua_State *L, size_t sz); - IMPORT_SYMBOL(lua_newuserdatauv, void *, lua_State *L, size_t sz, int nuvalue); - IMPORT_SYMBOL(lua_getmetatable, int , lua_State *L, int objindex); - IMPORT_SYMBOL(lua_getuservalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getiuservalue, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_setglobal, void , lua_State *L, const char *var); - IMPORT_SYMBOL(lua_settable, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_setfield, void , lua_State *L, int idx, const char *k); - IMPORT_SYMBOL(lua_rawset, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_rawseti, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_rawsetp, void , lua_State *L, int idx, const void *p); - IMPORT_SYMBOL(lua_setmetatable, int , lua_State *L, int objindex); - IMPORT_SYMBOL(lua_setuservalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_setiuservalue, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); - IMPORT_SYMBOL(lua_getctx, int , lua_State *L, int *ctx); - IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); - IMPORT_SYMBOL(lua_load, int , lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); - IMPORT_SYMBOL(lua_dump, int , lua_State *L, lua_Writer writer, void *data, int strip); - IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, int ctx, lua_CFunction k); - IMPORT_SYMBOL(lua_resume, int , lua_State *L, lua_State *from, int narg); - IMPORT_SYMBOL(lua_status, int , lua_State *L); - IMPORT_SYMBOL(lua_gc, int , lua_State *L, int what, int data); - IMPORT_SYMBOL(lua_error, int , lua_State *L); - IMPORT_SYMBOL(lua_next, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_concat, void , lua_State *L, int n); - IMPORT_SYMBOL(lua_len, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getallocf, lua_Alloc , lua_State *L, void **ud); - IMPORT_SYMBOL(lua_setallocf, void , lua_State *L, lua_Alloc f, void *ud); - IMPORT_SYMBOL(lua_getstack, int , lua_State *L, int level, lua_Debug *ar); - IMPORT_SYMBOL(lua_getinfo, int , lua_State *L, const char *what, lua_Debug *ar); - IMPORT_SYMBOL(lua_getlocal, const char *, lua_State *L, const lua_Debug *ar, int n); - IMPORT_SYMBOL(lua_setlocal, const char *, lua_State *L, const lua_Debug *ar, int n); - IMPORT_SYMBOL(lua_getupvalue, const char *, lua_State *L, int funcindex, int n); - IMPORT_SYMBOL(lua_setupvalue, const char *, lua_State *L, int funcindex, int n); - IMPORT_SYMBOL(lua_upvalueid, void *, lua_State *L, int fidx, int n); - IMPORT_SYMBOL(lua_upvaluejoin, void , lua_State *L, int fidx1, int n1, int fidx2, int n2); - IMPORT_SYMBOL(lua_sethook, int , lua_State *L, lua_Hook func, int mask, int count); - IMPORT_SYMBOL(lua_gethook, lua_Hook , lua_State *L); - IMPORT_SYMBOL(lua_gethookmask, int , lua_State *L); - IMPORT_SYMBOL(lua_gethookcount, int , lua_State *L); - IMPORT_SYMBOL(luaL_checkversion_, void , lua_State *L, lua_Number ver); - IMPORT_SYMBOL(luaL_getmetafield, int , lua_State *L, int obj, const char *e); - IMPORT_SYMBOL(luaL_callmeta, int , lua_State *L, int obj, const char *e); - IMPORT_SYMBOL(luaL_tolstring, const char *, lua_State *L, int idx, size_t *len); - IMPORT_SYMBOL(luaL_argerror, int , lua_State *L, int numarg, const char *extramsg); - IMPORT_SYMBOL(luaL_checklstring, const char *, lua_State *L, int numArg, size_t *l); - IMPORT_SYMBOL(luaL_optlstring, const char *, lua_State *L, int numArg, const char *def, size_t *l); - IMPORT_SYMBOL(luaL_checknumber, lua_Number , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optnumber, lua_Number , lua_State *L, int nArg, lua_Number def); - IMPORT_SYMBOL(luaL_checkinteger, lua_Integer , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optinteger, lua_Integer , lua_State *L, int nArg, lua_Integer def); - IMPORT_SYMBOL(luaL_checkunsigned, lua_Unsigned , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optunsigned, lua_Unsigned , lua_State *L, int numArg, lua_Unsigned def); - IMPORT_SYMBOL(luaL_checkstack, void , lua_State *L, int sz, const char *msg); - IMPORT_SYMBOL(luaL_checktype, void , lua_State *L, int narg, int t); - IMPORT_SYMBOL(luaL_checkany, void , lua_State *L, int narg); - IMPORT_SYMBOL(luaL_newmetatable, int , lua_State *L, const char *tname); - IMPORT_SYMBOL(luaL_setmetatable, void , lua_State *L, const char *tname); - IMPORT_SYMBOL(luaL_testudata, void *, lua_State *L, int ud, const char *tname); - IMPORT_SYMBOL(luaL_checkudata, void *, lua_State *L, int ud, const char *tname); - IMPORT_SYMBOL(luaL_where, void , lua_State *L, int lvl); - IMPORT_SYMBOL(luaL_error, int , lua_State *L, const char *fmt, ...); - IMPORT_SYMBOL(luaL_typeerror, int , lua_State *L, int narg, const char *tname); - IMPORT_SYMBOL(luaL_checkoption, int , lua_State *L, int narg, const char *def, const char *const lst[]); - IMPORT_SYMBOL(luaL_fileresult, int , lua_State *L, int stat, const char *fname); - IMPORT_SYMBOL(luaL_execresult, int , lua_State *L, int stat); - IMPORT_SYMBOL(luaL_ref, int , lua_State *L, int t); - IMPORT_SYMBOL(luaL_unref, void , lua_State *L, int t, int ref); - IMPORT_SYMBOL(luaL_loadfilex, int , lua_State *L, const char *filename, const char *mode); - IMPORT_SYMBOL(luaL_loadbufferx, int , lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); - IMPORT_SYMBOL(luaL_loadstring, int , lua_State *L, const char *s); - IMPORT_SYMBOL(luaL_newstate, lua_State *, void); - IMPORT_SYMBOL(luaL_len, int , lua_State *L, int idx); - IMPORT_SYMBOL(luaL_gsub, const char *, lua_State *L, const char *s, const char *p, const char *r); - IMPORT_SYMBOL(luaL_setfuncs, void , lua_State *L, const luaL_Reg *l, int nup); - IMPORT_SYMBOL(luaL_getsubtable, int , lua_State *L, int idx, const char *fname); - IMPORT_SYMBOL(luaL_traceback, void , lua_State *L, lua_State *L1, const char *msg, int level); - IMPORT_SYMBOL(luaL_requiref, void , lua_State *L, const char *modname, lua_CFunction openf, int glb); - IMPORT_SYMBOL(luaL_buffinit, void , lua_State *L, luaL_Buffer *B); - IMPORT_SYMBOL(luaL_prepbuffsize, char *, luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_addlstring, void , luaL_Buffer *B, const char *s, size_t l); - IMPORT_SYMBOL(luaL_addstring, void , luaL_Buffer *B, const char *s); - IMPORT_SYMBOL(luaL_addvalue, void , luaL_Buffer *B); - IMPORT_SYMBOL(luaL_pushresult, void , luaL_Buffer *B); - IMPORT_SYMBOL(luaL_pushresultsize, void , luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_buffinitsize, char *, lua_State *L, luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_openlibs, void, lua_State* L); +#ifdef LITE_XL_PLUGIN_ENTRYPOINT + +SYMBOL_WRAP_DECL(lua_State *, lua_newstate, lua_Alloc f, void *ud){ + SYMBOL_WRAP_CALL(lua_newstate, f, ud); } -#endif +SYMBOL_WRAP_DECL(void, lua_close, lua_State *L){ + SYMBOL_WRAP_CALL(lua_close, L); +} +SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L){ + SYMBOL_WRAP_CALL(lua_newthread, L); +} +SYMBOL_WRAP_DECL(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf){ + SYMBOL_WRAP_CALL(lua_atpanic, L, panicf); +} +SYMBOL_WRAP_DECL(const lua_Number *, lua_version, lua_State *L){ + SYMBOL_WRAP_CALL(lua_version, L); +} +SYMBOL_WRAP_DECL(int, lua_absindex, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_absindex, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_gettop, lua_State *L){ + SYMBOL_WRAP_CALL(lua_gettop, L); +} +SYMBOL_WRAP_DECL(void, lua_settop, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_settop, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_pushvalue, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_pushvalue, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_copy, lua_State *L, int fromidx, int toidx){ + SYMBOL_WRAP_CALL(lua_copy, L, fromidx, toidx); +} +SYMBOL_WRAP_DECL(int, lua_checkstack, lua_State *L, int sz){ + SYMBOL_WRAP_CALL(lua_checkstack, L, sz); +} +SYMBOL_WRAP_DECL(void, lua_xmove, lua_State *from, lua_State *to, int n){ + SYMBOL_WRAP_CALL(lua_xmove, from, to, n); +} +SYMBOL_WRAP_DECL(int, lua_isnumber, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_isnumber, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_isstring, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_isstring, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_iscfunction, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_iscfunction, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_isuserdata, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_isuserdata, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_type, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_type, L, idx); +} +SYMBOL_WRAP_DECL(const char *, lua_typename, lua_State *L, int tp){ + SYMBOL_WRAP_CALL(lua_typename, L, tp); +} +SYMBOL_WRAP_DECL(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum){ + SYMBOL_WRAP_CALL(lua_tonumberx, L, idx, isnum); +} +SYMBOL_WRAP_DECL(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum){ + SYMBOL_WRAP_CALL(lua_tointegerx, L, idx, isnum); +} +SYMBOL_WRAP_DECL(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum){ + SYMBOL_WRAP_CALL(lua_tounsignedx, L, idx, isnum); +} +SYMBOL_WRAP_DECL(int, lua_toboolean, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_toboolean, L, idx); +} +SYMBOL_WRAP_DECL(const char *, lua_tolstring, lua_State *L, int idx, size_t *len){ + SYMBOL_WRAP_CALL(lua_tolstring, L, idx, len); +} +SYMBOL_WRAP_DECL(size_t, lua_rawlen, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_rawlen, L, idx); +} +SYMBOL_WRAP_DECL(lua_CFunction, lua_tocfunction, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_tocfunction, L, idx); +} +SYMBOL_WRAP_DECL(void *, lua_touserdata, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_touserdata, L, idx); +} +SYMBOL_WRAP_DECL(lua_State *, lua_tothread, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_tothread, L, idx); +} +SYMBOL_WRAP_DECL(const void *, lua_topointer, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_topointer, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_arith, lua_State *L, int op){ + SYMBOL_WRAP_CALL(lua_arith, L, op); +} +SYMBOL_WRAP_DECL(int, lua_rawequal, lua_State *L, int idx1, int idx2){ + SYMBOL_WRAP_CALL(lua_rawequal, L, idx1, idx2); +} +SYMBOL_WRAP_DECL(int, lua_compare, lua_State *L, int idx1, int idx2, int op){ + SYMBOL_WRAP_CALL(lua_compare, L, idx1, idx2, op); +} +SYMBOL_WRAP_DECL(void, lua_pushnil, lua_State *L){ + SYMBOL_WRAP_CALL(lua_pushnil, L); +} +SYMBOL_WRAP_DECL(void, lua_pushnumber, lua_State *L, lua_Number n){ + SYMBOL_WRAP_CALL(lua_pushnumber, L, n); +} +SYMBOL_WRAP_DECL(void, lua_pushinteger, lua_State *L, lua_Integer n){ + SYMBOL_WRAP_CALL(lua_pushinteger, L, n); +} +SYMBOL_WRAP_DECL(void, lua_pushunsigned, lua_State *L, lua_Unsigned n){ + SYMBOL_WRAP_CALL(lua_pushunsigned, L, n); +} +SYMBOL_WRAP_DECL(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l){ + SYMBOL_WRAP_CALL(lua_pushlstring, L, s, l); +} +SYMBOL_WRAP_DECL(const char *, lua_pushstring, lua_State *L, const char *s){ + SYMBOL_WRAP_CALL(lua_pushstring, L, s); +} +SYMBOL_WRAP_DECL(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp){ + SYMBOL_WRAP_CALL(lua_pushvfstring, L, fmt, argp); +} +SYMBOL_WRAP_DECL(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...){ + SYMBOL_WRAP_CALL(lua_pushfstring, L, fmt); +} +SYMBOL_WRAP_DECL(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n){ + SYMBOL_WRAP_CALL(lua_pushcclosure, L, fn, n); +} +SYMBOL_WRAP_DECL(void, lua_pushboolean, lua_State *L, int b){ + SYMBOL_WRAP_CALL(lua_pushboolean, L, b); +} +SYMBOL_WRAP_DECL(void, lua_pushlightuserdata, lua_State *L, void *p){ + SYMBOL_WRAP_CALL(lua_pushlightuserdata, L, p); +} +SYMBOL_WRAP_DECL(int, lua_pushthread, lua_State *L){ + SYMBOL_WRAP_CALL(lua_pushthread, L); +} +SYMBOL_WRAP_DECL(void, lua_getglobal, lua_State *L, const char *var){ + SYMBOL_WRAP_CALL(lua_getglobal, L, var); +} +SYMBOL_WRAP_DECL(void, lua_gettable, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_gettable, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_getfield, lua_State *L, int idx, const char *k){ + SYMBOL_WRAP_CALL(lua_getfield, L, idx, k); +} +SYMBOL_WRAP_DECL(void, lua_rawget, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_rawget, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_rawgeti, lua_State *L, int idx, int n){ + SYMBOL_WRAP_CALL(lua_rawgeti, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_rawgetp, lua_State *L, int idx, const void *p){ + SYMBOL_WRAP_CALL(lua_rawgetp, L, idx, p); +} +SYMBOL_WRAP_DECL(void, lua_createtable, lua_State *L, int narr, int nrec){ + SYMBOL_WRAP_CALL(lua_createtable, L, narr, nrec); +} +SYMBOL_WRAP_DECL(void *, lua_newuserdata, lua_State *L, size_t sz){ + if (__lua_newuserdatauv != NULL) { + return lua_newuserdatauv(L, sz, 1); + } else if (__lua_newuserdata != NULL) { + SYMBOL_WRAP_CALL(lua_newuserdata, L, sz); + } + SYMBOL_WRAP_CALL_FB(lua_newuserdata, L, sz); +} +SYMBOL_WRAP_DECL(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue){ + SYMBOL_WRAP_CALL(lua_newuserdatauv, L, sz, nuvalue); +} +SYMBOL_WRAP_DECL(int, lua_getmetatable, lua_State *L, int objindex){ + SYMBOL_WRAP_CALL(lua_getmetatable, L, objindex); +} +SYMBOL_WRAP_DECL(void, lua_getuservalue, lua_State *L, int idx){ + if (__lua_getiuservalue != NULL) { + return lua_getiuservalue(L, idx, 1); + } else if (__lua_getuservalue != NULL) { + SYMBOL_WRAP_CALL(lua_getuservalue, L, idx); + } + SYMBOL_WRAP_CALL_FB(lua_getuservalue, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_getiuservalue, lua_State *L, int idx, int n){ + SYMBOL_WRAP_CALL(lua_getiuservalue, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_setglobal, lua_State *L, const char *var){ + SYMBOL_WRAP_CALL(lua_setglobal, L, var); +} +SYMBOL_WRAP_DECL(void, lua_settable, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_settable, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_setfield, lua_State *L, int idx, const char *k){ + SYMBOL_WRAP_CALL(lua_setfield, L, idx, k); +} +SYMBOL_WRAP_DECL(void, lua_rawset, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_rawset, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_rawseti, lua_State *L, int idx, int n){ + SYMBOL_WRAP_CALL(lua_rawseti, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_rawsetp, lua_State *L, int idx, const void *p){ + SYMBOL_WRAP_CALL(lua_rawsetp, L, idx, p); +} +SYMBOL_WRAP_DECL(int, lua_setmetatable, lua_State *L, int objindex){ + SYMBOL_WRAP_CALL(lua_setmetatable, L, objindex); +} +SYMBOL_WRAP_DECL(void, lua_setuservalue, lua_State *L, int idx){ + if (__lua_setiuservalue != NULL) { + return lua_setiuservalue(L, idx, 1); + } else if (__lua_setuservalue != NULL) { + SYMBOL_WRAP_CALL(lua_setuservalue, L, idx); + } + SYMBOL_WRAP_CALL_FB(lua_setuservalue, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_setiuservalue, lua_State *L, int idx, int n){ + SYMBOL_WRAP_CALL(lua_setiuservalue, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k){ + SYMBOL_WRAP_CALL(lua_callk, L, nargs, nresults, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_getctx, lua_State *L, int *ctx){ + SYMBOL_WRAP_CALL(lua_getctx, L, ctx); +} +SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k){ + SYMBOL_WRAP_CALL(lua_pcallk, L, nargs, nresults, errfunc, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode){ + SYMBOL_WRAP_CALL(lua_load, L, reader, dt, chunkname, mode); +} +SYMBOL_WRAP_DECL(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip){ + SYMBOL_WRAP_CALL(lua_dump, L, writer, data, strip); +} +SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k){ + SYMBOL_WRAP_CALL(lua_yieldk, L, nresults, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_resume, lua_State *L, lua_State *from, int narg){ + SYMBOL_WRAP_CALL(lua_resume, L, from, narg); +} +SYMBOL_WRAP_DECL(int, lua_status, lua_State *L){ + SYMBOL_WRAP_CALL(lua_status, L); +} +SYMBOL_WRAP_DECL(int, lua_gc, lua_State *L, int what, int data){ + SYMBOL_WRAP_CALL(lua_gc, L, what, data); +} +SYMBOL_WRAP_DECL(int, lua_error, lua_State *L){ + SYMBOL_WRAP_CALL(lua_error, L); +} +SYMBOL_WRAP_DECL(int, lua_next, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_next, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_concat, lua_State *L, int n){ + SYMBOL_WRAP_CALL(lua_concat, L, n); +} +SYMBOL_WRAP_DECL(void, lua_len, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(lua_len, L, idx); +} +SYMBOL_WRAP_DECL(lua_Alloc, lua_getallocf, lua_State *L, void **ud){ + SYMBOL_WRAP_CALL(lua_getallocf, L, ud); +} +SYMBOL_WRAP_DECL(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud){ + SYMBOL_WRAP_CALL(lua_setallocf, L, f, ud); +} +SYMBOL_WRAP_DECL(int, lua_getstack, lua_State *L, int level, lua_Debug *ar){ + SYMBOL_WRAP_CALL(lua_getstack, L, level, ar); +} +SYMBOL_WRAP_DECL(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar){ + SYMBOL_WRAP_CALL(lua_getinfo, L, what, ar); +} +SYMBOL_WRAP_DECL(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n){ + SYMBOL_WRAP_CALL(lua_getlocal, L, ar, n); +} +SYMBOL_WRAP_DECL(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n){ + SYMBOL_WRAP_CALL(lua_setlocal, L, ar, n); +} +SYMBOL_WRAP_DECL(const char *, lua_getupvalue, lua_State *L, int funcindex, int n){ + SYMBOL_WRAP_CALL(lua_getupvalue, L, funcindex, n); +} +SYMBOL_WRAP_DECL(const char *, lua_setupvalue, lua_State *L, int funcindex, int n){ + SYMBOL_WRAP_CALL(lua_setupvalue, L, funcindex, n); +} +SYMBOL_WRAP_DECL(void *, lua_upvalueid, lua_State *L, int fidx, int n){ + SYMBOL_WRAP_CALL(lua_upvalueid, L, fidx, n); +} +SYMBOL_WRAP_DECL(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2){ + SYMBOL_WRAP_CALL(lua_upvaluejoin, L, fidx1, n1, fidx2, n2); +} +SYMBOL_WRAP_DECL(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count){ + SYMBOL_WRAP_CALL(lua_sethook, L, func, mask, count); +} +SYMBOL_WRAP_DECL(lua_Hook, lua_gethook, lua_State *L){ + SYMBOL_WRAP_CALL(lua_gethook, L); +} +SYMBOL_WRAP_DECL(int, lua_gethookmask, lua_State *L){ + SYMBOL_WRAP_CALL(lua_gethookmask, L); +} +SYMBOL_WRAP_DECL(int, lua_gethookcount, lua_State *L){ + SYMBOL_WRAP_CALL(lua_gethookcount, L); +} +SYMBOL_WRAP_DECL(void, luaL_checkversion_, lua_State *L, lua_Number ver){ + SYMBOL_WRAP_CALL(luaL_checkversion_, L, ver); +} +SYMBOL_WRAP_DECL(int, luaL_getmetafield, lua_State *L, int obj, const char *e){ + SYMBOL_WRAP_CALL(luaL_getmetafield, L, obj, e); +} +SYMBOL_WRAP_DECL(int, luaL_callmeta, lua_State *L, int obj, const char *e){ + SYMBOL_WRAP_CALL(luaL_callmeta, L, obj, e); +} +SYMBOL_WRAP_DECL(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len){ + SYMBOL_WRAP_CALL(luaL_tolstring, L, idx, len); +} +SYMBOL_WRAP_DECL(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg){ + SYMBOL_WRAP_CALL(luaL_argerror, L, numarg, extramsg); +} +SYMBOL_WRAP_DECL(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l){ + SYMBOL_WRAP_CALL(luaL_checklstring, L, numArg, l); +} +SYMBOL_WRAP_DECL(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l){ + SYMBOL_WRAP_CALL(luaL_optlstring, L, numArg, def, l); +} +SYMBOL_WRAP_DECL(lua_Number, luaL_checknumber, lua_State *L, int numArg){ + SYMBOL_WRAP_CALL(luaL_checknumber, L, numArg); +} +SYMBOL_WRAP_DECL(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def){ + SYMBOL_WRAP_CALL(luaL_optnumber, L, nArg, def); +} +SYMBOL_WRAP_DECL(lua_Integer, luaL_checkinteger, lua_State *L, int numArg){ + SYMBOL_WRAP_CALL(luaL_checkinteger, L, numArg); +} +SYMBOL_WRAP_DECL(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def){ + SYMBOL_WRAP_CALL(luaL_optinteger, L, nArg, def); +} +SYMBOL_WRAP_DECL(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg){ + SYMBOL_WRAP_CALL(luaL_checkunsigned, L, numArg); +} +SYMBOL_WRAP_DECL(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def){ + SYMBOL_WRAP_CALL(luaL_optunsigned, L, numArg, def); +} +SYMBOL_WRAP_DECL(void, luaL_checkstack, lua_State *L, int sz, const char *msg){ + SYMBOL_WRAP_CALL(luaL_checkstack, L, sz, msg); +} +SYMBOL_WRAP_DECL(void, luaL_checktype, lua_State *L, int narg, int t){ + SYMBOL_WRAP_CALL(luaL_checktype, L, narg, t); +} +SYMBOL_WRAP_DECL(void, luaL_checkany, lua_State *L, int narg){ + SYMBOL_WRAP_CALL(luaL_checkany, L, narg); +} +SYMBOL_WRAP_DECL(int, luaL_newmetatable, lua_State *L, const char *tname){ + SYMBOL_WRAP_CALL(luaL_newmetatable, L, tname); +} +SYMBOL_WRAP_DECL(void, luaL_setmetatable, lua_State *L, const char *tname){ + SYMBOL_WRAP_CALL(luaL_setmetatable, L, tname); +} +SYMBOL_WRAP_DECL(void *, luaL_testudata, lua_State *L, int ud, const char *tname){ + SYMBOL_WRAP_CALL(luaL_testudata, L, ud, tname); +} +SYMBOL_WRAP_DECL(void *, luaL_checkudata, lua_State *L, int ud, const char *tname){ + SYMBOL_WRAP_CALL(luaL_checkudata, L, ud, tname); +} +SYMBOL_WRAP_DECL(void, luaL_where, lua_State *L, int lvl){ + SYMBOL_WRAP_CALL(luaL_where, L, lvl); +} +SYMBOL_WRAP_DECL(int, luaL_error, lua_State *L, const char *fmt, ...){ + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} +SYMBOL_WRAP_DECL(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]){ + SYMBOL_WRAP_CALL(luaL_checkoption, L, narg, def, lst); +} +SYMBOL_WRAP_DECL(int, luaL_fileresult, lua_State *L, int stat, const char *fname){ + SYMBOL_WRAP_CALL(luaL_fileresult, L, stat, fname); +} +SYMBOL_WRAP_DECL(int, luaL_execresult, lua_State *L, int stat){ + SYMBOL_WRAP_CALL(luaL_execresult, L, stat); +} +SYMBOL_WRAP_DECL(int, luaL_ref, lua_State *L, int t){ + SYMBOL_WRAP_CALL(luaL_ref, L, t); +} +SYMBOL_WRAP_DECL(void, luaL_unref, lua_State *L, int t, int ref){ + SYMBOL_WRAP_CALL(luaL_unref, L, t, ref); +} +SYMBOL_WRAP_DECL(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode){ + SYMBOL_WRAP_CALL(luaL_loadfilex, L, filename, mode); +} +SYMBOL_WRAP_DECL(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode){ + SYMBOL_WRAP_CALL(luaL_loadbufferx, L, buff, sz, name, mode); +} +SYMBOL_WRAP_DECL(int, luaL_loadstring, lua_State *L, const char *s){ + SYMBOL_WRAP_CALL(luaL_loadstring, L, s); +} +SYMBOL_WRAP_DECL(lua_State *, luaL_newstate, void){ + return __luaL_newstate(); +} +SYMBOL_WRAP_DECL(int, luaL_len, lua_State *L, int idx){ + SYMBOL_WRAP_CALL(luaL_len, L, idx); +} +SYMBOL_WRAP_DECL(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r){ + SYMBOL_WRAP_CALL(luaL_gsub, L, s, p, r); +} +SYMBOL_WRAP_DECL(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup){ + SYMBOL_WRAP_CALL(luaL_setfuncs, L, l, nup); +} +SYMBOL_WRAP_DECL(int, luaL_getsubtable, lua_State *L, int idx, const char *fname){ + SYMBOL_WRAP_CALL(luaL_getsubtable, L, idx, fname); +} +SYMBOL_WRAP_DECL(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level){ + SYMBOL_WRAP_CALL(luaL_traceback, L, L1, msg, level); +} +SYMBOL_WRAP_DECL(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb){ + SYMBOL_WRAP_CALL(luaL_requiref, L, modname, openf, glb); +} +SYMBOL_WRAP_DECL(void, luaL_buffinit, lua_State *L, luaL_Buffer *B){ + SYMBOL_WRAP_CALL(luaL_buffinit, L, B); +} +SYMBOL_WRAP_DECL(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz){ + SYMBOL_WRAP_CALL(luaL_prepbuffsize, B, sz); +} +SYMBOL_WRAP_DECL(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l){ + SYMBOL_WRAP_CALL(luaL_addlstring, B, s, l); +} +SYMBOL_WRAP_DECL(void, luaL_addstring, luaL_Buffer *B, const char *s){ + SYMBOL_WRAP_CALL(luaL_addstring, B, s); +} +SYMBOL_WRAP_DECL(void, luaL_addvalue, luaL_Buffer *B){ + SYMBOL_WRAP_CALL(luaL_addvalue, B); +} +SYMBOL_WRAP_DECL(void, luaL_pushresult, luaL_Buffer *B){ + SYMBOL_WRAP_CALL(luaL_pushresult, B); +} +SYMBOL_WRAP_DECL(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz){ + SYMBOL_WRAP_CALL(luaL_pushresultsize, B, sz); +} +SYMBOL_WRAP_DECL(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz){ + SYMBOL_WRAP_CALL(luaL_buffinitsize, L, B, sz); +} +SYMBOL_WRAP_DECL(void, luaL_openlibs, lua_State *L){ + SYMBOL_WRAP_CALL(luaL_openlibs, L); +} + +#define IMPORT_SYMBOL(name, ret, ...) \ + __##name = (\ + __##name = (ret (*) (__VA_ARGS__)) symbol(#name), \ + __##name == NULL ? &__lite_xl_fallback_##name : __##name\ + ) + +#define IMPORT_SYMBOL_OPT(name, ret, ...) \ + __##name = symbol(#name) + +static void lite_xl_plugin_init(void *XL) { + void* (*symbol)(const char *) = (void* (*) (const char *)) XL; + IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); + IMPORT_SYMBOL(lua_close, void , lua_State *L); + IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); + IMPORT_SYMBOL(lua_atpanic, lua_CFunction , lua_State *L, lua_CFunction panicf); + IMPORT_SYMBOL(lua_version, const lua_Number *, lua_State *L); + IMPORT_SYMBOL(lua_absindex, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_gettop, int , lua_State *L); + IMPORT_SYMBOL(lua_settop, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_pushvalue, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_copy, void , lua_State *L, int fromidx, int toidx); + IMPORT_SYMBOL(lua_checkstack, int , lua_State *L, int sz); + IMPORT_SYMBOL(lua_xmove, void , lua_State *from, lua_State *to, int n); + IMPORT_SYMBOL(lua_isnumber, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_isstring, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_iscfunction, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_isuserdata, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_type, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_typename, const char *, lua_State *L, int tp); + IMPORT_SYMBOL(lua_tonumberx, lua_Number , lua_State *L, int idx, int *isnum); + IMPORT_SYMBOL(lua_tointegerx, lua_Integer , lua_State *L, int idx, int *isnum); + IMPORT_SYMBOL(lua_tounsignedx, lua_Unsigned , lua_State *L, int idx, int *isnum); + IMPORT_SYMBOL(lua_toboolean, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_tolstring, const char *, lua_State *L, int idx, size_t *len); + IMPORT_SYMBOL(lua_rawlen, size_t , lua_State *L, int idx); + IMPORT_SYMBOL(lua_tocfunction, lua_CFunction , lua_State *L, int idx); + IMPORT_SYMBOL(lua_touserdata, void *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_tothread, lua_State *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_topointer, const void *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_arith, void , lua_State *L, int op); + IMPORT_SYMBOL(lua_rawequal, int , lua_State *L, int idx1, int idx2); + IMPORT_SYMBOL(lua_compare, int , lua_State *L, int idx1, int idx2, int op); + IMPORT_SYMBOL(lua_pushnil, void , lua_State *L); + IMPORT_SYMBOL(lua_pushnumber, void , lua_State *L, lua_Number n); + IMPORT_SYMBOL(lua_pushinteger, void , lua_State *L, lua_Integer n); + IMPORT_SYMBOL(lua_pushunsigned, void , lua_State *L, lua_Unsigned n); + IMPORT_SYMBOL(lua_pushlstring, const char *, lua_State *L, const char *s, size_t l); + IMPORT_SYMBOL(lua_pushstring, const char *, lua_State *L, const char *s); + IMPORT_SYMBOL(lua_pushvfstring, const char *, lua_State *L, const char *fmt, va_list argp); + IMPORT_SYMBOL(lua_pushfstring, const char *, lua_State *L, const char *fmt, ...); + IMPORT_SYMBOL(lua_pushcclosure, void , lua_State *L, lua_CFunction fn, int n); + IMPORT_SYMBOL(lua_pushboolean, void , lua_State *L, int b); + IMPORT_SYMBOL(lua_pushlightuserdata, void , lua_State *L, void *p); + IMPORT_SYMBOL(lua_pushthread, int , lua_State *L); + IMPORT_SYMBOL(lua_getglobal, void , lua_State *L, const char *var); + IMPORT_SYMBOL(lua_gettable, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_getfield, void , lua_State *L, int idx, const char *k); + IMPORT_SYMBOL(lua_rawget, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_rawgeti, void , lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_rawgetp, void , lua_State *L, int idx, const void *p); + IMPORT_SYMBOL(lua_createtable, void , lua_State *L, int narr, int nrec); + IMPORT_SYMBOL_OPT(lua_newuserdata, void *, lua_State *L, size_t sz); + IMPORT_SYMBOL(lua_newuserdatauv, void *, lua_State *L, size_t sz, int nuvalue); + IMPORT_SYMBOL(lua_getmetatable, int , lua_State *L, int objindex); + IMPORT_SYMBOL_OPT(lua_getuservalue, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_getiuservalue, void , lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_setglobal, void , lua_State *L, const char *var); + IMPORT_SYMBOL(lua_settable, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_setfield, void , lua_State *L, int idx, const char *k); + IMPORT_SYMBOL(lua_rawset, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_rawseti, void , lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_rawsetp, void , lua_State *L, int idx, const void *p); + IMPORT_SYMBOL(lua_setmetatable, int , lua_State *L, int objindex); + IMPORT_SYMBOL_OPT(lua_setuservalue, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_setiuservalue, void , lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_getctx, int , lua_State *L, int *ctx); + IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_load, int , lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); + IMPORT_SYMBOL(lua_dump, int , lua_State *L, lua_Writer writer, void *data, int strip); + IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_resume, int , lua_State *L, lua_State *from, int narg); + IMPORT_SYMBOL(lua_status, int , lua_State *L); + IMPORT_SYMBOL(lua_gc, int , lua_State *L, int what, int data); + IMPORT_SYMBOL(lua_error, int , lua_State *L); + IMPORT_SYMBOL(lua_next, int , lua_State *L, int idx); + IMPORT_SYMBOL(lua_concat, void , lua_State *L, int n); + IMPORT_SYMBOL(lua_len, void , lua_State *L, int idx); + IMPORT_SYMBOL(lua_getallocf, lua_Alloc , lua_State *L, void **ud); + IMPORT_SYMBOL(lua_setallocf, void , lua_State *L, lua_Alloc f, void *ud); + IMPORT_SYMBOL(lua_getstack, int , lua_State *L, int level, lua_Debug *ar); + IMPORT_SYMBOL(lua_getinfo, int , lua_State *L, const char *what, lua_Debug *ar); + IMPORT_SYMBOL(lua_getlocal, const char *, lua_State *L, const lua_Debug *ar, int n); + IMPORT_SYMBOL(lua_setlocal, const char *, lua_State *L, const lua_Debug *ar, int n); + IMPORT_SYMBOL(lua_getupvalue, const char *, lua_State *L, int funcindex, int n); + IMPORT_SYMBOL(lua_setupvalue, const char *, lua_State *L, int funcindex, int n); + IMPORT_SYMBOL(lua_upvalueid, void *, lua_State *L, int fidx, int n); + IMPORT_SYMBOL(lua_upvaluejoin, void , lua_State *L, int fidx1, int n1, int fidx2, int n2); + IMPORT_SYMBOL(lua_sethook, int , lua_State *L, lua_Hook func, int mask, int count); + IMPORT_SYMBOL(lua_gethook, lua_Hook , lua_State *L); + IMPORT_SYMBOL(lua_gethookmask, int , lua_State *L); + IMPORT_SYMBOL(lua_gethookcount, int , lua_State *L); + IMPORT_SYMBOL(luaL_checkversion_, void , lua_State *L, lua_Number ver); + IMPORT_SYMBOL(luaL_getmetafield, int , lua_State *L, int obj, const char *e); + IMPORT_SYMBOL(luaL_callmeta, int , lua_State *L, int obj, const char *e); + IMPORT_SYMBOL(luaL_tolstring, const char *, lua_State *L, int idx, size_t *len); + IMPORT_SYMBOL(luaL_argerror, int , lua_State *L, int numarg, const char *extramsg); + IMPORT_SYMBOL(luaL_checklstring, const char *, lua_State *L, int numArg, size_t *l); + IMPORT_SYMBOL(luaL_optlstring, const char *, lua_State *L, int numArg, const char *def, size_t *l); + IMPORT_SYMBOL(luaL_checknumber, lua_Number , lua_State *L, int numArg); + IMPORT_SYMBOL(luaL_optnumber, lua_Number , lua_State *L, int nArg, lua_Number def); + IMPORT_SYMBOL(luaL_checkinteger, lua_Integer , lua_State *L, int numArg); + IMPORT_SYMBOL(luaL_optinteger, lua_Integer , lua_State *L, int nArg, lua_Integer def); + IMPORT_SYMBOL(luaL_checkunsigned, lua_Unsigned , lua_State *L, int numArg); + IMPORT_SYMBOL(luaL_optunsigned, lua_Unsigned , lua_State *L, int numArg, lua_Unsigned def); + IMPORT_SYMBOL(luaL_checkstack, void , lua_State *L, int sz, const char *msg); + IMPORT_SYMBOL(luaL_checktype, void , lua_State *L, int narg, int t); + IMPORT_SYMBOL(luaL_checkany, void , lua_State *L, int narg); + IMPORT_SYMBOL(luaL_newmetatable, int , lua_State *L, const char *tname); + IMPORT_SYMBOL(luaL_setmetatable, void , lua_State *L, const char *tname); + IMPORT_SYMBOL(luaL_testudata, void *, lua_State *L, int ud, const char *tname); + IMPORT_SYMBOL(luaL_checkudata, void *, lua_State *L, int ud, const char *tname); + IMPORT_SYMBOL(luaL_where, void , lua_State *L, int lvl); + IMPORT_SYMBOL(luaL_error, int , lua_State *L, const char *fmt, ...); + IMPORT_SYMBOL(luaL_checkoption, int , lua_State *L, int narg, const char *def, const char *const lst[]); + IMPORT_SYMBOL(luaL_fileresult, int , lua_State *L, int stat, const char *fname); + IMPORT_SYMBOL(luaL_execresult, int , lua_State *L, int stat); + IMPORT_SYMBOL(luaL_ref, int , lua_State *L, int t); + IMPORT_SYMBOL(luaL_unref, void , lua_State *L, int t, int ref); + IMPORT_SYMBOL(luaL_loadfilex, int , lua_State *L, const char *filename, const char *mode); + IMPORT_SYMBOL(luaL_loadbufferx, int , lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); + IMPORT_SYMBOL(luaL_loadstring, int , lua_State *L, const char *s); + IMPORT_SYMBOL(luaL_newstate, lua_State *, void); + IMPORT_SYMBOL(luaL_len, int , lua_State *L, int idx); + IMPORT_SYMBOL(luaL_gsub, const char *, lua_State *L, const char *s, const char *p, const char *r); + IMPORT_SYMBOL(luaL_setfuncs, void , lua_State *L, const luaL_Reg *l, int nup); + IMPORT_SYMBOL(luaL_getsubtable, int , lua_State *L, int idx, const char *fname); + IMPORT_SYMBOL(luaL_traceback, void , lua_State *L, lua_State *L1, const char *msg, int level); + IMPORT_SYMBOL(luaL_requiref, void , lua_State *L, const char *modname, lua_CFunction openf, int glb); + IMPORT_SYMBOL(luaL_buffinit, void , lua_State *L, luaL_Buffer *B); + IMPORT_SYMBOL(luaL_prepbuffsize, char *, luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaL_addlstring, void , luaL_Buffer *B, const char *s, size_t l); + IMPORT_SYMBOL(luaL_addstring, void , luaL_Buffer *B, const char *s); + IMPORT_SYMBOL(luaL_addvalue, void , luaL_Buffer *B); + IMPORT_SYMBOL(luaL_pushresult, void , luaL_Buffer *B); + IMPORT_SYMBOL(luaL_pushresultsize, void , luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaL_buffinitsize, char *, lua_State *L, luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaL_openlibs, void, lua_State* L); +} + +#endif /* LITE_XL_PLUGIN_ENTRYPOINT */ + +#endif /* LITE_XL_PLUGIN_API */ From de06dcc5bb95d5775a634752a3971a98c4d0dd4b Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Thu, 19 Jan 2023 19:28:14 -0500 Subject: [PATCH 012/176] Added missing header declaration. --- resources/lite_xl_plugin_api.h | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lite_xl_plugin_api.h b/resources/lite_xl_plugin_api.h index 257791ce..6d68e454 100644 --- a/resources/lite_xl_plugin_api.h +++ b/resources/lite_xl_plugin_api.h @@ -28,6 +28,7 @@ Go figure. #include #include // for BUFSIZ? this is kinda weird +#include #define SYMBOL_WRAP_DECL(ret, name, ...) \ ret name(__VA_ARGS__) From 16182d01d8e58838442c4d323039d8299b13fcb9 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 22 Jan 2023 04:11:42 +0100 Subject: [PATCH 013/176] pass RenWindow by argument (#1321) * pass RenWindow to all renderer functions that need it * pass RenWindow to all rencache functions that need it --- src/api/renderer.c | 16 ++++++------ src/api/system.c | 6 ++--- src/main.c | 2 +- src/rencache.c | 22 ++++++++-------- src/rencache.h | 6 ++--- src/renderer.c | 64 +++++++++++++++++++++++----------------------- src/renderer.h | 27 +++++++++++-------- 7 files changed, 73 insertions(+), 70 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index ae2c7ae0..d96fbe0a 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -90,7 +90,7 @@ static int f_font_load(lua_State *L) { return ret_code; RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); - *font = ren_font_load(filename, size, antialiasing, hinting, style); + *font = ren_font_load(&window_renderer, filename, size, antialiasing, hinting, style); if (!*font) return luaL_error(L, "failed to load font"); luaL_setmetatable(L, API_TYPE_FONT); @@ -130,7 +130,7 @@ static int f_font_copy(lua_State *L) { } for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); - *font = ren_font_copy(fonts[i], size, antialiasing, hinting, style); + *font = ren_font_copy(&window_renderer, fonts[i], size, antialiasing, hinting, style); if (!*font) return luaL_error(L, "failed to copy font"); luaL_setmetatable(L, API_TYPE_FONT); @@ -198,7 +198,7 @@ static int f_font_get_width(lua_State *L) { size_t len; const char *text = luaL_checklstring(L, 2, &len); - lua_pushnumber(L, ren_font_group_get_width(fonts, text, len)); + lua_pushnumber(L, ren_font_group_get_width(&window_renderer, fonts, text, len)); return 1; } @@ -217,7 +217,7 @@ static int f_font_get_size(lua_State *L) { static int f_font_set_size(lua_State *L) { RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1); float size = luaL_checknumber(L, 2); - ren_font_group_set_size(fonts, size); + ren_font_group_set_size(&window_renderer, fonts, size); return 0; } @@ -276,7 +276,7 @@ static int f_show_debug(lua_State *L) { static int f_get_size(lua_State *L) { int w, h; - ren_get_size(&w, &h); + ren_get_size(&window_renderer, &w, &h); lua_pushnumber(L, w); lua_pushnumber(L, h); return 2; @@ -284,13 +284,13 @@ static int f_get_size(lua_State *L) { static int f_begin_frame(UNUSED lua_State *L) { - rencache_begin_frame(); + rencache_begin_frame(&window_renderer); return 0; } static int f_end_frame(UNUSED lua_State *L) { - rencache_end_frame(); + rencache_end_frame(&window_renderer); // clear the font reference table lua_newtable(L); lua_rawseti(L, LUA_REGISTRYINDEX, RENDERER_FONT_REF); @@ -348,7 +348,7 @@ static int f_draw_text(lua_State *L) { float x = luaL_checknumber(L, 3); int y = luaL_checknumber(L, 4); RenColor color = checkcolor(L, 5, 255); - x = rencache_draw_text(fonts, text, len, x, y, color); + x = rencache_draw_text(&window_renderer, fonts, text, len, x, y, color); lua_pushnumber(L, x); return 1; } diff --git a/src/api/system.c b/src/api/system.c index 36d9c680..ad7cede8 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -37,8 +37,6 @@ #endif #endif -extern RenWindow window_renderer; - static const char* button_name(int button) { switch (button) { case SDL_BUTTON_LEFT : return "left"; @@ -188,7 +186,7 @@ top: case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) { - ren_resize_window(); + ren_resize_window(&window_renderer); lua_pushstring(L, "resized"); /* The size below will be in points. */ lua_pushinteger(L, e.window.data1); @@ -473,7 +471,7 @@ static int f_set_window_size(lua_State *L) { double y = luaL_checknumber(L, 4); SDL_SetWindowSize(window_renderer.window, w, h); SDL_SetWindowPosition(window_renderer.window, x, y); - ren_resize_window(); + ren_resize_window(&window_renderer); return 0; } diff --git a/src/main.c b/src/main.c index 3c08a643..32212df8 100644 --- a/src/main.c +++ b/src/main.c @@ -260,7 +260,7 @@ init_lua: } lua_close(L); - ren_free_window_resources(); + ren_free_window_resources(&window_renderer); return EXIT_SUCCESS; } diff --git a/src/rencache.c b/src/rencache.c index f0243f0b..5b930482 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -175,9 +175,9 @@ void rencache_draw_rect(RenRect rect, RenColor color) { } } -float rencache_draw_text(RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) +float rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { - float width = ren_font_group_get_width(fonts, text, len); + float width = ren_font_group_get_width(window_renderer, fonts, text, len); RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; @@ -201,11 +201,11 @@ void rencache_invalidate(void) { } -void rencache_begin_frame() { +void rencache_begin_frame(RenWindow *window_renderer) { /* reset all cells if the screen width/height has changed */ int w, h; resize_issue = false; - ren_get_size(&w, &h); + ren_get_size(window_renderer, &w, &h); if (screen_rect.width != w || h != screen_rect.height) { screen_rect.width = w; screen_rect.height = h; @@ -244,7 +244,7 @@ static void push_rect(RenRect r, int *count) { } -void rencache_end_frame() { +void rencache_end_frame(RenWindow *window_renderer) { /* update cells from commands */ Command *cmd = NULL; RenRect cr = screen_rect; @@ -286,33 +286,33 @@ void rencache_end_frame() { for (int i = 0; i < rect_count; i++) { /* draw */ RenRect r = rect_buf[i]; - ren_set_clip_rect(r); + ren_set_clip_rect(window_renderer, r); cmd = NULL; while (next_command(&cmd)) { switch (cmd->type) { case SET_CLIP: - ren_set_clip_rect(intersect_rects(cmd->rect, r)); + ren_set_clip_rect(window_renderer, intersect_rects(cmd->rect, r)); break; case DRAW_RECT: - ren_draw_rect(cmd->rect, cmd->color); + ren_draw_rect(window_renderer, cmd->rect, cmd->color); break; case DRAW_TEXT: ren_font_group_set_tab_size(cmd->fonts, cmd->tab_size); - ren_draw_text(cmd->fonts, cmd->text, cmd->len, cmd->text_x, cmd->rect.y, cmd->color); + ren_draw_text(window_renderer, cmd->fonts, cmd->text, cmd->len, cmd->text_x, cmd->rect.y, cmd->color); break; } } if (show_debug) { RenColor color = { rand(), rand(), rand(), 50 }; - ren_draw_rect(r, color); + ren_draw_rect(window_renderer, r, color); } } /* update dirty rects */ if (rect_count > 0) { - ren_update_rects(rect_buf, rect_count); + ren_update_rects(window_renderer, rect_buf, rect_count); } /* swap cell buffer and reset */ diff --git a/src/rencache.h b/src/rencache.h index 49ca9135..925b50f0 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -8,9 +8,9 @@ void rencache_show_debug(bool enable); void rencache_set_clip_rect(RenRect rect); void rencache_draw_rect(RenRect rect, RenColor color); -float rencache_draw_text(RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +float rencache_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); void rencache_invalidate(void); -void rencache_begin_frame(); -void rencache_end_frame(); +void rencache_begin_frame(RenWindow *window_renderer); +void rencache_end_frame(RenWindow *window_renderer); #endif diff --git a/src/renderer.c b/src/renderer.c index 2932784a..53be1046 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -214,7 +214,7 @@ static void font_clear_glyph_cache(RenFont* font) { } } -RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { +RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { FT_Face face = NULL; #ifdef _WIN32 @@ -257,7 +257,7 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial #endif - const int surface_scale = renwin_surface_scale(&window_renderer); + const int surface_scale = renwin_surface_scale(window_renderer); if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale))) goto failure; int len = strlen(path); @@ -300,12 +300,12 @@ failure: return NULL; } -RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style) { +RenFont* ren_font_copy(RenWindow *window_renderer, RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style) { antialiasing = antialiasing == -1 ? font->antialiasing : antialiasing; hinting = hinting == -1 ? font->hinting : hinting; style = style == -1 ? font->style : style; - return ren_font_load(font->path, size, antialiasing, hinting, style); + return ren_font_load(window_renderer, font->path, size, antialiasing, hinting, style); } const char* ren_font_get_path(RenFont *font) { @@ -341,8 +341,8 @@ float ren_font_group_get_size(RenFont **fonts) { return fonts[0]->size; } -void ren_font_group_set_size(RenFont **fonts, float size) { - const int surface_scale = renwin_surface_scale(&window_renderer); +void ren_font_group_set_size(RenWindow *window_renderer, RenFont **fonts, float size) { + const int surface_scale = renwin_surface_scale(window_renderer); for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { font_clear_glyph_cache(fonts[i]); FT_Face face = fonts[i]->face; @@ -360,7 +360,7 @@ int ren_font_group_get_height(RenFont **fonts) { return fonts[0]->height; } -float ren_font_group_get_width(RenFont **fonts, const char *text, size_t len) { +float ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len) { float width = 0; const char* end = text + len; GlyphMetric* metric = NULL; GlyphSet* set = NULL; @@ -372,15 +372,15 @@ float ren_font_group_get_width(RenFont **fonts, const char *text, size_t len) { break; width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance; } - const int surface_scale = renwin_surface_scale(&window_renderer); + const int surface_scale = renwin_surface_scale(window_renderer); return width / surface_scale; } -float ren_draw_text(RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { - SDL_Surface *surface = renwin_get_surface(&window_renderer); - const RenRect clip = window_renderer.clip; +float ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { + SDL_Surface *surface = renwin_get_surface(window_renderer); + const RenRect clip = window_renderer->clip; - const int surface_scale = renwin_surface_scale(&window_renderer); + const int surface_scale = renwin_surface_scale(window_renderer); float pen_x = x * surface_scale; y *= surface_scale; int bytes_per_pixel = surface->format->BytesPerPixel; @@ -404,7 +404,7 @@ float ren_draw_text(RenFont **fonts, const char *text, size_t len, float x, int int end_x = (metric->x1 - metric->x0) + start_x; int glyph_end = metric->x1, glyph_start = metric->x0; if (!metric->loaded && codepoint > 0xFF) - ren_draw_rect((RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); + ren_draw_rect(window_renderer, (RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) { uint8_t* source_pixels = set->surface->pixels; for (int line = metric->y0; line < metric->y1; ++line) { @@ -455,9 +455,9 @@ float ren_draw_text(RenFont **fonts, const char *text, size_t len, float x, int else if(font != last || text == end) { float local_pen_x = text == end ? pen_x + adv : pen_x; if (underline) - ren_draw_rect((RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); if (strikethrough) - ren_draw_rect((RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); last = font; last_pen_x = pen_x; } @@ -476,10 +476,10 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) { return dst; } -void ren_draw_rect(RenRect rect, RenColor color) { +void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { if (color.a == 0) { return; } - const int surface_scale = renwin_surface_scale(&window_renderer); + const int surface_scale = renwin_surface_scale(window_renderer); /* transforms coordinates in pixels. */ rect.x *= surface_scale; @@ -487,7 +487,7 @@ void ren_draw_rect(RenRect rect, RenColor color) { rect.width *= surface_scale; rect.height *= surface_scale; - const RenRect clip = window_renderer.clip; + const RenRect clip = window_renderer->clip; int x1 = rect.x < clip.x ? clip.x : rect.x; int y1 = rect.y < clip.y ? clip.y : rect.y; int x2 = rect.x + rect.width; @@ -495,7 +495,7 @@ void ren_draw_rect(RenRect rect, RenColor color) { x2 = x2 > clip.x + clip.width ? clip.x + clip.width : x2; y2 = y2 > clip.y + clip.height ? clip.y + clip.height : y2; - SDL_Surface *surface = renwin_get_surface(&window_renderer); + SDL_Surface *surface = renwin_get_surface(window_renderer); SDL_Rect dest_rect = { x1, y1, x2 - x1, y2 - y1 }; if (color.a == 0xff) { uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b); @@ -508,16 +508,17 @@ void ren_draw_rect(RenRect rect, RenColor color) { } /*************** Window Management ****************/ -void ren_free_window_resources() { +void ren_free_window_resources(RenWindow *window_renderer) { extern uint8_t *command_buf; extern size_t command_buf_size; - renwin_free(&window_renderer); + renwin_free(window_renderer); SDL_FreeSurface(draw_rect_surface); free(command_buf); command_buf = NULL; command_buf_size = 0; } +// TODO remove global and return RenWindow* void ren_init(SDL_Window *win) { assert(win); int error = FT_Init_FreeType( &library ); @@ -533,30 +534,29 @@ void ren_init(SDL_Window *win) { } -void ren_resize_window() { - renwin_resize_surface(&window_renderer); +void ren_resize_window(RenWindow *window_renderer) { + renwin_resize_surface(window_renderer); } -void ren_update_rects(RenRect *rects, int count) { +void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count) { static bool initial_frame = true; if (initial_frame) { - renwin_show_window(&window_renderer); + renwin_show_window(window_renderer); initial_frame = false; } - renwin_update_rects(&window_renderer, rects, count); + renwin_update_rects(window_renderer, rects, count); } -void ren_set_clip_rect(RenRect rect) { - renwin_set_clip_rect(&window_renderer, rect); +void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect) { + renwin_set_clip_rect(window_renderer, rect); } -void ren_get_size(int *x, int *y) { - RenWindow *ren = &window_renderer; - const int scale = renwin_surface_scale(ren); - SDL_Surface *surface = renwin_get_surface(ren); +void ren_get_size(RenWindow *window_renderer, int *x, int *y) { + const int scale = renwin_surface_scale(window_renderer); + SDL_Surface *surface = renwin_get_surface(window_renderer); *x = surface->w / scale; *y = surface->h / scale; } diff --git a/src/renderer.h b/src/renderer.h index c1b80f51..46e04341 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -11,6 +11,7 @@ #define UNUSED #endif + #define FONT_FALLBACK_MAX 10 typedef struct RenFont RenFont; typedef enum { FONT_HINTING_NONE, FONT_HINTING_SLIGHT, FONT_HINTING_FULL } ERenFontHinting; @@ -19,26 +20,30 @@ typedef enum { FONT_STYLE_BOLD = 1, FONT_STYLE_ITALIC = 2, FONT_STYLE_UNDERLINE typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect; -RenFont* ren_font_load(const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style); -RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style); +struct RenWindow; +typedef struct RenWindow RenWindow; +extern RenWindow window_renderer; + +RenFont* ren_font_load(RenWindow *window_renderer, const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style); +RenFont* ren_font_copy(RenWindow *window_renderer, RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style); const char* ren_font_get_path(RenFont *font); void ren_font_free(RenFont *font); int ren_font_group_get_tab_size(RenFont **font); int ren_font_group_get_height(RenFont **font); float ren_font_group_get_size(RenFont **font); -void ren_font_group_set_size(RenFont **font, float size); +void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); -float ren_font_group_get_width(RenFont **font, const char *text, size_t len); -float ren_draw_text(RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +float ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); +float ren_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); -void ren_draw_rect(RenRect rect, RenColor color); +void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color); void ren_init(SDL_Window *win); -void ren_resize_window(); -void ren_update_rects(RenRect *rects, int count); -void ren_set_clip_rect(RenRect rect); -void ren_get_size(int *x, int *y); /* Reports the size in points. */ -void ren_free_window_resources(); +void ren_resize_window(RenWindow *window_renderer); +void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count); +void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect); +void ren_get_size(RenWindow *window_renderer, int *x, int *y); /* Reports the size in points. */ +void ren_free_window_resources(RenWindow *window_renderer); #endif From ccceb2a65cf05f530283a8722ad4a828b2053c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Tue, 24 Jan 2023 15:25:56 -0400 Subject: [PATCH 014/176] ci: fix msys build now requiring ca-certificates (#1348) Thanks to Guldoman who discovered the cause for meson failing to validate SSL certificates which turned out to be MSYS now requiring ca-certificates package installed for the different architectures. --- scripts/install-dependencies.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh index d817097d..1290cfcc 100644 --- a/scripts/install-dependencies.sh +++ b/scripts/install-dependencies.sh @@ -63,10 +63,10 @@ main() { elif [[ "$OSTYPE" == "msys" ]]; then if [[ $lhelper == true ]]; then pacman --noconfirm -S \ - ${MINGW_PACKAGE_PREFIX}-{gcc,meson,ninja,ntldd,pkg-config,mesa} unzip + ${MINGW_PACKAGE_PREFIX}-{ca-certificates,gcc,meson,ninja,ntldd,pkg-config,mesa} unzip else pacman --noconfirm -S \ - ${MINGW_PACKAGE_PREFIX}-{gcc,meson,ninja,ntldd,pkg-config,mesa,freetype,pcre2,SDL2} unzip + ${MINGW_PACKAGE_PREFIX}-{ca-certificates,gcc,meson,ninja,ntldd,pkg-config,mesa,freetype,pcre2,SDL2} unzip fi fi } From 8fbc843260b0475c98f240982dbd024fe924da1a Mon Sep 17 00:00:00 2001 From: jgmdev Date: Wed, 25 Jan 2023 17:28:34 -0400 Subject: [PATCH 015/176] gh workflow: fix path to macOS arm64 cross file --- .github/workflows/release.yml | 2 +- scripts/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a8d97e54..ea0e1848 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,7 +93,7 @@ jobs: LiteXL-${{ env.INSTALL_REF }}-addons-x86_64.AppImage build_macos: - name: macOS (x86_64) + name: macOS needs: release runs-on: macos-11 strategy: diff --git a/scripts/build.sh b/scripts/build.sh index 5812bd8b..82eb95f0 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -111,7 +111,7 @@ main() { if [[ $platform == "macos" ]]; then macos_version_min=10.11 if [[ $CROSS_ARCH == "arm64" ]]; then - cross_file="--cross-file resources/macos/macos_arm64.conf" + cross_file="--cross-file resources/cross/macos_arm64.txt" macos_version_min=11.0 fi export MACOSX_DEPLOYMENT_TARGET=$macos_version_min From f74716b436602a72598c7cfd1d4d057d4b114c2c Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 30 Jan 2023 11:10:11 -0500 Subject: [PATCH 016/176] Getting rid of annoying forward slash on windows. (#1345) --- data/core/init.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index d8f77b19..130bc97a 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -18,13 +18,13 @@ local Doc local core = {} local function load_session() - local ok, t = pcall(dofile, USERDIR .. "/session.lua") + local ok, t = pcall(dofile, USERDIR .. PATHSEP .. "session.lua") return ok and t or {} end local function save_session() - local fp = io.open(USERDIR .. "/session.lua", "w") + local fp = io.open(USERDIR .. PATHSEP .. "session.lua", "w") if fp then fp:write("return {recents=", common.serialize(core.recent_projects), ", window=", common.serialize(table.pack(system.get_window_size())), @@ -607,7 +607,7 @@ function core.load_user_directory() if not stat_dir then create_user_directory() end - local init_filename = USERDIR .. "/init.lua" + local init_filename = USERDIR .. PATHSEP .. "init.lua" local stat_file = system.get_file_info(init_filename) if not stat_file then write_user_init_file(init_filename) @@ -924,7 +924,7 @@ end local function get_plugin_details(filename) local info = system.get_file_info(filename) if info ~= nil and info.type == "dir" then - filename = filename .. "/init.lua" + filename = filename .. PATHSEP .. "init.lua" info = system.get_file_info(filename) end if not info or not filename:match("%.lua$") then return false end @@ -963,7 +963,7 @@ function core.load_plugins() } local files, ordered = {}, {} for _, root_dir in ipairs {DATADIR, USERDIR} do - local plugin_dir = root_dir .. "/plugins" + local plugin_dir = root_dir .. PATHSEP .. "plugins" for _, filename in ipairs(system.list_dir(plugin_dir) or {}) do if not files[filename] then table.insert( @@ -978,7 +978,7 @@ function core.load_plugins() for _, plugin in ipairs(ordered) do local dir = files[plugin.file] local name = plugin.file:match("(.-)%.lua$") or plugin.file - local is_lua_file, details = get_plugin_details(dir .. '/' .. plugin.file) + local is_lua_file, details = get_plugin_details(dir .. PATHSEP .. plugin.file) plugin.valid = is_lua_file plugin.name = name @@ -1425,7 +1425,7 @@ end function core.on_error(err) -- write error to file - local fp = io.open(USERDIR .. "/error.txt", "wb") + local fp = io.open(USERDIR .. PATHSEP .. "error.txt", "wb") fp:write("Error: " .. tostring(err) .. "\n") fp:write(debug.traceback("", 4) .. "\n") fp:close() From 4ef4b99c7a0e97d8af6318597819416e15b315f7 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 30 Jan 2023 11:12:44 -0500 Subject: [PATCH 017/176] Abstracted open_doc out to allow for more easy overriding. (#1344) --- data/plugins/treeview.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index dee02846..9aa39ca2 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -441,6 +441,11 @@ function TreeView:toggle_expand(toggle) end +function TreeView:open_doc(filename) + core.root_view:open_doc(core.open_doc(filename)) +end + + -- init local view = TreeView() local node = core.root_view:get_active_node() @@ -610,8 +615,7 @@ command.add(TreeView, { if core.last_active_view and core.active_view == view then core.set_active_view(core.last_active_view) end - local doc_filename = core.normalize_to_project_dir(item.abs_filename) - core.root_view:open_doc(core.open_doc(doc_filename)) + view:open_doc(core.normalize_to_project_dir(item.abs_filename)) end) end end, @@ -759,7 +763,7 @@ command.add( local file = io.open(doc_filename, "a+") file:write("") file:close() - core.root_view:open_doc(core.open_doc(doc_filename)) + view:open_doc(doc_filename) core.log("Created %s", doc_filename) end, suggest = function(text) @@ -801,8 +805,8 @@ local projectsearch = pcall(require, "plugins.projectsearch") if projectsearch then menu:register(function() return view.hovered_item and view.hovered_item.type == "dir" - end, { - { text = "Find in directory", command = "treeview:search-in-directory" } + end, { + { text = "Find in directory", command = "treeview:search-in-directory" } }) command.add(function() return view.hovered_item and view.hovered_item.type == "dir" From 3f917dcb4520bbbb8281b4f78afde57734611531 Mon Sep 17 00:00:00 2001 From: sammyette Date: Mon, 30 Jan 2023 12:43:26 -0400 Subject: [PATCH 018/176] feat: add option to only draw whitespace if it is within selection (#1312) * refactor: remove sort_positions usage * refactor: move draw conditional to has_any_selection and other changes - snake case (sssss) - break after finding selection * fix: typo of config plugins * fix: do check for show selected only properly * feat: only draw within selection per substitution * `drawwhitespace`: Make `show_selected_only` work properly --------- Co-authored-by: Guldoman --- data/plugins/drawwhitespace.lua | 49 +++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/data/plugins/drawwhitespace.lua b/data/plugins/drawwhitespace.lua index 89be875d..6c422172 100644 --- a/data/plugins/drawwhitespace.lua +++ b/data/plugins/drawwhitespace.lua @@ -1,5 +1,6 @@ -- mod-version:3 +local core = require "core" local style = require "core.style" local DocView = require "core.docview" local common = require "core.common" @@ -11,6 +12,7 @@ config.plugins.drawwhitespace = common.merge({ show_leading = true, show_trailing = true, show_middle = true, + show_selected_only = false, show_middle_min = 1, @@ -64,6 +66,13 @@ config.plugins.drawwhitespace = common.merge({ type = "toggle", default = true, }, + { + label = "Show Selected Only", + description = "Only draw whitespaces if it is within a selection.", + path = "show_selected_only", + type = "toggle", + default = false, + }, { label = "Show Trailing as Error", description = "Uses an error square to spot them easily, requires 'Show Trailing' enabled.", @@ -292,11 +301,41 @@ function DocView:draw_line_text(idx, x, y) for i=1,#cache,4 do local tx = cache[i + 1] + x local tw = cache[i + 2] - if tx <= x2 then - local sub = cache[i] - local color = cache[i + 3] - if tx + tw >= x1 then - tx = renderer.draw_text(font, sub, tx, ty, color) + local sub = cache[i] + local color = cache[i + 3] + local partials = {} + if config.plugins.drawwhitespace.show_selected_only and self.doc:has_any_selection() then + for _, l1, c1, l2, c2 in self.doc:get_selections(true) do + if idx > l1 and idx < l2 then + -- Between selection lines, so everything is selected + table.insert(partials, false) + elseif idx == l1 and idx == l2 then + -- Both ends of the selection are on the same line + local _x1 = math.max(cache[i + 1], self:get_col_x_offset(idx, c1)) + local _x2 = math.min((cache[i + 1] + tw), self:get_col_x_offset(idx, c2)) + if _x1 < _x2 then + table.insert(partials, {_x1 + x, 0, _x2 - _x1, math.huge}) + end + elseif idx >= l1 and idx <= l2 then + -- On one of the selection ends + if idx == l1 then -- Start of the selection + local _x = math.max(cache[i + 1], self:get_col_x_offset(idx, c1)) + table.insert(partials, {_x + x, 0, math.huge, math.huge}) + else -- End of the selection + local _x = math.min((cache[i + 1] + tw), self:get_col_x_offset(idx, c2)) + table.insert(partials, {0, 0, _x + x, math.huge}) + end + end + end + end + + if #partials == 0 and not config.plugins.drawwhitespace.show_selected_only then + renderer.draw_text(font, sub, tx, ty, color) + else + for _, p in pairs(partials) do + if p then core.push_clip_rect(table.unpack(p)) end + renderer.draw_text(font, sub, tx, ty, color) + if p then core.pop_clip_rect() end end end end From aef400bc90e38088a1bdd01671784bd275559dc7 Mon Sep 17 00:00:00 2001 From: Himura Kazuto Date: Tue, 31 Jan 2023 01:00:48 +0800 Subject: [PATCH 019/176] Replace globally when replacing from selection (#1331) --- data/core/commands/findreplace.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua index 4a456aae..0125a0a1 100644 --- a/data/core/commands/findreplace.lua +++ b/data/core/commands/findreplace.lua @@ -211,6 +211,7 @@ command.add("core.docview!", { ["find-replace:replace"] = function() local l1, c1, l2, c2 = doc():get_selection() local selected_text = doc():get_text(l1, c1, l2, c2) + doc():set_selection(l2, c2, l2, c2) replace("Text", l1 == l2 and selected_text or "", function(text, old, new) if not find_regex then return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) From b634b6186621007125c89b90baf76df48314d1c6 Mon Sep 17 00:00:00 2001 From: vqn <85911372+vqns@users.noreply.github.com> Date: Mon, 30 Jan 2023 18:36:17 +0100 Subject: [PATCH 020/176] Context menu fixes and keyboard navigation (#1338) * fix Doc contextmenu not registering commands if scale plugin is not found * fix TreeView contextmenu commands not working if the mouse hovers DocView * add keyboard navigation to TreeView contextmenu * fix incorrect contextmenu predicate --- data/plugins/contextmenu.lua | 31 ++++++++----- data/plugins/treeview.lua | 87 ++++++++++++++++++++++++++++-------- 2 files changed, 87 insertions(+), 31 deletions(-) diff --git a/data/plugins/contextmenu.lua b/data/plugins/contextmenu.lua index db6d28db..26afbb57 100644 --- a/data/plugins/contextmenu.lua +++ b/data/plugins/contextmenu.lua @@ -4,6 +4,7 @@ local command = require "core.command" local keymap = require "core.keymap" local ContextMenu = require "core.contextmenu" local RootView = require "core.rootview" +local config = require "core.config" local menu = ContextMenu() local on_view_mouse_pressed = RootView.on_view_mouse_pressed @@ -61,18 +62,24 @@ keymap.add { ["up"] = "context:focus-previous" } keymap.add { ["down"] = "context:focus-next" } keymap.add { ["escape"] = "context:hide" } -if require("plugins.scale") then - menu:register("core.docview", { - { text = "Cut", command = "doc:cut" }, - { text = "Copy", command = "doc:copy" }, - { text = "Paste", command = "doc:paste" }, - { text = "Font +", command = "scale:increase" }, - { text = "Font -", command = "scale:decrease" }, - { text = "Font Reset", command = "scale:reset" }, - ContextMenu.DIVIDER, - { text = "Find", command = "find-replace:find" }, - { text = "Replace", command = "find-replace:replace" } - }) + +local cmds = { + { text = "Cut", command = "doc:cut" }, + { text = "Copy", command = "doc:copy" }, + { text = "Paste", command = "doc:paste" }, + ContextMenu.DIVIDER, + { text = "Find", command = "find-replace:find" }, + { text = "Replace", command = "find-replace:replace" } +} + +if config.plugins.scale ~= false and require("plugins.scale") then + table.move(cmds, 4, 6, 7) + cmds[4] = { text = "Font +", command = "scale:increase" } + cmds[5] = { text = "Font -", command = "scale:decrease" } + cmds[6] = { text = "Font Reset", command = "scale:reset" } end +menu:register("core.docview", cmds) + + return menu diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 9aa39ca2..78015f2c 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -523,15 +523,19 @@ local function is_primary_project_folder(path) return core.project_dir == path end -menu:register(function() return view.hovered_item end, { + +local function treeitem() return view.hovered_item or view.selected_item end + + +menu:register(function() return core.active_view:is(TreeView) and treeitem() end, { { text = "Open in System", command = "treeview:open-in-system" }, ContextMenu.DIVIDER }) menu:register( function() - return view.hovered_item - and not is_project_folder(view.hovered_item.abs_filename) + local item = treeitem() + return core.active_view:is(TreeView) and item and not is_project_folder(item.abs_filename) end, { { text = "Rename", command = "treeview:rename" }, @@ -541,7 +545,8 @@ menu:register( menu:register( function() - return view.hovered_item and view.hovered_item.type == "dir" + local item = treeitem() + return core.active_view:is(TreeView) and item and item.type == "dir" end, { { text = "New File", command = "treeview:new-file" }, @@ -551,9 +556,10 @@ menu:register( menu:register( function() - return view.hovered_item - and not is_primary_project_folder(view.hovered_item.abs_filename) - and is_project_folder(view.hovered_item.abs_filename) + local item = treeitem() + return core.active_view:is(TreeView) and item + and not is_primary_project_folder(item.abs_filename) + and is_project_folder(item.abs_filename) end, { { text = "Remove directory", command = "treeview:remove-project-directory" }, @@ -594,7 +600,10 @@ command.add(nil, { end }) -command.add(TreeView, { +command.add( + function() + return not menu.show_context_menu and core.active_view:extends(TreeView), TreeView + end, { ["treeview:next"] = function() local item, _, item_y = view:get_next(view.selected_item) view:set_selection(item, item_y) @@ -661,22 +670,33 @@ command.add(TreeView, { view:toggle_expand(true) end end, + + ["treeview-context:show"] = function() + if view.hovered_item then + menu:show(view.cursor_pos.x, view.cursor_pos.y) + return + end + + local item = view.selected_item + if not item then return end + + local x, y + for _i, _x, _y, _w, _h in view:each_item() do + if _i == item then + x = _x + _w / 2 + y = _y + _h / 2 + break + end + end + menu:show(x, y) + end }) -local function treeitem() return view.hovered_item or view.selected_item end - - command.add( function() local item = treeitem() - return item ~= nil - and ( - core.active_view == view or core.active_view == menu - or (view.toolbar and core.active_view == view.toolbar) - -- sometimes the context menu is shown on top of statusbar - or core.active_view == core.status_view - ), item + return item ~= nil and (core.active_view == view or menu.show_context_menu), item end, { ["treeview:delete"] = function(item) local filename = item.abs_filename @@ -804,7 +824,8 @@ command.add( local projectsearch = pcall(require, "plugins.projectsearch") if projectsearch then menu:register(function() - return view.hovered_item and view.hovered_item.type == "dir" + local item = treeitem() + return item and item.type == "dir" end, { { text = "Find in directory", command = "treeview:search-in-directory" } }) @@ -829,6 +850,25 @@ command.add(function() }) +command.add( + function() + return menu.show_context_menu == true and core.active_view:is(TreeView) + end, { + ["treeview-context:focus-previous"] = function() + menu:focus_previous() + end, + ["treeview-context:focus-next"] = function() + menu:focus_next() + end, + ["treeview-context:hide"] = function() + menu:hide() + end, + ["treeview-context:on-selected"] = function() + menu:call_selected_item() + end, +}) + + keymap.add { ["ctrl+\\"] = "treeview:toggle", ["up"] = "treeview:previous", @@ -844,6 +884,15 @@ keymap.add { ["ctrl+lclick"] = "treeview:new-folder" } +keymap.add { + ["menu"] = "treeview-context:show", + ["return"] = "treeview-context:on-selected", + ["up"] = "treeview-context:focus-previous", + ["down"] = "treeview-context:focus-next", + ["escape"] = "treeview-context:hide" +} + + -- The config specification used by gui generators config.plugins.treeview.config_spec = { name = "Treeview", From ab3d6004a193f1fb39cbd44f99301f9cc0dd3b6f Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Wed, 1 Feb 2023 06:26:15 +0800 Subject: [PATCH 021/176] fix: exec() error not returned to parent (#1363) * fix: exec() error not returned to parent * chore: remove accidental lua.h inclusion --- src/api/process.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/api/process.c b/src/api/process.c index 60efe5f9..081e6ab6 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -293,6 +293,7 @@ static int process_start(lua_State* L) { CloseHandle(self->process_information.hProcess); CloseHandle(self->process_information.hThread); #else + int control_pipe[2] = { 0 }; for (int i = 0; i < 3; ++i) { // Make only the parents fd's non-blocking. Children should block. if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1) { lua_pushfstring(L, "Error creating pipes: %s", strerror(errno)); @@ -300,12 +301,25 @@ static int process_start(lua_State* L) { goto cleanup; } } + // create a pipe to get the exit code of exec() + if (pipe(control_pipe) == -1) { + lua_pushfstring(L, "Error creating control pipe: %s", strerror(errno)); + retval = -1; + goto cleanup; + } + if (fcntl(control_pipe[1], F_SETFD, FD_CLOEXEC) == -1) { + lua_pushfstring(L, "Error setting FD_CLOEXEC: %s", strerror(errno)); + retval = -1; + goto cleanup; + } + self->pid = (long)fork(); if (self->pid < 0) { lua_pushfstring(L, "Error running fork: %s.", strerror(errno)); retval = -1; goto cleanup; } else if (!self->pid) { + // child process if (!detach) setpgid(0,0); for (int stream = 0; stream < 3; ++stream) { @@ -320,12 +334,39 @@ static int process_start(lua_State* L) { for (set = 0; set < env_len && setenv(env_names[set], env_values[set], 1) == 0; ++set); if (set == env_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1)) execvp(cmd[0], (char** const)cmd); - const char* msg = strerror(errno); - size_t result = write(STDERR_FD, msg, strlen(msg)+1); - _exit(result == strlen(msg)+1 ? -1 : -2); + write(control_pipe[1], &errno, sizeof(errno)); + _exit(-1); } + // close our write side so we can read from child + close(control_pipe[1]); + control_pipe[1] = 0; + + // wait for child process to respond + int sz, process_rc; + while ((sz = read(control_pipe[0], &process_rc, sizeof(int))) == -1) { + if (errno == EPIPE) break; + if (errno != EINTR) { + lua_pushfstring(L, "Error getting child process status: %s", strerror(errno)); + retval = -1; + goto cleanup; + } + } + + if (sz) { + // read something from pipe; exec failed + int status; + waitpid(self->pid, &status, 0); + lua_pushfstring(L, "Error creating child process: %s", strerror(process_rc)); + retval = -1; + goto cleanup; + } + #endif cleanup: + #ifndef _WIN32 + if (control_pipe[0]) close(control_pipe[0]); + if (control_pipe[1]) close(control_pipe[1]); + #endif for (size_t i = 0; i < env_len; ++i) { free((char*)env_names[i]); free((char*)env_values[i]); From 57cd4e294903c5bf1036c5e17f841d9338a0aad0 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 2 Feb 2023 01:28:21 +0100 Subject: [PATCH 022/176] Make mod-version follow semver (#1036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make mod-version follow semver Now plugins can optionally specify the minor and patch version they support. If no minor or patch version is specified, it's considered 0. Plugins are only loaded if they have the same major version and a smaller or equal minor+patch version. * Add modversion to logging and plugin mismatch nagview --------- Co-authored-by: Jefferson González --- data/core/init.lua | 52 ++++++++++++++++++++++++++++++++++++--------- data/core/start.lua | 5 ++++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 130bc97a..09bf5a4c 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -673,6 +673,9 @@ end function core.init() + core.log_items = {} + core.log_quiet("Lite XL version %s - mod-version %s", VERSION, MOD_VERSION_STRING) + command = require "core.command" keymap = require "core.keymap" dirwatch = require "core.dirwatch" @@ -726,7 +729,6 @@ function core.init() core.frame_start = 0 core.clip_rect_stack = {{ 0,0,0,0 }} - core.log_items = {} core.docs = {} core.cursor_clipboard = {} core.cursor_clipboard_whole_line = {} @@ -824,15 +826,19 @@ function core.init() local msg = {} for _, entry in pairs(plugins_refuse_list) do if #entry.plugins > 0 then - msg[#msg + 1] = string.format("Plugins from directory \"%s\":\n%s", common.home_encode(entry.dir), table.concat(entry.plugins, "\n")) + local msg_list = {} + for _, p in pairs(entry.plugins) do + table.insert(msg_list, string.format("%s[%s]", p.file, p.version_string)) + end + msg[#msg + 1] = string.format("Plugins from directory \"%s\":\n%s", common.home_encode(entry.dir), table.concat(msg_list, "\n")) end end core.nag_view:show( "Refused Plugins", string.format( - "Some plugins are not loaded due to version mismatch.\n\n%s.\n\n" .. + "Some plugins are not loaded due to version mismatch. Expected version %s.\n\n%s.\n\n" .. "Please download a recent version from https://github.com/lite-xl/lite-xl-plugins.", - table.concat(msg, ".\n\n")), + MOD_VERSION_STRING, table.concat(msg, ".\n\n")), opt, function(item) if item.text == "Exit" then os.exit(1) end end) @@ -921,6 +927,8 @@ function core.restart() end +local mod_version_regex = + regex.compile([[--.*mod-version:(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:$|\s)]]) local function get_plugin_details(filename) local info = system.get_file_info(filename) if info ~= nil and info.type == "dir" then @@ -932,17 +940,32 @@ local function get_plugin_details(filename) if not f then return false end local priority = false local version_match = false + local major, minor, patch + for line in f:lines() do if not version_match then - local mod_version = line:match('%-%-.*%f[%a]mod%-version%s*:%s*(%d+)') - if mod_version then - version_match = (mod_version == MOD_VERSION) + local _major, _minor, _patch = mod_version_regex:match(line) + if _major then + _major = tonumber(_major) or 0 + _minor = tonumber(_minor) or 0 + _patch = tonumber(_patch) or 0 + major, minor, patch = _major, _minor, _patch + + version_match = major == MOD_VERSION_MAJOR + if version_match then + version_match = minor <= MOD_VERSION_MINOR + end + if version_match then + version_match = patch <= MOD_VERSION_PATCH + end end end + if not priority then priority = line:match('%-%-.*%f[%a]priority%s*:%s*(%d+)') if priority then priority = tonumber(priority) end end + if version_match then break end @@ -950,6 +973,7 @@ local function get_plugin_details(filename) f:close() return true, { version_match = version_match, + version = major and {major, minor, patch} or {}, priority = priority or 100 } end @@ -985,6 +1009,8 @@ function core.load_plugins() plugin.dir = dir plugin.priority = details and details.priority or 100 plugin.version_match = details and details.version_match or false + plugin.version = details and details.version or {} + plugin.version_string = #plugin.version > 0 and table.concat(plugin.version, ".") or "unknown" end -- sort by priority or name for plugins that have same priority @@ -1000,21 +1026,27 @@ function core.load_plugins() if plugin.valid then if not config.skip_plugins_version and not plugin.version_match then core.log_quiet( - "Version mismatch for plugin %q from %s", + "Version mismatch for plugin %q[%s] from %s", plugin.name, + plugin.version_string, plugin.dir ) local rlist = plugin.dir:find(USERDIR, 1, true) == 1 and 'userdir' or 'datadir' local list = refused_list[rlist].plugins - table.insert(list, plugin.file) + table.insert(list, plugin) elseif config.plugins[plugin.name] ~= false then local start = system.get_time() local ok, loaded_plugin = core.try(require, "plugins." .. plugin.name) if ok then + local plugin_version = "" + if plugin.version_string ~= MOD_VERSION_STRING then + plugin_version = "["..plugin.version_string.."]" + end core.log_quiet( - "Loaded plugin %q from %s in %.1fms", + "Loaded plugin %q%s from %s in %.1fms", plugin.name, + plugin_version, plugin.dir, (system.get_time() - start) * 1000 ) diff --git a/data/core/start.lua b/data/core/start.lua index d504108a..bb10d7ef 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -1,6 +1,9 @@ -- this file is used by lite-xl to setup the Lua environment when starting VERSION = "@PROJECT_VERSION@" -MOD_VERSION = "3" +MOD_VERSION_MAJOR = 3 +MOD_VERSION_MINOR = 0 +MOD_VERSION_PATCH = 0 +MOD_VERSION_STRING = string.format("%d.%d.%d", MOD_VERSION_MAJOR, MOD_VERSION_MINOR, MOD_VERSION_PATCH) SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or SCALE PATHSEP = package.config:sub(1, 1) From d68583b688d91dc601a0de772f5d1be7f528a838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Mon, 6 Feb 2023 13:32:44 -0400 Subject: [PATCH 023/176] Improved plugins config table handling (#1356) * Warns user if trying to disable a plugin that is already enabled when doing `config.plugins.plugin_name = false` and also prevents replacing the current plugin config table with the false value to mitigate runtime issues. * Uses a merge strategy by default when assigning a table to a plugin config to prevent a user from removing a plugin default config values as experienced and explained on this issue lite-xl-plugins#158 * This change is basically backwards compatible, but will require a change on the settings ui plugin on how it checks for already enabled plugins, since rawget will no longer be a working hack or workaround for this. * As suggested by Adam dropped loaded key and switched to package.loaded --- data/core/config.lua | 46 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/data/core/config.lua b/data/core/config.lua index ecdcfdb5..fc5da98a 100644 --- a/data/core/config.lua +++ b/data/core/config.lua @@ -1,3 +1,5 @@ +local common = require "core.common" + local config = {} config.fps = 60 @@ -55,13 +57,47 @@ config.max_clicks = 3 -- set as true to be able to test non supported plugins config.skip_plugins_version = false +-- holds the plugins real config table +local plugins_config = {} + +-- virtual representation of plugins config table config.plugins = {} --- Allow you to set plugin configs even if we haven't seen the plugin before. + +-- allows virtual access to the plugins config table setmetatable(config.plugins, { - __index = function(t, k) - local v = rawget(t, k) - if v == true or v == nil then v = {} rawset(t, k, v) end - return v + __index = function(_, k) + if not plugins_config[k] then + plugins_config[k] = { enabled = true, config = {} } + end + if plugins_config[k].enabled ~= false then + return plugins_config[k].config + end + return false + end, + __newindex = function(_, k, v) + if not plugins_config[k] then + plugins_config[k] = { enabled = nil, config = {} } + end + if v == false and package.loaded["plugins."..k] then + local core = require "core" + core.warn("[%s] is already enabled, restart the editor for the change to take effect", k) + return + elseif plugins_config[k].enabled == false and v ~= false then + plugins_config[k].enabled = true + end + if v == false then + plugins_config[k].enabled = false + elseif type(v) == "table" then + plugins_config[k].enabled = true + plugins_config[k].config = common.merge(plugins_config[k].config, v) + end + end, + __pairs = function() + return coroutine.wrap(function() + for name, status in pairs(plugins_config) do + coroutine.yield(name, status.config) + end + end) end }) From 1c2571bad766acb97f62815a42b91b275004fe7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Mon, 6 Feb 2023 13:34:59 -0400 Subject: [PATCH 024/176] Restore in-selection replace as discussed in #1331 (#1368) --- data/core/commands/findreplace.lua | 32 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua index 0125a0a1..3d364dc6 100644 --- a/data/core/commands/findreplace.lua +++ b/data/core/commands/findreplace.lua @@ -193,6 +193,23 @@ local function select_next(reverse) if l2 then doc():set_selection(l2, c2, l1, c1) end end +---@param in_selection? boolean whether to replace in the selections only, or in the whole file. +local function find_replace(in_selection) + local l1, c1, l2, c2 = doc():get_selection() + local selected_text = "" + if not in_selection then + selected_text = doc():get_text(l1, c1, l2, c2) + doc():set_selection(l2, c2, l2, c2) + end + replace("Text", l1 == l2 and selected_text or "", function(text, old, new) + if not find_regex then + return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) + end + local result, matches = regex.gsub(regex.compile(old, "m"), text, new) + return result, matches + end) +end + command.add(has_unique_selection, { ["find-replace:select-next"] = select_next, ["find-replace:select-previous"] = function() select_next(true) end, @@ -209,16 +226,11 @@ command.add("core.docview!", { end, ["find-replace:replace"] = function() - local l1, c1, l2, c2 = doc():get_selection() - local selected_text = doc():get_text(l1, c1, l2, c2) - doc():set_selection(l2, c2, l2, c2) - replace("Text", l1 == l2 and selected_text or "", function(text, old, new) - if not find_regex then - return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) - end - local result, matches = regex.gsub(regex.compile(old, "m"), text, new) - return result, matches - end) + find_replace() + end, + + ["find-replace:replace-in-selection"] = function() + find_replace(true) end, ["find-replace:replace-symbol"] = function() From 84039331a53e86491533405ab6e43be95fd59f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Mon, 6 Feb 2023 13:38:00 -0400 Subject: [PATCH 025/176] NagView: properly rescale on scale change (#1379) * drop font option since style.font is always used --- data/core/commands/doc.lua | 4 ++-- data/core/init.lua | 8 ++++---- data/core/nagview.lua | 14 ++++++++++++-- data/plugins/autoreload.lua | 4 ++-- data/plugins/treeview.lua | 4 ++-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 6d32219a..ebaf698c 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -44,8 +44,8 @@ local function save(filename) else core.error(err) core.nag_view:show("Saving failed", string.format("Could not save \"%s\" do you want to save to another location?", doc().filename), { - { font = style.font, text = "No", default_no = true }, - { font = style.font, text = "Yes" , default_yes = true } + { text = "No", default_no = true }, + { text = "Yes", default_yes = true } }, function(item) if item.text == "Yes" then core.add_thread(function() diff --git a/data/core/init.lua b/data/core/init.lua index 09bf5a4c..f7063a26 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -820,8 +820,8 @@ function core.init() if #plugins_refuse_list.userdir.plugins > 0 or #plugins_refuse_list.datadir.plugins > 0 then local opt = { - { font = style.font, text = "Exit", default_no = true }, - { font = style.font, text = "Continue" , default_yes = true } + { text = "Exit", default_no = true }, + { text = "Continue", default_yes = true } } local msg = {} for _, entry in pairs(plugins_refuse_list) do @@ -866,8 +866,8 @@ function core.confirm_close_docs(docs, close_fn, ...) end local args = {...} local opt = { - { font = style.font, text = "Yes", default_yes = true }, - { font = style.font, text = "No" , default_no = true } + { text = "Yes", default_yes = true }, + { text = "No", default_no = true } } core.nag_view:show("Unsaved Changes", text, opt, function(item) if item.text == "Yes" then close_fn(table.unpack(args)) end diff --git a/data/core/nagview.lua b/data/core/nagview.lua index 9c373f58..b66da75c 100644 --- a/data/core/nagview.lua +++ b/data/core/nagview.lua @@ -91,7 +91,7 @@ function NagView:each_option() for i = #self.options, 1, -1 do opt = self.options[i] - bw = opt.font:get_width(opt.text) + 2 * BORDER_WIDTH + style.padding.x + bw = style.font:get_width(opt.text) + 2 * BORDER_WIDTH + style.padding.x ox = ox - bw - style.padding.x coroutine.yield(i, opt, ox,oy,bw,bh) @@ -230,7 +230,7 @@ local function draw_nagview_message(self) renderer.draw_rect(lx,ly,uw,UNDERLINE_WIDTH, style.nagbar_text) end - common.draw_text(opt.font, style.nagbar_text, opt.text, "center", fx,fy,fw,fh) + common.draw_text(style.font, style.nagbar_text, opt.text, "center", fx,fy,fw,fh) end self:draw_scrollbar() @@ -245,6 +245,16 @@ function NagView:draw() core.root_view:defer_draw(draw_nagview_message, self) end +function NagView:on_scale_change(new_scale, old_scale) + BORDER_WIDTH = common.round(1 * new_scale) + UNDERLINE_WIDTH = common.round(2 * new_scale) + UNDERLINE_MARGIN = common.round(1 * new_scale) + self.target_height = math.max( + self:get_message_height(), + self:get_buttons_height() + ) +end + function NagView:get_message_height() local h = 0 for str in string.gmatch(self.message, "(.-)\n") do diff --git a/data/plugins/autoreload.lua b/data/plugins/autoreload.lua index cde1c085..8286d62f 100644 --- a/data/plugins/autoreload.lua +++ b/data/plugins/autoreload.lua @@ -46,8 +46,8 @@ end local function check_prompt_reload(doc) if doc and doc.deferred_reload then core.nag_view:show("File Changed", doc.filename .. " has changed. Reload this file?", { - { font = style.font, text = "Yes", default_yes = true }, - { font = style.font, text = "No" , default_no = true } + { text = "Yes", default_yes = true }, + { text = "No", default_no = true } }, function(item) if item.text == "Yes" then reload_doc(doc) end doc.deferred_reload = false diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 78015f2c..ff646847 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -709,8 +709,8 @@ command.add( local file_type = file_info.type == "dir" and "Directory" or "File" -- Ask before deleting local opt = { - { font = style.font, text = "Yes", default_yes = true }, - { font = style.font, text = "No" , default_no = true } + { text = "Yes", default_yes = true }, + { text = "No", default_no = true } } core.nag_view:show( string.format("Delete %s", file_type), From ce9d540e92552bd59467633e1ca3983b98f2f874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Mon, 6 Feb 2023 13:40:12 -0400 Subject: [PATCH 026/176] plugins scale: also rescale style.expanded_scrollbar_size (#1380) --- data/plugins/scale.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/data/plugins/scale.lua b/data/plugins/scale.lua index 0c9c8657..7c9e6d4c 100644 --- a/data/plugins/scale.lua +++ b/data/plugins/scale.lua @@ -39,12 +39,13 @@ local function set_scale(scale) if config.plugins.scale.mode == "ui" then SCALE = scale - style.padding.x = style.padding.x * s - style.padding.y = style.padding.y * s - style.divider_size = style.divider_size * s - style.scrollbar_size = style.scrollbar_size * s - style.caret_width = style.caret_width * s - style.tab_width = style.tab_width * s + style.padding.x = style.padding.x * s + style.padding.y = style.padding.y * s + style.divider_size = style.divider_size * s + style.scrollbar_size = style.scrollbar_size * s + style.expanded_scrollbar_size = style.expanded_scrollbar_size * s + style.caret_width = style.caret_width * s + style.tab_width = style.tab_width * s for _, name in ipairs {"font", "big_font", "icon_font", "icon_big_font", "code_font"} do style[name]:set_size(s * style[name]:get_size()) From be5d23557d51525e1ea7e9cdf24de568e3f3a530 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 6 Feb 2023 19:03:29 +0100 Subject: [PATCH 027/176] Improve `DocView:get_visible_line_range` precision (#1382) --- data/core/docview.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/docview.lua b/data/core/docview.lua index bf222738..1c3ff6de 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -160,8 +160,8 @@ end function DocView:get_visible_line_range() local x, y, x2, y2 = self:get_content_bounds() local lh = self:get_line_height() - local minline = math.max(1, math.floor(y / lh)) - local maxline = math.min(#self.doc.lines, math.floor(y2 / lh) + 1) + local minline = math.max(1, math.floor((y - style.padding.y) / lh) + 1) + local maxline = math.min(#self.doc.lines, math.floor((y2 - style.padding.y) / lh) + 1) return minline, maxline end From d9925b7d447d1b6df5935c88f3caac35ee7f729a Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 6 Feb 2023 20:24:40 +0100 Subject: [PATCH 028/176] Allow groups to be used in end delimiter patterns in tokenizer (#1317) * Allow empty groups as first match in tokenizer * Avoid pushing tokens with empty strings * Allow groups to be used in end delimiter in tokenizer * Use the first entry of the type table for the middle part of a subsyntax This applies to delimited matches with a table for `type` and without a `syntax` field. * Match only once if using `at_start` in tokenizer `find_text` * Check if match is escaped in the "close" case too Also allow continuing matching if the match was escaped. --- data/core/tokenizer.lua | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index b2126124..0a3b58b1 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -5,6 +5,7 @@ local tokenizer = {} local bad_patterns = {} local function push_token(t, type, text) + if not text or #text == 0 then return end type = type or "normal" local prev_type = t[#t-1] local prev_text = t[#t] @@ -26,11 +27,8 @@ local function push_tokens(t, syn, pattern, full_text, find_results) -- Each position spans characters from i_n to ((i_n+1) - 1), to form -- consecutive spans of text. -- - -- If i_1 is not equal to start, start is automatically inserted at - -- that index. - if find_results[3] ~= find_results[1] then - table.insert(find_results, 3, find_results[1]) - end + -- Insert the start index at i_1 to make iterating easier + table.insert(find_results, 3, find_results[1]) -- Copy the ending index to the end of the table, so that an ending index -- always follows a starting index after position 3 in the table. table.insert(find_results, find_results[2] + 1) @@ -40,8 +38,10 @@ local function push_tokens(t, syn, pattern, full_text, find_results) local fin = find_results[i + 1] - 1 local type = pattern.type[i - 2] -- ↑ (i - 2) to convert from [3; n] to [1; n] - local text = full_text:usub(start, fin) - push_token(t, syn.symbols[text] or type, text) + if fin >= start then + local text = full_text:usub(start, fin) + push_token(t, syn.symbols[text] or type, text) + end end else local start, fin = find_results[1], find_results[2] @@ -224,6 +224,7 @@ function tokenizer.tokenize(incoming_syntax, text, state) res[1] = char_pos_1 res[2] = char_pos_2 end + if not res[1] then return end if res[1] and target[3] then -- Check to see if the escaped character is there, -- and if it is not itself escaped. @@ -235,12 +236,12 @@ function tokenizer.tokenize(incoming_syntax, text, state) if count % 2 == 0 then -- The match is not escaped, so confirm it break - elseif not close then - -- The *open* match is escaped, so avoid it - return + else + -- The match is escaped, so avoid it + res[1] = false end end - until not res[1] or not close or not target[3] + until at_start or not close or not target[3] return table.unpack(res) end @@ -250,6 +251,9 @@ function tokenizer.tokenize(incoming_syntax, text, state) if current_pattern_idx > 0 then local p = current_syntax.patterns[current_pattern_idx] local s, e = find_text(text, p, i, false, true) + -- Use the first token type specified in the type table for the "middle" + -- part of the subsyntax. + local token_type = type(p.type) == "table" and p.type[1] or p.type local cont = true -- If we're in subsyntax mode, always check to see if we end our syntax @@ -262,7 +266,7 @@ function tokenizer.tokenize(incoming_syntax, text, state) -- treat the bit after as a token to be normally parsed -- (as it's the syntax delimiter). if ss and (s == nil or ss < s) then - push_token(res, p.type, text:usub(i, ss - 1)) + push_token(res, token_type, text:usub(i, ss - 1)) i = ss cont = false end @@ -271,11 +275,11 @@ function tokenizer.tokenize(incoming_syntax, text, state) -- continue on as normal. if cont then if s then - push_token(res, p.type, text:usub(i, e)) + push_token(res, token_type, text:usub(i, e)) set_subsyntax_pattern_idx(0) i = e + 1 else - push_token(res, p.type, text:usub(i)) + push_token(res, token_type, text:usub(i)) break end end @@ -284,9 +288,10 @@ function tokenizer.tokenize(incoming_syntax, text, state) -- we're ending early in the middle of a delimiter, or -- just normally, upon finding a token. while subsyntax_info do - local s, e = find_text(text, subsyntax_info, i, true, true) + local find_results = { find_text(text, subsyntax_info, i, true, true) } + local s, e = find_results[1], find_results[2] if s then - push_token(res, subsyntax_info.type, text:usub(i, e)) + push_tokens(res, current_syntax, subsyntax_info, text, find_results) -- On finding unescaped delimiter, pop it. pop_subsyntax() i = e + 1 From 911eb325cceeda2ee7d125d57de05f65df222a4a Mon Sep 17 00:00:00 2001 From: Eric Gaudet Date: Mon, 6 Feb 2023 20:40:04 +0100 Subject: [PATCH 029/176] Make mouse scrollwheel hovering tabs scroll the tab bar (#1314) --- data/core/rootview.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/data/core/rootview.lua b/data/core/rootview.lua index 7230e8e1..7ff54a45 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -323,10 +323,19 @@ function RootView:on_file_dropped(filename, x, y) end -function RootView:on_mouse_wheel(...) +function RootView:on_mouse_wheel(dy, dx) local x, y = self.mouse.x, self.mouse.y local node = self.root_node:get_child_overlapping_point(x, y) - return node.active_view:on_mouse_wheel(...) + + local idx = node:get_tab_overlapping_point(x, y) + if idx then + local delta = dx == 0.0 and dy or dx + local button = delta > 0 and 2 or 1 + node:scroll_tabs(button) + return true + end + + return node.active_view:on_mouse_wheel(dy, dx) end From 51ab72f71581b87f9b73906842c234df60c13d80 Mon Sep 17 00:00:00 2001 From: jgmdev Date: Mon, 6 Feb 2023 15:44:19 -0400 Subject: [PATCH 030/176] Correct the inverted tabs scrolling --- data/core/rootview.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/core/rootview.lua b/data/core/rootview.lua index 7ff54a45..002029c4 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -326,15 +326,15 @@ end function RootView:on_mouse_wheel(dy, dx) local x, y = self.mouse.x, self.mouse.y local node = self.root_node:get_child_overlapping_point(x, y) - + local idx = node:get_tab_overlapping_point(x, y) if idx then local delta = dx == 0.0 and dy or dx - local button = delta > 0 and 2 or 1 + local button = delta < 0 and 2 or 1 node:scroll_tabs(button) return true end - + return node.active_view:on_mouse_wheel(dy, dx) end From 7e0ddf2817be52c965663e5dc347e1234e71f798 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 9 Feb 2023 17:51:41 +0100 Subject: [PATCH 031/176] Make tab scrolling more flexible (#1384) * Add `Object:{is_class_of,is_extended_by}` to check inverse relationships * Make tab scrolling more flexible This adds tab scrolling commands and connects them to mouse scroll events. This way scrolling behavior can be customized more easily. For example an alternative behavior could be: ```lua keymap.add({ ["wheelup"] = "root:switch-to-hovered-previous-tab", ["wheeldown"] = "root:switch-to-hovered-next-tab" }) ``` --- data/core/commands/root.lua | 71 +++++++++++++++++++++++++++++-------- data/core/keymap-macos.lua | 2 ++ data/core/keymap.lua | 2 ++ data/core/object.lua | 23 ++++++++++++ data/core/rootview.lua | 13 ++----- 5 files changed, 86 insertions(+), 25 deletions(-) diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua index 61e3890b..acbd697c 100644 --- a/data/core/commands/root.lua +++ b/data/core/commands/root.lua @@ -4,6 +4,7 @@ local DocView = require "core.docview" local command = require "core.command" local common = require "core.common" local config = require "core.config" +local Node = require "core.node" local t = { @@ -29,20 +30,6 @@ local t = { core.confirm_close_docs(docs, core.root_view.close_all_docviews, core.root_view, true) end, - ["root:switch-to-previous-tab"] = function(node) - local idx = node:get_view_idx(core.active_view) - idx = idx - 1 - if idx < 1 then idx = #node.views end - node:set_active_view(node.views[idx]) - end, - - ["root:switch-to-next-tab"] = function(node) - local idx = node:get_view_idx(core.active_view) - idx = idx + 1 - if idx > #node.views then idx = 1 end - node:set_active_view(node.views[idx]) - end, - ["root:move-tab-left"] = function(node) local idx = node:get_view_idx(core.active_view) if idx > 1 then @@ -133,3 +120,59 @@ command.add(nil, { return false end }) + +command.add(function(node) + if not Node:is_extended_by(node) then node = nil end + -- No node was specified, use the active one + node = node or core.root_view:get_active_node() + if not node then return false end + return true, node + end, + { + ["root:switch-to-previous-tab"] = function(node) + local idx = node:get_view_idx(node.active_view) + idx = idx - 1 + if idx < 1 then idx = #node.views end + node:set_active_view(node.views[idx]) + end, + + ["root:switch-to-next-tab"] = function(node) + local idx = node:get_view_idx(node.active_view) + idx = idx + 1 + if idx > #node.views then idx = 1 end + node:set_active_view(node.views[idx]) + end, + + ["root:scroll-tabs-backward"] = function(node) + node:scroll_tabs(1) + end, + + ["root:scroll-tabs-forward"] = function(node) + node:scroll_tabs(2) + end + } +) + +command.add(function() + local node = core.root_view.overlapping_node + if not node then return false end + return (node.hovered_tab or node.hovered_scroll_button > 0) and true, node + end, + { + ["root:switch-to-hovered-previous-tab"] = function(node) + command.perform("root:switch-to-previous-tab", node) + end, + + ["root:switch-to-hovered-next-tab"] = function(node) + command.perform("root:switch-to-next-tab", node) + end, + + ["root:scroll-hovered-tabs-backward"] = function(node) + command.perform("root:scroll-tabs-backward", node) + end, + + ["root:scroll-hovered-tabs-forward"] = function(node) + command.perform("root:scroll-tabs-forward", node) + end + } +) diff --git a/data/core/keymap-macos.lua b/data/core/keymap-macos.lua index 8fe04b39..965191ef 100644 --- a/data/core/keymap-macos.lua +++ b/data/core/keymap-macos.lua @@ -36,6 +36,8 @@ local function keymap_macos(keymap) ["wheel"] = "root:scroll", ["hwheel"] = "root:horizontal-scroll", ["shift+hwheel"] = "root:horizontal-scroll", + ["wheelup"] = "root:scroll-hovered-tabs-backward", + ["wheeldown"] = "root:scroll-hovered-tabs-forward", ["cmd+f"] = "find-replace:find", ["cmd+r"] = "find-replace:replace", diff --git a/data/core/keymap.lua b/data/core/keymap.lua index 35e34e6a..c0a78dd3 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -302,6 +302,8 @@ keymap.add_direct { ["wheel"] = "root:scroll", ["hwheel"] = "root:horizontal-scroll", ["shift+wheel"] = "root:horizontal-scroll", + ["wheelup"] = "root:scroll-hovered-tabs-backward", + ["wheeldown"] = "root:scroll-hovered-tabs-forward", ["ctrl+f"] = "find-replace:find", ["ctrl+r"] = "find-replace:replace", diff --git a/data/core/object.lua b/data/core/object.lua index afd13cdf..7b712cff 100644 --- a/data/core/object.lua +++ b/data/core/object.lua @@ -27,6 +27,13 @@ function Object:is(T) return getmetatable(self) == T end +---Check if the parameter is strictly of the object type. +---@param T any +---@return boolean +function Object:is_class_of(T) + return getmetatable(T) == self +end + ---Check if the object inherits from the given type. ---@param T any ---@return boolean @@ -41,6 +48,22 @@ function Object:extends(T) return false end +---Check if the parameter inherits from the object. +---@param T any +---@return boolean +function Object:is_extended_by(T) + local mt = getmetatable(T) + while mt do + if mt == self then + return true + end + local _mt = getmetatable(T) + if mt == _mt then break end + mt = _mt + end + return false +end + ---Metamethod to get a string representation of an object. ---@return string function Object:__tostring() diff --git a/data/core/rootview.lua b/data/core/rootview.lua index 002029c4..7230e8e1 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -323,19 +323,10 @@ function RootView:on_file_dropped(filename, x, y) end -function RootView:on_mouse_wheel(dy, dx) +function RootView:on_mouse_wheel(...) local x, y = self.mouse.x, self.mouse.y local node = self.root_node:get_child_overlapping_point(x, y) - - local idx = node:get_tab_overlapping_point(x, y) - if idx then - local delta = dx == 0.0 and dy or dx - local button = delta < 0 and 2 or 1 - node:scroll_tabs(button) - return true - end - - return node.active_view:on_mouse_wheel(dy, dx) + return node.active_view:on_mouse_wheel(...) end From b9cc661a84242822018b5c3e3ee5d0d23aa0c5d9 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 9 Feb 2023 11:55:47 -0500 Subject: [PATCH 032/176] Fixed up some post 5.1/jit Symbols (#1385) * Updated k functions to have appropriate method signatures for 5.3 and up. * Fixed up some inconsistent signatures that I forgot. --- resources/lite_xl_plugin_api.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/resources/lite_xl_plugin_api.h b/resources/lite_xl_plugin_api.h index 6d68e454..8bf74054 100644 --- a/resources/lite_xl_plugin_api.h +++ b/resources/lite_xl_plugin_api.h @@ -205,6 +205,7 @@ Go figure. #define luai_numisnan(L,a) (!luai_numeq((a), (a))) #endif #define LUA_INTEGER ptrdiff_t +#define LUA_KCONTEXT ptrdiff_t #define LUA_UNSIGNED unsigned LUA_INT32 #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) @@ -235,10 +236,12 @@ typedef int (*lua_CFunction) (lua_State *L); typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); +typedef LUA_KCONTEXT lua_KContext; typedef LUA_NUMBER lua_Number; typedef LUA_INTEGER lua_Integer; typedef LUA_UNSIGNED lua_Unsigned; typedef struct lua_Debug lua_Debug; +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); struct lua_Debug { int event; @@ -321,12 +324,12 @@ SYMBOL_DECLARE(void, lua_rawsetp, lua_State *L, int idx, SYMBOL_DECLARE(int, lua_setmetatable, lua_State *L, int objindex) SYMBOL_DECLARE(void, lua_setuservalue, lua_State *L, int idx) SYMBOL_DECLARE(void, lua_setiuservalue, lua_State *L, int idx, int n) -SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) +SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) SYMBOL_DECLARE(int, lua_getctx, lua_State *L, int *ctx) -SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k) +SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) SYMBOL_DECLARE(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) SYMBOL_DECLARE(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) -SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k) +SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k) SYMBOL_DECLARE(int, lua_resume, lua_State *L, lua_State *from, int narg) SYMBOL_DECLARE(int, lua_status, lua_State *L) SYMBOL_DECLARE(int, lua_gc, lua_State *L, int what, int data) @@ -740,13 +743,13 @@ SYMBOL_WRAP_DECL(void, lua_setuservalue, lua_State *L, int idx){ SYMBOL_WRAP_DECL(void, lua_setiuservalue, lua_State *L, int idx, int n){ SYMBOL_WRAP_CALL(lua_setiuservalue, L, idx, n); } -SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k){ +SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k){ SYMBOL_WRAP_CALL(lua_callk, L, nargs, nresults, ctx, k); } SYMBOL_WRAP_DECL(int, lua_getctx, lua_State *L, int *ctx){ SYMBOL_WRAP_CALL(lua_getctx, L, ctx); } -SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k){ +SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k){ SYMBOL_WRAP_CALL(lua_pcallk, L, nargs, nresults, errfunc, ctx, k); } SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode){ @@ -755,7 +758,7 @@ SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const SYMBOL_WRAP_DECL(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip){ SYMBOL_WRAP_CALL(lua_dump, L, writer, data, strip); } -SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k){ +SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k){ SYMBOL_WRAP_CALL(lua_yieldk, L, nresults, ctx, k); } SYMBOL_WRAP_DECL(int, lua_resume, lua_State *L, lua_State *from, int narg){ @@ -1041,12 +1044,12 @@ static void lite_xl_plugin_init(void *XL) { IMPORT_SYMBOL(lua_setmetatable, int , lua_State *L, int objindex); IMPORT_SYMBOL_OPT(lua_setuservalue, void , lua_State *L, int idx); IMPORT_SYMBOL(lua_setiuservalue, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k); IMPORT_SYMBOL(lua_getctx, int , lua_State *L, int *ctx); - IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k); IMPORT_SYMBOL(lua_load, int , lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); IMPORT_SYMBOL(lua_dump, int , lua_State *L, lua_Writer writer, void *data, int strip); - IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, int ctx, lua_CFunction k); + IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k); IMPORT_SYMBOL(lua_resume, int , lua_State *L, lua_State *from, int narg); IMPORT_SYMBOL(lua_status, int , lua_State *L); IMPORT_SYMBOL(lua_gc, int , lua_State *L, int what, int data); From 9b4a86f763363057ea6ffb2e3d3371a54c5af62c Mon Sep 17 00:00:00 2001 From: vqn <85911372+vqns@users.noreply.github.com> Date: Thu, 9 Feb 2023 18:26:32 +0100 Subject: [PATCH 033/176] fix incorrect x_offset if opened docs have different tab sizes (#1383) --- data/core/docview.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data/core/docview.lua b/data/core/docview.lua index 1c3ff6de..cdfb0298 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -168,10 +168,13 @@ end function DocView:get_col_x_offset(line, col) local default_font = self:get_font() + local _, indent_size = self.doc:get_indent_info() + default_font:set_tab_size(indent_size) local column = 1 local xoffset = 0 for _, type, text in self.doc.highlighter:each_token(line) do local font = style.syntax_fonts[type] or default_font + if font ~= default_font then font:set_tab_size(indent_size) end for char in common.utf8_chars(text) do if column == col then return xoffset @@ -190,8 +193,11 @@ function DocView:get_x_offset_col(line, x) local xoffset, last_i, i = 0, 1, 1 local default_font = self:get_font() + local _, indent_size = self.doc:get_indent_info() + default_font:set_tab_size(indent_size) for _, type, text in self.doc.highlighter:each_token(line) do local font = style.syntax_fonts[type] or default_font + if font ~= default_font then font:set_tab_size(indent_size) end for char in common.utf8_chars(text) do local w = font:get_width(char) if xoffset >= x then From 83c27cf9f4371b286021c0a3cd3de10c45cb8b2b Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 15 Feb 2023 20:48:09 -0500 Subject: [PATCH 034/176] Added in ability to specify prefix via env variable. (#1388) --- data/core/start.lua | 2 +- src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/start.lua b/data/core/start.lua index bb10d7ef..2ad71d54 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -12,7 +12,7 @@ EXEDIR = EXEFILE:match("^(.+)[/\\][^/\\]+$") if MACOS_RESOURCES then DATADIR = MACOS_RESOURCES else - local prefix = EXEDIR:match("^(.+)[/\\]bin$") + local prefix = os.getenv('LITE_PREFIX') or EXEDIR:match("^(.+)[/\\]bin$") DATADIR = prefix and (prefix .. PATHSEP .. 'share' .. PATHSEP .. 'lite-xl') or (EXEDIR .. PATHSEP .. 'data') end USERDIR = (system.get_file_info(EXEDIR .. PATHSEP .. 'user') and (EXEDIR .. PATHSEP .. 'user')) diff --git a/src/main.c b/src/main.c index 32212df8..c5e15707 100644 --- a/src/main.c +++ b/src/main.c @@ -222,7 +222,7 @@ init_lua: "xpcall(function()\n" " HOME = os.getenv('" LITE_OS_HOME "')\n" " local exedir = EXEFILE:match('^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$')\n" - " local prefix = exedir:match('^(.*)" LITE_PATHSEP_PATTERN "bin$')\n" + " local prefix = os.getenv('LITE_PREFIX') or exedir:match('^(.*)" LITE_PATHSEP_PATTERN "bin$')\n" " dofile((MACOS_RESOURCES or (prefix and prefix .. '/share/lite-xl' or exedir .. '/data')) .. '/core/start.lua')\n" " core = require(os.getenv('LITE_XL_RUNTIME') or 'core')\n" " core.init()\n" From e1f92683bcb51f2ec657df923bfecd4b5d99ee72 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 3 Mar 2023 11:42:31 +0100 Subject: [PATCH 035/176] Use correct view for scrolling to `find-replace:repeat-find` results (#1400) --- data/core/commands/findreplace.lua | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua index 3d364dc6..a3151cb7 100644 --- a/data/core/commands/findreplace.lua +++ b/data/core/commands/findreplace.lua @@ -253,34 +253,38 @@ command.add("core.docview!", { }) local function valid_for_finding() - return core.active_view:is(DocView) or core.active_view:is(CommandView) + -- Allow using this while in the CommandView + if core.active_view:is(CommandView) and last_view then + return true, last_view + end + return core.active_view:is(DocView), core.active_view end command.add(valid_for_finding, { - ["find-replace:repeat-find"] = function() + ["find-replace:repeat-find"] = function(dv) if not last_fn then core.error("No find to continue from") else - local sl1, sc1, sl2, sc2 = doc():get_selection(true) - local line1, col1, line2, col2 = last_fn(doc(), sl1, sc2, last_text, case_sensitive, find_regex, false) + local sl1, sc1, sl2, sc2 = dv.doc:get_selection(true) + local line1, col1, line2, col2 = last_fn(dv.doc, sl1, sc2, last_text, case_sensitive, find_regex, false) if line1 then - doc():set_selection(line2, col2, line1, col1) - last_view:scroll_to_line(line2, true) + dv.doc:set_selection(line2, col2, line1, col1) + dv:scroll_to_line(line2, true) else core.error("Couldn't find %q", last_text) end end end, - ["find-replace:previous-find"] = function() + ["find-replace:previous-find"] = function(dv) if not last_fn then core.error("No find to continue from") else - local sl1, sc1, sl2, sc2 = doc():get_selection(true) - local line1, col1, line2, col2 = last_fn(doc(), sl1, sc1, last_text, case_sensitive, find_regex, true) + local sl1, sc1, sl2, sc2 = dv.doc:get_selection(true) + local line1, col1, line2, col2 = last_fn(dv.doc, sl1, sc1, last_text, case_sensitive, find_regex, true) if line1 then - doc():set_selection(line2, col2, line1, col1) - last_view:scroll_to_line(line2, true) + dv.doc:set_selection(line2, col2, line1, col1) + dv:scroll_to_line(line2, true) else core.error("Couldn't find %q", last_text) end From 2d2d715fd9a8c9870ffb360deba62ef26a38c35f Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 3 Mar 2023 22:07:45 +0800 Subject: [PATCH 036/176] Add manifest on Windows (#1405) * fix(gitignore): add exclusion for manifest files * feat(windows): add application manifest * feat(build): use application manifest on windows * refactor(build): use genrate_file to generate the manifest * style(manifest): remove trailing whitespace --- .gitignore | 1 + meson.build | 6 ++++ resources/windows/lite-xl.exe.manifest.in | 41 +++++++++++++++++++++++ resources/windows/manifest.rc | 4 +++ src/meson.build | 1 + 5 files changed, 53 insertions(+) create mode 100644 resources/windows/lite-xl.exe.manifest.in create mode 100644 resources/windows/manifest.rc diff --git a/.gitignore b/.gitignore index b1d18a64..9b248455 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ lite-xl* LiteXL* !resources/windows/*.diff +!resources/windows/*.exe.manifest.in diff --git a/meson.build b/meson.build index 7bbecc68..cfef8ec8 100644 --- a/meson.build +++ b/meson.build @@ -36,6 +36,7 @@ conf_data = configuration_data() conf_data.set('PROJECT_BUILD_DIR', meson.current_build_dir()) conf_data.set('PROJECT_SOURCE_DIR', meson.current_source_dir()) conf_data.set('PROJECT_VERSION', version) +conf_data.set('PROJECT_ASSEMBLY_VERSION', meson.project_version() + '.0') #=============================================================================== # Compiler Settings @@ -165,6 +166,11 @@ if get_option('portable') or host_machine.system() == 'windows' lite_bindir = '/' lite_docdir = '/doc' lite_datadir = '/data' + configure_file( + input: 'resources/windows/lite-xl.exe.manifest.in', + output: 'lite-xl.exe.manifest', + configuration: conf_data + ) elif get_option('bundle') and host_machine.system() == 'darwin' lite_cargs += '-DMACOS_USE_BUNDLE' lite_bindir = 'Contents/MacOS' diff --git a/resources/windows/lite-xl.exe.manifest.in b/resources/windows/lite-xl.exe.manifest.in new file mode 100644 index 00000000..9e787587 --- /dev/null +++ b/resources/windows/lite-xl.exe.manifest.in @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/windows/manifest.rc b/resources/windows/manifest.rc new file mode 100644 index 00000000..95b17e2d --- /dev/null +++ b/resources/windows/manifest.rc @@ -0,0 +1,4 @@ +#define IDR_RT_MANIFEST1 1 +#define RT_MANIFEST 24 + +IDR_RT_MANIFEST1 RT_MANIFEST "lite-xl.exe.manifest" diff --git a/src/meson.build b/src/meson.build index fee36d1d..a156ae3f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -50,6 +50,7 @@ lite_rc = [] if host_machine.system() == 'windows' windows = import('windows') lite_rc += windows.compile_resources('../resources/icons/icon.rc') + lite_rc += windows.compile_resources('../resources/windows/manifest.rc') elif host_machine.system() == 'darwin' lite_sources += 'bundle_open.m' endif From dbb9f30c815a7cb9cd2f48321814839cc487a6c8 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 4 Mar 2023 21:23:09 +0100 Subject: [PATCH 037/176] Split `Command` struct into different structs for each command type (#1407) This reduces the space needed for each command. --- src/rencache.c | 54 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/rencache.c b/src/rencache.c index 5b930482..fda33e31 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -28,21 +28,36 @@ #define CELL_SIZE 96 #define CMD_BUF_RESIZE_RATE 1.2 #define CMD_BUF_INIT_SIZE (1024 * 512) -#define COMMAND_BARE_SIZE offsetof(Command, text) +#define COMMAND_BARE_SIZE offsetof(Command, command) -enum { SET_CLIP, DRAW_TEXT, DRAW_RECT }; +enum CommandType { SET_CLIP, DRAW_TEXT, DRAW_RECT }; + +typedef struct { + enum CommandType type; + uint32_t size; + /* Commands *must* always begin with a RenRect + ** This is done to ensure alignment */ + RenRect command[]; +} Command; + +typedef struct { + RenRect rect; +} SetClipCommand; typedef struct { - int8_t type; - int8_t tab_size; - int32_t size; RenRect rect; RenColor color; RenFont *fonts[FONT_FALLBACK_MAX]; float text_x; size_t len; + int8_t tab_size; char text[]; -} Command; +} DrawTextCommand; + +typedef struct { + RenRect rect; + RenColor color; +} DrawRectCommand; static unsigned cells_buf1[CELLS_X * CELLS_Y]; static unsigned cells_buf2[CELLS_X * CELLS_Y]; @@ -114,13 +129,14 @@ static bool expand_command_buffer() { return true; } -static Command* push_command(int type, int size) { +static void* push_command(enum CommandType type, int size) { if (resize_issue) { // Don't push new commands as we had problems resizing the command buffer. // Let's wait for the next frame. return NULL; } size_t alignment = alignof(max_align_t) - 1; + size += COMMAND_BARE_SIZE; size = (size + alignment) & ~alignment; int n = command_buf_idx + size; while (n > command_buf_size) { @@ -136,7 +152,7 @@ static Command* push_command(int type, int size) { memset(cmd, 0, size); cmd->type = type; cmd->size = size; - return cmd; + return cmd->command; } @@ -156,7 +172,7 @@ void rencache_show_debug(bool enable) { void rencache_set_clip_rect(RenRect rect) { - Command *cmd = push_command(SET_CLIP, COMMAND_BARE_SIZE); + SetClipCommand *cmd = push_command(SET_CLIP, sizeof(SetClipCommand)); if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); last_clip_rect = cmd->rect; @@ -168,7 +184,7 @@ void rencache_draw_rect(RenRect rect, RenColor color) { if (rect.width == 0 || rect.height == 0 || !rects_overlap(last_clip_rect, rect)) { return; } - Command *cmd = push_command(DRAW_RECT, COMMAND_BARE_SIZE); + DrawRectCommand *cmd = push_command(DRAW_RECT, sizeof(DrawRectCommand)); if (cmd) { cmd->rect = rect; cmd->color = color; @@ -181,7 +197,7 @@ float rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; - Command *cmd = push_command(DRAW_TEXT, COMMAND_BARE_SIZE + sz); + DrawTextCommand *cmd = push_command(DRAW_TEXT, sizeof(DrawTextCommand) + sz); if (cmd) { memcpy(cmd->text, text, sz); cmd->color = color; @@ -249,8 +265,9 @@ void rencache_end_frame(RenWindow *window_renderer) { Command *cmd = NULL; RenRect cr = screen_rect; while (next_command(&cmd)) { - if (cmd->type == SET_CLIP) { cr = cmd->rect; } - RenRect r = intersect_rects(cmd->rect, cr); + /* cmd->command[0] should always be the Command rect */ + if (cmd->type == SET_CLIP) { cr = cmd->command[0]; } + RenRect r = intersect_rects(cmd->command[0], cr); if (r.width == 0 || r.height == 0) { continue; } unsigned h = HASH_INITIAL; hash(&h, cmd, cmd->size); @@ -290,16 +307,19 @@ void rencache_end_frame(RenWindow *window_renderer) { cmd = NULL; while (next_command(&cmd)) { + SetClipCommand *ccmd = (SetClipCommand*)&cmd->command; + DrawRectCommand *rcmd = (DrawRectCommand*)&cmd->command; + DrawTextCommand *tcmd = (DrawTextCommand*)&cmd->command; switch (cmd->type) { case SET_CLIP: - ren_set_clip_rect(window_renderer, intersect_rects(cmd->rect, r)); + ren_set_clip_rect(window_renderer, intersect_rects(ccmd->rect, r)); break; case DRAW_RECT: - ren_draw_rect(window_renderer, cmd->rect, cmd->color); + ren_draw_rect(window_renderer, rcmd->rect, rcmd->color); break; case DRAW_TEXT: - ren_font_group_set_tab_size(cmd->fonts, cmd->tab_size); - ren_draw_text(window_renderer, cmd->fonts, cmd->text, cmd->len, cmd->text_x, cmd->rect.y, cmd->color); + ren_font_group_set_tab_size(tcmd->fonts, tcmd->tab_size); + ren_draw_text(window_renderer, tcmd->fonts, tcmd->text, tcmd->len, tcmd->text_x, tcmd->rect.y, tcmd->color); break; } } From 193871869d4a61e0ffd73bde392b0cef3cb2e990 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:58:32 +0800 Subject: [PATCH 038/176] refactor(main): move SetProcessDPIAware to manifests (#1413) --- resources/windows/lite-xl.exe.manifest.in | 7 +++++++ src/main.c | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/windows/lite-xl.exe.manifest.in b/resources/windows/lite-xl.exe.manifest.in index 9e787587..a01ac8d2 100644 --- a/resources/windows/lite-xl.exe.manifest.in +++ b/resources/windows/lite-xl.exe.manifest.in @@ -24,6 +24,13 @@ /> + + + + true + + + diff --git a/src/main.c b/src/main.c index c5e15707..7bc57b6e 100644 --- a/src/main.c +++ b/src/main.c @@ -120,11 +120,7 @@ void set_macos_bundle_resources(lua_State *L); #endif int main(int argc, char **argv) { -#ifdef _WIN32 - HINSTANCE lib = LoadLibrary("user32.dll"); - int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware"); - SetProcessDPIAware(); -#else +#ifndef _WIN32 signal(SIGPIPE, SIG_IGN); #endif From 7907fa785cbf2da4bc3553366b4915b11b51d2de Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 9 Mar 2023 16:48:46 +0100 Subject: [PATCH 039/176] Improve text width calculation precision (#1408) In some extreme cases (~30000 chars) text width precision takes a hit. Using double instead of float fixes that. --- src/api/renderer.c | 2 +- src/rencache.c | 4 ++-- src/rencache.h | 2 +- src/renderer.c | 12 ++++++------ src/renderer.h | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index d96fbe0a..b619b586 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -345,7 +345,7 @@ static int f_draw_text(lua_State *L) { size_t len; const char *text = luaL_checklstring(L, 2, &len); - float x = luaL_checknumber(L, 3); + double x = luaL_checknumber(L, 3); int y = luaL_checknumber(L, 4); RenColor color = checkcolor(L, 5, 255); x = rencache_draw_text(&window_renderer, fonts, text, len, x, y, color); diff --git a/src/rencache.c b/src/rencache.c index fda33e31..946aa3fb 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -191,9 +191,9 @@ void rencache_draw_rect(RenRect rect, RenColor color) { } } -float rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) +double rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, double x, int y, RenColor color) { - float width = ren_font_group_get_width(window_renderer, fonts, text, len); + double width = ren_font_group_get_width(window_renderer, fonts, text, len); RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; diff --git a/src/rencache.h b/src/rencache.h index 925b50f0..2453d808 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -8,7 +8,7 @@ void rencache_show_debug(bool enable); void rencache_set_clip_rect(RenRect rect); void rencache_draw_rect(RenRect rect, RenColor color); -float rencache_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +double rencache_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, double x, int y, RenColor color); void rencache_invalidate(void); void rencache_begin_frame(RenWindow *window_renderer); void rencache_end_frame(RenWindow *window_renderer); diff --git a/src/renderer.c b/src/renderer.c index 53be1046..59004bc0 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -360,8 +360,8 @@ int ren_font_group_get_height(RenFont **fonts) { return fonts[0]->height; } -float ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len) { - float width = 0; +double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len) { + double width = 0; const char* end = text + len; GlyphMetric* metric = NULL; GlyphSet* set = NULL; while (text < end) { @@ -376,12 +376,12 @@ float ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, cons return width / surface_scale; } -float ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { +double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { SDL_Surface *surface = renwin_get_surface(window_renderer); const RenRect clip = window_renderer->clip; const int surface_scale = renwin_surface_scale(window_renderer); - float pen_x = x * surface_scale; + double pen_x = x * surface_scale; y *= surface_scale; int bytes_per_pixel = surface->format->BytesPerPixel; const char* end = text + len; @@ -389,7 +389,7 @@ float ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *tex int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height; RenFont* last = NULL; - float last_pen_x = x; + double last_pen_x = x; bool underline = fonts[0]->style & FONT_STYLE_UNDERLINE; bool strikethrough = fonts[0]->style & FONT_STYLE_STRIKETHROUGH; @@ -453,7 +453,7 @@ float ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *tex if(!last) last = font; else if(font != last || text == end) { - float local_pen_x = text == end ? pen_x + adv : pen_x; + double local_pen_x = text == end ? pen_x + adv : pen_x; if (underline) ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); if (strikethrough) diff --git a/src/renderer.h b/src/renderer.h index 46e04341..3897421e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -33,8 +33,8 @@ int ren_font_group_get_height(RenFont **font); float ren_font_group_get_size(RenFont **font); void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); -float ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); -float ren_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); +double ren_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color); From 4f1360a6c53e5819b5f1cb8f093fa9d3695dfefe Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 14 Mar 2023 16:39:00 +0100 Subject: [PATCH 040/176] Use clipping functions provided by SDL (#1426) --- src/renderer.c | 31 ++++++++++++++----------------- src/renwindow.c | 6 ++++-- src/renwindow.h | 1 - 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/renderer.c b/src/renderer.c index 59004bc0..226dbe71 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -378,7 +378,8 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { SDL_Surface *surface = renwin_get_surface(window_renderer); - const RenRect clip = window_renderer->clip; + SDL_Rect clip; + SDL_GetClipRect(surface, &clip); const int surface_scale = renwin_surface_scale(window_renderer); double pen_x = x * surface_scale; @@ -386,7 +387,7 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te int bytes_per_pixel = surface->format->BytesPerPixel; const char* end = text + len; uint8_t* destination_pixels = surface->pixels; - int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height; + int clip_end_x = clip.x + clip.w, clip_end_y = clip.y + clip.h; RenFont* last = NULL; double last_pen_x = x; @@ -479,28 +480,24 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) { void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { if (color.a == 0) { return; } + SDL_Surface *surface = renwin_get_surface(window_renderer); const int surface_scale = renwin_surface_scale(window_renderer); - /* transforms coordinates in pixels. */ - rect.x *= surface_scale; - rect.y *= surface_scale; - rect.width *= surface_scale; - rect.height *= surface_scale; + SDL_Rect dest_rect = { rect.x * surface_scale, + rect.y * surface_scale, + rect.width * surface_scale, + rect.height * surface_scale }; - const RenRect clip = window_renderer->clip; - int x1 = rect.x < clip.x ? clip.x : rect.x; - int y1 = rect.y < clip.y ? clip.y : rect.y; - int x2 = rect.x + rect.width; - int y2 = rect.y + rect.height; - x2 = x2 > clip.x + clip.width ? clip.x + clip.width : x2; - y2 = y2 > clip.y + clip.height ? clip.y + clip.height : y2; - - SDL_Surface *surface = renwin_get_surface(window_renderer); - SDL_Rect dest_rect = { x1, y1, x2 - x1, y2 - y1 }; if (color.a == 0xff) { uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b); SDL_FillRect(surface, &dest_rect, translated); } else { + // Seems like SDL doesn't handle clipping as we expect when using + // scaled blitting, so we "clip" manually. + SDL_Rect clip; + SDL_GetClipRect(surface, &clip); + if (!SDL_IntersectRect(&clip, &dest_rect, &dest_rect)) return; + uint32_t *pixel = (uint32_t *)draw_rect_surface->pixels; *pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a); SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect); diff --git a/src/renwindow.c b/src/renwindow.c index 85fd7a07..c700cedf 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -61,12 +61,14 @@ static RenRect scaled_rect(const RenRect rect, const int scale) { void renwin_clip_to_surface(RenWindow *ren) { SDL_Surface *surface = renwin_get_surface(ren); - ren->clip = (RenRect) {0, 0, surface->w, surface->h}; + SDL_SetClipRect(surface, NULL); } void renwin_set_clip_rect(RenWindow *ren, RenRect rect) { - ren->clip = scaled_rect(rect, renwin_surface_scale(ren)); + SDL_Surface *surface = renwin_get_surface(ren); + RenRect sr = scaled_rect(rect, renwin_surface_scale(ren)); + SDL_SetClipRect(surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); } diff --git a/src/renwindow.h b/src/renwindow.h index 8edc03d8..7f08aa2f 100644 --- a/src/renwindow.h +++ b/src/renwindow.h @@ -3,7 +3,6 @@ struct RenWindow { SDL_Window *window; - RenRect clip; /* Clipping rect in pixel coordinates. */ #ifdef LITE_USE_SDL_RENDERER SDL_Renderer *renderer; SDL_Texture *texture; From 3739bf018668913f3ecde9abbf9fffdd23a7b611 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 16 Mar 2023 22:29:33 +0100 Subject: [PATCH 041/176] Make `TreeView` follow the current tab (#1411) * Make `TreeView` follow the current tab * Use `TreeView:toggle_expand` in `TreeView:set_selection_to_path` We can't use `item.expanded` directly because we need to update the cached tree structure. --- data/plugins/treeview.lua | 94 +++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index ff646847..cab3d410 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -9,10 +9,15 @@ local View = require "core.view" local ContextMenu = require "core.contextmenu" local RootView = require "core.rootview" local CommandView = require "core.commandview" +local DocView = require "core.docview" config.plugins.treeview = common.merge({ -- Default treeview width - size = 200 * SCALE + size = 200 * SCALE, + highlight_focused_file = true, + expand_dirs_to_focused_file = false, + scroll_to_focused_file = false, + animate_scroll_to_focused_file = true }, config.plugins.treeview) local tooltip_offset = style.font:get_height() @@ -169,20 +174,73 @@ function TreeView:each_item() end -function TreeView:set_selection(selection, selection_y) +function TreeView:set_selection(selection, selection_y, center, instant) self.selected_item = selection if selection and selection_y and (selection_y <= 0 or selection_y >= self.size.y) then - local lh = self:get_item_height() - if selection_y >= self.size.y - lh then + if not center and selection_y >= self.size.y - lh then selection_y = selection_y - self.size.y + lh end + if center then + selection_y = selection_y - (self.size.y - lh) / 2 + end local _, y = self:get_content_offset() - self.scroll.to.y = selection and (selection_y - y) + self.scroll.to.y = selection_y - y + self.scroll.to.y = common.clamp(self.scroll.to.y, 0, self:get_scrollable_size() - self.size.y) + if instant then + self.scroll.y = self.scroll.to.y + end end end +---Sets the selection to the file with the specified path. +--- +---@param path string #Absolute path of item to select +---@param expand boolean #Expand dirs leading to the item +---@param scroll_to boolean #Scroll to make the item visible +---@param instant boolean #Don't animate the scroll +---@return table? #The selected item +function TreeView:set_selection_to_path(path, expand, scroll_to, instant) + local to_select, to_select_y + local let_it_finish, done + ::restart:: + for item, x,y,w,h in self:each_item() do + if not done then + if item.type == "dir" then + local _, to = string.find(path, item.abs_filename..PATHSEP, 1, true) + if to and to == #item.abs_filename + #PATHSEP then + to_select, to_select_y = item, y + if expand and not item.expanded then + -- Use TreeView:toggle_expand to update the directory structure. + -- Directly using item.expanded doesn't update the cached tree. + self:toggle_expand(true, item) + -- Because we altered the size of the TreeView + -- and because TreeView:get_scrollable_size uses self.count_lines + -- which gets updated only when TreeView:each_item finishes, + -- we can't stop here or we risk that the scroll + -- gets clamped by View:clamp_scroll_position. + let_it_finish = true + -- We need to restart the process because if TreeView:toggle_expand + -- altered the cache, TreeView:each_item risks looping indefinitely. + goto restart + end + end + else + if item.abs_filename == path then + to_select, to_select_y = item, y + done = true + if not let_it_finish then break end + end + end + end + end + if to_select then + self:set_selection(to_select, scroll_to and to_select_y, true, instant) + end + return to_select +end + function TreeView:get_text_bounding_box(item, x, y, w, h) local icon_width = style.icon_font:get_width("D") @@ -233,7 +291,7 @@ function TreeView:update() self:move_towards(self.size, "x", dest, nil, "treeview") end - if not self.visible then return end + if self.size.x == 0 or self.size.y == 0 or not self.visible then return end local duration = system.get_time() - self.tooltip.begin if self.hovered_item and self.tooltip.x and duration > tooltip_delay then @@ -252,6 +310,26 @@ function TreeView:update() self:on_mouse_moved(self.cursor_pos.x, self.cursor_pos.y, 0, 0) end + local config = config.plugins.treeview + if config.highlight_focused_file then + -- Try to only highlight when we actually change tabs + local current_node = core.root_view:get_active_node() + local current_active_view = core.active_view + if current_node and not current_node.locked + and current_active_view ~= self and current_active_view ~= self.last_active_view then + self.selected_item = nil + self.last_active_view = current_active_view + if DocView:is_extended_by(current_active_view) then + local abs_filename = current_active_view.doc + and current_active_view.doc.abs_filename or "" + self:set_selection_to_path(abs_filename, + config.expand_dirs_to_focused_file, + config.scroll_to_focused_file, + not config.animate_scroll_to_focused_file) + end + end + end + TreeView.super.update(self) end @@ -422,8 +500,8 @@ function TreeView:get_previous(item) end -function TreeView:toggle_expand(toggle) - local item = self.selected_item +function TreeView:toggle_expand(toggle, item) + item = item or self.selected_item if not item then return end From 1d86665b6d3d18cdcb91449ece91cca756de716b Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 19 Mar 2023 20:39:52 +0100 Subject: [PATCH 042/176] Aggregate `SDL_Surface`s and their scale in `RenSurface` (#1429) --- src/rencache.c | 8 +++++--- src/renderer.c | 31 +++++++++++++++---------------- src/renderer.h | 5 +++-- src/renwindow.c | 43 +++++++++++++++++-------------------------- src/renwindow.h | 6 ++---- 5 files changed, 42 insertions(+), 51 deletions(-) diff --git a/src/rencache.c b/src/rencache.c index 946aa3fb..928d0b0d 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -17,6 +17,7 @@ #include #include "rencache.h" +#include "renwindow.h" /* a cache over the software renderer -- all drawing operations are stored as ** commands when issued. At the end of the frame we write the commands to a grid @@ -299,6 +300,7 @@ void rencache_end_frame(RenWindow *window_renderer) { *r = intersect_rects(*r, screen_rect); } + RenSurface rs = renwin_get_surface(window_renderer); /* redraw updated regions */ for (int i = 0; i < rect_count; i++) { /* draw */ @@ -315,18 +317,18 @@ void rencache_end_frame(RenWindow *window_renderer) { ren_set_clip_rect(window_renderer, intersect_rects(ccmd->rect, r)); break; case DRAW_RECT: - ren_draw_rect(window_renderer, rcmd->rect, rcmd->color); + ren_draw_rect(&rs, rcmd->rect, rcmd->color); break; case DRAW_TEXT: ren_font_group_set_tab_size(tcmd->fonts, tcmd->tab_size); - ren_draw_text(window_renderer, tcmd->fonts, tcmd->text, tcmd->len, tcmd->text_x, tcmd->rect.y, tcmd->color); + ren_draw_text(&rs, tcmd->fonts, tcmd->text, tcmd->len, tcmd->text_x, tcmd->rect.y, tcmd->color); break; } } if (show_debug) { RenColor color = { rand(), rand(), rand(), 50 }; - ren_draw_rect(window_renderer, r, color); + ren_draw_rect(&rs, r, color); } } diff --git a/src/renderer.c b/src/renderer.c index 226dbe71..e9e715ef 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -257,7 +257,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, #endif - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale))) goto failure; int len = strlen(path); @@ -342,7 +342,7 @@ float ren_font_group_get_size(RenFont **fonts) { } void ren_font_group_set_size(RenWindow *window_renderer, RenFont **fonts, float size) { - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { font_clear_glyph_cache(fonts[i]); FT_Face face = fonts[i]->face; @@ -372,16 +372,16 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con break; width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance; } - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; return width / surface_scale; } -double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { - SDL_Surface *surface = renwin_get_surface(window_renderer); +double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { + SDL_Surface *surface = rs->surface; SDL_Rect clip; SDL_GetClipRect(surface, &clip); - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = rs->scale; double pen_x = x * surface_scale; y *= surface_scale; int bytes_per_pixel = surface->format->BytesPerPixel; @@ -405,7 +405,7 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te int end_x = (metric->x1 - metric->x0) + start_x; int glyph_end = metric->x1, glyph_start = metric->x0; if (!metric->loaded && codepoint > 0xFF) - ren_draw_rect(window_renderer, (RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); + ren_draw_rect(rs, (RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) { uint8_t* source_pixels = set->surface->pixels; for (int line = metric->y0; line < metric->y1; ++line) { @@ -456,9 +456,9 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te else if(font != last || text == end) { double local_pen_x = text == end ? pen_x + adv : pen_x; if (underline) - ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(rs, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); if (strikethrough) - ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(rs, (RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); last = font; last_pen_x = pen_x; } @@ -477,11 +477,11 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) { return dst; } -void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { +void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) { if (color.a == 0) { return; } - SDL_Surface *surface = renwin_get_surface(window_renderer); - const int surface_scale = renwin_surface_scale(window_renderer); + SDL_Surface *surface = rs->surface; + const int surface_scale = rs->scale; SDL_Rect dest_rect = { rect.x * surface_scale, rect.y * surface_scale, @@ -552,8 +552,7 @@ void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect) { void ren_get_size(RenWindow *window_renderer, int *x, int *y) { - const int scale = renwin_surface_scale(window_renderer); - SDL_Surface *surface = renwin_get_surface(window_renderer); - *x = surface->w / scale; - *y = surface->h / scale; + RenSurface rs = renwin_get_surface(window_renderer); + *x = rs.surface->w / rs.scale; + *y = rs.surface->h / rs.scale; } diff --git a/src/renderer.h b/src/renderer.h index 3897421e..0e96d9a9 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -19,6 +19,7 @@ typedef enum { FONT_ANTIALIASING_NONE, FONT_ANTIALIASING_GRAYSCALE, FONT_ANTIALI typedef enum { FONT_STYLE_BOLD = 1, FONT_STYLE_ITALIC = 2, FONT_STYLE_UNDERLINE = 4, FONT_STYLE_SMOOTH = 8, FONT_STYLE_STRIKETHROUGH = 16 } ERenFontStyle; typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect; +typedef struct { SDL_Surface *surface; int scale; } RenSurface; struct RenWindow; typedef struct RenWindow RenWindow; @@ -34,9 +35,9 @@ float ren_font_group_get_size(RenFont **font); void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); -double ren_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); -void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color); +void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color); void ren_init(SDL_Window *win); void ren_resize_window(RenWindow *window_renderer); diff --git a/src/renwindow.c b/src/renwindow.c index c700cedf..ba671404 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -24,20 +24,20 @@ static void setup_renderer(RenWindow *ren, int w, int h) { SDL_DestroyTexture(ren->texture); } ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); - ren->surface_scale = query_surface_scale(ren); + ren->rensurface.scale = query_surface_scale(ren); } #endif void renwin_init_surface(UNUSED RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER - if (ren->surface) { - SDL_FreeSurface(ren->surface); + if (ren->rensurface.surface) { + SDL_FreeSurface(ren->rensurface.surface); } int w, h; SDL_GL_GetDrawableSize(ren->window, &w, &h); - ren->surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); - if (!ren->surface) { + ren->rensurface.surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); + if (!ren->rensurface.surface) { fprintf(stderr, "Error creating surface: %s", SDL_GetError()); exit(1); } @@ -45,14 +45,6 @@ void renwin_init_surface(UNUSED RenWindow *ren) { #endif } -int renwin_surface_scale(UNUSED RenWindow *ren) { -#ifdef LITE_USE_SDL_RENDERER - return ren->surface_scale; -#else - return 1; -#endif -} - static RenRect scaled_rect(const RenRect rect, const int scale) { return (RenRect) {rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale}; @@ -60,28 +52,27 @@ static RenRect scaled_rect(const RenRect rect, const int scale) { void renwin_clip_to_surface(RenWindow *ren) { - SDL_Surface *surface = renwin_get_surface(ren); - SDL_SetClipRect(surface, NULL); + SDL_SetClipRect(renwin_get_surface(ren).surface, NULL); } void renwin_set_clip_rect(RenWindow *ren, RenRect rect) { - SDL_Surface *surface = renwin_get_surface(ren); - RenRect sr = scaled_rect(rect, renwin_surface_scale(ren)); - SDL_SetClipRect(surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); + RenSurface rs = renwin_get_surface(ren); + RenRect sr = scaled_rect(rect, rs.scale); + SDL_SetClipRect(rs.surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); } -SDL_Surface *renwin_get_surface(RenWindow *ren) { +RenSurface renwin_get_surface(RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER - return ren->surface; + return ren->rensurface; #else SDL_Surface *surface = SDL_GetWindowSurface(ren->window); if (!surface) { fprintf(stderr, "Error getting window surface: %s", SDL_GetError()); exit(1); } - return surface; + return (RenSurface){.surface = surface, .scale = 1}; #endif } @@ -90,7 +81,7 @@ void renwin_resize_surface(UNUSED RenWindow *ren) { int new_w, new_h; SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h); /* Note that (w, h) may differ from (new_w, new_h) on retina displays. */ - if (new_w != ren->surface->w || new_h != ren->surface->h) { + if (new_w != ren->rensurface.surface->w || new_h != ren->rensurface.surface->h) { renwin_init_surface(ren); renwin_clip_to_surface(ren); setup_renderer(ren, new_w, new_h); @@ -104,14 +95,14 @@ void renwin_show_window(RenWindow *ren) { void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) { #ifdef LITE_USE_SDL_RENDERER - const int scale = ren->surface_scale; + const int scale = ren->rensurface.scale; for (int i = 0; i < count; i++) { const RenRect *r = &rects[i]; const int x = scale * r->x, y = scale * r->y; const int w = scale * r->width, h = scale * r->height; const SDL_Rect sr = {.x = x, .y = y, .w = w, .h = h}; - int32_t *pixels = ((int32_t *) ren->surface->pixels) + x + ren->surface->w * y; - SDL_UpdateTexture(ren->texture, &sr, pixels, ren->surface->w * 4); + int32_t *pixels = ((int32_t *) ren->rensurface.surface->pixels) + x + ren->rensurface.surface->w * y; + SDL_UpdateTexture(ren->texture, &sr, pixels, ren->rensurface.surface->w * 4); } SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL); SDL_RenderPresent(ren->renderer); @@ -126,6 +117,6 @@ void renwin_free(RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER SDL_DestroyTexture(ren->texture); SDL_DestroyRenderer(ren->renderer); - SDL_FreeSurface(ren->surface); + SDL_FreeSurface(ren->rensurface.surface); #endif } diff --git a/src/renwindow.h b/src/renwindow.h index 7f08aa2f..6b0b9eaa 100644 --- a/src/renwindow.h +++ b/src/renwindow.h @@ -6,19 +6,17 @@ struct RenWindow { #ifdef LITE_USE_SDL_RENDERER SDL_Renderer *renderer; SDL_Texture *texture; - SDL_Surface *surface; - int surface_scale; + RenSurface rensurface; #endif }; typedef struct RenWindow RenWindow; void renwin_init_surface(RenWindow *ren); -int renwin_surface_scale(RenWindow *ren); void renwin_clip_to_surface(RenWindow *ren); void renwin_set_clip_rect(RenWindow *ren, RenRect rect); void renwin_resize_surface(RenWindow *ren); void renwin_show_window(RenWindow *ren); void renwin_update_rects(RenWindow *ren, RenRect *rects, int count); void renwin_free(RenWindow *ren); -SDL_Surface *renwin_get_surface(RenWindow *ren); +RenSurface renwin_get_surface(RenWindow *ren); From 350131dabc6bebfd3b2ab0c0d9f34386707bb792 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Wed, 22 Mar 2023 20:36:05 +0800 Subject: [PATCH 043/176] Asynchronous process reaping (#1412) * refactor(process): introduce process_stream_handle separate from process_handle * feat(process): introduce process_handle helper functions * feat(process): add asynchronous process reaping * feat(process): wait for shorter period if possible * style(process): remove unecessary brackets * style(process): fix parentheses * refactor(process): remove useless setvbuf call * style(process): remove unecessary value * refactor(process): add size field into kill_list * refactor(process): use SDL_Delay for sleeping * style(process): remove trailing whitespace * fix(main): destroy window before closing lua * fix(process): check for timeout correctly * refactor(process): remove unecessary if check * refactor(process): remove size from the list * fix(process): fix invalid delay calculation Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- src/api/process.c | 312 ++++++++++++++++++++++++++++++++++++++-------- src/main.c | 4 +- 2 files changed, 262 insertions(+), 54 deletions(-) diff --git a/src/api/process.c b/src/api/process.c index 081e6ab6..2b0a5008 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -5,12 +5,13 @@ #include #include #include +#include #include #if _WIN32 // https://stackoverflow.com/questions/60645/overlapped-i-o-on-anonymous-pipe // https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output - #include + #include #else #include #include @@ -21,11 +22,15 @@ #endif #define READ_BUF_SIZE 2048 +#define PROCESS_TERM_TRIES 3 +#define PROCESS_TERM_DELAY 50 #if _WIN32 +typedef HANDLE process_stream_handle; typedef HANDLE process_handle; #else -typedef int process_handle; +typedef int process_stream_handle; +typedef pid_t process_handle; #endif typedef struct { @@ -38,9 +43,24 @@ typedef struct { bool reading[2]; char buffer[2][READ_BUF_SIZE]; #endif - process_handle child_pipes[3][2]; + process_stream_handle child_pipes[3][2]; } process_t; +typedef struct process_kill_s { + int tries; + uint32_t start_time; + process_handle handle; + struct process_kill_s *next; +} process_kill_t; + +typedef struct { + bool stop; + SDL_mutex *mutex; + SDL_cond *has_work, *work_done; + process_kill_t *head; + process_kill_t *tail; +} process_kill_list_t; + typedef enum { SIGNAL_KILL, SIGNAL_TERM, @@ -63,60 +83,201 @@ typedef enum { REDIRECT_PARENT = -3, } filed_e; +static process_kill_list_t kill_list = { 0 }; +static SDL_Thread *kill_list_thread = NULL; + #ifdef _WIN32 static volatile long PipeSerialNumber; static void close_fd(HANDLE* handle) { if (*handle) CloseHandle(*handle); *handle = INVALID_HANDLE_VALUE; } + #define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess) #else static void close_fd(int* fd) { if (*fd) close(*fd); *fd = 0; } + #define PROCESS_GET_HANDLE(P) ((P)->pid) #endif + +static void kill_list_free(process_kill_list_t *list) { + process_kill_t *node, *temp; + SDL_DestroyMutex(list->mutex); + SDL_DestroyCond(list->has_work); + SDL_DestroyCond(list->work_done); + node = list->head; + while (node) { + temp = node; + node = node->next; + free(temp); + } +} + + +static bool kill_list_init(process_kill_list_t *list) { + list->mutex = SDL_CreateMutex(); + list->has_work = SDL_CreateCond(); + list->work_done = SDL_CreateCond(); + list->head = list->tail = NULL; + list->stop = false; + if (!list->mutex || !list->has_work || !list->work_done) { + kill_list_free(list); + return false; + } + return true; +} + + +static void kill_list_push(process_kill_list_t *list, process_kill_t *task) { + if (!list) return; + task->next = NULL; + if (list->tail) { + list->tail->next = task; + list->tail = task; + } else { + list->head = list->tail = task; + } +} + + +static void kill_list_pop(process_kill_list_t *list) { + if (!list || !list->head) return; + process_kill_t *head = list->head; + list->head = list->head->next; + if (!list->head) list->tail = NULL; + head->next = NULL; +} + + +static void kill_list_wait_all(process_kill_list_t *list) { + SDL_LockMutex(list->mutex); + // wait until list is empty + while (list->head) + SDL_CondWait(list->work_done, list->mutex); + // tell the worker to stop + list->stop = true; + SDL_CondSignal(list->has_work); + SDL_UnlockMutex(list->mutex); +} + + +static void process_handle_close(process_handle *handle) { +#ifdef _WIN32 + if (*handle) { + CloseHandle(*handle); + *handle = NULL; + } +#endif + (void) 0; +} + + +static bool process_handle_is_running(process_handle handle, int *status) { +#ifdef _WIN32 + DWORD s; + if (GetExitCodeProcess(handle, &s) && s != STILL_ACTIVE) { + if (status != NULL) + *status = s; + return false; + } +#else + int s; + if (waitpid(handle, &s, WNOHANG) != 0) { + if (status != NULL) + *status = WEXITSTATUS(s); + return false; + } +#endif + return true; +} + + +static bool process_handle_signal(process_handle handle, signal_e sig) { +#if _WIN32 + switch(sig) { + case SIGNAL_TERM: return GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetProcessId(handle)); + case SIGNAL_KILL: return TerminateProcess(handle, -1); + case SIGNAL_INTERRUPT: return DebugBreakProcess(handle); + } +#else + switch (sig) { + case SIGNAL_TERM: return kill(-handle, SIGTERM) == 0; break; + case SIGNAL_KILL: return kill(-handle, SIGKILL) == 0; break; + case SIGNAL_INTERRUPT: return kill(-handle, SIGINT) == 0; break; + } +#endif + return false; +} + + +static int kill_list_worker(void *ud) { + process_kill_list_t *list = (process_kill_list_t *) ud; + process_kill_t *current_task; + uint32_t delay; + + while (true) { + SDL_LockMutex(list->mutex); + + // wait until we have work to do + while (!list->head && !list->stop) + SDL_CondWait(list->has_work, list->mutex); // LOCK MUTEX + + if (list->stop) break; + + while ((current_task = list->head)) { + if ((SDL_GetTicks() - current_task->start_time) < PROCESS_TERM_DELAY) + break; + kill_list_pop(list); + if (process_handle_is_running(current_task->handle, NULL)) { + if (current_task->tries < PROCESS_TERM_TRIES) + process_handle_signal(current_task->handle, SIGNAL_TERM); + else if (current_task->tries == PROCESS_TERM_TRIES) + process_handle_signal(current_task->handle, SIGNAL_KILL); + else + goto free_task; + + // add the task back into the queue + current_task->tries++; + current_task->start_time = SDL_GetTicks(); + kill_list_push(list, current_task); + } else { + free_task: + SDL_CondSignal(list->work_done); + process_handle_close(¤t_task->handle); + free(current_task); + } + } + delay = list->head ? (list->head->start_time + PROCESS_TERM_DELAY) - SDL_GetTicks() : 0; + SDL_UnlockMutex(list->mutex); + SDL_Delay(delay); + } + SDL_UnlockMutex(list->mutex); + return 0; +} + + static bool poll_process(process_t* proc, int timeout) { + uint32_t ticks; + if (!proc->running) return false; - uint32_t ticks = SDL_GetTicks(); + if (timeout == WAIT_DEADLINE) timeout = proc->deadline; + ticks = SDL_GetTicks(); do { - #ifdef _WIN32 - DWORD exit_code = -1; - if (!GetExitCodeProcess( proc->process_information.hProcess, &exit_code ) || exit_code != STILL_ACTIVE) { - proc->returncode = exit_code; - proc->running = false; - break; - } - #else - int status; - pid_t wait_response = waitpid(proc->pid, &status, WNOHANG); - if (wait_response != 0) { - proc->running = false; - proc->returncode = WEXITSTATUS(status); - break; - } - #endif + int status; + if (!process_handle_is_running(PROCESS_GET_HANDLE(proc), &status)) { + proc->running = false; + proc->returncode = status; + break; + } if (timeout) - SDL_Delay(5); + SDL_Delay(timeout >= 5 ? 5 : 0); } while (timeout == WAIT_INFINITE || (int)SDL_GetTicks() - ticks < timeout); return proc->running; } static bool signal_process(process_t* proc, signal_e sig) { - bool terminate = false; - #if _WIN32 - switch(sig) { - case SIGNAL_TERM: terminate = GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetProcessId(proc->process_information.hProcess)); break; - case SIGNAL_KILL: terminate = TerminateProcess(proc->process_information.hProcess, -1); break; - case SIGNAL_INTERRUPT: DebugBreakProcess(proc->process_information.hProcess); break; - } - #else - switch (sig) { - case SIGNAL_TERM: terminate = kill(-proc->pid, SIGTERM) == 1; break; - case SIGNAL_KILL: terminate = kill(-proc->pid, SIGKILL) == 1; break; - case SIGNAL_INTERRUPT: kill(-proc->pid, SIGINT); break; - } - #endif - if (terminate) + if (process_handle_signal(PROCESS_GET_HANDLE(proc), sig)) poll_process(proc, WAIT_NONE); return true; } @@ -152,7 +313,7 @@ static int process_start(lua_State* L) { if (arg_len > 1) { lua_getfield(L, 2, "env"); if (!lua_isnil(L, -1)) { - lua_pushnil(L); + lua_pushnil(L); while (lua_next(L, -2) != 0) { const char* key = luaL_checklstring(L, -2, &key_len); const char* val = luaL_checklstring(L, -1, &val_len); @@ -179,7 +340,7 @@ static int process_start(lua_State* L) { } } } - + process_t* self = lua_newuserdata(L, sizeof(process_t)); memset(self, 0, sizeof(process_t)); luaL_setmetatable(L, API_TYPE_PROCESS); @@ -196,9 +357,9 @@ static int process_start(lua_State* L) { } self->child_pipes[i][i == STDIN_FD ? 1 : 0] = INVALID_HANDLE_VALUE; break; - case REDIRECT_DISCARD: - self->child_pipes[i][0] = INVALID_HANDLE_VALUE; - self->child_pipes[i][1] = INVALID_HANDLE_VALUE; + case REDIRECT_DISCARD: + self->child_pipes[i][0] = INVALID_HANDLE_VALUE; + self->child_pipes[i][1] = INVALID_HANDLE_VALUE; break; default: { if (new_fds[i] == i) { @@ -289,7 +450,7 @@ static int process_start(lua_State* L) { goto cleanup; } self->pid = (long)self->process_information.dwProcessId; - if (detach) + if (detach) CloseHandle(self->process_information.hProcess); CloseHandle(self->process_information.hThread); #else @@ -372,7 +533,7 @@ static int process_start(lua_State* L) { free((char*)env_values[i]); } for (int stream = 0; stream < 3; ++stream) { - process_handle* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; + process_stream_handle* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; if (*pipe) { close_fd(pipe); } @@ -467,7 +628,7 @@ static int f_close_stream(lua_State* L) { static int process_strerror(lua_State* L) { #if _WIN32 return 1; - #endif + #endif int error_code = luaL_checknumber(L, 1); if (error_code < 0) lua_pushstring(L, strerror(error_code)); @@ -525,14 +686,37 @@ static int self_signal(lua_State* L, signal_e sig) { static int f_terminate(lua_State* L) { return self_signal(L, SIGNAL_TERM); } static int f_kill(lua_State* L) { return self_signal(L, SIGNAL_KILL); } static int f_interrupt(lua_State* L) { return self_signal(L, SIGNAL_INTERRUPT); } -static int f_gc(lua_State* L) { + +static int f_gc(lua_State* L) { process_t* self = (process_t*) luaL_checkudata(L, 1, API_TYPE_PROCESS); - if (!self->detached) + + if (poll_process(self, 0) && !self->detached) { + // attempt to kill the process if not detached + process_kill_t *p; + signal_process(self, SIGNAL_TERM); + p = malloc(sizeof(process_kill_t)); + if (!p || !kill_list_thread) { + // if we can't allocate, we'll use the old method + poll_process(self, PROCESS_TERM_DELAY); + if (self->running) { + signal_process(self, SIGNAL_KILL); + poll_process(self, PROCESS_TERM_DELAY); + } + } else { + // send the handle to a queue for asynchronous waiting + p->handle = PROCESS_GET_HANDLE(self); + p->start_time = SDL_GetTicks(); + p->tries = 1; + SDL_LockMutex(kill_list.mutex); + kill_list_push(&kill_list, p); + SDL_CondSignal(kill_list.has_work); + SDL_UnlockMutex(kill_list.mutex); + } + } close_fd(&self->child_pipes[STDIN_FD ][1]); close_fd(&self->child_pipes[STDOUT_FD][0]); - close_fd(&self->child_pipes[STDERR_FD][0]); - poll_process(self, 10); + close_fd(&self->child_pipes[STDERR_FD][0]); return 0; } @@ -542,11 +726,16 @@ static int f_running(lua_State* L) { return 1; } -static const struct luaL_Reg lib[] = { +static int process_gc(lua_State *L) { + kill_list_wait_all(&kill_list); + SDL_WaitThread(kill_list_thread, NULL); + kill_list_free(&kill_list); + return 0; +} + +static const struct luaL_Reg process_metatable[] = { {"__gc", f_gc}, {"__tostring", f_tostring}, - {"start", process_start}, - {"strerror", process_strerror}, {"pid", f_pid}, {"returncode", f_returncode}, {"read", f_read}, @@ -562,12 +751,29 @@ static const struct luaL_Reg lib[] = { {NULL, NULL} }; +static const struct luaL_Reg lib[] = { + { "start", process_start }, + { "strerror", process_strerror }, + { NULL, NULL } +}; + int luaopen_process(lua_State *L) { + if (kill_list_init(&kill_list)) + kill_list_thread = SDL_CreateThread(kill_list_worker, "process_kill", &kill_list); + + // create the process metatable luaL_newmetatable(L, API_TYPE_PROCESS); - luaL_setfuncs(L, lib, 0); + luaL_setfuncs(L, process_metatable, 0); lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); + // create the process library + luaL_newlib(L, lib); + lua_newtable(L); + lua_pushcfunction(L, process_gc); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + API_CONSTANT_DEFINE(L, -1, "WAIT_INFINITE", WAIT_INFINITE); API_CONSTANT_DEFINE(L, -1, "WAIT_DEADLINE", WAIT_DEADLINE); @@ -576,7 +782,7 @@ int luaopen_process(lua_State *L) { API_CONSTANT_DEFINE(L, -1, "STREAM_STDERR", STDERR_FD); API_CONSTANT_DEFINE(L, -1, "REDIRECT_DEFAULT", REDIRECT_DEFAULT); - API_CONSTANT_DEFINE(L, -1, "REDIRECT_STDOUT", STDOUT_FD); + API_CONSTANT_DEFINE(L, -1, "REDIRECT_STDOUT", STDOUT_FD); API_CONSTANT_DEFINE(L, -1, "REDIRECT_STDERR", STDERR_FD); API_CONSTANT_DEFINE(L, -1, "REDIRECT_PARENT", REDIRECT_PARENT); // Redirects to parent's STDOUT/STDERR API_CONSTANT_DEFINE(L, -1, "REDIRECT_DISCARD", REDIRECT_DISCARD); // Closes the filehandle, discarding it. diff --git a/src/main.c b/src/main.c index 7bc57b6e..ab2da5ca 100644 --- a/src/main.c +++ b/src/main.c @@ -255,8 +255,10 @@ init_lua: goto init_lua; } - lua_close(L); + // This allows the window to be destroyed before lite-xl is done with + // reaping child processes ren_free_window_resources(&window_renderer); + lua_close(L); return EXIT_SUCCESS; } From 146dca9188968f03cd70464ebb4e5ae9ba9cd00a Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 28 Mar 2023 01:17:11 +0200 Subject: [PATCH 044/176] Don't calculate widths per-uft8-char when not needed (#1409) --- data/core/docview.lua | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/data/core/docview.lua b/data/core/docview.lua index cdfb0298..908d7c6a 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -175,12 +175,21 @@ function DocView:get_col_x_offset(line, col) for _, type, text in self.doc.highlighter:each_token(line) do local font = style.syntax_fonts[type] or default_font if font ~= default_font then font:set_tab_size(indent_size) end - for char in common.utf8_chars(text) do - if column == col then + local length = #text + if column + length <= col then + xoffset = xoffset + font:get_width(text) + column = column + length + if column >= col then return xoffset end - xoffset = xoffset + font:get_width(char) - column = column + #char + else + for char in common.utf8_chars(text) do + if column >= col then + return xoffset + end + xoffset = xoffset + font:get_width(char) + column = column + #char + end end end @@ -198,14 +207,22 @@ function DocView:get_x_offset_col(line, x) for _, type, text in self.doc.highlighter:each_token(line) do local font = style.syntax_fonts[type] or default_font if font ~= default_font then font:set_tab_size(indent_size) end - for char in common.utf8_chars(text) do - local w = font:get_width(char) - if xoffset >= x then - return (xoffset - x > w / 2) and last_i or i + local width = font:get_width(text) + -- Don't take the shortcut if the width matches x, + -- because we need last_i which should be calculated using utf-8. + if xoffset + width < x then + xoffset = xoffset + width + i = i + #text + else + for char in common.utf8_chars(text) do + local w = font:get_width(char) + if xoffset >= x then + return (xoffset - x > w / 2) and last_i or i + end + xoffset = xoffset + w + last_i = i + i = i + #char end - xoffset = xoffset + w - last_i = i - i = i + #char end end From 7f0651155dda2495c5459eb80d9b88afd0fe141c Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 28 Mar 2023 12:57:47 -0400 Subject: [PATCH 045/176] Made coroutines make more sense, and fixed a bug. (#1381) * Made coroutines make more sense, and fixed a bug. * Fixed typo. * Additional checking for off-cycles. * Fixed issue with calling step too much. * If we have no redraw, set next step time for next frame. * Added in `now` variables to reduce calls. --- data/core/init.lua | 58 ++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index f7063a26..00322121 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -305,7 +305,7 @@ function core.add_project_directory(path) end end if project_dir_open then - coroutine.yield(changed and 0.05 or 0) + coroutine.yield(changed and 0 or 0.05) else return end @@ -1384,7 +1384,7 @@ end local run_threads = coroutine.wrap(function() while true do local max_time = 1 / config.fps - 0.004 - local need_more_work = false + local minimal_time_to_wake = math.huge for k, thread in pairs(core.threads) do -- run thread @@ -1398,48 +1398,60 @@ local run_threads = coroutine.wrap(function() end elseif wait then thread.wake = system.get_time() + wait + minimal_time_to_wake = math.min(minimal_time_to_wake, wait) else - need_more_work = true + minimal_time_to_wake = 0 end + else + minimal_time_to_wake = math.min(minimal_time_to_wake, thread.wake - system.get_time()) end -- stop running threads if we're about to hit the end of frame if system.get_time() - core.frame_start > max_time then - coroutine.yield(true) + coroutine.yield(0) end end - if not need_more_work then coroutine.yield(false) end + coroutine.yield(minimal_time_to_wake) end end) function core.run() - local idle_iterations = 0 + local next_step while true do core.frame_start = system.get_time() - local need_more_work = run_threads() - local did_redraw = core.step() + local time_to_wake = run_threads() + local did_redraw = false + if not next_step or system.get_time() >= next_step then + did_redraw = core.step() + next_step = nil + end if core.restart_request or core.quit_request then break end - if not did_redraw and not need_more_work then - idle_iterations = idle_iterations + 1 - -- do not wait of events at idle_iterations = 1 to give a chance at core.step to run - -- and set "redraw" flag. - if idle_iterations > 1 then - if system.window_has_focus() then - -- keep running even with no events to make the cursor blinks - local t = system.get_time() - core.blink_start + + if not did_redraw then + if system.window_has_focus() then + local now = system.get_time() + if not next_step then -- compute the time until the next blink + local t = now - core.blink_start local h = config.blink_period / 2 local dt = math.ceil(t / h) * h - t - system.wait_event(dt + 1 / config.fps) - else - system.wait_event() + local cursor_time_to_wake = dt + 1 / config.fps + next_step = now + cursor_time_to_wake end + if time_to_wake > 0 and system.wait_event(math.min(next_step - now, time_to_wake)) then + next_step = nil -- if we've recevied an event, perform a step + end + else + system.wait_event() + next_step = nil -- perform a step when we're not in focus if get we an event end - else - idle_iterations = 0 - local elapsed = system.get_time() - core.frame_start - system.sleep(math.max(0, 1 / config.fps - elapsed)) + else -- if we redrew, then make sure we only draw at most FPS/sec + local now = system.get_time() + local elapsed = now - core.frame_start + local next_frame = math.max(0, 1 / config.fps - elapsed) + next_step = next_step or (now + next_frame) + system.sleep(math.min(next_frame, time_to_wake)) end end end From 73ff0255523b04da1d62816966a493b7297f6cd5 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Tue, 28 Mar 2023 14:17:30 -0400 Subject: [PATCH 046/176] Made things clearer, as per jgm's suggestion. --- data/core/init.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 00322121..e11d2568 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1396,11 +1396,10 @@ local run_threads = coroutine.wrap(function() else core.threads[k] = nil end - elseif wait then + else + wait = wait or 0 thread.wake = system.get_time() + wait minimal_time_to_wake = math.min(minimal_time_to_wake, wait) - else - minimal_time_to_wake = 0 end else minimal_time_to_wake = math.min(minimal_time_to_wake, thread.wake - system.get_time()) From b005454652df62c53404d7b6c68aba111ffd4285 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Mar 2023 00:33:29 +0200 Subject: [PATCH 047/176] Limit `core.threads` without a timeout to run 30 times per second --- data/core/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/core/init.lua b/data/core/init.lua index e11d2568..b14c0104 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1397,7 +1397,7 @@ local run_threads = coroutine.wrap(function() core.threads[k] = nil end else - wait = wait or 0 + wait = wait or (1/30) thread.wake = system.get_time() + wait minimal_time_to_wake = math.min(minimal_time_to_wake, wait) end From 1becf3550823c937af618437d77c83ba2aa4167a Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 28 Mar 2023 19:57:24 -0400 Subject: [PATCH 048/176] Disable `trimwhitespace` and `drawwhitespace` via their configs (#1446) Instead of completely disabling them, we now use their internal toggle. Also moved `drawwhitespace` commands inside the plugin. --- * Fixed bug where commands would show even when plugin was disbled. Also removed antiquated way of disabling. * Fixed typos. * Also moved trimwhitespace out of config, if it already has a default enabled value of false. * Changed documentation. * Clarified comments. --- data/core/command.lua | 2 +- data/core/commands/drawwhitespace.lua | 16 ---------------- data/core/config.lua | 3 --- data/core/init.lua | 7 ++----- data/plugins/drawwhitespace.lua | 20 ++++++++++++++++++-- data/plugins/trimwhitespace.lua | 4 ++-- 6 files changed, 23 insertions(+), 29 deletions(-) delete mode 100644 data/core/commands/drawwhitespace.lua diff --git a/data/core/command.lua b/data/core/command.lua index f5738304..faf872e2 100644 --- a/data/core/command.lua +++ b/data/core/command.lua @@ -107,7 +107,7 @@ end function command.add_defaults() local reg = { "core", "root", "command", "doc", "findreplace", - "files", "drawwhitespace", "dialog", "log", "statusbar" + "files", "dialog", "log", "statusbar" } for _, name in ipairs(reg) do require("core.commands." .. name) diff --git a/data/core/commands/drawwhitespace.lua b/data/core/commands/drawwhitespace.lua deleted file mode 100644 index 9372c55d..00000000 --- a/data/core/commands/drawwhitespace.lua +++ /dev/null @@ -1,16 +0,0 @@ -local command = require "core.command" -local config = require "core.config" - -command.add(nil, { - ["draw-whitespace:toggle"] = function() - config.draw_whitespace = not config.draw_whitespace - end, - - ["draw-whitespace:disable"] = function() - config.draw_whitespace = false - end, - - ["draw-whitespace:enable"] = function() - config.draw_whitespace = true - end, -}) diff --git a/data/core/config.lua b/data/core/config.lua index fc5da98a..c1a16b11 100644 --- a/data/core/config.lua +++ b/data/core/config.lua @@ -101,8 +101,5 @@ setmetatable(config.plugins, { end }) --- Disable these plugins by default. -config.plugins.trimwhitespace = false -config.plugins.drawwhitespace = false return config diff --git a/data/core/init.lua b/data/core/init.lua index b14c0104..1aba9ff7 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -531,12 +531,9 @@ local style = require "core.style" ------------------------------ Plugins ---------------------------------------- --- enable or disable plugin loading setting config entries: +-- disable plugin loading setting config entries: --- enable plugins.trimwhitespace, otherwise it is disabled by default: --- config.plugins.trimwhitespace = true --- --- disable detectindent, otherwise it is enabled by default +-- disable plugin detectindent, otherwise it is enabled by default: -- config.plugins.detectindent = false ---------------------------- Miscellaneous ------------------------------------- diff --git a/data/plugins/drawwhitespace.lua b/data/plugins/drawwhitespace.lua index 6c422172..753b3bb4 100644 --- a/data/plugins/drawwhitespace.lua +++ b/data/plugins/drawwhitespace.lua @@ -4,11 +4,12 @@ local core = require "core" local style = require "core.style" local DocView = require "core.docview" local common = require "core.common" +local command = require "core.command" local config = require "core.config" local Highlighter = require "core.doc.highlighter" config.plugins.drawwhitespace = common.merge({ - enabled = true, + enabled = false, show_leading = true, show_trailing = true, show_middle = true, @@ -43,7 +44,7 @@ config.plugins.drawwhitespace = common.merge({ description = "Disable or enable the drawing of white spaces.", path = "enabled", type = "toggle", - default = true + default = false }, { label = "Show Leading", @@ -342,3 +343,18 @@ function DocView:draw_line_text(idx, x, y) return draw_line_text(self, idx, x, y) end + + +command.add(nil, { + ["draw-whitespace:toggle"] = function() + config.plugins.drawwhitespace.enabled = not config.drawwhitespace.enabled + end, + + ["draw-whitespace:disable"] = function() + config.plugins.drawwhitespace.enabled = false + end, + + ["draw-whitespace:enable"] = function() + config.plugins.drawwhitespace.enabled = true + end, +}) diff --git a/data/plugins/trimwhitespace.lua b/data/plugins/trimwhitespace.lua index 6fb67230..8daa77e0 100644 --- a/data/plugins/trimwhitespace.lua +++ b/data/plugins/trimwhitespace.lua @@ -8,7 +8,7 @@ local Doc = require "core.doc" ---@field enabled boolean ---@field trim_empty_end_lines boolean config.plugins.trimwhitespace = common.merge({ - enabled = true, + enabled = false, trim_empty_end_lines = false, config_spec = { name = "Trim Whitespace", @@ -17,7 +17,7 @@ config.plugins.trimwhitespace = common.merge({ description = "Disable or enable the trimming of white spaces by default.", path = "enabled", type = "toggle", - default = true + default = false }, { label = "Trim Empty End Lines", From 1c8c569fae9390e9a52dcebed0669e1ee82186a0 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 1 Apr 2023 18:12:39 +0200 Subject: [PATCH 049/176] Allow `tokenizer` to pause and resume in the middle of a line (#1444) --- data/core/doc/highlighter.lua | 25 ++++++++++++++++-------- data/core/tokenizer.lua | 36 ++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua index 0cddb2c3..b1367049 100644 --- a/data/core/doc/highlighter.lua +++ b/data/core/doc/highlighter.lua @@ -19,25 +19,34 @@ function Highlighter:start() if self.running then return end self.running = true core.add_thread(function() - while self.first_invalid_line < self.max_wanted_line do + while self.first_invalid_line <= self.max_wanted_line do local max = math.min(self.first_invalid_line + 40, self.max_wanted_line) local retokenized_from for i = self.first_invalid_line, max do local state = (i > 1) and self.lines[i - 1].state local line = self.lines[i] - if not (line and line.init_state == state and line.text == self.doc.lines[i]) then + if line and line.resume and (line.init_state ~= state or line.text ~= self.doc.lines[i]) then + -- Reset the progress if no longer valid + line.resume = nil + end + if not (line and line.init_state == state and line.text == self.doc.lines[i] and not line.resume) then retokenized_from = retokenized_from or i - self.lines[i] = self:tokenize_line(i, state) + self.lines[i] = self:tokenize_line(i, state, line and line.resume) + if self.lines[i].resume then + self.first_invalid_line = i + goto yield + end elseif retokenized_from then self:update_notify(retokenized_from, i - retokenized_from - 1) retokenized_from = nil end end + + self.first_invalid_line = max + 1 + ::yield:: if retokenized_from then self:update_notify(retokenized_from, max - retokenized_from) end - - self.first_invalid_line = max + 1 core.redraw = true coroutine.yield() end @@ -48,7 +57,7 @@ end local function set_max_wanted_lines(self, amount) self.max_wanted_line = amount - if self.first_invalid_line < self.max_wanted_line then + if self.first_invalid_line <= self.max_wanted_line then self:start() end end @@ -91,11 +100,11 @@ function Highlighter:update_notify(line, n) end -function Highlighter:tokenize_line(idx, state) +function Highlighter:tokenize_line(idx, state, resume) local res = {} res.init_state = state res.text = self.doc.lines[idx] - res.tokens, res.state = tokenizer.tokenize(self.doc.syntax, res.text, state) + res.tokens, res.state, res.resume = tokenizer.tokenize(self.doc.syntax, res.text, state, resume) return res end diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index 0a3b58b1..fe74ca6d 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -1,5 +1,6 @@ local core = require "core" local syntax = require "core.syntax" +local config = require "core.config" local tokenizer = {} local bad_patterns = {} @@ -9,7 +10,7 @@ local function push_token(t, type, text) type = type or "normal" local prev_type = t[#t-1] local prev_text = t[#t] - if prev_type and (prev_type == type or prev_text:ufind("^%s*$")) then + if prev_type and (prev_type == type or (prev_text:ufind("^%s*$") and type ~= "incomplete")) then t[#t-1] = type t[#t] = prev_text .. text else @@ -128,8 +129,8 @@ end ---@param incoming_syntax table ---@param text string ---@param state string -function tokenizer.tokenize(incoming_syntax, text, state) - local res = {} +function tokenizer.tokenize(incoming_syntax, text, state, resume) + local res local i = 1 if #incoming_syntax.patterns == 0 then @@ -137,6 +138,20 @@ function tokenizer.tokenize(incoming_syntax, text, state) end state = state or string.char(0) + + if resume then + res = resume.res + -- Remove "incomplete" tokens + while res[#res-1] == "incomplete" do + table.remove(res, #res) + table.remove(res, #res) + end + i = resume.i + state = resume.state + end + + res = res or {} + -- incoming_syntax : the parent syntax of the file. -- state : a string of bytes representing syntax state (see above) @@ -246,7 +261,22 @@ function tokenizer.tokenize(incoming_syntax, text, state) end local text_len = text:ulen() + local start_time = system.get_time() + local starting_i = i while i <= text_len do + -- Every 200 chars, check if we're out of time + if i - starting_i > 200 then + starting_i = i + if system.get_time() - start_time > 0.5 / config.fps then + -- We're out of time + push_token(res, "incomplete", string.usub(text, i)) + return res, string.char(0), { + res = res, + i = i, + state = state + } + end + end -- continue trying to match the end pattern of a pair if we have a state set if current_pattern_idx > 0 then local p = current_syntax.patterns[current_pattern_idx] From ee80b451c6b59f00a4f4b7170b6c014e233fed1e Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 7 Apr 2023 12:42:46 -0400 Subject: [PATCH 050/176] Added in explicit touchscreen keyboard support. (#1389) --- data/core/commandview.lua | 5 +++++ data/core/docview.lua | 5 +++++ data/core/init.lua | 1 + data/core/view.lua | 4 ++++ src/api/system.c | 14 ++++++++++++-- src/main.c | 2 ++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/data/core/commandview.lua b/data/core/commandview.lua index 1f388678..dd2c5e42 100644 --- a/data/core/commandview.lua +++ b/data/core/commandview.lua @@ -84,6 +84,11 @@ function CommandView:get_line_screen_position(line, col) end +function CommandView:supports_text_input() + return true +end + + function CommandView:get_scrollable_size() return 0 end diff --git a/data/core/docview.lua b/data/core/docview.lua index 908d7c6a..7b04dba4 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -252,6 +252,11 @@ function DocView:scroll_to_line(line, ignore_if_visible, instant) end +function DocView:supports_text_input() + return true +end + + function DocView:scroll_to_make_visible(line, col) local ox, oy = self:get_content_offset() local _, ly = self:get_line_screen_position(line, col) diff --git a/data/core/init.lua b/data/core/init.lua index 1aba9ff7..8c9dafcc 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1105,6 +1105,7 @@ function core.set_active_view(view) -- Reset the IME even if the focus didn't change ime.stop() if view ~= core.active_view then + system.text_input(view:supports_text_input()) if core.active_view and core.active_view.force_focus then core.next_active_view = view return diff --git a/data/core/view.lua b/data/core/view.lua index 77378b90..36580677 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -108,6 +108,10 @@ function View:get_h_scrollable_size() end +function View:supports_text_input() + return false +end + ---@param x number ---@param y number ---@return boolean diff --git a/src/api/system.c b/src/api/system.c index ad7cede8..9da499a6 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -966,7 +966,7 @@ static int f_library_gc(lua_State *L) { lua_getfield(L, 1, "handle"); void* handle = lua_touserdata(L, -1); SDL_UnloadObject(handle); - + return 0; } @@ -1069,6 +1069,15 @@ static int f_path_compare(lua_State *L) { } +static int f_text_input(lua_State* L) { + if (lua_toboolean(L, 1)) + SDL_StartTextInput(); + else + SDL_StopTextInput(); + return 0; +} + + static const luaL_Reg lib[] = { { "poll_event", f_poll_event }, { "wait_event", f_wait_event }, @@ -1102,12 +1111,13 @@ static const luaL_Reg lib[] = { { "load_native_plugin", f_load_native_plugin }, { "path_compare", f_path_compare }, { "get_fs_type", f_get_fs_type }, + { "text_input", f_text_input }, { NULL, NULL } }; int luaopen_system(lua_State *L) { - luaL_newmetatable(L, API_TYPE_NATIVE_PLUGIN); + luaL_newmetatable(L, API_TYPE_NATIVE_PLUGIN); lua_pushcfunction(L, f_library_gc); lua_setfield(L, -2, "__gc"); luaL_newlib(L, lib); diff --git a/src/main.c b/src/main.c index ab2da5ca..e433fe18 100644 --- a/src/main.c +++ b/src/main.c @@ -212,6 +212,8 @@ init_lua: set_macos_bundle_resources(L); #endif #endif + SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE); + SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE); const char *init_lite_code = \ "local core\n" From 46ea86e28cecceabe0f3137720bf848c0898f640 Mon Sep 17 00:00:00 2001 From: vqn <85911372+vqns@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:54:00 +0000 Subject: [PATCH 051/176] fix cursors positions when deleting multiple selections (#1393) * correctly handle overlapping selections merge cursors in Doc:raw_remove --- data/core/commands/doc.lua | 4 ++-- data/core/doc/init.lua | 48 +++++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index ebaf698c..eca876ea 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -323,7 +323,7 @@ local commands = { end, ["doc:delete"] = function(dv) - for idx, line1, col1, line2, col2 in dv.doc:get_selections() do + for idx, line1, col1, line2, col2 in dv.doc:get_selections(true, true) do if line1 == line2 and col1 == col2 and dv.doc.lines[line1]:find("^%s*$", col1) then dv.doc:remove(line1, col1, line1, math.huge) end @@ -333,7 +333,7 @@ local commands = { ["doc:backspace"] = function(dv) local _, indent_size = dv.doc:get_indent_info() - for idx, line1, col1, line2, col2 in dv.doc:get_selections() do + for idx, line1, col1, line2, col2 in dv.doc:get_selections(true, true) do if line1 == line2 and col1 == col2 then local text = dv.doc:get_text(line1, 1, line1, col1) if #text >= indent_size and text:find("^ *$") then diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 26fc2a52..7fdd896c 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -427,19 +427,51 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) local before = self.lines[line1]:sub(1, col1 - 1) local after = self.lines[line2]:sub(col2) - -- splice line into line array - common.splice(self.lines, line1, line2 - line1 + 1, { before .. after }) + local line_removal = line2 - line1 + local col_removal = col2 - col1 - -- move all cursors back if they share a line with the removed text + -- splice line into line array + common.splice(self.lines, line1, line_removal + 1, { before .. after }) + + local merge = false + + -- keep selections in correct positions: each pair (line, col) + -- * remains unchanged if before the deleted text + -- * is set to (line1, col1) if in the deleted text + -- * is set to (line1, col - col_removal) if on line2 but out of the deleted text + -- * is set to (line - line_removal, col) if after line2 for idx, cline1, ccol1, cline2, ccol2 in self:get_selections(true, true) do - if cline1 < line2 then break end - local line_removal = line2 - line1 - local column_removal = line2 == cline2 and col2 < ccol1 and (line2 == line1 and col2 - col1 or col2) or 0 - self:set_selections(idx, cline1 - line_removal, ccol1 - column_removal, cline2 - line_removal, ccol2 - column_removal) + if cline2 < line1 then break end + local l1, c1, l2, c2 = cline1, ccol1, cline2, ccol2 + + if cline1 > line1 or (cline1 == line1 and ccol1 > col1) then + if cline1 > line2 then + l1 = l1 - line_removal + else + l1 = line1 + c1 = (cline1 == line2 and ccol1 > col2) and c1 - col_removal or col1 + end + end + + if cline2 > line1 or (cline2 == line2 and ccol2 > col1) then + if cline2 > line2 then + l2 = l2 - line_removal + else + l2 = line1 + c2 = (cline2 == line2 and ccol2 > col2) and c2 - col_removal or col1 + end + end + + if l1 == line1 and c1 == col1 then merge = true end + self:set_selections(idx, l1, c1, l2, c2) + end + + if merge then + self:merge_cursors() end -- update highlighter and assure selection is in bounds - self.highlighter:remove_notify(line1, line2 - line1) + self.highlighter:remove_notify(line1, line_removal) self:sanitize_selection() end From 449f7d66c339a8035d450a0c30e8039d79fcf1a9 Mon Sep 17 00:00:00 2001 From: vqn <85911372+vqns@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:54:52 +0000 Subject: [PATCH 052/176] add autocompletion to multicursor (#1394) * use Doc:remove --- data/plugins/autocomplete.lua | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/data/plugins/autocomplete.lua b/data/plugins/autocomplete.lua index 5921e838..cf228b6e 100644 --- a/data/plugins/autocomplete.lua +++ b/data/plugins/autocomplete.lua @@ -631,7 +631,6 @@ end command.add(predicate, { ["autocomplete:complete"] = function(dv) local doc = dv.doc - local line, col = doc:get_selection() local item = suggestions[suggestions_idx] local text = item.text local inserted = false @@ -640,9 +639,23 @@ command.add(predicate, { end if not inserted then local current_partial = get_partial_symbol() - doc:insert(line, col, text) - doc:remove(line, col, line, col - #current_partial) - doc:set_selection(line, col + #text - #current_partial) + local sz = #current_partial + + for idx, line1, col1, line2, col2 in doc:get_selections(true) do + local n = col1 - 1 + local line = doc.lines[line1] + for i = 1, sz + 1 do + local j = sz - i + local subline = line:sub(n - j, n) + local subpartial = current_partial:sub(i, -1) + if subpartial == subline then + doc:remove(line1, col1, line2, n - j) + break + end + end + end + + doc:text_input(item.text) end reset_suggestions() end, From 7ca0ec18caf2f025ebf5f3d8f29fcbf13353edcd Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 7 Apr 2023 12:58:56 -0400 Subject: [PATCH 053/176] Added in support for foreground and background events. (#1395) --- data/core/init.lua | 5 +++++ src/api/system.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/data/core/init.lua b/data/core/init.lua index 8c9dafcc..016385fd 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1338,6 +1338,11 @@ function core.step() did_keymap = false elseif type == "mousemoved" then core.try(core.on_event, type, a, b, c, d) + elseif type == "enteringforeground" then + -- to break our frame refresh in two if we get entering/entered at the same time. + -- required to avoid flashing and refresh issues on mobile + core.redraw = true + break else local _, res = core.try(core.on_event, type, a, b, c, d) did_keymap = res or did_keymap diff --git a/src/api/system.c b/src/api/system.c index 9da499a6..ba4f39f9 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -358,6 +358,21 @@ top: lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h)); lua_pushinteger(L, e.tfinger.fingerId); return 6; + case SDL_APP_WILLENTERFOREGROUND: + case SDL_APP_DIDENTERFOREGROUND: + #ifdef LITE_USE_SDL_RENDERER + rencache_invalidate(); + #else + SDL_UpdateWindowSurface(window_renderer.window); + #endif + lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground"); + return 1; + case SDL_APP_WILLENTERBACKGROUND: + lua_pushstring(L, "enteringbackground"); + return 1; + case SDL_APP_DIDENTERBACKGROUND: + lua_pushstring(L, "enteredbackground"); + return 1; default: goto top; From e9354549928aaea02418924f36a222bd2150f5d5 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:06:01 +0800 Subject: [PATCH 054/176] Fix invalid EXEFILE and EXEDIR on Windows (#1396) * fix(main): fix get_exe_filename returning invalid result on Windows * fix(main): fix bootstrap not intepreting UTF-8 properly --- src/main.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index e433fe18..3294ff3a 100644 --- a/src/main.c +++ b/src/main.c @@ -32,8 +32,18 @@ static double get_scale(void) { static void get_exe_filename(char *buf, int sz) { #if _WIN32 - int len = GetModuleFileName(NULL, buf, sz - 1); - buf[len] = '\0'; + int len; + wchar_t *buf_w = malloc(sizeof(wchar_t) * sz); + if (buf_w) { + len = GetModuleFileNameW(NULL, buf_w, sz - 1); + buf_w[len] = L'\0'; + // if the conversion failed we'll empty the string + if (!WideCharToMultiByte(CP_UTF8, 0, buf_w, -1, buf, sz, NULL, NULL)) + buf[0] = '\0'; + free(buf_w); + } else { + buf[0] = '\0'; + } #elif __linux__ char path[] = "/proc/self/exe"; ssize_t len = readlink(path, buf, sz - 1); @@ -218,9 +228,10 @@ init_lua: const char *init_lite_code = \ "local core\n" "xpcall(function()\n" + " local match = require('utf8extra').match\n" " HOME = os.getenv('" LITE_OS_HOME "')\n" - " local exedir = EXEFILE:match('^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$')\n" - " local prefix = os.getenv('LITE_PREFIX') or exedir:match('^(.*)" LITE_PATHSEP_PATTERN "bin$')\n" + " local exedir = match(EXEFILE, '^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$')\n" + " local prefix = os.getenv('LITE_PREFIX') or match(exedir, '^(.*)" LITE_PATHSEP_PATTERN "bin$')\n" " dofile((MACOS_RESOURCES or (prefix and prefix .. '/share/lite-xl' or exedir .. '/data')) .. '/core/start.lua')\n" " core = require(os.getenv('LITE_XL_RUNTIME') or 'core')\n" " core.init()\n" From bc2c433b00770d93be9a9221d32329927e6b0bab Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:11:01 +0800 Subject: [PATCH 055/176] fix(windows-utf8-patch): fix os.getenv() not supporting UTF-8 output (#1397) --- resources/windows/001-lua-unicode.diff | 64 +++++++++++++++++++------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/resources/windows/001-lua-unicode.diff b/resources/windows/001-lua-unicode.diff index 7785b8ea..31fec364 100644 --- a/resources/windows/001-lua-unicode.diff +++ b/resources/windows/001-lua-unicode.diff @@ -1,6 +1,6 @@ -diff -ruN lua-5.4.4/meson.build lua-5.4.4-mod/meson.build ---- lua-5.4.4/meson.build 2022-11-16 10:33:38.424383300 +0800 -+++ lua-5.4.4-mod/meson.build 2022-11-16 09:40:57.697918000 +0800 +diff -ruN lua-5.4.4\meson.build lua-5.4.4-patched\meson.build +--- lua-5.4.4\meson.build Wed Feb 22 18:16:56 2023 ++++ lua-5.4.4-patched\meson.build Wed Feb 22 04:10:01 2023 @@ -85,6 +85,7 @@ 'src/lutf8lib.c', 'src/lvm.c', @@ -9,9 +9,9 @@ diff -ruN lua-5.4.4/meson.build lua-5.4.4-mod/meson.build dependencies: lua_lib_deps, version: meson.project_version(), soversion: lua_versions[0] + '.' + lua_versions[1], -diff -ruN lua-5.4.4/src/luaconf.h lua-5.4.4-mod/src/luaconf.h ---- lua-5.4.4/src/luaconf.h 2022-01-13 19:24:43.000000000 +0800 -+++ lua-5.4.4-mod/src/luaconf.h 2022-11-16 09:40:57.703926000 +0800 +diff -ruN lua-5.4.4\src\luaconf.h lua-5.4.4-patched\src\luaconf.h +--- lua-5.4.4\src\luaconf.h Thu Jan 13 19:24:43 2022 ++++ lua-5.4.4-patched\src\luaconf.h Wed Feb 22 04:10:02 2023 @@ -782,5 +782,15 @@ @@ -28,9 +28,9 @@ diff -ruN lua-5.4.4/src/luaconf.h lua-5.4.4-mod/src/luaconf.h + #endif -diff -ruN lua-5.4.4/src/Makefile lua-5.4.4-mod/src/Makefile ---- lua-5.4.4/src/Makefile 2021-07-15 22:01:52.000000000 +0800 -+++ lua-5.4.4-mod/src/Makefile 2022-11-16 09:40:57.708921800 +0800 +diff -ruN lua-5.4.4\src\Makefile lua-5.4.4-patched\src\Makefile +--- lua-5.4.4\src\Makefile Thu Jul 15 22:01:52 2021 ++++ lua-5.4.4-patched\src\Makefile Wed Feb 22 04:10:02 2023 @@ -33,7 +33,7 @@ PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris @@ -40,10 +40,10 @@ diff -ruN lua-5.4.4/src/Makefile lua-5.4.4-mod/src/Makefile LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) -diff -ruN lua-5.4.4/src/utf8_wrappers.c lua-5.4.4-mod/src/utf8_wrappers.c ---- lua-5.4.4/src/utf8_wrappers.c 1970-01-01 07:30:00.000000000 +0730 -+++ lua-5.4.4-mod/src/utf8_wrappers.c 2022-11-16 10:09:04.583866600 +0800 -@@ -0,0 +1,101 @@ +diff -ruN lua-5.4.4\src\utf8_wrappers.c lua-5.4.4-patched\src\utf8_wrappers.c +--- lua-5.4.4\src\utf8_wrappers.c Thu Jan 01 08:00:00 1970 ++++ lua-5.4.4-patched\src\utf8_wrappers.c Wed Feb 22 18:13:45 2023 +@@ -0,0 +1,129 @@ +/** + * Wrappers to provide Unicode (UTF-8) support on Windows. + * @@ -58,12 +58,17 @@ diff -ruN lua-5.4.4/src/utf8_wrappers.c lua-5.4.4-mod/src/utf8_wrappers.c +#include +#include + ++// A environment variable has the maximum length of 32767 characters ++// including the terminator. ++#define MAX_ENV_SIZE 32767 +// Set a high limit in case long paths are enabled. +#define MAX_PATH_SIZE 4096 +#define MAX_MODE_SIZE 128 +// cmd.exe argument length is reportedly limited to 8192. +#define MAX_CMD_SIZE 8192 + ++static char env_value[MAX_ENV_SIZE]; ++ +FILE *fopen_utf8(const char *pathname, const char *mode) { + wchar_t pathname_w[MAX_PATH_SIZE]; + wchar_t mode_w[MAX_MODE_SIZE]; @@ -144,11 +149,34 @@ diff -ruN lua-5.4.4/src/utf8_wrappers.c lua-5.4.4-mod/src/utf8_wrappers.c + } + return LoadLibraryExW(pathname_w, hFile, dwFlags); +} ++ ++char* getenv_utf8(const char *varname) { ++ /** This implementation is not thread safe. ++ * The string is only valid until the next call to getenv. ++ * This behavior is allowed per POSIX.1-2017 where it was said that: ++ * > The returned string pointer might be invalidated or the string content might be overwritten by a subsequent call to getenv(), setenv(), unsetenv(), or (if supported) putenv() but they shall not be affected by a call to any other function in this volume of POSIX.1-2017. ++ * > The returned string pointer might also be invalidated if the calling thread is terminated. ++ * > The getenv() function need not be thread-safe. ++ */ ++ wchar_t *value_w; ++ wchar_t varname_w[MAX_ENV_SIZE]; ++ ++ if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, varname, -1, varname_w, MAX_ENV_SIZE)) ++ return NULL; ++ value_w = _wgetenv((const wchar_t *) varname_w); ++ if (!value_w) ++ return NULL; ++ ++ if (!WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, value_w, -1, env_value, MAX_ENV_SIZE, NULL, NULL)) ++ return NULL; ++ ++ return env_value; ++} +#endif -diff -ruN lua-5.4.4/src/utf8_wrappers.h lua-5.4.4-mod/src/utf8_wrappers.h ---- lua-5.4.4/src/utf8_wrappers.h 1970-01-01 07:30:00.000000000 +0730 -+++ lua-5.4.4-mod/src/utf8_wrappers.h 2022-11-16 10:29:46.044102000 +0800 -@@ -0,0 +1,44 @@ +diff -ruN lua-5.4.4\src\utf8_wrappers.h lua-5.4.4-patched\src\utf8_wrappers.h +--- lua-5.4.4\src\utf8_wrappers.h Thu Jan 01 08:00:00 1970 ++++ lua-5.4.4-patched\src\utf8_wrappers.h Wed Feb 22 18:09:48 2023 +@@ -0,0 +1,46 @@ +/** + * Wrappers to provide Unicode (UTF-8) support on Windows. + * @@ -180,9 +208,11 @@ diff -ruN lua-5.4.4/src/utf8_wrappers.h lua-5.4.4-mod/src/utf8_wrappers.h +int remove_utf8(const char *pathname); +int rename_utf8(const char *oldpath, const char *newpath); +int system_utf8(const char *command); ++char *getenv_utf8(const char *varname); +#define remove remove_utf8 +#define rename rename_utf8 +#define system system_utf8 ++#define getenv getenv_utf8 +#endif + +#ifdef loadlib_c From 662fde364bc45d8cf5f089c85abd4cd283f1bb71 Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 7 Apr 2023 19:15:50 +0200 Subject: [PATCH 056/176] Add View dragging (#1402) --- data/core/init.lua | 6 ++++++ data/core/node.lua | 7 +++++++ data/core/rootview.lua | 43 ++++++++++++++++++++++++++++++++++++++++++ data/core/view.lua | 17 +++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/data/core/init.lua b/data/core/init.lua index 016385fd..050a8ee2 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1289,6 +1289,12 @@ function core.on_event(type, ...) if not core.root_view:on_mouse_wheel(...) then did_keymap = keymap.on_mouse_wheel(...) end + elseif type == "touchpressed" then + core.root_view:on_touch_pressed(...) + elseif type == "touchreleased" then + core.root_view:on_touch_released(...) + elseif type == "touchmoved" then + core.root_view:on_touch_moved(...) elseif type == "resized" then core.window_mode = system.get_window_mode() elseif type == "minimized" or type == "maximized" or type == "restored" then diff --git a/data/core/node.lua b/data/core/node.lua index 2ce52cc2..aff4bb11 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -60,6 +60,13 @@ function Node:on_mouse_left() end end +function Node:on_touch_moved(...) + if self.type == "leaf" then + self.active_view:on_touch_moved(...) + else + self:propagate("on_touch_moved", ...) + end +end function Node:consume(node) for k, _ in pairs(self) do self[k] = nil end diff --git a/data/core/rootview.lua b/data/core/rootview.lua index 7230e8e1..f9bde17e 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -334,6 +334,49 @@ function RootView:on_text_input(...) core.active_view:on_text_input(...) end +function RootView:on_touch_pressed(x, y, ...) + self.touched_node = self.root_node:get_child_overlapping_point(x, y) +end + +function RootView:on_touch_released(x, y, ...) + self.touched_node = nil +end + +function RootView:on_touch_moved(x, y, dx, dy, ...) + if not self.touched_node then return end + if core.active_view == core.nag_view then + core.active_view:on_touch_moved(x, y, dx, dy, ...) + return + end + + if self.dragged_divider then + local node = self.dragged_divider + if node.type == "hsplit" then + x = common.clamp(x, 0, self.root_node.size.x * 0.95) + resize_child_node(node, "x", x, dx) + elseif node.type == "vsplit" then + y = common.clamp(y, 0, self.root_node.size.y * 0.95) + resize_child_node(node, "y", y, dy) + end + node.divider = common.clamp(node.divider, 0.01, 0.99) + return + end + + local dn = self.dragged_node + if dn and not dn.dragging then + -- start dragging only after enough movement + dn.dragging = common.distance(x, y, dn.drag_start_x, dn.drag_start_y) > style.tab_width * .05 + if dn.dragging then + core.request_cursor("hand") + end + end + + -- avoid sending on_touch_moved events when dragging tabs + if dn then return end + + self.touched_node:on_touch_moved(x, y, dx, dy, ...) +end + function RootView:on_ime_text_editing(...) core.active_view:on_ime_text_editing(...) end diff --git a/data/core/view.lua b/data/core/view.lua index 36580677..02560ff8 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -248,6 +248,23 @@ function View:get_content_bounds() return x, y, x + self.size.x, y + self.size.y end +---@param x number +---@param y number +---@param dx number +---@param dy number +---@param i number +function View:on_touch_moved(x, y, dx, dy, i) + if not self.scrollable then return end + if self.dragging_scrollbar then + local delta = self:get_scrollable_size() / self.size.y * dy + self.scroll.to.y = self.scroll.to.y + delta + end + self.hovered_scrollbar = self:scrollbar_overlaps_point(x, y) + + self.scroll.to.y = self.scroll.to.y + -dy + self.scroll.to.x = self.scroll.to.x + -dx +end + ---@return number x ---@return number y From 26ff5e28a63878388ae2a582befd837b969ccc22 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:18:16 +0800 Subject: [PATCH 057/176] fix: fix differing stacktrace on stdout and file (#1404) * fix(c-bootstrap): produce identical stack traces --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 3294ff3a..f6e980a5 100644 --- a/src/main.c +++ b/src/main.c @@ -239,7 +239,7 @@ init_lua: "end, function(err)\n" " local error_dir\n" " io.stdout:write('Error: '..tostring(err)..'\\n')\n" - " io.stdout:write(debug.traceback(nil, 4)..'\\n')\n" + " io.stdout:write(debug.traceback(nil, 2)..'\\n')\n" " if core and core.on_error then\n" " error_dir=USERDIR\n" " pcall(core.on_error, err)\n" From ac9ca96698d8e15e64b4d1bedfa88dbe566d783f Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:24:27 +0800 Subject: [PATCH 058/176] fix(CI): bump dependency versions (#1434) * refactor(ci): use microsoft/setup-msbuild * fix(ci): fix wrong option name for setup-msbuild * fix(ci): bump setup-python version * fix(lua-utf8-patch): enable support for windows vista and above * fix(ci): use vs backend * fix(ci): reconfigure project manually after patch * fix(ci): add a separate build step * fix(ci): use msvc-dev-cmd again --- .github/workflows/build.yml | 33 ++++++++++++++++++--------------- .github/workflows/release.yml | 12 ++++++------ 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8fb880ff..a3cbb2a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,9 +30,9 @@ jobs: echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_REF=${GITHUB_REF##*/}" >> "$GITHUB_ENV" echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-linux-$(uname -m)-portable" >> "$GITHUB_ENV" - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Python Setup - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.9 - name: Update Packages @@ -47,7 +47,7 @@ jobs: if: ${{ matrix.config.cc == 'gcc' }} run: bash scripts/package.sh --version ${INSTALL_REF} --debug --binary - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ matrix.config.cc == 'gcc' }} with: name: Linux Artifacts @@ -71,9 +71,9 @@ jobs: echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_REF=${GITHUB_REF##*/}" >> "$GITHUB_ENV" echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-$(uname -m)" >> "$GITHUB_ENV" - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Python Setup - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.9 - name: Install Dependencies @@ -85,7 +85,7 @@ jobs: - name: Create DMG Image run: bash scripts/package.sh --version ${INSTALL_REF} --debug --dmg - name: Upload DMG Image - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: macOS DMG Image path: ${{ env.INSTALL_NAME }}.dmg @@ -100,7 +100,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} @@ -127,7 +127,7 @@ jobs: - name: Package run: bash scripts/package.sh --version ${INSTALL_REF} --debug --binary - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: Windows Artifacts path: ${{ env.INSTALL_NAME }}.zip @@ -137,20 +137,22 @@ jobs: runs-on: windows-2019 strategy: matrix: - arch: [amd64, amd64_x86] + arch: + - { target: x86, name: i686 } + - { target: x64, name: x86_64 } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ilammy/msvc-dev-cmd@v1 with: - arch: ${{ matrix.arch }} - - uses: actions/setup-python@v1 + arch: ${{ matrix.arch.target }} + - uses: actions/setup-python@v2 with: python-version: '3.x' - name: Install meson and ninja run: pip install meson ninja - name: Set up environment variables run: | - "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch }}" >> $env:GITHUB_ENV + "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV "INSTALL_REF=$($env:GITHUB_REF -replace ".*/")" >> $env:GITHUB_ENV "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV - name: Configure @@ -158,13 +160,14 @@ jobs: meson setup --wrap-mode=forcefallback build Get-Content -Path resources/windows/001-lua-unicode.diff -Raw | patch -d $env:LUA_SUBPROJECT_PATH -p1 --forward - name: Build - run: meson install -C build --destdir="../lite-xl" + run: | + meson install -C build --destdir="../lite-xl" - name: Package run: | Remove-Item -Recurse -Force -Path "lite-xl/lib","lite-xl/include" Compress-Archive -Path lite-xl -DestinationPath "$env:INSTALL_NAME.zip" - name: Upload Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: Windows Artifacts (MSVC) path: ${{ env.INSTALL_NAME }}.zip diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea0e1848..47b826dd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: version: ${{ steps.tag.outputs.version }} steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Fetch Version id: tag run: | @@ -58,9 +58,9 @@ jobs: run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_REF=${{ needs.release.outputs.version }}" >> "$GITHUB_ENV" - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Python Setup - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.9 - name: Update Packages @@ -115,9 +115,9 @@ jobs: echo "INSTALL_REF=${{ needs.release.outputs.version }}" >> "$GITHUB_ENV" echo "INSTALL_NAME=lite-xl-${{ needs.release.outputs.version }}-macos-${{ matrix.arch }}" >> "$GITHUB_ENV" echo "INSTALL_NAME_ADDONS=lite-xl-${{ needs.release.outputs.version }}-addons-macos-${{ matrix.arch }}" >> "$GITHUB_ENV" - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Python Setup - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.9 - name: Install Dependencies @@ -150,7 +150,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.msystem }} From c133c39e92abce672781c71ac6a204542819d37a Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:25:31 +0800 Subject: [PATCH 059/176] Optimizing MSYS2 CI (#1435) * feat(ci): install dependencies on setup * fix(ci): don't update msys2 when setup * fix(ci): download subprojects before patching * doc(ci): document why meson subprojects download is called --- .github/workflows/build.yml | 18 ++++++++++++++---- scripts/build.sh | 15 ++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a3cbb2a4..12247bfb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -95,7 +95,9 @@ jobs: runs-on: windows-2019 strategy: matrix: - msystem: [MINGW32, MINGW64] + config: + - {msystem: MINGW32, arch: i686} + - {msystem: MINGW64, arch: x86_64} defaults: run: shell: msys2 {0} @@ -103,12 +105,16 @@ jobs: - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: - msystem: ${{ matrix.msystem }} - update: true + msystem: ${{ matrix.config.msystem }} install: >- base-devel git zip + mingw-w64-${{ matrix.config.arch }}-gcc + mingw-w64-${{ matrix.config.arch }}-meson + mingw-w64-${{ matrix.config.arch }}-ninja + mingw-w64-${{ matrix.config.arch }}-ca-certificates + mingw-w64-${{ matrix.config.arch }}-ntldd - name: Set Environment Variables run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" @@ -119,6 +125,7 @@ jobs: echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-windows-i686" >> "$GITHUB_ENV" fi - name: Install Dependencies + if: false run: bash scripts/install-dependencies.sh --debug - name: Build run: | @@ -157,8 +164,11 @@ jobs: "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV - name: Configure run: | - meson setup --wrap-mode=forcefallback build + # Download the subprojects first so we can patch it before configuring. + # This avoids reconfiguring the subprojects when compiling. + meson subprojects download Get-Content -Path resources/windows/001-lua-unicode.diff -Raw | patch -d $env:LUA_SUBPROJECT_PATH -p1 --forward + meson setup --wrap-mode=forcefallback build - name: Build run: | meson install -C build --destdir="../lite-xl" diff --git a/scripts/build.sh b/scripts/build.sh index 82eb95f0..0cd4e8d8 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -124,6 +124,16 @@ main() { rm -rf "${build_dir}" + if [[ $patch_lua == "true" ]] && [[ ! -z $force_fallback ]]; then + # download the subprojects so we can start patching before configure. + # this will prevent reconfiguring the project. + meson subprojects download + lua_subproject_path=$(echo subprojects/lua-*/) + if [[ -d $lua_subproject_path ]]; then + patch -d $lua_subproject_path -p1 --forward < resources/windows/001-lua-unicode.diff + fi + fi + CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS meson setup \ --buildtype=$build_type \ --prefix "$prefix" \ @@ -134,11 +144,6 @@ main() { $pgo \ "${build_dir}" - lua_subproject_path=$(echo subprojects/lua-*/) - if [[ $patch_lua == "true" ]] && [[ ! -z $force_fallback ]] && [[ -d $lua_subproject_path ]]; then - patch -d $lua_subproject_path -p1 --forward < resources/windows/001-lua-unicode.diff - fi - meson compile -C "${build_dir}" if [[ $pgo != "" ]]; then From 4e626bc3204802a8b537fbd8c82c2c6348ce43b5 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 8 Apr 2023 01:45:28 +0800 Subject: [PATCH 060/176] Update api_require to expose more symbols (#1437) * feat(system): update api_require for more symbols * fix(system): fix missing 5.1 symbols * fix(system): add more missing symbols * fix(system): add all symbols We got'em this time. I swear. * fix(system): fix undefined symbols due to conditional compilation There is only pain and suffering. Turns out some of the symbols are only exported when the options are enabled. We need to preprocess the header. --- src/api/system.c | 93 ++++++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index ba4f39f9..dddbf6bf 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -928,47 +928,70 @@ typedef struct lua_function_node { #define P(FUNC) { "lua_" #FUNC, (fptr)(lua_##FUNC) } #define U(FUNC) { "luaL_" #FUNC, (fptr)(luaL_##FUNC) } +#define S(FUNC) { #FUNC, (fptr)(FUNC) } static void* api_require(const char* symbol) { static const lua_function_node nodes[] = { - P(atpanic), P(checkstack), - P(close), P(concat), P(copy), P(createtable), P(dump), - P(error), P(gc), P(getallocf), P(getfield), - P(gethook), P(gethookcount), P(gethookmask), P(getinfo), P(getlocal), - P(getmetatable), P(getstack), P(gettable), P(gettop), P(getupvalue), - P(isnumber), P(isstring), P(isuserdata), - P(load), P(newstate), P(newthread), P(next), + #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + U(addlstring), U(addstring), U(addvalue), U(argerror), U(buffinit), + U(callmeta), U(checkany), U(checkinteger), U(checklstring), + U(checknumber), U(checkoption), U(checkstack), U(checktype), + U(checkudata), U(error), U(getmetafield), U(gsub), U(loadstring), + U(newmetatable), U(newstate), U(openlibs), U(optinteger), U(optlstring), + U(optnumber), U(pushresult), U(ref), U(unref), U(where), P(atpanic), + P(checkstack), P(close), P(concat), P(createtable), P(dump), P(error), + P(gc), P(getallocf), P(getfield), P(gethook), P(gethookcount), + P(gethookmask), P(getinfo), P(getlocal), P(getmetatable), P(getstack), + P(gettable), P(gettop), P(getupvalue), P(iscfunction), P(isnumber), + P(isstring), P(isuserdata), P(load), P(newstate), P(newthread), P(next), P(pushboolean), P(pushcclosure), P(pushfstring), P(pushinteger), P(pushlightuserdata), P(pushlstring), P(pushnil), P(pushnumber), - P(pushstring), P(pushthread), P(pushvalue), - P(pushvfstring), P(rawequal), P(rawget), P(rawgeti), - P(rawset), P(rawseti), P(resume), - P(setallocf), P(setfield), P(sethook), P(setlocal), - P(setmetatable), P(settable), P(settop), P(setupvalue), - P(status), P(tocfunction), P(tointegerx), P(tolstring), P(toboolean), - P(tonumberx), P(topointer), P(tothread), P(touserdata), - P(type), P(typename), P(upvalueid), P(upvaluejoin), P(version), P(xmove), - U(getmetafield), U(callmeta), U(argerror), U(checknumber), U(optnumber), - U(checkinteger), U(checkstack), U(checktype), U(checkany), - U(newmetatable), U(setmetatable), U(testudata), U(checkudata), U(where), - U(error), U(fileresult), U(execresult), U(ref), U(unref), U(loadstring), - U(newstate), U(setfuncs), U(buffinit), U(addlstring), U(addstring), - U(addvalue), U(pushresult), U(openlibs), {"api_load_libs", (void*)(api_load_libs)}, - #if LUA_VERSION_NUM >= 502 - P(absindex), P(arith), P(callk), P(compare), P(getglobal), - P(len), P(pcallk), P(rawgetp), P(rawlen), P(rawsetp), P(setglobal), - P(iscfunction), P(yieldk), - U(checkversion_), U(tolstring), U(len), U(getsubtable), U(prepbuffsize), - U(pushresultsize), U(buffinitsize), U(checklstring), U(checkoption), U(gsub), U(loadbufferx), - U(loadfilex), U(optinteger), U(optlstring), U(requiref), U(traceback), - #else - P(objlen), + P(pushstring), P(pushthread), P(pushvalue), P(pushvfstring), P(rawequal), + P(rawget), P(rawgeti), P(rawset), P(rawseti), P(resume), P(setallocf), + P(setfield), P(sethook), P(setlocal), P(setmetatable), P(settable), + P(settop), P(setupvalue), P(status), P(toboolean), P(tocfunction), + P(tolstring), P(topointer), P(tothread), P(touserdata), P(type), + P(typename), P(xmove), S(luaopen_base), S(luaopen_debug), S(luaopen_io), + S(luaopen_math), S(luaopen_os), S(luaopen_package), S(luaopen_string), + S(luaopen_table), S(api_load_libs), #endif - #if LUA_VERSION_NUM >= 504 - P(newuserdatauv), P(setiuservalue), P(getiuservalue) - #else - P(newuserdata), P(setuservalue), P(getuservalue) + #if LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + U(buffinitsize), U(checkversion_), U(execresult), U(fileresult), + U(getsubtable), U(len), U(loadbufferx), U(loadfilex), U(prepbuffsize), + U(pushresultsize), U(requiref), U(setfuncs), U(setmetatable), + U(testudata), U(tolstring), U(traceback), P(absindex), P(arith), + P(callk), P(compare), P(copy), P(getglobal), P(len), P(pcallk), + P(rawgetp), P(rawlen), P(rawsetp), P(setglobal), P(tointegerx), + P(tonumberx), P(upvalueid), P(upvaluejoin), P(version), P(yieldk), + S(luaopen_coroutine), + #endif + #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 + P(newuserdata), + #endif + #if LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + P(geti), P(isinteger), P(isyieldable), P(rotate), P(seti), + P(stringtonumber), S(luaopen_utf8), + #endif + #if LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 + P(getuservalue), P(setuservalue), S(luaopen_bit32), + #endif + #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 + P(insert), P(remove), P(replace), + #endif + #if LUA_VERSION_NUM == 504 + U(addgsub), U(typeerror), P(closeslot), P(getiuservalue), + P(newuserdatauv), P(resetthread), P(setcstacklimit), P(setiuservalue), + P(setwarnf), P(toclose), P(warning), + #endif + #if LUA_VERSION_NUM == 502 + U(checkunsigned), U(optunsigned), P(getctx), P(pushunsigned), + P(tounsignedx), + #endif + #if LUA_VERSION_NUM == 501 + U(findtable), U(loadbuffer), U(loadfile), U(openlib), U(prepbuffer), + U(register), U(typerror), P(call), P(cpcall), P(equal), P(getfenv), + P(lessthan), P(objlen), P(pcall), P(setfenv), P(setlevel), P(tointeger), + P(tonumber), P(yield), #endif - }; for (size_t i = 0; i < sizeof(nodes) / sizeof(lua_function_node); ++i) { if (strcmp(nodes[i].symbol, symbol) == 0) From 0ee346014e5775ff14fd93265345ccb5b30d920f Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 7 Apr 2023 20:41:32 +0200 Subject: [PATCH 061/176] Make `system.path_compare` more case-aware (#1457) * Use Lua-provided string lengths for `system.path_compare` * Make `system.path_compare` more case-aware Before, strings like `README.md` would be sorted before `changelog.md`, because we only looked at the raw ascii values. Now the character case is considered as a secondary sorting key. --- src/api/system.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index dddbf6bf..56f03a15 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -1059,11 +1059,11 @@ static int f_load_native_plugin(lua_State *L) { order used in the TreeView view of the project's files. Returns true iff path1 < path2 in the TreeView order. */ static int f_path_compare(lua_State *L) { - const char *path1 = luaL_checkstring(L, 1); + size_t len1, len2; + const char *path1 = luaL_checklstring(L, 1, &len1); const char *type1_s = luaL_checkstring(L, 2); - const char *path2 = luaL_checkstring(L, 3); + const char *path2 = luaL_checklstring(L, 3, &len2); const char *type2_s = luaL_checkstring(L, 4); - const int len1 = strlen(path1), len2 = strlen(path2); int type1 = strcmp(type1_s, "dir") != 0; int type2 = strcmp(type2_s, "dir") != 0; /* Find the index of the common part of the path. */ @@ -1088,17 +1088,34 @@ static int f_path_compare(lua_State *L) { return 1; } /* If types are the same compare the files' path alphabetically. */ - int cfr = 0; + int cfr = -1; int len_min = (len1 < len2 ? len1 : len2); + bool same_len = len1 == len2; for (int j = offset; j <= len_min; j++) { - if (path1[j] == path2[j]) continue; if (path1[j] == 0 || path2[j] == 0) { - cfr = (path1[j] == 0); + if (cfr < 0) cfr = 0; // The strings are equal + if (!same_len) { + cfr = (path1[j] == 0); + } + } else if (path1[j] == path2[j]) { + continue; } else if (path1[j] == PATHSEP || path2[j] == PATHSEP) { /* For comparison we treat PATHSEP as if it was the string terminator. */ cfr = (path1[j] == PATHSEP); } else { - cfr = (path1[j] < path2[j]); + char a = path1[j], b = path2[j]; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a == b) { + /* If the strings have the same length, we need + to keep the first case sensitive difference. */ + if (same_len && cfr < 0) { + /* Give priority to lower-case characters */ + cfr = (path1[j] > path2[j]); + } + continue; + } + cfr = (a < b); } break; } From 7aa121787895eb39a7bec890341383cfa80d8b66 Mon Sep 17 00:00:00 2001 From: vqn <85911372+vqns@users.noreply.github.com> Date: Mon, 10 Apr 2023 21:57:11 +0200 Subject: [PATCH 062/176] #1393 followup (#1463) * Fix incorrect check in doc:raw_remove Restore caret position on command doc:cut * merge cursors and fix new line in clipboard * add new line to the last copied line --- data/core/commands/doc.lua | 8 +++++--- data/core/doc/init.lua | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index eca876ea..d9803bce 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -62,10 +62,10 @@ local function cut_or_copy(delete) local text = "" core.cursor_clipboard = {} core.cursor_clipboard_whole_line = {} - for idx, line1, col1, line2, col2 in doc():get_selections() do + for idx, line1, col1, line2, col2 in doc():get_selections(true, true) do if line1 ~= line2 or col1 ~= col2 then text = doc():get_text(line1, col1, line2, col2) - full_text = full_text == "" and text or (full_text .. " " .. text) + full_text = full_text == "" and text or (text .. " " .. full_text) core.cursor_clipboard_whole_line[idx] = false if delete then doc():delete_to_cursor(idx, 0) @@ -73,7 +73,7 @@ local function cut_or_copy(delete) else -- Cut/copy whole line -- Remove newline from the text. It will be added as needed on paste. text = string.sub(doc().lines[line1], 1, -2) - full_text = full_text == "" and text or (full_text .. text .. "\n") + full_text = full_text == "" and text .. "\n" or (text .. "\n" .. full_text) core.cursor_clipboard_whole_line[idx] = true if delete then if line1 < #doc().lines then @@ -83,10 +83,12 @@ local function cut_or_copy(delete) else doc():remove(line1 - 1, math.huge, line1, math.huge) end + doc():set_selections(idx, line1, col1, line2, col2) end end core.cursor_clipboard[idx] = text end + if delete then doc():merge_cursors() end core.cursor_clipboard["full"] = full_text system.set_clipboard(full_text) end diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 7fdd896c..74116fd5 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -453,7 +453,7 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) end end - if cline2 > line1 or (cline2 == line2 and ccol2 > col1) then + if cline2 > line1 or (cline2 == line1 and ccol2 > col1) then if cline2 > line2 then l2 = l2 - line_removal else From 2978037f513be61e459dfbbdec4ef4f928c686a4 Mon Sep 17 00:00:00 2001 From: sammyette Date: Mon, 10 Apr 2023 18:16:41 -0400 Subject: [PATCH 063/176] feat: add statusview item to show selections (#1445) --- data/core/statusview.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 9c4e33fa..35fff21b 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -241,6 +241,21 @@ function StatusView:register_docview_items() tooltip = "line : column" }) + self:add_item({ + predicate = predicate_docview, + name = "doc:selections", + alignment = StatusView.Item.LEFT, + get_item = function() + local dv = core.active_view + local nsel = #dv.doc.selections // 4 + if nsel > 1 then + return { style.text, nsel, " selections" } + end + + return {} + end + }) + self:add_item({ predicate = predicate_docview, name = "doc:indentation", From baa8f528f1ce023dda0a0dcc1f1e769db3879f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Mon, 10 Apr 2023 21:29:31 -0400 Subject: [PATCH 064/176] Fix for api_require wrong macro && conditions (#1465) This mistake escaped my eyes when reviewing #1437 and causes some symbols to not be exported, because the preprocessor macros are expecting multiple LUA versions to evaluate as true at once. The fix is to replace `&&` with `||`. --- src/api/system.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index 56f03a15..66a46092 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -931,7 +931,7 @@ typedef struct lua_function_node { #define S(FUNC) { #FUNC, (fptr)(FUNC) } static void* api_require(const char* symbol) { static const lua_function_node nodes[] = { - #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + #if LUA_VERSION_NUM == 501 || LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 || LUA_VERSION_NUM == 504 U(addlstring), U(addstring), U(addvalue), U(argerror), U(buffinit), U(callmeta), U(checkany), U(checkinteger), U(checklstring), U(checknumber), U(checkoption), U(checkstack), U(checktype), @@ -954,7 +954,7 @@ static void* api_require(const char* symbol) { S(luaopen_math), S(luaopen_os), S(luaopen_package), S(luaopen_string), S(luaopen_table), S(api_load_libs), #endif - #if LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + #if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 || LUA_VERSION_NUM == 504 U(buffinitsize), U(checkversion_), U(execresult), U(fileresult), U(getsubtable), U(len), U(loadbufferx), U(loadfilex), U(prepbuffsize), U(pushresultsize), U(requiref), U(setfuncs), U(setmetatable), @@ -964,17 +964,17 @@ static void* api_require(const char* symbol) { P(tonumberx), P(upvalueid), P(upvaluejoin), P(version), P(yieldk), S(luaopen_coroutine), #endif - #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 + #if LUA_VERSION_NUM == 501 || LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 P(newuserdata), #endif - #if LUA_VERSION_NUM == 503 && LUA_VERSION_NUM == 504 + #if LUA_VERSION_NUM == 503 || LUA_VERSION_NUM == 504 P(geti), P(isinteger), P(isyieldable), P(rotate), P(seti), P(stringtonumber), S(luaopen_utf8), #endif - #if LUA_VERSION_NUM == 502 && LUA_VERSION_NUM == 503 + #if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 P(getuservalue), P(setuservalue), S(luaopen_bit32), #endif - #if LUA_VERSION_NUM == 501 && LUA_VERSION_NUM == 502 + #if LUA_VERSION_NUM == 501 || LUA_VERSION_NUM == 502 P(insert), P(remove), P(replace), #endif #if LUA_VERSION_NUM == 504 From c2357721e5411eb1e7600158c25a48d40a86b0f4 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Tue, 11 Apr 2023 23:20:28 +0800 Subject: [PATCH 065/176] upgrade header files to Lua 5.4 (#1436) * refactor(native_api_header): upgrade header files to Lua 5.4. Almost all of the symbols in this file was from 5.2. This will obviously not work because some function signatures have changed and some have completely wrong return values, etc. This commit updates the header files to Lua 5.4 based on the source code and changes a few things. * refactor(plugin_api): move the header into include/ * fix(lite_xl_plugin_api.h): include stdlib to avoid errors with exit * refactor(lite_xl_plugin_api.h): do not return in SYMBOL_WRAP_CALL * fix(lite_xl_plugin_api.h): fix wrong way of passing varargs * fix(lite_xl_plugin_api.h): fix differing lua_rawlen definition * fix(lite_xl_plugin_api.h): fix fallback function signature * fix(lite_xl_plugin_api.h): fix conversion from void * to function pointer --- resources/include/lite_xl_plugin_api.h | 2563 ++++++++++++++++++++++++ resources/lite_xl_plugin_api.h | 1124 ----------- 2 files changed, 2563 insertions(+), 1124 deletions(-) create mode 100644 resources/include/lite_xl_plugin_api.h delete mode 100644 resources/lite_xl_plugin_api.h diff --git a/resources/include/lite_xl_plugin_api.h b/resources/include/lite_xl_plugin_api.h new file mode 100644 index 00000000..2947039e --- /dev/null +++ b/resources/include/lite_xl_plugin_api.h @@ -0,0 +1,2563 @@ +/** + * lite_xl_plugin_api.h + * API for writing C extension modules loaded by Lite XL. + * This file is licensed under MIT. + * + * The Lite XL plugin API is quite simple. + * You would write a lua C extension and replace any references to lua.h, lauxlib.h + * and lualib.h with lite_xl_plugin_api.h. + * In your main file (where your entrypoint resides), define LITE_XL_PLUGIN_ENTRYPOINT. + * If you have multiple entrypoints, define LITE_XL_PLUGIN_ENTRYPOINT in one of them. + * + * After that, you need to create a Lite XL entrypoint, which is formatted as + * luaopen_lite_xl_xxxxx instead of luaopen_xxxxx. + * This entrypoint accepts a lua_State and an extra parameter of type void *. + * In this entrypoint, call lite_xl_plugin_init() with the extra parameter. + * If you have multiple entrypoints, you must call lite_xl_plugin_init() in + * each of them. + * This function is not thread safe, so don't try to do anything stupid. + * + * An example: + * + * #define LITE_XL_PLUGIN_ENTRYPOINT + * #include "lite_xl_plugin_api.h" + * int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) { + * lite_xl_plugin_init(XL); + * ... + * return 1; + * } + * + * You can compile the library just like any Lua library without linking to Lua. + * An example command would be: gcc -shared -o xxxxx.so xxxxx.c + * You must not link to ANY lua library to avoid symbol collision. + * + * This file contains stock configuration for a typical installation of Lua 5.4. + * DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK + * COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS. +**/ +#ifndef LITE_XL_PLUGIN_API +#define LITE_XL_PLUGIN_API + +#include +#include + +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif + +/* FOR_EACH macro */ +#define CONCAT(arg1, arg2) CONCAT1(arg1, arg2) +#define CONCAT1(arg1, arg2) CONCAT2(arg1, arg2) +#define CONCAT2(arg1, arg2) arg1##arg2 +#define FE_1(what, x) what x +#define FE_2(what, x, ...) what x,FE_1(what, __VA_ARGS__) +#define FE_3(what, x, ...) what x,FE_2(what, __VA_ARGS__) +#define FE_4(what, x, ...) what x,FE_3(what, __VA_ARGS__) +#define FE_5(what, x, ...) what x,FE_4(what, __VA_ARGS__) +#define FE_6(what, x, ...) what x,FE_5(what, __VA_ARGS__) +#define FE_7(what, x, ...) what x,FE_6(what, __VA_ARGS__) +#define FE_8(what, x, ...) what x,FE_7(what, __VA_ARGS__) +#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N()) +#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__) +#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define FOR_EACH_(N, what, ...) CONCAT(FE_, N)(what, __VA_ARGS__) +#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__) + +#define SYMBOL_WRAP_DECL(ret, name, ...) \ + ret name(__VA_ARGS__) + +#define SYMBOL_WRAP_CALL(name, ...) \ + __##name(__VA_ARGS__) + +#define SYMBOL_WRAP_CALL_FB(name, ...) \ + return __lite_xl_fallback_##name(__VA_ARGS__) + +#ifdef LITE_XL_PLUGIN_ENTRYPOINT + #define SYMBOL_DECLARE(ret, name, ...) \ + static ret (*__##name) (__VA_ARGS__); \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); \ + static ret __lite_xl_fallback_##name(FOR_EACH(UNUSED, __VA_ARGS__)) { \ + fputs("warning: " #name " is a stub", stderr); \ + exit(1); \ + } + #define SYMBOL_DECLARE_VARARG(ret, name, ...) \ + static ret (*__##name) (__VA_ARGS__, ...); \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__, ...); \ + static ret __lite_xl_fallback_##name(FOR_EACH(UNUSED, __VA_ARGS__), ...) { \ + fputs("warning: " #name " is a stub", stderr); \ + exit(1); \ + } +#else + #define SYMBOL_DECLARE(ret, name, ...) \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); + #define SYMBOL_DECLARE_VARARG(ret, name, ...) \ + SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__, ...); +#endif + + + + + +/* +** $Id: luaconf.h $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** General Configuration File for Lua +** +** Some definitions here can be changed externally, through the compiler +** (e.g., with '-D' options): They are commented out or protected +** by '#if !defined' guards. However, several other definitions +** should be changed directly here, either because they affect the +** Lua ABI (by making the changes here, you ensure that all software +** connected to Lua, such as C libraries, will be compiled with the same +** configuration); or because they are seldom changed. +** +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#endif + + +/* +@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. +*/ +#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3) + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Number types. These options should not be +** set externally, because any other code connected to Lua must +** use the same configuration. +** =================================================================== +*/ + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options supported +** by your C compiler. The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + + +/* Default configuration ('long long' and 'double', for 64-bit Lua) */ +#define LUA_INT_DEFAULT LUA_INT_LONGLONG +#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE + + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. +*/ +#define LUA_32BITS 0 + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS 1 +#else +#define LUA_C89_NUMBERS 0 +#endif + + +#if LUA_32BITS /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_IS32INT /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif LUA_C89_NUMBERS /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#else /* }{ */ +/* use defaults */ + +#define LUA_INT_TYPE LUA_INT_DEFAULT +#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT + +#endif /* } */ + + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +*/ +#define LUA_PATH_SEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXEC_DIR "!" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" +#endif + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif + +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if !defined(LUA_DIRSEP) + +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* +** More often than not the libs go together with the core. +*/ +#define LUALIB_API LUA_API +#define LUAMOD_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables, +** none of which to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("internal"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC(dec) LUAI_FUNC dec +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_3) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +** (These functions were already officially removed in 5.3; +** nevertheless they are still available here.) +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +** (These macros were also officially removed in 5.3, but they are still +** available here.) +*/ +#define LUA_COMPAT_APIINTCASTS + + +/* +@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod +** using '__lt'. +*/ +#define LUA_COMPAT_LT_LE + + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +** (Once more, these macros were officially removed in 5.3, but they are +** still available here.) +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +#endif /* } */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers (low-level part). +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_floatatt(x) corrects float attribute 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeral to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) \ + l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) + +/* +@@ lua_numbertointeger converts a float number with an integral value +** to an integer, or returns 0 if float is not within the range of +** a lua_Integer. (The range comparisons are tricky because of +** rounding. The tests here assume a two-complement representation, +** where MININTEGER always has an exact representation as a float; +** MAXINTEGER may not have one, and therefore its conversion to float +** may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_floatatt(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_floatatt(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_floatatt(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +@@ LUAI_UACINT is the result of a 'default argument promotion' +@@ over a LUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" + +#define LUAI_UACINT LUA_INTEGER + +#define lua_integer2str(s,sz,n) \ + l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#define LUA_MAXUNSIGNED UINT_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#define LUA_MAXUNSIGNED ULONG_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#define LUA_MAXUNSIGNED ULLONG_MAX + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#define LUA_MAXUNSIGNED _UI64_MAX + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts a hexadecimal numeral to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_pointer2str converts a pointer to a readable string in a +** non-specified way. +*/ +#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) + + +/* +@@ lua_number2strx converts a float to a hexadecimal numeral. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) \ + ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include the header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + + +/* +** macros to improve jump prediction, used mostly for error handling +** and debug facilities. (Some macros in the Lua API use these macros. +** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your +** code.) +*/ +#if !defined(luai_likely) + +#if defined(__GNUC__) && !defined(LUA_NOBUILTIN) +#define luai_likely(x) (__builtin_expect(((x) != 0), 1)) +#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0)) +#else +#define luai_likely(x) (x) +#define luai_unlikely(x) (x) +#endif + +#endif + + +#if defined(LUA_CORE) || defined(LUA_LIB) +/* shorter names for Lua's own use */ +#define l_likely(x) luai_likely(x) +#define l_unlikely(x) luai_unlikely(x) +#endif + + + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +** (It must fit into max(size_t)/32.) +*/ +#if LUAI_IS32INT +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) + + +/* +@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure +** maximum alignment for the other items in that union. +*/ +#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l + +/* }================================================================== */ + +#endif + + + + + +/* +** $Id: lua.h $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "4" +#define LUA_VERSION_RELEASE "4" + +#define LUA_VERSION_NUM 504 +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4) + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTYPES 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** Type for warning functions +*/ +typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); + + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) +SYMBOL_DECLARE(void, lua_close, lua_State *L) +SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) +SYMBOL_DECLARE(int, lua_resetthread, lua_State *L) + +SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) + + +SYMBOL_DECLARE(lua_Number, lua_version, lua_State *L) + + +/* +** basic stack manipulation +*/ +SYMBOL_DECLARE(int , lua_absindex, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_gettop, lua_State *L) +SYMBOL_DECLARE(void, lua_settop, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_pushvalue, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_rotate, lua_State *L, int idx, int n) +SYMBOL_DECLARE(void, lua_copy, lua_State *L, int fromidx, int toidx) +SYMBOL_DECLARE(int , lua_checkstack, lua_State *L, int n) + +SYMBOL_DECLARE(void, lua_xmove, lua_State *from, lua_State *to, int n) + + +/* +** access functions (stack -> C) +*/ + +SYMBOL_DECLARE(int , lua_isnumber, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_isstring, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_iscfunction, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_isinteger, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_isuserdata, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_type, lua_State *L, int idx) +SYMBOL_DECLARE(const char *, lua_typename, lua_State *L, int tp) + +SYMBOL_DECLARE(lua_Number , lua_tonumberx, lua_State *L, int idx, int *isnum) +SYMBOL_DECLARE(lua_Integer , lua_tointegerx, lua_State *L, int idx, int *isnum) +SYMBOL_DECLARE(int , lua_toboolean, lua_State *L, int idx) +SYMBOL_DECLARE(const char *, lua_tolstring, lua_State *L, int idx, size_t *len) +SYMBOL_DECLARE(lua_Unsigned , lua_rawlen, lua_State *L, int idx) +SYMBOL_DECLARE(lua_CFunction , lua_tocfunction, lua_State *L, int idx) +SYMBOL_DECLARE(void *, lua_touserdata, lua_State *L, int idx) +SYMBOL_DECLARE(lua_State *, lua_tothread, lua_State *L, int idx) +SYMBOL_DECLARE(const void *, lua_topointer, lua_State *L, int idx) + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +SYMBOL_DECLARE(void , lua_arith, lua_State *L, int op) + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +SYMBOL_DECLARE(int , lua_rawequal, lua_State *L, int idx1, int idx2) +SYMBOL_DECLARE(int , lua_compare, lua_State *L, int idx1, int idx2, int op) + + +/* +** push functions (C -> stack) +*/ +SYMBOL_DECLARE(void , lua_pushnil, lua_State *L) +SYMBOL_DECLARE(void , lua_pushnumber, lua_State *L, lua_Number n) +SYMBOL_DECLARE(void , lua_pushinteger, lua_State *L, lua_Integer n) +SYMBOL_DECLARE(const char *, lua_pushlstring, lua_State *L, const char *s, size_t len) +SYMBOL_DECLARE(const char *, lua_pushstring, lua_State *L, const char *s) +SYMBOL_DECLARE(const char *, lua_pushvfstring, lua_State *L, const char *fmt, + va_list argp) +SYMBOL_DECLARE_VARARG(const char *, lua_pushfstring, lua_State *L, const char *fmt) +SYMBOL_DECLARE(void , lua_pushcclosure, lua_State *L, lua_CFunction fn, int n) +SYMBOL_DECLARE(void , lua_pushboolean, lua_State *L, int b) +SYMBOL_DECLARE(void , lua_pushlightuserdata, lua_State *L, void *p) +SYMBOL_DECLARE(int , lua_pushthread, lua_State *L) + + +/* +** get functions (Lua -> stack) +*/ +SYMBOL_DECLARE(int , lua_getglobal, lua_State *L, const char *name) +SYMBOL_DECLARE(int , lua_gettable, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_getfield, lua_State *L, int idx, const char *k) +SYMBOL_DECLARE(int , lua_geti, lua_State *L, int idx, lua_Integer n) +SYMBOL_DECLARE(int , lua_rawget, lua_State *L, int idx) +SYMBOL_DECLARE(int , lua_rawgeti, lua_State *L, int idx, lua_Integer n) +SYMBOL_DECLARE(int , lua_rawgetp, lua_State *L, int idx, const void *p) + +SYMBOL_DECLARE(void , lua_createtable, lua_State *L, int narr, int nrec) +SYMBOL_DECLARE(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue) +SYMBOL_DECLARE(int , lua_getmetatable, lua_State *L, int objindex) +SYMBOL_DECLARE(int , lua_getiuservalue, lua_State *L, int idx, int n) + + +/* +** set functions (stack -> Lua) +*/ +SYMBOL_DECLARE(void , lua_setglobal, lua_State *L, const char *name) +SYMBOL_DECLARE(void , lua_settable, lua_State *L, int idx) +SYMBOL_DECLARE(void , lua_setfield, lua_State *L, int idx, const char *k) +SYMBOL_DECLARE(void , lua_seti, lua_State *L, int idx, lua_Integer n) +SYMBOL_DECLARE(void , lua_rawset, lua_State *L, int idx) +SYMBOL_DECLARE(void , lua_rawseti, lua_State *L, int idx, lua_Integer n) +SYMBOL_DECLARE(void , lua_rawsetp, lua_State *L, int idx, const void *p) +SYMBOL_DECLARE(int , lua_setmetatable, lua_State *L, int objindex) +SYMBOL_DECLARE(int , lua_setiuservalue, lua_State *L, int idx, int n) + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +SYMBOL_DECLARE(int, lua_load, lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode) + +SYMBOL_DECLARE(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) + + +/* +** coroutine functions +*/ +SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k) +SYMBOL_DECLARE(int, lua_resume, lua_State *L, lua_State *from, int narg, + int *nres) +SYMBOL_DECLARE(int, lua_status, lua_State *L) +SYMBOL_DECLARE(int, lua_isyieldable, lua_State *L) + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** Warning-related functions +*/ +SYMBOL_DECLARE(void, lua_setwarnf, lua_State *L, lua_WarnFunction f, void *ud) +SYMBOL_DECLARE(void, lua_warning, lua_State *L, const char *msg, int tocont) + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +SYMBOL_DECLARE_VARARG(int, lua_gc, lua_State *L, int what) + + +/* +** miscellaneous functions +*/ + +SYMBOL_DECLARE(int , lua_error, lua_State *L) + +SYMBOL_DECLARE(int , lua_next, lua_State *L, int idx) + +SYMBOL_DECLARE(void, lua_concat, lua_State *L, int n) +SYMBOL_DECLARE(void, lua_len, lua_State *L, int idx) + +SYMBOL_DECLARE(size_t, lua_stringtonumber, lua_State *L, const char *s) + +SYMBOL_DECLARE(lua_Alloc, lua_getallocf, lua_State *L, void **ud) +SYMBOL_DECLARE(void , lua_setallocf, lua_State *L, lua_Alloc f, void *ud) + +SYMBOL_DECLARE(void, lua_toclose, lua_State *L, int idx) +SYMBOL_DECLARE(void, lua_closeslot, lua_State *L, int idx) + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif + +#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1) +#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) +#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) + +#define LUA_NUMTAGS LUA_NUMTYPES + +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +SYMBOL_DECLARE(int, lua_getstack, lua_State *L, int level, lua_Debug *ar) +SYMBOL_DECLARE(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar) +SYMBOL_DECLARE(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n) +SYMBOL_DECLARE(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n) +SYMBOL_DECLARE(const char *, lua_getupvalue, lua_State *L, int funcindex, int n) +SYMBOL_DECLARE(const char *, lua_setupvalue, lua_State *L, int funcindex, int n) + +SYMBOL_DECLARE(void *, lua_upvalueid, lua_State *L, int fidx, int n) +SYMBOL_DECLARE(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, + int fidx2, int n2) + +SYMBOL_DECLARE(void, lua_sethook, lua_State *L, lua_Hook func, int mask, int count) +SYMBOL_DECLARE(lua_Hook, lua_gethook, lua_State *L) +SYMBOL_DECLARE(int, lua_gethookmask, lua_State *L) +SYMBOL_DECLARE(int, lua_gethookcount, lua_State *L) + +SYMBOL_DECLARE(int, lua_setcstacklimit, lua_State *L, unsigned int limit) + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + size_t srclen; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + unsigned short ftransfer; /* (r) index of first value transferred */ + unsigned short ntransfer; /* (r) number of transferred values */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +#endif + + + + + +/* +** $Id: lauxlib.h $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + + +/* global table */ +#define LUA_GNAME "_G" + + +typedef struct luaL_Buffer luaL_Buffer; + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +SYMBOL_DECLARE(void, luaL_checkversion_, lua_State *L, lua_Number ver, size_t sz) +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +SYMBOL_DECLARE(int, luaL_getmetafield, lua_State *L, int obj, const char *e) +SYMBOL_DECLARE(int, luaL_callmeta, lua_State *L, int obj, const char *e) +SYMBOL_DECLARE(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len) +SYMBOL_DECLARE(int, luaL_argerror, lua_State *L, int arg, const char *extramsg) +SYMBOL_DECLARE(int, luaL_typeerror, lua_State *L, int arg, const char *tname) +SYMBOL_DECLARE(const char *, luaL_checklstring, lua_State *L, int arg, + size_t *l) +SYMBOL_DECLARE(const char *, luaL_optlstring, lua_State *L, int arg, + const char *def, size_t *l) +SYMBOL_DECLARE(lua_Number, luaL_checknumber, lua_State *L, int arg) +SYMBOL_DECLARE(lua_Number, luaL_optnumber, lua_State *L, int arg, lua_Number def) + +SYMBOL_DECLARE(lua_Integer, luaL_checkinteger, lua_State *L, int arg) +SYMBOL_DECLARE(lua_Integer, luaL_optinteger, lua_State *L, int arg, + lua_Integer def) + +SYMBOL_DECLARE(void, luaL_checkstack, lua_State *L, int sz, const char *msg) +SYMBOL_DECLARE(void, luaL_checktype, lua_State *L, int arg, int t) +SYMBOL_DECLARE(void, luaL_checkany, lua_State *L, int arg) + +SYMBOL_DECLARE(int , luaL_newmetatable, lua_State *L, const char *tname) +SYMBOL_DECLARE(void , luaL_setmetatable, lua_State *L, const char *tname) +SYMBOL_DECLARE(void *, luaL_testudata, lua_State *L, int ud, const char *tname) +SYMBOL_DECLARE(void *, luaL_checkudata, lua_State *L, int ud, const char *tname) + +SYMBOL_DECLARE(void, luaL_where, lua_State *L, int lvl) +SYMBOL_DECLARE_VARARG(int, luaL_error, lua_State *L, const char *fmt) + +SYMBOL_DECLARE(int, luaL_checkoption, lua_State *L, int arg, const char *def, + const char *const lst[]) + +SYMBOL_DECLARE(int, luaL_fileresult, lua_State *L, int stat, const char *fname) +SYMBOL_DECLARE(int, luaL_execresult, lua_State *L, int stat) + + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +SYMBOL_DECLARE(int, luaL_ref, lua_State *L, int t) +SYMBOL_DECLARE(void, luaL_unref, lua_State *L, int t, int ref) + +SYMBOL_DECLARE(int, luaL_loadfilex, lua_State *L, const char *filename, + const char *mode) + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +SYMBOL_DECLARE(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode) +SYMBOL_DECLARE(int, luaL_loadstring, lua_State *L, const char *s) + +SYMBOL_DECLARE(lua_State *, luaL_newstate, void) + +SYMBOL_DECLARE(lua_Integer, luaL_len, lua_State *L, int idx) + +SYMBOL_DECLARE(void, luaL_addgsub, luaL_Buffer *b, const char *s, + const char *p, const char *r) +SYMBOL_DECLARE(const char *, luaL_gsub, lua_State *L, const char *s, + const char *p, const char *r) + +SYMBOL_DECLARE(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup) + +SYMBOL_DECLARE(int, luaL_getsubtable, lua_State *L, int idx, const char *fname) + +SYMBOL_DECLARE(void, luaL_traceback, lua_State *L, lua_State *L1, + const char *msg, int level) + +SYMBOL_DECLARE(void, luaL_requiref, lua_State *L, const char *modname, + lua_CFunction openf, int glb) + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg)))) + +#define luaL_argexpected(L,cond,arg,tname) \ + ((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname)))) + +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** Perform arithmetic operations on lua_Integer values with wrap-around +** semantics, as the Lua core does. +*/ +#define luaL_intop(op,v1,v2) \ + ((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2))) + + +/* push the value used to represent failure/error */ +#define luaL_pushfail(L) lua_pushnil(L) + + +/* +** Internal assertions for in-house debugging +*/ +#if !defined(lua_assert) + +#if defined LUAI_ASSERT + #include + #define lua_assert(c) assert(c) +#else + #define lua_assert(c) ((void)0) +#endif + +#endif + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + union { + LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ + char b[LUAL_BUFFERSIZE]; /* initial buffer */ + } init; +}; + + +#define luaL_bufflen(bf) ((bf)->n) +#define luaL_buffaddr(bf) ((bf)->b) + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +#define luaL_buffsub(B,s) ((B)->n -= (s)) + +SYMBOL_DECLARE(void, luaL_buffinit, lua_State *L, luaL_Buffer *B) +SYMBOL_DECLARE(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz) +SYMBOL_DECLARE(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l) +SYMBOL_DECLARE(void, luaL_addstring, luaL_Buffer *B, const char *s) +SYMBOL_DECLARE(void, luaL_addvalue, luaL_Buffer *B) +SYMBOL_DECLARE(void, luaL_pushresult, luaL_Buffer *B) +SYMBOL_DECLARE(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz) +SYMBOL_DECLARE(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz) + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + + + + +/* +** $Id: lualib.h $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + + +/* version suffix for environment variable names */ +#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +SYMBOL_DECLARE(int, luaopen_base, lua_State *L) + +#define LUA_COLIBNAME "coroutine" +SYMBOL_DECLARE(int, luaopen_coroutine, lua_State *L) + +#define LUA_TABLIBNAME "table" +SYMBOL_DECLARE(int, luaopen_table, lua_State *L) + +#define LUA_IOLIBNAME "io" +SYMBOL_DECLARE(int, luaopen_io, lua_State *L) + +#define LUA_OSLIBNAME "os" +SYMBOL_DECLARE(int, luaopen_os, lua_State *L) + +#define LUA_STRLIBNAME "string" +SYMBOL_DECLARE(int, luaopen_string, lua_State *L) + +#define LUA_UTF8LIBNAME "utf8" +SYMBOL_DECLARE(int, luaopen_utf8, lua_State *L) + +#define LUA_MATHLIBNAME "math" +SYMBOL_DECLARE(int, luaopen_math, lua_State *L) + +#define LUA_DBLIBNAME "debug" +SYMBOL_DECLARE(int, luaopen_debug, lua_State *L) + +#define LUA_LOADLIBNAME "package" +SYMBOL_DECLARE(int, luaopen_package, lua_State *L) + + +/* open all previous libraries */ +SYMBOL_DECLARE(void, luaL_openlibs, lua_State *L) + + +#endif + + + + + +#ifdef LITE_XL_PLUGIN_ENTRYPOINT + +SYMBOL_WRAP_DECL(lua_State *, lua_newstate, lua_Alloc f, void *ud) { + return SYMBOL_WRAP_CALL(lua_newstate, f, ud); +} +SYMBOL_WRAP_DECL(void, lua_close, lua_State *L) { + SYMBOL_WRAP_CALL(lua_close, L); +} +SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_newthread, L); +} +SYMBOL_WRAP_DECL(int, lua_resetthread, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_resetthread, L); +} + +SYMBOL_WRAP_DECL(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) { + return SYMBOL_WRAP_CALL(lua_atpanic, L, panicf); +} + + +SYMBOL_WRAP_DECL(lua_Number, lua_version, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_version, L); +} + + + + + +SYMBOL_WRAP_DECL(int, lua_absindex, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_absindex, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_gettop, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_gettop, L); +} +SYMBOL_WRAP_DECL(void, lua_settop, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_settop, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_pushvalue, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_pushvalue, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_rotate, lua_State *L, int idx, int n) { + SYMBOL_WRAP_CALL(lua_rotate, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_copy, lua_State *L, int fromidx, int toidx) { + SYMBOL_WRAP_CALL(lua_copy, L, fromidx, toidx); +} +SYMBOL_WRAP_DECL(int, lua_checkstack, lua_State *L, int sz) { + return SYMBOL_WRAP_CALL(lua_checkstack, L, sz); +} +SYMBOL_WRAP_DECL(void, lua_xmove, lua_State *from, lua_State *to, int n) { + SYMBOL_WRAP_CALL(lua_xmove, from, to, n); +} + + + + + + +SYMBOL_WRAP_DECL(int, lua_isnumber, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_isnumber, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_isstring, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_isstring, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_iscfunction, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_iscfunction, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_isinteger, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_isinteger, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_isuserdata, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_isuserdata, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_type, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_type, L, idx); +} +SYMBOL_WRAP_DECL(const char *, lua_typename, lua_State *L, int tp) { + return SYMBOL_WRAP_CALL(lua_typename, L, tp); +} + +SYMBOL_WRAP_DECL(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum) { + return SYMBOL_WRAP_CALL(lua_tonumberx, L, idx, isnum); +} +SYMBOL_WRAP_DECL(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum) { + return SYMBOL_WRAP_CALL(lua_tointegerx, L, idx, isnum); +} +SYMBOL_WRAP_DECL(int, lua_toboolean, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_toboolean, L, idx); +} +SYMBOL_WRAP_DECL(const char *, lua_tolstring, lua_State *L, int idx, size_t *len) { + return SYMBOL_WRAP_CALL(lua_tolstring, L, idx, len); +} +SYMBOL_WRAP_DECL(lua_Unsigned, lua_rawlen, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_rawlen, L, idx); +} +SYMBOL_WRAP_DECL(lua_CFunction, lua_tocfunction, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_tocfunction, L, idx); +} +SYMBOL_WRAP_DECL(void *, lua_touserdata, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_touserdata, L, idx); +} +SYMBOL_WRAP_DECL(lua_State *, lua_tothread, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_tothread, L, idx); +} +SYMBOL_WRAP_DECL(const void *, lua_topointer, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_topointer, L, idx); +} + + + + + + +SYMBOL_WRAP_DECL(void, lua_arith, lua_State *L, int op) { + SYMBOL_WRAP_CALL(lua_arith, L, op); +} + +SYMBOL_WRAP_DECL(int, lua_rawequal, lua_State *L, int idx1, int idx2) { + return SYMBOL_WRAP_CALL(lua_rawequal, L, idx1, idx2); +} +SYMBOL_WRAP_DECL(int, lua_compare, lua_State *L, int idx1, int idx2, int op) { + return SYMBOL_WRAP_CALL(lua_compare, L, idx1, idx2, op); +} + +SYMBOL_WRAP_DECL(void, lua_pushnil, lua_State *L) { + SYMBOL_WRAP_CALL(lua_pushnil, L); +} +SYMBOL_WRAP_DECL(void, lua_pushnumber, lua_State *L, lua_Number n) { + SYMBOL_WRAP_CALL(lua_pushnumber, L, n); +} +SYMBOL_WRAP_DECL(void, lua_pushinteger, lua_State *L, lua_Integer n) { + SYMBOL_WRAP_CALL(lua_pushinteger, L, n); +} +SYMBOL_WRAP_DECL(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l) { + return SYMBOL_WRAP_CALL(lua_pushlstring, L, s, l); +} +SYMBOL_WRAP_DECL(const char *, lua_pushstring, lua_State *L, const char *s) { + return SYMBOL_WRAP_CALL(lua_pushstring, L, s); +} +SYMBOL_WRAP_DECL(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp) { + return SYMBOL_WRAP_CALL(lua_pushvfstring, L, fmt, argp); +} +SYMBOL_WRAP_DECL(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...) { + const char *res; + va_list argp; + va_start(argp, fmt); + res = lua_pushvfstring(L, fmt, argp); + va_end(argp); + return res; +} +SYMBOL_WRAP_DECL(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n) { + SYMBOL_WRAP_CALL(lua_pushcclosure, L, fn, n); +} +SYMBOL_WRAP_DECL(void, lua_pushboolean, lua_State *L, int b) { + SYMBOL_WRAP_CALL(lua_pushboolean, L, b); +} +SYMBOL_WRAP_DECL(void, lua_pushlightuserdata, lua_State *L, void *p) { + SYMBOL_WRAP_CALL(lua_pushlightuserdata, L, p); +} +SYMBOL_WRAP_DECL(int, lua_pushthread, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_pushthread, L); +} + + + + + +SYMBOL_WRAP_DECL(int, lua_getglobal, lua_State *L, const char *var) { + return SYMBOL_WRAP_CALL(lua_getglobal, L, var); +} +SYMBOL_WRAP_DECL(int, lua_gettable, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_gettable, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_getfield, lua_State *L, int idx, const char *k) { + return SYMBOL_WRAP_CALL(lua_getfield, L, idx, k); +} +SYMBOL_WRAP_DECL(int , lua_geti, lua_State *L, int idx, lua_Integer n) { + return SYMBOL_WRAP_CALL(lua_geti, L, idx, n); +} +SYMBOL_WRAP_DECL(int, lua_rawget, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_rawget, L, idx); +} +SYMBOL_WRAP_DECL(int, lua_rawgeti, lua_State *L, int idx, lua_Integer n) { + return SYMBOL_WRAP_CALL(lua_rawgeti, L, idx, n); +} +SYMBOL_WRAP_DECL(int, lua_rawgetp, lua_State *L, int idx, const void *p) { + return SYMBOL_WRAP_CALL(lua_rawgetp, L, idx, p); +} +SYMBOL_WRAP_DECL(void, lua_createtable, lua_State *L, int narr, int nrec) { + SYMBOL_WRAP_CALL(lua_createtable, L, narr, nrec); +} +SYMBOL_WRAP_DECL(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue) { + return SYMBOL_WRAP_CALL(lua_newuserdatauv, L, sz, nuvalue); +} +SYMBOL_WRAP_DECL(int, lua_getmetatable, lua_State *L, int objindex) { + return SYMBOL_WRAP_CALL(lua_getmetatable, L, objindex); +} +SYMBOL_WRAP_DECL(int, lua_getiuservalue, lua_State *L, int idx, int n) { + return SYMBOL_WRAP_CALL(lua_getiuservalue, L, idx, n); +} + +SYMBOL_WRAP_DECL(void, lua_setglobal, lua_State *L, const char *var) { + SYMBOL_WRAP_CALL(lua_setglobal, L, var); +} +SYMBOL_WRAP_DECL(void, lua_settable, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_settable, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_setfield, lua_State *L, int idx, const char *k) { + SYMBOL_WRAP_CALL(lua_setfield, L, idx, k); +} +SYMBOL_WRAP_DECL(void, lua_seti, lua_State *L, int idx, lua_Integer n) { + SYMBOL_WRAP_CALL(lua_seti, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_rawset, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_rawset, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_rawseti, lua_State *L, int idx, lua_Integer n) { + SYMBOL_WRAP_CALL(lua_rawseti, L, idx, n); +} +SYMBOL_WRAP_DECL(void, lua_rawsetp, lua_State *L, int idx, const void *p) { + SYMBOL_WRAP_CALL(lua_rawsetp, L, idx, p); +} +SYMBOL_WRAP_DECL(int, lua_setmetatable, lua_State *L, int objindex) { + return SYMBOL_WRAP_CALL(lua_setmetatable, L, objindex); +} +SYMBOL_WRAP_DECL(int, lua_setiuservalue, lua_State *L, int idx, int n) { + return SYMBOL_WRAP_CALL(lua_setiuservalue, L, idx, n); +} + + + + + +SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) { + SYMBOL_WRAP_CALL(lua_callk, L, nargs, nresults, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) { + return SYMBOL_WRAP_CALL(lua_pcallk, L, nargs, nresults, errfunc, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) { + return SYMBOL_WRAP_CALL(lua_load, L, reader, dt, chunkname, mode); +} +SYMBOL_WRAP_DECL(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) { + return SYMBOL_WRAP_CALL(lua_dump, L, writer, data, strip); +} + + + + + +SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k) { + return SYMBOL_WRAP_CALL(lua_yieldk, L, nresults, ctx, k); +} +SYMBOL_WRAP_DECL(int, lua_resume, lua_State *L, lua_State *from, int narg, int *nres) { + return SYMBOL_WRAP_CALL(lua_resume, L, from, narg, nres); +} +SYMBOL_WRAP_DECL(int, lua_status, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_status, L); +} +SYMBOL_WRAP_DECL(int, lua_isyieldable, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_isyieldable, L); +} + + + + + +SYMBOL_WRAP_DECL(void, lua_setwarnf, lua_State *L, lua_WarnFunction f, void *ud) { + SYMBOL_WRAP_CALL(lua_setwarnf, L, f, ud); +} +SYMBOL_WRAP_DECL(void, lua_warning, lua_State *L, const char *msg, int tocont) { + SYMBOL_WRAP_CALL(lua_warning, L, msg, tocont); +} + + + + + + +SYMBOL_WRAP_DECL(int, lua_gc, lua_State *L, int what, ...) { + /* there are no straightforward ways of passing data. */ + int r; + va_list ap; + va_start(ap, what); + if (what == LUA_GCSTEP) { + int stepsize = va_arg(ap, int); + r = __lua_gc(L, what, stepsize); + } else if (what == LUA_GCINC) { + int pause = va_arg(ap, int); + int stepmul = va_arg(ap, int); + int stepsize = va_arg(ap, int); + r = __lua_gc(L, what, pause, stepmul, stepsize); + } else if (what == LUA_GCGEN) { + int minormul = va_arg(ap, int); + int majormul = va_arg(ap, int); + r = __lua_gc(L, what, minormul, majormul); + } else { + r = __lua_gc(L, what); + } + return r; +} + + + + + + +SYMBOL_WRAP_DECL(int, lua_error, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_error, L); +} + +SYMBOL_WRAP_DECL(int, lua_next, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(lua_next, L, idx); +} + +SYMBOL_WRAP_DECL(void, lua_concat, lua_State *L, int n) { + SYMBOL_WRAP_CALL(lua_concat, L, n); +} +SYMBOL_WRAP_DECL(void, lua_len, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_len, L, idx); +} + +SYMBOL_WRAP_DECL(size_t, lua_stringtonumber, lua_State *L, const char *s) { + return SYMBOL_WRAP_CALL(lua_stringtonumber, L, s); +} + +SYMBOL_WRAP_DECL(lua_Alloc, lua_getallocf, lua_State *L, void **ud) { + return SYMBOL_WRAP_CALL(lua_getallocf, L, ud); +} +SYMBOL_WRAP_DECL(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud) { + SYMBOL_WRAP_CALL(lua_setallocf, L, f, ud); +} + +SYMBOL_WRAP_DECL(void, lua_toclose, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_toclose, L, idx); +} +SYMBOL_WRAP_DECL(void, lua_closeslot, lua_State *L, int idx) { + SYMBOL_WRAP_CALL(lua_closeslot, L, idx); +} + + + + + + +SYMBOL_WRAP_DECL(int, lua_getstack, lua_State *L, int level, lua_Debug *ar) { + return SYMBOL_WRAP_CALL(lua_getstack, L, level, ar); +} +SYMBOL_WRAP_DECL(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar) { + return SYMBOL_WRAP_CALL(lua_getinfo, L, what, ar); +} +SYMBOL_WRAP_DECL(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n) { + return SYMBOL_WRAP_CALL(lua_getlocal, L, ar, n); +} +SYMBOL_WRAP_DECL(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n) { + return SYMBOL_WRAP_CALL(lua_setlocal, L, ar, n); +} +SYMBOL_WRAP_DECL(const char *, lua_getupvalue, lua_State *L, int funcindex, int n) { + return SYMBOL_WRAP_CALL(lua_getupvalue, L, funcindex, n); +} +SYMBOL_WRAP_DECL(const char *, lua_setupvalue, lua_State *L, int funcindex, int n) { + return SYMBOL_WRAP_CALL(lua_setupvalue, L, funcindex, n); +} + +SYMBOL_WRAP_DECL(void *, lua_upvalueid, lua_State *L, int fidx, int n) { + return SYMBOL_WRAP_CALL(lua_upvalueid, L, fidx, n); +} +SYMBOL_WRAP_DECL(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2) { + SYMBOL_WRAP_CALL(lua_upvaluejoin, L, fidx1, n1, fidx2, n2); +} + +SYMBOL_WRAP_DECL(void, lua_sethook, lua_State *L, lua_Hook func, int mask, int count) { + SYMBOL_WRAP_CALL(lua_sethook, L, func, mask, count); +} +SYMBOL_WRAP_DECL(lua_Hook, lua_gethook, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_gethook, L); +} +SYMBOL_WRAP_DECL(int, lua_gethookmask, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_gethookmask, L); +} +SYMBOL_WRAP_DECL(int, lua_gethookcount, lua_State *L) { + return SYMBOL_WRAP_CALL(lua_gethookcount, L); +} + +SYMBOL_WRAP_DECL(int, lua_setcstacklimit, lua_State *L, unsigned int limit) { + return SYMBOL_WRAP_CALL(lua_setcstacklimit, L, limit); +} + + + + + + +SYMBOL_WRAP_DECL(void, luaL_checkversion_, lua_State *L, lua_Number ver, size_t sz) { + SYMBOL_WRAP_CALL(luaL_checkversion_, L, ver, sz); +} +SYMBOL_WRAP_DECL(int, luaL_getmetafield, lua_State *L, int obj, const char *e) { + return SYMBOL_WRAP_CALL(luaL_getmetafield, L, obj, e); +} +SYMBOL_WRAP_DECL(int, luaL_callmeta, lua_State *L, int obj, const char *e) { + return SYMBOL_WRAP_CALL(luaL_callmeta, L, obj, e); +} +SYMBOL_WRAP_DECL(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len) { + return SYMBOL_WRAP_CALL(luaL_tolstring, L, idx, len); +} +SYMBOL_WRAP_DECL(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg) { + return SYMBOL_WRAP_CALL(luaL_argerror, L, numarg, extramsg); +} +SYMBOL_WRAP_DECL(int, luaL_typeerror, lua_State *L, int arg, const char *tname) { + return SYMBOL_WRAP_CALL(luaL_typeerror, L, arg, tname); +} +SYMBOL_WRAP_DECL(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l) { + return SYMBOL_WRAP_CALL(luaL_checklstring, L, numArg, l); +} +SYMBOL_WRAP_DECL(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l) { + return SYMBOL_WRAP_CALL(luaL_optlstring, L, numArg, def, l); +} +SYMBOL_WRAP_DECL(lua_Number, luaL_checknumber, lua_State *L, int numArg) { + return SYMBOL_WRAP_CALL(luaL_checknumber, L, numArg); +} +SYMBOL_WRAP_DECL(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def) { + return SYMBOL_WRAP_CALL(luaL_optnumber, L, nArg, def); +} + +SYMBOL_WRAP_DECL(lua_Integer, luaL_checkinteger, lua_State *L, int numArg) { + return SYMBOL_WRAP_CALL(luaL_checkinteger, L, numArg); +} +SYMBOL_WRAP_DECL(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def) { + return SYMBOL_WRAP_CALL(luaL_optinteger, L, nArg, def); +} + +SYMBOL_WRAP_DECL(void, luaL_checkstack, lua_State *L, int sz, const char *msg) { + SYMBOL_WRAP_CALL(luaL_checkstack, L, sz, msg); +} +SYMBOL_WRAP_DECL(void, luaL_checktype, lua_State *L, int narg, int t) { + SYMBOL_WRAP_CALL(luaL_checktype, L, narg, t); +} +SYMBOL_WRAP_DECL(void, luaL_checkany, lua_State *L, int narg) { + SYMBOL_WRAP_CALL(luaL_checkany, L, narg); +} +SYMBOL_WRAP_DECL(int, luaL_newmetatable, lua_State *L, const char *tname) { + return SYMBOL_WRAP_CALL(luaL_newmetatable, L, tname); +} +SYMBOL_WRAP_DECL(void, luaL_setmetatable, lua_State *L, const char *tname) { + SYMBOL_WRAP_CALL(luaL_setmetatable, L, tname); +} +SYMBOL_WRAP_DECL(void *, luaL_testudata, lua_State *L, int ud, const char *tname) { + return SYMBOL_WRAP_CALL(luaL_testudata, L, ud, tname); +} +SYMBOL_WRAP_DECL(void *, luaL_checkudata, lua_State *L, int ud, const char *tname) { + return SYMBOL_WRAP_CALL(luaL_checkudata, L, ud, tname); +} + +SYMBOL_WRAP_DECL(void, luaL_where, lua_State *L, int lvl) { + SYMBOL_WRAP_CALL(luaL_where, L, lvl); +} +SYMBOL_WRAP_DECL(int, luaL_error, lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +SYMBOL_WRAP_DECL(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]) { + return SYMBOL_WRAP_CALL(luaL_checkoption, L, narg, def, lst); +} + +SYMBOL_WRAP_DECL(int, luaL_fileresult, lua_State *L, int stat, const char *fname) { + return SYMBOL_WRAP_CALL(luaL_fileresult, L, stat, fname); +} +SYMBOL_WRAP_DECL(int, luaL_execresult, lua_State *L, int stat) { + return SYMBOL_WRAP_CALL(luaL_execresult, L, stat); +} + + + + + + +SYMBOL_WRAP_DECL(int, luaL_ref, lua_State *L, int t) { + return SYMBOL_WRAP_CALL(luaL_ref, L, t); +} +SYMBOL_WRAP_DECL(void, luaL_unref, lua_State *L, int t, int ref) { + SYMBOL_WRAP_CALL(luaL_unref, L, t, ref); +} + +SYMBOL_WRAP_DECL(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode) { + return SYMBOL_WRAP_CALL(luaL_loadfilex, L, filename, mode); +} + +SYMBOL_WRAP_DECL(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { + return SYMBOL_WRAP_CALL(luaL_loadbufferx, L, buff, sz, name, mode); +} + +SYMBOL_WRAP_DECL(int, luaL_loadstring, lua_State *L, const char *s) { + return SYMBOL_WRAP_CALL(luaL_loadstring, L, s); +} + +SYMBOL_WRAP_DECL(lua_State *, luaL_newstate, void) { + return __luaL_newstate(); +} +SYMBOL_WRAP_DECL(lua_Integer, luaL_len, lua_State *L, int idx) { + return SYMBOL_WRAP_CALL(luaL_len, L, idx); +} + +SYMBOL_WRAP_DECL(void, luaL_addgsub, luaL_Buffer *b, const char *s, + const char *p, const char *r) { + SYMBOL_WRAP_CALL(luaL_addgsub, b, s, p, r); +} +SYMBOL_WRAP_DECL(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r) { + return SYMBOL_WRAP_CALL(luaL_gsub, L, s, p, r); +} + +SYMBOL_WRAP_DECL(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup) { + SYMBOL_WRAP_CALL(luaL_setfuncs, L, l, nup); +} + +SYMBOL_WRAP_DECL(int, luaL_getsubtable, lua_State *L, int idx, const char *fname) { + return SYMBOL_WRAP_CALL(luaL_getsubtable, L, idx, fname); +} + +SYMBOL_WRAP_DECL(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level) { + SYMBOL_WRAP_CALL(luaL_traceback, L, L1, msg, level); +} + +SYMBOL_WRAP_DECL(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb) { + SYMBOL_WRAP_CALL(luaL_requiref, L, modname, openf, glb); +} + + + + + + +SYMBOL_WRAP_DECL(void, luaL_buffinit, lua_State *L, luaL_Buffer *B) { + SYMBOL_WRAP_CALL(luaL_buffinit, L, B); +} +SYMBOL_WRAP_DECL(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz) { + return SYMBOL_WRAP_CALL(luaL_prepbuffsize, B, sz); +} +SYMBOL_WRAP_DECL(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l) { + SYMBOL_WRAP_CALL(luaL_addlstring, B, s, l); +} +SYMBOL_WRAP_DECL(void, luaL_addstring, luaL_Buffer *B, const char *s) { + SYMBOL_WRAP_CALL(luaL_addstring, B, s); +} +SYMBOL_WRAP_DECL(void, luaL_addvalue, luaL_Buffer *B) { + SYMBOL_WRAP_CALL(luaL_addvalue, B); +} +SYMBOL_WRAP_DECL(void, luaL_pushresult, luaL_Buffer *B) { + SYMBOL_WRAP_CALL(luaL_pushresult, B); +} +SYMBOL_WRAP_DECL(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz) { + SYMBOL_WRAP_CALL(luaL_pushresultsize, B, sz); +} +SYMBOL_WRAP_DECL(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz) { + return SYMBOL_WRAP_CALL(luaL_buffinitsize, L, B, sz); +} + +SYMBOL_WRAP_DECL(int, luaopen_base, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_base, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_coroutine, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_coroutine, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_table, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_table, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_io, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_io, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_os, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_os, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_string, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_string, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_utf8, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_utf8, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_math, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_math, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_debug, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_debug, L); +} + +SYMBOL_WRAP_DECL(int, luaopen_package, lua_State *L) { + return SYMBOL_WRAP_CALL(luaopen_package, L); +} + +SYMBOL_WRAP_DECL(void, luaL_openlibs, lua_State *L) { + SYMBOL_WRAP_CALL(luaL_openlibs, L); +} + + + + + + +#define IMPORT_SYMBOL(name, ret, ...) \ + __##name = (\ + (*(void **) (&__##name) = symbol(#name)), \ + __##name == NULL ? ((ret (*) (__VA_ARGS__)) &__lite_xl_fallback_##name) : __##name\ + ) + +void lite_xl_plugin_init(void *XL) { + void* (*symbol)(const char *); + *(void **) (&symbol) = XL; + IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); + IMPORT_SYMBOL(lua_close, void, lua_State *L); + IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); + IMPORT_SYMBOL(lua_resetthread, int, lua_State *L); + IMPORT_SYMBOL(lua_atpanic, lua_CFunction, lua_State *L, lua_CFunction panicf); + IMPORT_SYMBOL(lua_version, lua_Number, lua_State *L); + IMPORT_SYMBOL(lua_absindex, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_gettop, int, lua_State *L); + IMPORT_SYMBOL(lua_settop, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_pushvalue, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_rotate, void, lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_copy, void, lua_State *L, int fromidx, int toidx); + IMPORT_SYMBOL(lua_checkstack, int, lua_State *L, int sz); + IMPORT_SYMBOL(lua_xmove, void, lua_State *from, lua_State *to, int n); + IMPORT_SYMBOL(lua_isnumber, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_isstring, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_iscfunction, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_isinteger, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_isuserdata, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_type, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_typename, const char *, lua_State *L, int tp); + IMPORT_SYMBOL(lua_tonumberx, lua_Number, lua_State *L, int idx, int *isnum); + IMPORT_SYMBOL(lua_tointegerx, lua_Integer, lua_State *L, int idx, int *isnum); + IMPORT_SYMBOL(lua_toboolean, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_tolstring, const char *, lua_State *L, int idx, size_t *len); + IMPORT_SYMBOL(lua_rawlen, lua_Unsigned, lua_State *L, int idx); + IMPORT_SYMBOL(lua_tocfunction, lua_CFunction, lua_State *L, int idx); + IMPORT_SYMBOL(lua_touserdata, void *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_tothread, lua_State *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_topointer, const void *, lua_State *L, int idx); + IMPORT_SYMBOL(lua_arith, void, lua_State *L, int op); + IMPORT_SYMBOL(lua_rawequal, int, lua_State *L, int idx1, int idx2); + IMPORT_SYMBOL(lua_compare, int, lua_State *L, int idx1, int idx2, int op); + IMPORT_SYMBOL(lua_pushnil, void, lua_State *L); + IMPORT_SYMBOL(lua_pushnumber, void, lua_State *L, lua_Number n); + IMPORT_SYMBOL(lua_pushinteger, void, lua_State *L, lua_Integer n); + IMPORT_SYMBOL(lua_pushlstring, const char *, lua_State *L, const char *s, size_t l); + IMPORT_SYMBOL(lua_pushstring, const char *, lua_State *L, const char *s); + IMPORT_SYMBOL(lua_pushvfstring, const char *, lua_State *L, const char *fmt, va_list argp); + IMPORT_SYMBOL(lua_pushfstring, const char *, lua_State *L, const char *fmt, ...); + IMPORT_SYMBOL(lua_pushcclosure, void, lua_State *L, lua_CFunction fn, int n); + IMPORT_SYMBOL(lua_pushboolean, void, lua_State *L, int b); + IMPORT_SYMBOL(lua_pushlightuserdata, void, lua_State *L, void *p); + IMPORT_SYMBOL(lua_pushthread, int, lua_State *L); + IMPORT_SYMBOL(lua_getglobal, int, lua_State *L, const char *var); + IMPORT_SYMBOL(lua_gettable, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_getfield, int, lua_State *L, int idx, const char *k); + IMPORT_SYMBOL(lua_geti, int, lua_State *L, int idx, lua_Integer n); + IMPORT_SYMBOL(lua_rawget, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_rawgeti, int, lua_State *L, int idx, lua_Integer n); + IMPORT_SYMBOL(lua_rawgetp, int, lua_State *L, int idx, const void *p); + IMPORT_SYMBOL(lua_createtable, void, lua_State *L, int narr, int nrec); + IMPORT_SYMBOL(lua_newuserdatauv, void *, lua_State *L, size_t sz, int nuvalue); + IMPORT_SYMBOL(lua_getmetatable, int, lua_State *L, int objindex); + IMPORT_SYMBOL(lua_getiuservalue, int, lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_setglobal, void, lua_State *L, const char *var); + IMPORT_SYMBOL(lua_settable, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_setfield, void, lua_State *L, int idx, const char *k); + IMPORT_SYMBOL(lua_seti, void, lua_State *L, int idx, lua_Integer n); + IMPORT_SYMBOL(lua_rawset, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_rawseti, void, lua_State *L, int idx, lua_Integer n); + IMPORT_SYMBOL(lua_rawsetp, void, lua_State *L, int idx, const void *p); + IMPORT_SYMBOL(lua_setmetatable, int, lua_State *L, int objindex); + IMPORT_SYMBOL(lua_setiuservalue, int, lua_State *L, int idx, int n); + IMPORT_SYMBOL(lua_callk, void, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k); + IMPORT_SYMBOL(lua_pcallk, int, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k); + IMPORT_SYMBOL(lua_load, int, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); + IMPORT_SYMBOL(lua_dump, int, lua_State *L, lua_Writer writer, void *data, int strip); + IMPORT_SYMBOL(lua_yieldk, int, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k); + IMPORT_SYMBOL(lua_resume, int, lua_State *L, lua_State *from, int narg, int *nres); + IMPORT_SYMBOL(lua_status, int, lua_State *L); + IMPORT_SYMBOL(lua_isyieldable, int, lua_State *L); + IMPORT_SYMBOL(lua_setwarnf, void, lua_State *L, lua_WarnFunction f, void *ud); + IMPORT_SYMBOL(lua_warning, void, lua_State *L, const char *msg, int tocont); + IMPORT_SYMBOL(lua_gc, int, lua_State *L, int what, ...); + IMPORT_SYMBOL(lua_error, int, lua_State *L); + IMPORT_SYMBOL(lua_next, int, lua_State *L, int idx); + IMPORT_SYMBOL(lua_concat, void, lua_State *L, int n); + IMPORT_SYMBOL(lua_len, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_stringtonumber, size_t, lua_State *L, const char *s); + IMPORT_SYMBOL(lua_getallocf, lua_Alloc, lua_State *L, void **ud); + IMPORT_SYMBOL(lua_setallocf, void, lua_State *L, lua_Alloc f, void *ud); + IMPORT_SYMBOL(lua_toclose, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_closeslot, void, lua_State *L, int idx); + IMPORT_SYMBOL(lua_getstack, int, lua_State *L, int level, lua_Debug *ar); + IMPORT_SYMBOL(lua_getinfo, int, lua_State *L, const char *what, lua_Debug *ar); + IMPORT_SYMBOL(lua_getlocal, const char *, lua_State *L, const lua_Debug *ar, int n); + IMPORT_SYMBOL(lua_setlocal, const char *, lua_State *L, const lua_Debug *ar, int n); + IMPORT_SYMBOL(lua_getupvalue, const char *, lua_State *L, int funcindex, int n); + IMPORT_SYMBOL(lua_setupvalue, const char *, lua_State *L, int funcindex, int n); + IMPORT_SYMBOL(lua_upvalueid, void *, lua_State *L, int fidx, int n); + IMPORT_SYMBOL(lua_upvaluejoin, void, lua_State *L, int fidx1, int n1, int fidx2, int n2); + IMPORT_SYMBOL(lua_sethook, void, lua_State *L, lua_Hook func, int mask, int count); + IMPORT_SYMBOL(lua_gethook, lua_Hook, lua_State *L); + IMPORT_SYMBOL(lua_gethookmask, int, lua_State *L); + IMPORT_SYMBOL(lua_gethookcount, int, lua_State *L); + IMPORT_SYMBOL(lua_setcstacklimit, int, lua_State *L, unsigned int limit); + IMPORT_SYMBOL(luaL_checkversion_, void, lua_State *L, lua_Number ver, size_t sz); + IMPORT_SYMBOL(luaL_getmetafield, int, lua_State *L, int obj, const char *e); + IMPORT_SYMBOL(luaL_callmeta, int, lua_State *L, int obj, const char *e); + IMPORT_SYMBOL(luaL_tolstring, const char *, lua_State *L, int idx, size_t *len); + IMPORT_SYMBOL(luaL_argerror, int, lua_State *L, int numarg, const char *extramsg); + IMPORT_SYMBOL(luaL_typeerror, int, lua_State *L, int arg, const char *tname); + IMPORT_SYMBOL(luaL_checklstring, const char *, lua_State *L, int numArg, size_t *l); + IMPORT_SYMBOL(luaL_optlstring, const char *, lua_State *L, int numArg, const char *def, size_t *l); + IMPORT_SYMBOL(luaL_checknumber, lua_Number, lua_State *L, int numArg); + IMPORT_SYMBOL(luaL_optnumber, lua_Number, lua_State *L, int nArg, lua_Number def); + IMPORT_SYMBOL(luaL_checkinteger, lua_Integer, lua_State *L, int numArg); + IMPORT_SYMBOL(luaL_optinteger, lua_Integer, lua_State *L, int nArg, lua_Integer def); + IMPORT_SYMBOL(luaL_checkstack, void, lua_State *L, int sz, const char *msg); + IMPORT_SYMBOL(luaL_checktype, void, lua_State *L, int narg, int t); + IMPORT_SYMBOL(luaL_checkany, void, lua_State *L, int narg); + IMPORT_SYMBOL(luaL_newmetatable, int, lua_State *L, const char *tname); + IMPORT_SYMBOL(luaL_setmetatable, void, lua_State *L, const char *tname); + IMPORT_SYMBOL(luaL_testudata, void *, lua_State *L, int ud, const char *tname); + IMPORT_SYMBOL(luaL_checkudata, void *, lua_State *L, int ud, const char *tname); + IMPORT_SYMBOL(luaL_where, void, lua_State *L, int lvl); + IMPORT_SYMBOL(luaL_error, int, lua_State *L, const char *fmt, ...); + IMPORT_SYMBOL(luaL_checkoption, int, lua_State *L, int narg, const char *def, const char *const lst[]); + IMPORT_SYMBOL(luaL_fileresult, int, lua_State *L, int stat, const char *fname); + IMPORT_SYMBOL(luaL_execresult, int, lua_State *L, int stat); + IMPORT_SYMBOL(luaL_ref, int, lua_State *L, int t); + IMPORT_SYMBOL(luaL_unref, void, lua_State *L, int t, int ref); + IMPORT_SYMBOL(luaL_loadfilex, int, lua_State *L, const char *filename, const char *mode); + IMPORT_SYMBOL(luaL_loadbufferx, int, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); + IMPORT_SYMBOL(luaL_loadstring, int, lua_State *L, const char *s); + IMPORT_SYMBOL(luaL_newstate, lua_State *, void); + IMPORT_SYMBOL(luaL_len, lua_Integer, lua_State *L, int idx); + IMPORT_SYMBOL(luaL_addgsub, void, luaL_Buffer *b, const char *s, const char *p, const char *r); + IMPORT_SYMBOL(luaL_gsub, const char *, lua_State *L, const char *s, const char *p, const char *r); + IMPORT_SYMBOL(luaL_setfuncs, void, lua_State *L, const luaL_Reg *l, int nup); + IMPORT_SYMBOL(luaL_getsubtable, int, lua_State *L, int idx, const char *fname); + IMPORT_SYMBOL(luaL_traceback, void, lua_State *L, lua_State *L1, const char *msg, int level); + IMPORT_SYMBOL(luaL_requiref, void, lua_State *L, const char *modname, lua_CFunction openf, int glb); + IMPORT_SYMBOL(luaL_buffinit, void, lua_State *L, luaL_Buffer *B); + IMPORT_SYMBOL(luaL_prepbuffsize, char *, luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaL_addlstring, void, luaL_Buffer *B, const char *s, size_t l); + IMPORT_SYMBOL(luaL_addstring, void, luaL_Buffer *B, const char *s); + IMPORT_SYMBOL(luaL_addvalue, void, luaL_Buffer *B); + IMPORT_SYMBOL(luaL_pushresult, void, luaL_Buffer *B); + IMPORT_SYMBOL(luaL_pushresultsize, void, luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaL_buffinitsize, char *, lua_State *L, luaL_Buffer *B, size_t sz); + IMPORT_SYMBOL(luaopen_base, int, lua_State *L); + IMPORT_SYMBOL(luaopen_coroutine, int, lua_State *L); + IMPORT_SYMBOL(luaopen_table, int, lua_State *L); + IMPORT_SYMBOL(luaopen_io, int, lua_State *L); + IMPORT_SYMBOL(luaopen_os, int, lua_State *L); + IMPORT_SYMBOL(luaopen_string, int, lua_State *L); + IMPORT_SYMBOL(luaopen_utf8, int, lua_State *L); + IMPORT_SYMBOL(luaopen_math, int, lua_State *L); + IMPORT_SYMBOL(luaopen_debug, int, lua_State *L); + IMPORT_SYMBOL(luaopen_package, int, lua_State *L); + IMPORT_SYMBOL(luaL_openlibs, void, lua_State* L); +} + +#undef IMPORT_SYMBOL +#undef IMPORT_SYMBOL_OPT + +#else /* LITE_XL_PLUGIN_ENTRYPOINT */ + +void lite_xl_plugin_init(void *XL); + +#endif /* LITE_XL_PLUGIN_ENTRYPOINT */ + +#undef LITE_XL_API +#undef SYMBOL_WRAP_DECL +#undef SYMBOL_WRAP_CALL +#undef SYMBOL_WRAP_CALL_FB +#undef SYMBOL_DECLARE +#undef SYMBOL_DECLARE_VARARG +#undef UNUSED +#undef CONCAT +#undef CONCAT1 +#undef CONCAT2 +#undef FE_1 +#undef FE_2 +#undef FE_3 +#undef FE_4 +#undef FE_5 +#undef FE_6 +#undef FE_7 +#undef FE_8 +#undef FOR_EACH_NARG +#undef FOR_EACH_NARG_ +#undef FOR_EACH_ARG_N +#undef FOR_EACH_RSEQ_N +#undef FOR_EACH_ +#undef FOR_EACH + +#endif /* LITE_XL_PLUGIN_API */ + +/****************************************************************************** +* Copyright (C) 1994-2023 Lua.org, PUC-Rio; Lite XL contributors. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ \ No newline at end of file diff --git a/resources/lite_xl_plugin_api.h b/resources/lite_xl_plugin_api.h deleted file mode 100644 index 8bf74054..00000000 --- a/resources/lite_xl_plugin_api.h +++ /dev/null @@ -1,1124 +0,0 @@ -#ifndef LITE_XL_PLUGIN_API -#define LITE_XL_PLUGIN_API -/** -The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long -as it has an entrypoint that looks like the following, where xxxxx is the plugin name: - -#define LITE_XL_PLUGIN_ENTRYPOINT -#include "lite_xl_plugin_api.h" -int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) { - lite_xl_plugin_init(XL); - ... - return 1; -} - -NOTE: `#define LITE_XL_PLUGIN_ENTRYPOINT` needs to be defined only on the -source file where the lite_xl_plugin_init() initialization function is called. - -In linux, to compile this file, you'd do: 'gcc -o xxxxx.so -shared xxxxx.c'. Simple! -Due to the way the API is structured, you *should not* link or include lua libraries. -This file was automatically generated. DO NOT MODIFY DIRECTLY. - -UNLESS you're us, and you had to modify this file manually to get it ready for 2.1. - -Go figure. - -**/ - - -#include -#include // for BUFSIZ? this is kinda weird -#include - -#define SYMBOL_WRAP_DECL(ret, name, ...) \ - ret name(__VA_ARGS__) - -#define SYMBOL_WRAP_CALL(name, ...) \ - return __##name(__VA_ARGS__) - -#define SYMBOL_WRAP_CALL_FB(name, ...) \ - return __lite_xl_fallback_##name(__VA_ARGS__) - -#ifdef LITE_XL_PLUGIN_ENTRYPOINT - #define SYMBOL_DECLARE(ret, name, ...) \ - static ret (*__##name) (__VA_ARGS__); \ - SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); \ - static ret __lite_xl_fallback_##name(__VA_ARGS__) { \ - fputs("warning: " #name " is a stub", stderr); \ - exit(1); \ - } -#else - #define SYMBOL_DECLARE(ret, name, ...) \ - SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); -#endif - -/** luaconf.h **/ - -#ifndef lconfig_h -#define lconfig_h -#include -#include -#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif -#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN -#endif -#if defined(LUA_WIN) -#define LUA_DL_DLL -#define LUA_USE_AFORMAT -#endif -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN -#define LUA_USE_READLINE -#define LUA_USE_STRTODHEX -#define LUA_USE_AFORMAT -#define LUA_USE_LONGLONG -#endif -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN -#define LUA_USE_READLINE -#define LUA_USE_STRTODHEX -#define LUA_USE_AFORMAT -#define LUA_USE_LONGLONG -#endif -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#define LUA_USE_GMTIME_R -#endif -#if defined(_WIN32) -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" -#define LUA_CPATH_DEFAULT LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" -#else -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR -#define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" -#define LUA_CPATH_DEFAULT LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif -#define LUA_ENV "_ENV" -#if defined(LUA_BUILD_AS_DLL) -#if defined(LUA_CORE) || defined(LUA_LIB) -#define LUA_API __declspec(dllexport) -#else -#define LUA_API __declspec(dllimport) -#endif -#else -#define LUA_API extern -#endif -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && defined(__ELF__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF -#else -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF -#endif -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") -#define LUA_IDSIZE 60 -#if defined(LUA_LIB) || defined(lua_c) -#include -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) -#endif -#define luai_writestringerror(s,p) (fprintf(stderr, (s), (p)), fflush(stderr)) -#define LUAI_MAXSHORTLEN 40 -#if defined(LUA_COMPAT_ALL) -#define LUA_COMPAT_UNPACK -#define LUA_COMPAT_LOADERS -#define lua_cpcall(L,f,u) (lua_pushcfunction(L, (f)), lua_pushlightuserdata(L,(u)), lua_pcall(L,1,0,0)) -#define LUA_COMPAT_LOG10 -#define LUA_COMPAT_LOADSTRING -#define LUA_COMPAT_MAXN -#define lua_strlen(L,i) lua_rawlen(L, (i)) -#define lua_objlen(L,i) lua_rawlen(L, (i)) -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) -#define LUA_COMPAT_MODULE -#endif -#if INT_MAX-20 < 32760 -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L -#define LUAI_BITSINT 32 -#else -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif -#if LUAI_BITSINT >= 32 -#define LUA_INT32 int -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else -#define LUA_INT32 long -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif -#if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) -#define LUAL_BUFFERSIZE BUFSIZ -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double -#define LUAI_UACNUMBER double -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 -#define l_mathop(x) (x) -#define lua_str2number(s,p) strtod((s), (p)) -#if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) -#endif -#if defined(lobject_c) || defined(lvm_c) -#include -#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) -#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) -#endif -#if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(L,a,b) ((a)<(b)) -#define luai_numle(L,a,b) ((a)<=(b)) -#define luai_numisnan(L,a) (!luai_numeq((a), (a))) -#endif -#define LUA_INTEGER ptrdiff_t -#define LUA_KCONTEXT ptrdiff_t -#define LUA_UNSIGNED unsigned LUA_INT32 -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK -#elif defined(__i386__) || defined(__i386) || defined(__X86__) -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK -#elif defined(__x86_64) -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 -#elif defined(__POWERPC__) || defined(__ppc__) -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 -#else -#define LUA_IEEE754TRICK -#endif -#endif -#endif - -/** lua.h **/ - -typedef struct lua_State lua_State; -typedef int (*lua_CFunction) (lua_State *L); -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); -typedef LUA_KCONTEXT lua_KContext; -typedef LUA_NUMBER lua_Number; -typedef LUA_INTEGER lua_Integer; -typedef LUA_UNSIGNED lua_Unsigned; -typedef struct lua_Debug lua_Debug; -typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); -struct lua_Debug { - int event; - const char *name; - const char *namewhat; - const char *what; - const char *source; - int currentline; - int linedefined; - int lastlinedefined; - unsigned char nups; - unsigned char nparams; - char isvararg; - char istailcall; - char short_src[LUA_IDSIZE]; - struct CallInfo *i_ci; -}; - -SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) -SYMBOL_DECLARE(void, lua_close, lua_State *L) -SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) -SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) -SYMBOL_DECLARE(const lua_Number *, lua_version, lua_State *L) -SYMBOL_DECLARE(int, lua_absindex, lua_State *L, int idx) -SYMBOL_DECLARE(int, lua_gettop, lua_State *L) -SYMBOL_DECLARE(void, lua_settop, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_pushvalue, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_copy, lua_State *L, int fromidx, int toidx) -SYMBOL_DECLARE(int, lua_checkstack, lua_State *L, int sz) -SYMBOL_DECLARE(void, lua_xmove, lua_State *from, lua_State *to, int n) -SYMBOL_DECLARE(int, lua_isnumber, lua_State *L, int idx) -SYMBOL_DECLARE(int, lua_isstring, lua_State *L, int idx) -SYMBOL_DECLARE(int, lua_iscfunction, lua_State *L, int idx) -SYMBOL_DECLARE(int, lua_isuserdata, lua_State *L, int idx) -SYMBOL_DECLARE(int, lua_type, lua_State *L, int idx) -SYMBOL_DECLARE(const char *, lua_typename, lua_State *L, int tp) -SYMBOL_DECLARE(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum) -SYMBOL_DECLARE(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum) -SYMBOL_DECLARE(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum) -SYMBOL_DECLARE(int, lua_toboolean, lua_State *L, int idx) -SYMBOL_DECLARE(const char *, lua_tolstring, lua_State *L, int idx, size_t *len) -SYMBOL_DECLARE(size_t, lua_rawlen, lua_State *L, int idx) -SYMBOL_DECLARE(lua_CFunction, lua_tocfunction, lua_State *L, int idx) -SYMBOL_DECLARE(void *, lua_touserdata, lua_State *L, int idx) -SYMBOL_DECLARE(lua_State *, lua_tothread, lua_State *L, int idx) -SYMBOL_DECLARE(const void *, lua_topointer, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_arith, lua_State *L, int op) -SYMBOL_DECLARE(int, lua_rawequal, lua_State *L, int idx1, int idx2) -SYMBOL_DECLARE(int, lua_compare, lua_State *L, int idx1, int idx2, int op) -SYMBOL_DECLARE(void, lua_pushnil, lua_State *L) -SYMBOL_DECLARE(void, lua_pushnumber, lua_State *L, lua_Number n) -SYMBOL_DECLARE(void, lua_pushinteger, lua_State *L, lua_Integer n) -SYMBOL_DECLARE(void, lua_pushunsigned, lua_State *L, lua_Unsigned n) -SYMBOL_DECLARE(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l) -SYMBOL_DECLARE(const char *, lua_pushstring, lua_State *L, const char *s) -SYMBOL_DECLARE(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp) -SYMBOL_DECLARE(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...) -SYMBOL_DECLARE(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n) -SYMBOL_DECLARE(void, lua_pushboolean, lua_State *L, int b) -SYMBOL_DECLARE(void, lua_pushlightuserdata, lua_State *L, void *p) -SYMBOL_DECLARE(int, lua_pushthread, lua_State *L) -SYMBOL_DECLARE(void, lua_getglobal, lua_State *L, const char *var) -SYMBOL_DECLARE(void, lua_gettable, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_getfield, lua_State *L, int idx, const char *k) -SYMBOL_DECLARE(void, lua_rawget, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_rawgeti, lua_State *L, int idx, int n) -SYMBOL_DECLARE(void, lua_rawgetp, lua_State *L, int idx, const void *p) -SYMBOL_DECLARE(void, lua_createtable, lua_State *L, int narr, int nrec) -SYMBOL_DECLARE(void *, lua_newuserdata, lua_State *L, size_t sz) -SYMBOL_DECLARE(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue) -SYMBOL_DECLARE(int, lua_getmetatable, lua_State *L, int objindex) -SYMBOL_DECLARE(void, lua_getuservalue, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_getiuservalue, lua_State *L, int idx, int n) -SYMBOL_DECLARE(void, lua_setglobal, lua_State *L, const char *var) -SYMBOL_DECLARE(void, lua_settable, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_setfield, lua_State *L, int idx, const char *k) -SYMBOL_DECLARE(void, lua_rawset, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_rawseti, lua_State *L, int idx, int n) -SYMBOL_DECLARE(void, lua_rawsetp, lua_State *L, int idx, const void *p) -SYMBOL_DECLARE(int, lua_setmetatable, lua_State *L, int objindex) -SYMBOL_DECLARE(void, lua_setuservalue, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_setiuservalue, lua_State *L, int idx, int n) -SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) -SYMBOL_DECLARE(int, lua_getctx, lua_State *L, int *ctx) -SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) -SYMBOL_DECLARE(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) -SYMBOL_DECLARE(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) -SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k) -SYMBOL_DECLARE(int, lua_resume, lua_State *L, lua_State *from, int narg) -SYMBOL_DECLARE(int, lua_status, lua_State *L) -SYMBOL_DECLARE(int, lua_gc, lua_State *L, int what, int data) -SYMBOL_DECLARE(int, lua_error, lua_State *L) -SYMBOL_DECLARE(int, lua_next, lua_State *L, int idx) -SYMBOL_DECLARE(void, lua_concat, lua_State *L, int n) -SYMBOL_DECLARE(void, lua_len, lua_State *L, int idx) -SYMBOL_DECLARE(lua_Alloc, lua_getallocf, lua_State *L, void **ud) -SYMBOL_DECLARE(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud) -SYMBOL_DECLARE(int, lua_getstack, lua_State *L, int level, lua_Debug *ar) -SYMBOL_DECLARE(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar) -SYMBOL_DECLARE(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n) -SYMBOL_DECLARE(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n) -SYMBOL_DECLARE(const char *, lua_getupvalue, lua_State *L, int funcindex, int n) -SYMBOL_DECLARE(const char *, lua_setupvalue, lua_State *L, int funcindex, int n) -SYMBOL_DECLARE(void *, lua_upvalueid, lua_State *L, int fidx, int n) -SYMBOL_DECLARE(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2) -SYMBOL_DECLARE(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count) -SYMBOL_DECLARE(lua_Hook, lua_gethook, lua_State *L) -SYMBOL_DECLARE(int, lua_gethookmask, lua_State *L) -SYMBOL_DECLARE(int, lua_gethookcount, lua_State *L) - -#define lua_h -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "4" -#define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE "4" -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" -#define LUA_SIGNATURE "\033Lua" -#define LUA_MULTRET (-1) -#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRGCMM 5 -#define LUA_ERRERR 6 -#define LUA_TNONE (-1) -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 -#define LUA_NUMTAGS 9 -#define LUA_MINSTACK 20 -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS -#define LUA_OPADD 0 -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCSETMAJORINC 8 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 -#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) -#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) -#define lua_pop(L,n) lua_settop(L, -(n)-1) -#define lua_newtable(L) lua_createtable(L, 0, 0) -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -#define lua_pushliteral(L, s) lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) -#define lua_pushglobaltable(L) lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) -#define lua_insert(L,idx) lua_rotate(L, (idx), 1) -#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) -#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILCALL 4 -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -/** lauxlib.h **/ - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; -typedef struct luaL_Buffer { - char *b; - size_t size; - size_t n; - lua_State *L; - char initb[LUAL_BUFFERSIZE]; -} luaL_Buffer; -typedef struct luaL_Stream { - FILE *f; - lua_CFunction closef; -} luaL_Stream; - -SYMBOL_DECLARE(void, luaL_checkversion_, lua_State *L, lua_Number ver) -SYMBOL_DECLARE(int, luaL_getmetafield, lua_State *L, int obj, const char *e) -SYMBOL_DECLARE(int, luaL_callmeta, lua_State *L, int obj, const char *e) -SYMBOL_DECLARE(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len) -SYMBOL_DECLARE(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg) -SYMBOL_DECLARE(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l) -SYMBOL_DECLARE(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l) -SYMBOL_DECLARE(lua_Number, luaL_checknumber, lua_State *L, int numArg) -SYMBOL_DECLARE(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def) -SYMBOL_DECLARE(lua_Integer, luaL_checkinteger, lua_State *L, int numArg) -SYMBOL_DECLARE(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def) -SYMBOL_DECLARE(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg) -SYMBOL_DECLARE(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def) -SYMBOL_DECLARE(void, luaL_checkstack, lua_State *L, int sz, const char *msg) -SYMBOL_DECLARE(void, luaL_checktype, lua_State *L, int narg, int t) -SYMBOL_DECLARE(void, luaL_checkany, lua_State *L, int narg) -SYMBOL_DECLARE(int, luaL_newmetatable, lua_State *L, const char *tname) -SYMBOL_DECLARE(void, luaL_setmetatable, lua_State *L, const char *tname) -SYMBOL_DECLARE(void *, luaL_testudata, lua_State *L, int ud, const char *tname) -SYMBOL_DECLARE(void *, luaL_checkudata, lua_State *L, int ud, const char *tname) -SYMBOL_DECLARE(void, luaL_where, lua_State *L, int lvl) -SYMBOL_DECLARE(int, luaL_error, lua_State *L, const char *fmt, ...) -SYMBOL_DECLARE(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]) -SYMBOL_DECLARE(int, luaL_fileresult, lua_State *L, int stat, const char *fname) -SYMBOL_DECLARE(int, luaL_execresult, lua_State *L, int stat) -SYMBOL_DECLARE(int, luaL_ref, lua_State *L, int t) -SYMBOL_DECLARE(void, luaL_unref, lua_State *L, int t, int ref) -SYMBOL_DECLARE(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode) -SYMBOL_DECLARE(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) -SYMBOL_DECLARE(int, luaL_loadstring, lua_State *L, const char *s) -SYMBOL_DECLARE(lua_State *, luaL_newstate, void) -SYMBOL_DECLARE(int, luaL_len, lua_State *L, int idx) -SYMBOL_DECLARE(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r) -SYMBOL_DECLARE(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup) -SYMBOL_DECLARE(int, luaL_getsubtable, lua_State *L, int idx, const char *fname) -SYMBOL_DECLARE(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level) -SYMBOL_DECLARE(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb) -SYMBOL_DECLARE(void, luaL_buffinit, lua_State *L, luaL_Buffer *B) -SYMBOL_DECLARE(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz) -SYMBOL_DECLARE(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l) -SYMBOL_DECLARE(void, luaL_addstring, luaL_Buffer *B, const char *s) -SYMBOL_DECLARE(void, luaL_addvalue, luaL_Buffer *B) -SYMBOL_DECLARE(void, luaL_pushresult, luaL_Buffer *B) -SYMBOL_DECLARE(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz) -SYMBOL_DECLARE(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz) -SYMBOL_DECLARE(void, luaL_openlibs, lua_State *L) - -#define lauxlib_h -#define LUA_ERRFILE (LUA_ERRERR+1) -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) -#define luaL_newlibtable(L,l) lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) -#define luaL_argcheck(L, cond,numarg,extramsg) ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) -#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) -#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) -#define luaL_addchar(B,c) ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), ((B)->b[(B)->n++] = (c))) -#define luaL_addsize(B,s) ((B)->n += (s)) -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) -#define LUA_FILEHANDLE "FILE*" - -#ifdef LITE_XL_PLUGIN_ENTRYPOINT - -SYMBOL_WRAP_DECL(lua_State *, lua_newstate, lua_Alloc f, void *ud){ - SYMBOL_WRAP_CALL(lua_newstate, f, ud); -} -SYMBOL_WRAP_DECL(void, lua_close, lua_State *L){ - SYMBOL_WRAP_CALL(lua_close, L); -} -SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L){ - SYMBOL_WRAP_CALL(lua_newthread, L); -} -SYMBOL_WRAP_DECL(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf){ - SYMBOL_WRAP_CALL(lua_atpanic, L, panicf); -} -SYMBOL_WRAP_DECL(const lua_Number *, lua_version, lua_State *L){ - SYMBOL_WRAP_CALL(lua_version, L); -} -SYMBOL_WRAP_DECL(int, lua_absindex, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_absindex, L, idx); -} -SYMBOL_WRAP_DECL(int, lua_gettop, lua_State *L){ - SYMBOL_WRAP_CALL(lua_gettop, L); -} -SYMBOL_WRAP_DECL(void, lua_settop, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_settop, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_pushvalue, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_pushvalue, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_copy, lua_State *L, int fromidx, int toidx){ - SYMBOL_WRAP_CALL(lua_copy, L, fromidx, toidx); -} -SYMBOL_WRAP_DECL(int, lua_checkstack, lua_State *L, int sz){ - SYMBOL_WRAP_CALL(lua_checkstack, L, sz); -} -SYMBOL_WRAP_DECL(void, lua_xmove, lua_State *from, lua_State *to, int n){ - SYMBOL_WRAP_CALL(lua_xmove, from, to, n); -} -SYMBOL_WRAP_DECL(int, lua_isnumber, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_isnumber, L, idx); -} -SYMBOL_WRAP_DECL(int, lua_isstring, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_isstring, L, idx); -} -SYMBOL_WRAP_DECL(int, lua_iscfunction, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_iscfunction, L, idx); -} -SYMBOL_WRAP_DECL(int, lua_isuserdata, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_isuserdata, L, idx); -} -SYMBOL_WRAP_DECL(int, lua_type, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_type, L, idx); -} -SYMBOL_WRAP_DECL(const char *, lua_typename, lua_State *L, int tp){ - SYMBOL_WRAP_CALL(lua_typename, L, tp); -} -SYMBOL_WRAP_DECL(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum){ - SYMBOL_WRAP_CALL(lua_tonumberx, L, idx, isnum); -} -SYMBOL_WRAP_DECL(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum){ - SYMBOL_WRAP_CALL(lua_tointegerx, L, idx, isnum); -} -SYMBOL_WRAP_DECL(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum){ - SYMBOL_WRAP_CALL(lua_tounsignedx, L, idx, isnum); -} -SYMBOL_WRAP_DECL(int, lua_toboolean, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_toboolean, L, idx); -} -SYMBOL_WRAP_DECL(const char *, lua_tolstring, lua_State *L, int idx, size_t *len){ - SYMBOL_WRAP_CALL(lua_tolstring, L, idx, len); -} -SYMBOL_WRAP_DECL(size_t, lua_rawlen, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_rawlen, L, idx); -} -SYMBOL_WRAP_DECL(lua_CFunction, lua_tocfunction, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_tocfunction, L, idx); -} -SYMBOL_WRAP_DECL(void *, lua_touserdata, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_touserdata, L, idx); -} -SYMBOL_WRAP_DECL(lua_State *, lua_tothread, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_tothread, L, idx); -} -SYMBOL_WRAP_DECL(const void *, lua_topointer, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_topointer, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_arith, lua_State *L, int op){ - SYMBOL_WRAP_CALL(lua_arith, L, op); -} -SYMBOL_WRAP_DECL(int, lua_rawequal, lua_State *L, int idx1, int idx2){ - SYMBOL_WRAP_CALL(lua_rawequal, L, idx1, idx2); -} -SYMBOL_WRAP_DECL(int, lua_compare, lua_State *L, int idx1, int idx2, int op){ - SYMBOL_WRAP_CALL(lua_compare, L, idx1, idx2, op); -} -SYMBOL_WRAP_DECL(void, lua_pushnil, lua_State *L){ - SYMBOL_WRAP_CALL(lua_pushnil, L); -} -SYMBOL_WRAP_DECL(void, lua_pushnumber, lua_State *L, lua_Number n){ - SYMBOL_WRAP_CALL(lua_pushnumber, L, n); -} -SYMBOL_WRAP_DECL(void, lua_pushinteger, lua_State *L, lua_Integer n){ - SYMBOL_WRAP_CALL(lua_pushinteger, L, n); -} -SYMBOL_WRAP_DECL(void, lua_pushunsigned, lua_State *L, lua_Unsigned n){ - SYMBOL_WRAP_CALL(lua_pushunsigned, L, n); -} -SYMBOL_WRAP_DECL(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l){ - SYMBOL_WRAP_CALL(lua_pushlstring, L, s, l); -} -SYMBOL_WRAP_DECL(const char *, lua_pushstring, lua_State *L, const char *s){ - SYMBOL_WRAP_CALL(lua_pushstring, L, s); -} -SYMBOL_WRAP_DECL(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp){ - SYMBOL_WRAP_CALL(lua_pushvfstring, L, fmt, argp); -} -SYMBOL_WRAP_DECL(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...){ - SYMBOL_WRAP_CALL(lua_pushfstring, L, fmt); -} -SYMBOL_WRAP_DECL(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n){ - SYMBOL_WRAP_CALL(lua_pushcclosure, L, fn, n); -} -SYMBOL_WRAP_DECL(void, lua_pushboolean, lua_State *L, int b){ - SYMBOL_WRAP_CALL(lua_pushboolean, L, b); -} -SYMBOL_WRAP_DECL(void, lua_pushlightuserdata, lua_State *L, void *p){ - SYMBOL_WRAP_CALL(lua_pushlightuserdata, L, p); -} -SYMBOL_WRAP_DECL(int, lua_pushthread, lua_State *L){ - SYMBOL_WRAP_CALL(lua_pushthread, L); -} -SYMBOL_WRAP_DECL(void, lua_getglobal, lua_State *L, const char *var){ - SYMBOL_WRAP_CALL(lua_getglobal, L, var); -} -SYMBOL_WRAP_DECL(void, lua_gettable, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_gettable, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_getfield, lua_State *L, int idx, const char *k){ - SYMBOL_WRAP_CALL(lua_getfield, L, idx, k); -} -SYMBOL_WRAP_DECL(void, lua_rawget, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_rawget, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_rawgeti, lua_State *L, int idx, int n){ - SYMBOL_WRAP_CALL(lua_rawgeti, L, idx, n); -} -SYMBOL_WRAP_DECL(void, lua_rawgetp, lua_State *L, int idx, const void *p){ - SYMBOL_WRAP_CALL(lua_rawgetp, L, idx, p); -} -SYMBOL_WRAP_DECL(void, lua_createtable, lua_State *L, int narr, int nrec){ - SYMBOL_WRAP_CALL(lua_createtable, L, narr, nrec); -} -SYMBOL_WRAP_DECL(void *, lua_newuserdata, lua_State *L, size_t sz){ - if (__lua_newuserdatauv != NULL) { - return lua_newuserdatauv(L, sz, 1); - } else if (__lua_newuserdata != NULL) { - SYMBOL_WRAP_CALL(lua_newuserdata, L, sz); - } - SYMBOL_WRAP_CALL_FB(lua_newuserdata, L, sz); -} -SYMBOL_WRAP_DECL(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue){ - SYMBOL_WRAP_CALL(lua_newuserdatauv, L, sz, nuvalue); -} -SYMBOL_WRAP_DECL(int, lua_getmetatable, lua_State *L, int objindex){ - SYMBOL_WRAP_CALL(lua_getmetatable, L, objindex); -} -SYMBOL_WRAP_DECL(void, lua_getuservalue, lua_State *L, int idx){ - if (__lua_getiuservalue != NULL) { - return lua_getiuservalue(L, idx, 1); - } else if (__lua_getuservalue != NULL) { - SYMBOL_WRAP_CALL(lua_getuservalue, L, idx); - } - SYMBOL_WRAP_CALL_FB(lua_getuservalue, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_getiuservalue, lua_State *L, int idx, int n){ - SYMBOL_WRAP_CALL(lua_getiuservalue, L, idx, n); -} -SYMBOL_WRAP_DECL(void, lua_setglobal, lua_State *L, const char *var){ - SYMBOL_WRAP_CALL(lua_setglobal, L, var); -} -SYMBOL_WRAP_DECL(void, lua_settable, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_settable, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_setfield, lua_State *L, int idx, const char *k){ - SYMBOL_WRAP_CALL(lua_setfield, L, idx, k); -} -SYMBOL_WRAP_DECL(void, lua_rawset, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_rawset, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_rawseti, lua_State *L, int idx, int n){ - SYMBOL_WRAP_CALL(lua_rawseti, L, idx, n); -} -SYMBOL_WRAP_DECL(void, lua_rawsetp, lua_State *L, int idx, const void *p){ - SYMBOL_WRAP_CALL(lua_rawsetp, L, idx, p); -} -SYMBOL_WRAP_DECL(int, lua_setmetatable, lua_State *L, int objindex){ - SYMBOL_WRAP_CALL(lua_setmetatable, L, objindex); -} -SYMBOL_WRAP_DECL(void, lua_setuservalue, lua_State *L, int idx){ - if (__lua_setiuservalue != NULL) { - return lua_setiuservalue(L, idx, 1); - } else if (__lua_setuservalue != NULL) { - SYMBOL_WRAP_CALL(lua_setuservalue, L, idx); - } - SYMBOL_WRAP_CALL_FB(lua_setuservalue, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_setiuservalue, lua_State *L, int idx, int n){ - SYMBOL_WRAP_CALL(lua_setiuservalue, L, idx, n); -} -SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k){ - SYMBOL_WRAP_CALL(lua_callk, L, nargs, nresults, ctx, k); -} -SYMBOL_WRAP_DECL(int, lua_getctx, lua_State *L, int *ctx){ - SYMBOL_WRAP_CALL(lua_getctx, L, ctx); -} -SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k){ - SYMBOL_WRAP_CALL(lua_pcallk, L, nargs, nresults, errfunc, ctx, k); -} -SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode){ - SYMBOL_WRAP_CALL(lua_load, L, reader, dt, chunkname, mode); -} -SYMBOL_WRAP_DECL(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip){ - SYMBOL_WRAP_CALL(lua_dump, L, writer, data, strip); -} -SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k){ - SYMBOL_WRAP_CALL(lua_yieldk, L, nresults, ctx, k); -} -SYMBOL_WRAP_DECL(int, lua_resume, lua_State *L, lua_State *from, int narg){ - SYMBOL_WRAP_CALL(lua_resume, L, from, narg); -} -SYMBOL_WRAP_DECL(int, lua_status, lua_State *L){ - SYMBOL_WRAP_CALL(lua_status, L); -} -SYMBOL_WRAP_DECL(int, lua_gc, lua_State *L, int what, int data){ - SYMBOL_WRAP_CALL(lua_gc, L, what, data); -} -SYMBOL_WRAP_DECL(int, lua_error, lua_State *L){ - SYMBOL_WRAP_CALL(lua_error, L); -} -SYMBOL_WRAP_DECL(int, lua_next, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_next, L, idx); -} -SYMBOL_WRAP_DECL(void, lua_concat, lua_State *L, int n){ - SYMBOL_WRAP_CALL(lua_concat, L, n); -} -SYMBOL_WRAP_DECL(void, lua_len, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(lua_len, L, idx); -} -SYMBOL_WRAP_DECL(lua_Alloc, lua_getallocf, lua_State *L, void **ud){ - SYMBOL_WRAP_CALL(lua_getallocf, L, ud); -} -SYMBOL_WRAP_DECL(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud){ - SYMBOL_WRAP_CALL(lua_setallocf, L, f, ud); -} -SYMBOL_WRAP_DECL(int, lua_getstack, lua_State *L, int level, lua_Debug *ar){ - SYMBOL_WRAP_CALL(lua_getstack, L, level, ar); -} -SYMBOL_WRAP_DECL(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar){ - SYMBOL_WRAP_CALL(lua_getinfo, L, what, ar); -} -SYMBOL_WRAP_DECL(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n){ - SYMBOL_WRAP_CALL(lua_getlocal, L, ar, n); -} -SYMBOL_WRAP_DECL(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n){ - SYMBOL_WRAP_CALL(lua_setlocal, L, ar, n); -} -SYMBOL_WRAP_DECL(const char *, lua_getupvalue, lua_State *L, int funcindex, int n){ - SYMBOL_WRAP_CALL(lua_getupvalue, L, funcindex, n); -} -SYMBOL_WRAP_DECL(const char *, lua_setupvalue, lua_State *L, int funcindex, int n){ - SYMBOL_WRAP_CALL(lua_setupvalue, L, funcindex, n); -} -SYMBOL_WRAP_DECL(void *, lua_upvalueid, lua_State *L, int fidx, int n){ - SYMBOL_WRAP_CALL(lua_upvalueid, L, fidx, n); -} -SYMBOL_WRAP_DECL(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2){ - SYMBOL_WRAP_CALL(lua_upvaluejoin, L, fidx1, n1, fidx2, n2); -} -SYMBOL_WRAP_DECL(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count){ - SYMBOL_WRAP_CALL(lua_sethook, L, func, mask, count); -} -SYMBOL_WRAP_DECL(lua_Hook, lua_gethook, lua_State *L){ - SYMBOL_WRAP_CALL(lua_gethook, L); -} -SYMBOL_WRAP_DECL(int, lua_gethookmask, lua_State *L){ - SYMBOL_WRAP_CALL(lua_gethookmask, L); -} -SYMBOL_WRAP_DECL(int, lua_gethookcount, lua_State *L){ - SYMBOL_WRAP_CALL(lua_gethookcount, L); -} -SYMBOL_WRAP_DECL(void, luaL_checkversion_, lua_State *L, lua_Number ver){ - SYMBOL_WRAP_CALL(luaL_checkversion_, L, ver); -} -SYMBOL_WRAP_DECL(int, luaL_getmetafield, lua_State *L, int obj, const char *e){ - SYMBOL_WRAP_CALL(luaL_getmetafield, L, obj, e); -} -SYMBOL_WRAP_DECL(int, luaL_callmeta, lua_State *L, int obj, const char *e){ - SYMBOL_WRAP_CALL(luaL_callmeta, L, obj, e); -} -SYMBOL_WRAP_DECL(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len){ - SYMBOL_WRAP_CALL(luaL_tolstring, L, idx, len); -} -SYMBOL_WRAP_DECL(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg){ - SYMBOL_WRAP_CALL(luaL_argerror, L, numarg, extramsg); -} -SYMBOL_WRAP_DECL(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l){ - SYMBOL_WRAP_CALL(luaL_checklstring, L, numArg, l); -} -SYMBOL_WRAP_DECL(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l){ - SYMBOL_WRAP_CALL(luaL_optlstring, L, numArg, def, l); -} -SYMBOL_WRAP_DECL(lua_Number, luaL_checknumber, lua_State *L, int numArg){ - SYMBOL_WRAP_CALL(luaL_checknumber, L, numArg); -} -SYMBOL_WRAP_DECL(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def){ - SYMBOL_WRAP_CALL(luaL_optnumber, L, nArg, def); -} -SYMBOL_WRAP_DECL(lua_Integer, luaL_checkinteger, lua_State *L, int numArg){ - SYMBOL_WRAP_CALL(luaL_checkinteger, L, numArg); -} -SYMBOL_WRAP_DECL(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def){ - SYMBOL_WRAP_CALL(luaL_optinteger, L, nArg, def); -} -SYMBOL_WRAP_DECL(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg){ - SYMBOL_WRAP_CALL(luaL_checkunsigned, L, numArg); -} -SYMBOL_WRAP_DECL(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def){ - SYMBOL_WRAP_CALL(luaL_optunsigned, L, numArg, def); -} -SYMBOL_WRAP_DECL(void, luaL_checkstack, lua_State *L, int sz, const char *msg){ - SYMBOL_WRAP_CALL(luaL_checkstack, L, sz, msg); -} -SYMBOL_WRAP_DECL(void, luaL_checktype, lua_State *L, int narg, int t){ - SYMBOL_WRAP_CALL(luaL_checktype, L, narg, t); -} -SYMBOL_WRAP_DECL(void, luaL_checkany, lua_State *L, int narg){ - SYMBOL_WRAP_CALL(luaL_checkany, L, narg); -} -SYMBOL_WRAP_DECL(int, luaL_newmetatable, lua_State *L, const char *tname){ - SYMBOL_WRAP_CALL(luaL_newmetatable, L, tname); -} -SYMBOL_WRAP_DECL(void, luaL_setmetatable, lua_State *L, const char *tname){ - SYMBOL_WRAP_CALL(luaL_setmetatable, L, tname); -} -SYMBOL_WRAP_DECL(void *, luaL_testudata, lua_State *L, int ud, const char *tname){ - SYMBOL_WRAP_CALL(luaL_testudata, L, ud, tname); -} -SYMBOL_WRAP_DECL(void *, luaL_checkudata, lua_State *L, int ud, const char *tname){ - SYMBOL_WRAP_CALL(luaL_checkudata, L, ud, tname); -} -SYMBOL_WRAP_DECL(void, luaL_where, lua_State *L, int lvl){ - SYMBOL_WRAP_CALL(luaL_where, L, lvl); -} -SYMBOL_WRAP_DECL(int, luaL_error, lua_State *L, const char *fmt, ...){ - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} -SYMBOL_WRAP_DECL(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]){ - SYMBOL_WRAP_CALL(luaL_checkoption, L, narg, def, lst); -} -SYMBOL_WRAP_DECL(int, luaL_fileresult, lua_State *L, int stat, const char *fname){ - SYMBOL_WRAP_CALL(luaL_fileresult, L, stat, fname); -} -SYMBOL_WRAP_DECL(int, luaL_execresult, lua_State *L, int stat){ - SYMBOL_WRAP_CALL(luaL_execresult, L, stat); -} -SYMBOL_WRAP_DECL(int, luaL_ref, lua_State *L, int t){ - SYMBOL_WRAP_CALL(luaL_ref, L, t); -} -SYMBOL_WRAP_DECL(void, luaL_unref, lua_State *L, int t, int ref){ - SYMBOL_WRAP_CALL(luaL_unref, L, t, ref); -} -SYMBOL_WRAP_DECL(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode){ - SYMBOL_WRAP_CALL(luaL_loadfilex, L, filename, mode); -} -SYMBOL_WRAP_DECL(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode){ - SYMBOL_WRAP_CALL(luaL_loadbufferx, L, buff, sz, name, mode); -} -SYMBOL_WRAP_DECL(int, luaL_loadstring, lua_State *L, const char *s){ - SYMBOL_WRAP_CALL(luaL_loadstring, L, s); -} -SYMBOL_WRAP_DECL(lua_State *, luaL_newstate, void){ - return __luaL_newstate(); -} -SYMBOL_WRAP_DECL(int, luaL_len, lua_State *L, int idx){ - SYMBOL_WRAP_CALL(luaL_len, L, idx); -} -SYMBOL_WRAP_DECL(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r){ - SYMBOL_WRAP_CALL(luaL_gsub, L, s, p, r); -} -SYMBOL_WRAP_DECL(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup){ - SYMBOL_WRAP_CALL(luaL_setfuncs, L, l, nup); -} -SYMBOL_WRAP_DECL(int, luaL_getsubtable, lua_State *L, int idx, const char *fname){ - SYMBOL_WRAP_CALL(luaL_getsubtable, L, idx, fname); -} -SYMBOL_WRAP_DECL(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level){ - SYMBOL_WRAP_CALL(luaL_traceback, L, L1, msg, level); -} -SYMBOL_WRAP_DECL(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb){ - SYMBOL_WRAP_CALL(luaL_requiref, L, modname, openf, glb); -} -SYMBOL_WRAP_DECL(void, luaL_buffinit, lua_State *L, luaL_Buffer *B){ - SYMBOL_WRAP_CALL(luaL_buffinit, L, B); -} -SYMBOL_WRAP_DECL(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz){ - SYMBOL_WRAP_CALL(luaL_prepbuffsize, B, sz); -} -SYMBOL_WRAP_DECL(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l){ - SYMBOL_WRAP_CALL(luaL_addlstring, B, s, l); -} -SYMBOL_WRAP_DECL(void, luaL_addstring, luaL_Buffer *B, const char *s){ - SYMBOL_WRAP_CALL(luaL_addstring, B, s); -} -SYMBOL_WRAP_DECL(void, luaL_addvalue, luaL_Buffer *B){ - SYMBOL_WRAP_CALL(luaL_addvalue, B); -} -SYMBOL_WRAP_DECL(void, luaL_pushresult, luaL_Buffer *B){ - SYMBOL_WRAP_CALL(luaL_pushresult, B); -} -SYMBOL_WRAP_DECL(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz){ - SYMBOL_WRAP_CALL(luaL_pushresultsize, B, sz); -} -SYMBOL_WRAP_DECL(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz){ - SYMBOL_WRAP_CALL(luaL_buffinitsize, L, B, sz); -} -SYMBOL_WRAP_DECL(void, luaL_openlibs, lua_State *L){ - SYMBOL_WRAP_CALL(luaL_openlibs, L); -} - -#define IMPORT_SYMBOL(name, ret, ...) \ - __##name = (\ - __##name = (ret (*) (__VA_ARGS__)) symbol(#name), \ - __##name == NULL ? &__lite_xl_fallback_##name : __##name\ - ) - -#define IMPORT_SYMBOL_OPT(name, ret, ...) \ - __##name = symbol(#name) - -static void lite_xl_plugin_init(void *XL) { - void* (*symbol)(const char *) = (void* (*) (const char *)) XL; - IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); - IMPORT_SYMBOL(lua_close, void , lua_State *L); - IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); - IMPORT_SYMBOL(lua_atpanic, lua_CFunction , lua_State *L, lua_CFunction panicf); - IMPORT_SYMBOL(lua_version, const lua_Number *, lua_State *L); - IMPORT_SYMBOL(lua_absindex, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_gettop, int , lua_State *L); - IMPORT_SYMBOL(lua_settop, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_pushvalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_copy, void , lua_State *L, int fromidx, int toidx); - IMPORT_SYMBOL(lua_checkstack, int , lua_State *L, int sz); - IMPORT_SYMBOL(lua_xmove, void , lua_State *from, lua_State *to, int n); - IMPORT_SYMBOL(lua_isnumber, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_isstring, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_iscfunction, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_isuserdata, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_type, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_typename, const char *, lua_State *L, int tp); - IMPORT_SYMBOL(lua_tonumberx, lua_Number , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_tointegerx, lua_Integer , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_tounsignedx, lua_Unsigned , lua_State *L, int idx, int *isnum); - IMPORT_SYMBOL(lua_toboolean, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_tolstring, const char *, lua_State *L, int idx, size_t *len); - IMPORT_SYMBOL(lua_rawlen, size_t , lua_State *L, int idx); - IMPORT_SYMBOL(lua_tocfunction, lua_CFunction , lua_State *L, int idx); - IMPORT_SYMBOL(lua_touserdata, void *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_tothread, lua_State *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_topointer, const void *, lua_State *L, int idx); - IMPORT_SYMBOL(lua_arith, void , lua_State *L, int op); - IMPORT_SYMBOL(lua_rawequal, int , lua_State *L, int idx1, int idx2); - IMPORT_SYMBOL(lua_compare, int , lua_State *L, int idx1, int idx2, int op); - IMPORT_SYMBOL(lua_pushnil, void , lua_State *L); - IMPORT_SYMBOL(lua_pushnumber, void , lua_State *L, lua_Number n); - IMPORT_SYMBOL(lua_pushinteger, void , lua_State *L, lua_Integer n); - IMPORT_SYMBOL(lua_pushunsigned, void , lua_State *L, lua_Unsigned n); - IMPORT_SYMBOL(lua_pushlstring, const char *, lua_State *L, const char *s, size_t l); - IMPORT_SYMBOL(lua_pushstring, const char *, lua_State *L, const char *s); - IMPORT_SYMBOL(lua_pushvfstring, const char *, lua_State *L, const char *fmt, va_list argp); - IMPORT_SYMBOL(lua_pushfstring, const char *, lua_State *L, const char *fmt, ...); - IMPORT_SYMBOL(lua_pushcclosure, void , lua_State *L, lua_CFunction fn, int n); - IMPORT_SYMBOL(lua_pushboolean, void , lua_State *L, int b); - IMPORT_SYMBOL(lua_pushlightuserdata, void , lua_State *L, void *p); - IMPORT_SYMBOL(lua_pushthread, int , lua_State *L); - IMPORT_SYMBOL(lua_getglobal, void , lua_State *L, const char *var); - IMPORT_SYMBOL(lua_gettable, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getfield, void , lua_State *L, int idx, const char *k); - IMPORT_SYMBOL(lua_rawget, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_rawgeti, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_rawgetp, void , lua_State *L, int idx, const void *p); - IMPORT_SYMBOL(lua_createtable, void , lua_State *L, int narr, int nrec); - IMPORT_SYMBOL_OPT(lua_newuserdata, void *, lua_State *L, size_t sz); - IMPORT_SYMBOL(lua_newuserdatauv, void *, lua_State *L, size_t sz, int nuvalue); - IMPORT_SYMBOL(lua_getmetatable, int , lua_State *L, int objindex); - IMPORT_SYMBOL_OPT(lua_getuservalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getiuservalue, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_setglobal, void , lua_State *L, const char *var); - IMPORT_SYMBOL(lua_settable, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_setfield, void , lua_State *L, int idx, const char *k); - IMPORT_SYMBOL(lua_rawset, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_rawseti, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_rawsetp, void , lua_State *L, int idx, const void *p); - IMPORT_SYMBOL(lua_setmetatable, int , lua_State *L, int objindex); - IMPORT_SYMBOL_OPT(lua_setuservalue, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_setiuservalue, void , lua_State *L, int idx, int n); - IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k); - IMPORT_SYMBOL(lua_getctx, int , lua_State *L, int *ctx); - IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k); - IMPORT_SYMBOL(lua_load, int , lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); - IMPORT_SYMBOL(lua_dump, int , lua_State *L, lua_Writer writer, void *data, int strip); - IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, lua_KContext ctx, lua_KFunction k); - IMPORT_SYMBOL(lua_resume, int , lua_State *L, lua_State *from, int narg); - IMPORT_SYMBOL(lua_status, int , lua_State *L); - IMPORT_SYMBOL(lua_gc, int , lua_State *L, int what, int data); - IMPORT_SYMBOL(lua_error, int , lua_State *L); - IMPORT_SYMBOL(lua_next, int , lua_State *L, int idx); - IMPORT_SYMBOL(lua_concat, void , lua_State *L, int n); - IMPORT_SYMBOL(lua_len, void , lua_State *L, int idx); - IMPORT_SYMBOL(lua_getallocf, lua_Alloc , lua_State *L, void **ud); - IMPORT_SYMBOL(lua_setallocf, void , lua_State *L, lua_Alloc f, void *ud); - IMPORT_SYMBOL(lua_getstack, int , lua_State *L, int level, lua_Debug *ar); - IMPORT_SYMBOL(lua_getinfo, int , lua_State *L, const char *what, lua_Debug *ar); - IMPORT_SYMBOL(lua_getlocal, const char *, lua_State *L, const lua_Debug *ar, int n); - IMPORT_SYMBOL(lua_setlocal, const char *, lua_State *L, const lua_Debug *ar, int n); - IMPORT_SYMBOL(lua_getupvalue, const char *, lua_State *L, int funcindex, int n); - IMPORT_SYMBOL(lua_setupvalue, const char *, lua_State *L, int funcindex, int n); - IMPORT_SYMBOL(lua_upvalueid, void *, lua_State *L, int fidx, int n); - IMPORT_SYMBOL(lua_upvaluejoin, void , lua_State *L, int fidx1, int n1, int fidx2, int n2); - IMPORT_SYMBOL(lua_sethook, int , lua_State *L, lua_Hook func, int mask, int count); - IMPORT_SYMBOL(lua_gethook, lua_Hook , lua_State *L); - IMPORT_SYMBOL(lua_gethookmask, int , lua_State *L); - IMPORT_SYMBOL(lua_gethookcount, int , lua_State *L); - IMPORT_SYMBOL(luaL_checkversion_, void , lua_State *L, lua_Number ver); - IMPORT_SYMBOL(luaL_getmetafield, int , lua_State *L, int obj, const char *e); - IMPORT_SYMBOL(luaL_callmeta, int , lua_State *L, int obj, const char *e); - IMPORT_SYMBOL(luaL_tolstring, const char *, lua_State *L, int idx, size_t *len); - IMPORT_SYMBOL(luaL_argerror, int , lua_State *L, int numarg, const char *extramsg); - IMPORT_SYMBOL(luaL_checklstring, const char *, lua_State *L, int numArg, size_t *l); - IMPORT_SYMBOL(luaL_optlstring, const char *, lua_State *L, int numArg, const char *def, size_t *l); - IMPORT_SYMBOL(luaL_checknumber, lua_Number , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optnumber, lua_Number , lua_State *L, int nArg, lua_Number def); - IMPORT_SYMBOL(luaL_checkinteger, lua_Integer , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optinteger, lua_Integer , lua_State *L, int nArg, lua_Integer def); - IMPORT_SYMBOL(luaL_checkunsigned, lua_Unsigned , lua_State *L, int numArg); - IMPORT_SYMBOL(luaL_optunsigned, lua_Unsigned , lua_State *L, int numArg, lua_Unsigned def); - IMPORT_SYMBOL(luaL_checkstack, void , lua_State *L, int sz, const char *msg); - IMPORT_SYMBOL(luaL_checktype, void , lua_State *L, int narg, int t); - IMPORT_SYMBOL(luaL_checkany, void , lua_State *L, int narg); - IMPORT_SYMBOL(luaL_newmetatable, int , lua_State *L, const char *tname); - IMPORT_SYMBOL(luaL_setmetatable, void , lua_State *L, const char *tname); - IMPORT_SYMBOL(luaL_testudata, void *, lua_State *L, int ud, const char *tname); - IMPORT_SYMBOL(luaL_checkudata, void *, lua_State *L, int ud, const char *tname); - IMPORT_SYMBOL(luaL_where, void , lua_State *L, int lvl); - IMPORT_SYMBOL(luaL_error, int , lua_State *L, const char *fmt, ...); - IMPORT_SYMBOL(luaL_checkoption, int , lua_State *L, int narg, const char *def, const char *const lst[]); - IMPORT_SYMBOL(luaL_fileresult, int , lua_State *L, int stat, const char *fname); - IMPORT_SYMBOL(luaL_execresult, int , lua_State *L, int stat); - IMPORT_SYMBOL(luaL_ref, int , lua_State *L, int t); - IMPORT_SYMBOL(luaL_unref, void , lua_State *L, int t, int ref); - IMPORT_SYMBOL(luaL_loadfilex, int , lua_State *L, const char *filename, const char *mode); - IMPORT_SYMBOL(luaL_loadbufferx, int , lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); - IMPORT_SYMBOL(luaL_loadstring, int , lua_State *L, const char *s); - IMPORT_SYMBOL(luaL_newstate, lua_State *, void); - IMPORT_SYMBOL(luaL_len, int , lua_State *L, int idx); - IMPORT_SYMBOL(luaL_gsub, const char *, lua_State *L, const char *s, const char *p, const char *r); - IMPORT_SYMBOL(luaL_setfuncs, void , lua_State *L, const luaL_Reg *l, int nup); - IMPORT_SYMBOL(luaL_getsubtable, int , lua_State *L, int idx, const char *fname); - IMPORT_SYMBOL(luaL_traceback, void , lua_State *L, lua_State *L1, const char *msg, int level); - IMPORT_SYMBOL(luaL_requiref, void , lua_State *L, const char *modname, lua_CFunction openf, int glb); - IMPORT_SYMBOL(luaL_buffinit, void , lua_State *L, luaL_Buffer *B); - IMPORT_SYMBOL(luaL_prepbuffsize, char *, luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_addlstring, void , luaL_Buffer *B, const char *s, size_t l); - IMPORT_SYMBOL(luaL_addstring, void , luaL_Buffer *B, const char *s); - IMPORT_SYMBOL(luaL_addvalue, void , luaL_Buffer *B); - IMPORT_SYMBOL(luaL_pushresult, void , luaL_Buffer *B); - IMPORT_SYMBOL(luaL_pushresultsize, void , luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_buffinitsize, char *, lua_State *L, luaL_Buffer *B, size_t sz); - IMPORT_SYMBOL(luaL_openlibs, void, lua_State* L); -} - -#endif /* LITE_XL_PLUGIN_ENTRYPOINT */ - -#endif /* LITE_XL_PLUGIN_API */ From 6ad288aa39ac68ae57c9b1407b828f9f4afd8f04 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Tue, 11 Apr 2023 23:33:34 +0800 Subject: [PATCH 066/176] Cross compiling improvements + macOS universal binary (#1458) * chore(resources): rename macos_arm64.txt to macos-arm64.txt This matches the platform-arch convention like many other parts of the project. * chore(resources/cross): rename wasm.txt to unknown-wasm32.txt * refactor(scripts/common.sh): use parameter expansion instead of if else * feat(scripts/common.sh): support custom arch and platform for get_default_build_dir * feat(scripts/build.sh): add --cross-platform, --cross-arch and --cross-file * feat(scripts/package.sh): add --cross-platform and --cross-arch * feat(build-packages.sh): add support for new options in build.sh and packages.sh * ci(build): make arm64 binaries in CI * ci(build): do not install external libraries * ci(build): fix invalid artifact name * ci(build): fix INSTALL_NAME * ci(build): change name for macos artifacts * ci(build): add script to build universal dmgs from individual dmgs * ci(build): build universal dmgs * fix(make-universal-binaries): fix wrong path for hdiutil * ci(build): rename macos action * fix(make-universal-binaries.sh): fix wrong pathname for ditto * ci(release): build macos universal binaries * ci(release): remove useless variables * ci(release): fix wrong dependency * ci(build): fix old ubuntu version This version will be restored once I complete some container-specific fixes. * ci(build): make build_macos_universal depend on release * ci(build): fix wrong dmg dir * style(ci): capitalize 'universal' for CI name * fix(make-universal-binaries.sh): fix truncated dmg name when it contains dots * ci: styling changes * ci(release): install appdmg only --- .github/workflows/build.yml | 51 ++++++++- .github/workflows/release.yml | 66 ++++++++++- build-packages.sh | 76 +++++++++---- .../{macos_arm64.txt => macos-arm64.txt} | 0 .../cross/{wasm.txt => unknown-wasm32.txt} | 0 scripts/build.sh | 103 +++++++++++++----- scripts/common.sh | 8 +- scripts/make-universal-binaries.sh | 33 ++++++ scripts/package.sh | 57 +++++++--- 9 files changed, 315 insertions(+), 79 deletions(-) rename resources/cross/{macos_arm64.txt => macos-arm64.txt} (100%) rename resources/cross/{wasm.txt => unknown-wasm32.txt} (100%) create mode 100644 scripts/make-universal-binaries.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 12247bfb..0dabaaa5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,11 +54,14 @@ jobs: path: ${{ env.INSTALL_NAME }}.tar.gz build_macos: - name: macOS (x86_64) + name: macOS runs-on: macos-11 env: CC: clang CXX: clang++ + strategy: + matrix: + arch: ['x86_64', 'arm64'] steps: - name: System Information run: | @@ -70,24 +73,60 @@ jobs: run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_REF=${GITHUB_REF##*/}" >> "$GITHUB_ENV" - echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-$(uname -m)" >> "$GITHUB_ENV" + echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-${{ matrix.arch }}" >> "$GITHUB_ENV" + if [[ $(uname -m) != ${{ matrix.arch }} ]]; then echo "ARCH=--cross-arch ${{ matrix.arch }}" >> "$GITHUB_ENV"; fi - uses: actions/checkout@v3 - name: Python Setup uses: actions/setup-python@v4 with: python-version: 3.9 - name: Install Dependencies - run: bash scripts/install-dependencies.sh --debug + # --lhelper will eliminate a warning with arm64 and libusb + run: bash scripts/install-dependencies.sh --debug --lhelper - name: Build run: | bash --version - bash scripts/build.sh --bundle --debug --forcefallback + bash scripts/build.sh --bundle --debug --forcefallback $ARCH - name: Create DMG Image - run: bash scripts/package.sh --version ${INSTALL_REF} --debug --dmg + run: bash scripts/package.sh --version ${INSTALL_REF} $ARCH --debug --dmg - name: Upload DMG Image uses: actions/upload-artifact@v3 with: - name: macOS DMG Image + name: macOS DMG Images + path: ${{ env.INSTALL_NAME }}.dmg + + build_macos_universal: + name: macOS (Universal) + runs-on: macos-11 + needs: build_macos + steps: + - name: System Information + run: | + system_profiler SPSoftwareDataType + bash --version + gcc -v + xcodebuild -version + - name: Set Environment Variables + run: | + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-universal" >> "$GITHUB_ENV" + - uses: actions/checkout@v2 + - name: Download artifacts + uses: actions/download-artifact@v3 + id: download + with: + name: macOS DMG Images + path: dmgs-original + - name: Install appdmg + run: cd ~; npm i appdmg; cd - + - name: Make universal bundles + run: | + bash --version + bash scripts/make-universal-binaries.sh ${{ steps.download.outputs.download-path }} "${INSTALL_NAME}" + - name: Upload DMG Image + uses: actions/upload-artifact@v2 + with: + name: macOS Universal DMG Images path: ${{ env.INSTALL_NAME }}.dmg build_windows_msys2: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47b826dd..206931c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ on: jobs: release: name: Create Release - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} version: ${{ steps.tag.outputs.version }} @@ -49,7 +49,7 @@ jobs: build_linux: name: Linux needs: release - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest env: CC: gcc CXX: g++ @@ -115,6 +115,7 @@ jobs: echo "INSTALL_REF=${{ needs.release.outputs.version }}" >> "$GITHUB_ENV" echo "INSTALL_NAME=lite-xl-${{ needs.release.outputs.version }}-macos-${{ matrix.arch }}" >> "$GITHUB_ENV" echo "INSTALL_NAME_ADDONS=lite-xl-${{ needs.release.outputs.version }}-addons-macos-${{ matrix.arch }}" >> "$GITHUB_ENV" + if [[ $(uname -m) != ${{ matrix.arch }} ]]; then echo "ARCH=--cross-arch ${{ matrix.arch }}" >> "$GITHUB_ENV"; fi - uses: actions/checkout@v3 - name: Python Setup uses: actions/setup-python@v4 @@ -125,11 +126,18 @@ jobs: - name: Build run: | bash --version - CROSS_ARCH=${{ matrix.arch }} bash scripts/build.sh --bundle --debug --forcefallback --release + bash scripts/build.sh --bundle --debug --forcefallback --release $ARCH - name: Create DMG Image run: | - CROSS_ARCH=${{ matrix.arch }} bash scripts/package.sh --version ${INSTALL_REF} --debug --dmg --release - CROSS_ARCH=${{ matrix.arch }} bash scripts/package.sh --version ${INSTALL_REF} --debug --addons --dmg --release + bash scripts/package.sh --version ${INSTALL_REF} $ARCH --debug --dmg --release + bash scripts/package.sh --version ${INSTALL_REF} $ARCH --debug --addons --dmg --release + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: macOS DMG Images + path: | + ${{ env.INSTALL_NAME }}.dmg + ${{ env.INSTALL_NAME_ADDONS }}.dmg - name: Upload Files uses: softprops/action-gh-release@v1 with: @@ -139,6 +147,54 @@ jobs: ${{ env.INSTALL_NAME }}.dmg ${{ env.INSTALL_NAME_ADDONS }}.dmg + build_macos_universal: + name: macOS (Universal) + needs: [release, build_macos] + runs-on: macos-11 + steps: + - name: System Information + run: | + system_profiler SPSoftwareDataType + bash --version + gcc -v + xcodebuild -version + - name: Set Environment Variables + run: | + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + echo "INSTALL_BASE=lite-xl-${{ needs.release.outputs.version }}-macos" >> "$GITHUB_ENV" + echo "INSTALL_BASE_ADDONS=lite-xl-${{ needs.release.outputs.version }}-addons-macos" >> "$GITHUB_ENV" + - uses: actions/checkout@v2 + - name: Download Artifacts + uses: actions/download-artifact@v3 + id: download + with: + name: macOS DMG Images + path: dmgs-original + - name: Python Setup + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install appdmg + run: cd ~; npm i appdmg; cd - + - name: Prepare DMG Images + run: | + mkdir -p dmgs-addons dmgs-normal + mv -v "${{ steps.download.outputs.download-path }}/$INSTALL_BASE-"{x86_64,arm64}.dmg dmgs-normal + mv -v "${{ steps.download.outputs.download-path }}/$INSTALL_BASE_ADDONS-"{x86_64,arm64}.dmg dmgs-addons + - name: Create Universal DMGs + run: | + bash --version + bash scripts/make-universal-binaries.sh dmgs-normal "$INSTALL_BASE-universal" + bash scripts/make-universal-binaries.sh dmgs-addons "$INSTALL_BASE_ADDONS-universal" + - name: Upload Files + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ needs.release.outputs.version }} + draft: true + files: | + ${{ env.INSTALL_BASE }}-universal.dmg + ${{ env.INSTALL_BASE_ADDONS }}-universal.dmg + build_windows_msys2: name: Windows needs: release diff --git a/build-packages.sh b/build-packages.sh index 30a4ea2d..96a7d11d 100755 --- a/build-packages.sh +++ b/build-packages.sh @@ -13,33 +13,36 @@ show_help() { echo echo "Common options:" echo - echo "-h --help Show this help and exit." - echo "-b --builddir DIRNAME Set the name of the build directory (not path)." - echo " Default: '$(get_default_build_dir)'." - echo "-p --prefix PREFIX Install directory prefix." - echo " Default: '/'." - echo " --debug Debug this script." + echo "-h --help Show this help and exit." + echo "-b --builddir DIRNAME Set the name of the build directory (not path)." + echo " Default: '$(get_default_build_dir)'." + echo "-p --prefix PREFIX Install directory prefix." + echo " Default: '/'." + echo " --cross-platform PLATFORM The platform to cross compile for." + echo " --cross-arch ARCH The architecture to cross compile for." + echo " --debug Debug this script." echo echo "Build options:" echo - echo "-f --forcefallback Force to build subprojects dependencies statically." - echo "-B --bundle Create an App bundle (macOS only)" - echo "-P --portable Create a portable package." - echo "-O --pgo Use profile guided optimizations (pgo)." - echo " Requires running the application iteractively." + echo "-f --forcefallback Force to build subprojects dependencies statically." + echo "-B --bundle Create an App bundle (macOS only)" + echo "-P --portable Create a portable package." + echo "-O --pgo Use profile guided optimizations (pgo)." + echo " Requires running the application iteractively." + echo " --cross-file CROSS_FILE The cross file used for compiling." echo echo "Package options:" echo - echo "-d --destdir DIRNAME Set the name of the package directory (not path)." - echo " Default: 'lite-xl'." - echo "-v --version VERSION Sets the version on the package name." - echo "-A --appimage Create an AppImage (Linux only)." - echo "-D --dmg Create a DMG disk image (macOS only)." - echo " Requires NPM and AppDMG." - echo "-I --innosetup Create an InnoSetup installer (Windows only)." - echo "-r --release Compile in release mode." - echo "-S --source Create a source code package," - echo " including subprojects dependencies." + echo "-d --destdir DIRNAME Set the name of the package directory (not path)." + echo " Default: 'lite-xl'." + echo "-v --version VERSION Sets the version on the package name." + echo "-A --appimage Create an AppImage (Linux only)." + echo "-D --dmg Create a DMG disk image (macOS only)." + echo " Requires NPM and AppDMG." + echo "-I --innosetup Create an InnoSetup installer (Windows only)." + echo "-r --release Compile in release mode." + echo "-S --source Create a source code package," + echo " including subprojects dependencies." echo } @@ -60,6 +63,12 @@ main() { local portable local pgo local release + local cross_platform + local cross_platform_option=() + local cross_arch + local cross_arch_option=() + local cross_file + local cross_file_option=() for i in "$@"; do case $i in @@ -123,6 +132,21 @@ main() { pgo="--pgo" shift ;; + --cross-platform) + cross_platform="$2" + shift + shift + ;; + --cross-arch) + cross_arch="$2" + shift + shift + ;; + --cross-file) + cross_file="$2" + shift + shift + ;; --debug) debug="--debug" set -x @@ -143,10 +167,18 @@ main() { if [[ -n $dest_dir ]]; then dest_dir_option=("--destdir" "${dest_dir}"); fi if [[ -n $prefix ]]; then prefix_option=("--prefix" "${prefix}"); fi if [[ -n $version ]]; then version_option=("--version" "${version}"); fi + if [[ -n $cross_platform ]]; then cross_platform_option=("--cross-platform" "${cross_platform}"); fi + if [[ -n $cross_arch ]]; then cross_arch_option=("--cross-arch" "${cross_arch}"); fi + if [[ -n $cross_file ]]; then cross_file_option=("--cross-file" "${cross_file}"); fi + + source scripts/build.sh \ ${build_dir_option[@]} \ ${prefix_option[@]} \ + ${cross_platform_option[@]} \ + ${cross_arch_option[@]} \ + ${cross_file_option[@]} \ $debug \ $force_fallback \ $bundle \ @@ -159,6 +191,8 @@ main() { ${dest_dir_option[@]} \ ${prefix_option[@]} \ ${version_option[@]} \ + ${cross_platform_option[@]} \ + ${cross_arch_option[@]} \ --binary \ --addons \ $debug \ diff --git a/resources/cross/macos_arm64.txt b/resources/cross/macos-arm64.txt similarity index 100% rename from resources/cross/macos_arm64.txt rename to resources/cross/macos-arm64.txt diff --git a/resources/cross/wasm.txt b/resources/cross/unknown-wasm32.txt similarity index 100% rename from resources/cross/wasm.txt rename to resources/cross/unknown-wasm32.txt diff --git a/scripts/build.sh b/scripts/build.sh index 0cd4e8d8..778f596d 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -13,19 +13,26 @@ show_help() { echo echo "Available options:" echo - echo "-b --builddir DIRNAME Sets the name of the build directory (not path)." - echo " Default: '$(get_default_build_dir)'." - echo " --debug Debug this script." - echo "-f --forcefallback Force to build dependencies statically." - echo "-h --help Show this help and exit." - echo "-p --prefix PREFIX Install directory prefix. Default: '/'." - echo "-B --bundle Create an App bundle (macOS only)" - echo "-P --portable Create a portable binary package." - echo "-O --pgo Use profile guided optimizations (pgo)." - echo "-U --windows-lua-utf Use the UTF8 patch for Lua." - echo " macOS: disabled when used with --bundle," - echo " Windows: Implicit being the only option." - echo "-r --release Compile in release mode." + echo "-b --builddir DIRNAME Sets the name of the build directory (not path)." + echo " Default: '$(get_default_build_dir)'." + echo " --debug Debug this script." + echo "-f --forcefallback Force to build dependencies statically." + echo "-h --help Show this help and exit." + echo "-p --prefix PREFIX Install directory prefix. Default: '/'." + echo "-B --bundle Create an App bundle (macOS only)" + echo "-P --portable Create a portable binary package." + echo "-O --pgo Use profile guided optimizations (pgo)." + echo "-U --windows-lua-utf Use the UTF8 patch for Lua." + echo " macOS: disabled when used with --bundle," + echo " Windows: Implicit being the only option." + echo "-r --release Compile in release mode." + echo " --cross-platform PLATFORM Cross compile for this platform." + echo " The script will find the appropriate" + echo " cross file in 'resources/cross'." + echo " --cross-arch ARCH Cross compile for this architecture." + echo " The script will find the appropriate" + echo " cross file in 'resources/cross'." + echo " --cross-file CROSS_FILE Cross compile with the given cross file." echo } @@ -40,6 +47,10 @@ main() { local portable local pgo local patch_lua + local cross + local cross_platform + local cross_arch + local cross_file local lua_subproject_path @@ -87,6 +98,24 @@ main() { patch_lua="true" shift ;; + --cross-arch) + cross="true" + cross_arch="$2" + shift + shift + ;; + --cross-platform) + cross="true" + cross_platform="$2" + shift + shift + ;; + --cross-file) + cross="true" + cross_file="$2" + shift + shift + ;; -r|--release) build_type="release" shift @@ -107,19 +136,43 @@ main() { portable="" fi - if [[ $CROSS_ARCH != "" ]]; then - if [[ $platform == "macos" ]]; then - macos_version_min=10.11 - if [[ $CROSS_ARCH == "arm64" ]]; then - cross_file="--cross-file resources/cross/macos_arm64.txt" - macos_version_min=11.0 + # if CROSS_ARCH is used, it will be picked up + cross="${cross:-$CROSS_ARCH}" + if [[ -n "$cross" ]]; then + if [[ -n "$cross_file" ]] && ([[ -z "$cross_arch" ]] || [[ -z "$cross_platform" ]]); then + echo "Warning: --cross-platform or --cross-platform not set; guessing it from the filename." + # remove file extensions and directories from the path + cross_file_name="${cross_file##*/}" + cross_file_name="${cross_file_name%%.*}" + # cross_platform is the string before encountering the first hyphen + if [[ -z "$cross_platform" ]]; then + cross_platform="${cross_file_name%%-*}" + echo "Warning: Guessing --cross-platform $cross_platform" + fi + # cross_arch is the string after encountering the first hyphen + if [[ -z "$cross_arch" ]]; then + cross_arch="${cross_file_name#*-}" + echo "Warning: Guessing --cross-arch $cross_arch" fi - export MACOSX_DEPLOYMENT_TARGET=$macos_version_min - export MIN_SUPPORTED_MACOSX_DEPLOYMENT_TARGET=$macos_version_min - export CFLAGS=-mmacosx-version-min=$macos_version_min - export CXXFLAGS=-mmacosx-version-min=$macos_version_min - export LDFLAGS=-mmacosx-version-min=$macos_version_min fi + platform="${cross_platform:-$platform}" + arch="${cross_arch:-$arch}" + cross_file=("--cross-file" "${cross_file:-resources/cross/$platform-$arch.txt}") + # reload build_dir because platform and arch might change + build_dir="$(get_default_build_dir "$platform" "$arch")" + fi + + # arch and platform specific stuff + if [[ "$platform" == "macos" ]]; then + macos_version_min="10.11" + if [[ "$arch" == "arm64" ]]; then + macos_version_min="11.0" + fi + export MACOSX_DEPLOYMENT_TARGET="$macos_version_min" + export MIN_SUPPORTED_MACOSX_DEPLOYMENT_TARGET="$macos_version_min" + export CFLAGS="-mmacosx-version-min=$macos_version_min" + export CXXFLAGS="-mmacosx-version-min=$macos_version_min" + export LDFLAGS="-mmacosx-version-min=$macos_version_min" fi rm -rf "${build_dir}" @@ -137,7 +190,7 @@ main() { CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS meson setup \ --buildtype=$build_type \ --prefix "$prefix" \ - $cross_file \ + "${cross_file[@]}" \ $force_fallback \ $bundle \ $portable \ diff --git a/scripts/common.sh b/scripts/common.sh index 7078c99c..14402138 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -75,22 +75,20 @@ get_platform_name() { get_platform_arch() { platform=$(get_platform_name) - arch=$(uname -m) + arch=${CROSS_ARCH:-$(uname -m)} if [[ $MSYSTEM != "" ]]; then if [[ $MSYSTEM == "MINGW64" ]]; then arch=x86_64 else arch=i686 fi - elif [[ $CROSS_ARCH != "" ]]; then - arch=$CROSS_ARCH fi echo "$arch" } get_default_build_dir() { - platform=$(get_platform_name) - arch=$(get_platform_arch) + platform="${1:-$(get_platform_name)}" + arch="${2:-$(get_platform_arch)}" echo "build-$platform-$arch" } diff --git a/scripts/make-universal-binaries.sh b/scripts/make-universal-binaries.sh new file mode 100644 index 00000000..e3f2d373 --- /dev/null +++ b/scripts/make-universal-binaries.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -ex + +if [ ! -e "src/api/api.h" ]; then + echo "Please run this script from the root directory of Lite XL." + exit 1 +fi + +WORKDIR="work" +DMGDIR="$1" + +if [[ -z "$DMGDIR" ]]; then + echo "Please provide a path containing the dmg files." + exit 1 +fi + +rm -rf "$WORKDIR" +mkdir -p "$WORKDIR" + +for dmg_path in "$DMGDIR"/*.dmg; do + dmg="${dmg_path##*/}" + dmg="${dmg%.dmg}" + hdiutil attach -mountpoint "/Volumes/$dmg" "$dmg_path" + if [[ ! -d "$WORKDIR/dmg" ]]; then + ditto "/Volumes/$dmg/Lite XL.app" "Lite XL.app" + fi + cp "/Volumes/$dmg/Lite XL.app/Contents/MacOS/lite-xl" "$WORKDIR/$dmg-lite-xl" + hdiutil detach "/Volumes/$dmg" +done + +lipo -create -output "Lite XL.app/Contents/MacOS/lite-xl" "$WORKDIR/"*-lite-xl + +source scripts/appdmg.sh "$2" \ No newline at end of file diff --git a/scripts/package.sh b/scripts/package.sh index 15dbd47f..d2346b76 100644 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -13,23 +13,25 @@ show_help() { echo echo "Available options:" echo - echo "-b --builddir DIRNAME Sets the name of the build directory (not path)." - echo " Default: '$(get_default_build_dir)'." - echo "-d --destdir DIRNAME Set the name of the package directory (not path)." - echo " Default: 'lite-xl'." - echo "-h --help Show this help and exit." - echo "-p --prefix PREFIX Install directory prefix. Default: '/'." - echo "-v --version VERSION Sets the version on the package name." - echo "-a --addons Install 3rd party addons." - echo " --debug Debug this script." - echo "-A --appimage Create an AppImage (Linux only)." - echo "-B --binary Create a normal / portable package or macOS bundle," - echo " depending on how the build was configured. (Default.)" - echo "-D --dmg Create a DMG disk image with AppDMG (macOS only)." - echo "-I --innosetup Create a InnoSetup package (Windows only)." - echo "-r --release Strip debugging symbols." - echo "-S --source Create a source code package," - echo " including subprojects dependencies." + echo "-b --builddir DIRNAME Sets the name of the build directory (not path)." + echo " Default: '$(get_default_build_dir)'." + echo "-d --destdir DIRNAME Set the name of the package directory (not path)." + echo " Default: 'lite-xl'." + echo "-h --help Show this help and exit." + echo "-p --prefix PREFIX Install directory prefix. Default: '/'." + echo "-v --version VERSION Sets the version on the package name." + echo "-a --addons Install 3rd party addons." + echo " --debug Debug this script." + echo "-A --appimage Create an AppImage (Linux only)." + echo "-B --binary Create a normal / portable package or macOS bundle," + echo " depending on how the build was configured. (Default.)" + echo "-D --dmg Create a DMG disk image with AppDMG (macOS only)." + echo "-I --innosetup Create a InnoSetup package (Windows only)." + echo "-r --release Strip debugging symbols." + echo "-S --source Create a source code package," + echo " including subprojects dependencies." + echo " --cross-platform PLATFORM The platform to package for." + echo " --cross-arch ARCH The architecture to package for." echo } @@ -73,6 +75,9 @@ main() { local innosetup=false local release=false local source=false + local cross + local cross_arch + local cross_platform # store the current flags to easily pass them to appimage script local flags="$@" @@ -143,6 +148,18 @@ main() { addons=true shift ;; + --cross-platform) + cross=true + cross_platform="$2" + shift + shift + ;; + --cross-arch) + cross=true + cross_arch="$2" + shift + shift + ;; --debug) set -x shift @@ -159,6 +176,12 @@ main() { if [[ -n $1 ]]; then show_help; exit 1; fi + if [[ -n "$cross" ]]; then + platform="${cross_platform:-$platform}" + arch="${cross_arch:-$arch}" + build_dir="$(get_default_build_dir "$platform" "$arch")" + fi + # The source package doesn't require a previous build, # nor the following install step, so run it now. if [[ $source == true ]]; then source_package "lite-xl$version-src"; fi From 0be18493a943b5e694568ea3d5de906aa0632fe8 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 14 Apr 2023 21:22:22 +0200 Subject: [PATCH 067/176] Show error message in crash message box (#1461) * Save to `error.txt` the same traceback shown on stdout * Show error message in crash message box --- src/main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index f6e980a5..e3a9b1ac 100644 --- a/src/main.c +++ b/src/main.c @@ -237,22 +237,23 @@ init_lua: " core.init()\n" " core.run()\n" "end, function(err)\n" - " local error_dir\n" + " local error_path = 'error.txt'\n" " io.stdout:write('Error: '..tostring(err)..'\\n')\n" " io.stdout:write(debug.traceback(nil, 2)..'\\n')\n" " if core and core.on_error then\n" - " error_dir=USERDIR\n" + " error_path = USERDIR .. PATHSEP .. error_path\n" " pcall(core.on_error, err)\n" " else\n" - " error_dir=system.absolute_path('.')\n" - " local fp = io.open('error.txt', 'wb')\n" + " local fp = io.open(error_path, 'wb')\n" " fp:write('Error: ' .. tostring(err) .. '\\n')\n" - " fp:write(debug.traceback(nil, 4)..'\\n')\n" + " fp:write(debug.traceback(nil, 2)..'\\n')\n" " fp:close()\n" + " error_path = system.absolute_path(error_path)\n" " end\n" " system.show_fatal_error('Lite XL internal error',\n" " 'An internal error occurred in a critical part of the application.\\n\\n'..\n" - " 'Please verify the file \\\"error.txt\\\" in the directory '..error_dir)\n" + " 'Error: '..tostring(err)..'\\n\\n'..\n" + " 'Details can be found in \\\"'..error_path..'\\\"')\n" " os.exit(1)\n" "end)\n" "return core and core.restart_request\n"; From 7f75619aa28d8c73c2328c162d2f1c66d0578fa5 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 15 Apr 2023 03:45:46 +0800 Subject: [PATCH 068/176] refactor(plugin_api): move the header into include/ (#1440) --- resources/README.md | 4 ++-- resources/include/lite_xl_plugin_api.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/README.md b/resources/README.md index 975881c4..cf30432c 100644 --- a/resources/README.md +++ b/resources/README.md @@ -17,7 +17,7 @@ This folder contains resources that is used for building or packaging the projec ### Development -- `lite_xl_plugin_api.h`: Native plugin API header. See the contents of `lite_xl_plugin_api.h` for more details. +- `include/lite_xl_plugin_api.h`: Native plugin API header. See the contents of `lite_xl_plugin_api.h` for more details. -[1]: https://mesonbuild.com/Cross-compilation.html \ No newline at end of file +[1]: https://mesonbuild.com/Cross-compilation.html diff --git a/resources/include/lite_xl_plugin_api.h b/resources/include/lite_xl_plugin_api.h index 2947039e..0c5e93e9 100644 --- a/resources/include/lite_xl_plugin_api.h +++ b/resources/include/lite_xl_plugin_api.h @@ -2560,4 +2560,4 @@ void lite_xl_plugin_init(void *XL); * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ \ No newline at end of file +******************************************************************************/ From 532d3a6572d27ccc29978eef3353db5495635033 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 14 Apr 2023 23:49:26 +0200 Subject: [PATCH 069/176] Merge carets after `doc:move-to-{previous,next}-char` (#1462) --- data/core/commands/doc.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index d9803bce..0530f6e9 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -700,6 +700,7 @@ commands["doc:move-to-previous-char"] = function(dv) dv.doc:move_to_cursor(idx, translate.previous_char) end end + dv.doc:merge_cursors() end commands["doc:move-to-next-char"] = function(dv) @@ -710,6 +711,7 @@ commands["doc:move-to-next-char"] = function(dv) dv.doc:move_to_cursor(idx, translate.next_char) end end + dv.doc:merge_cursors() end command.add("core.docview", commands) From 3c60c1c7f1e354dc62f81147be7d5dbea26314c5 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 16 Apr 2023 21:18:40 +0800 Subject: [PATCH 070/176] Build releases with Ubuntu 18.04 container (#1460) * ci(release): try using lite-xl-build-box * ci(build): test with my own fork * ci(build): do not install python via actions * ci(build): disable package updates * fix(scripts/appimage.sh): add workaround for non-FUSE environments * ci(build): document why the actions are disabled * ci(release): fix typo --- .github/workflows/release.yml | 11 +++++++++++ scripts/appimage.sh | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 206931c7..581b6469 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,6 +50,7 @@ jobs: name: Linux needs: release runs-on: ubuntu-latest + container: ghcr.io/takase1121/lite-xl-build-box:latest env: CC: gcc CXX: g++ @@ -59,16 +60,26 @@ jobs: echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_REF=${{ needs.release.outputs.version }}" >> "$GITHUB_ENV" - uses: actions/checkout@v3 + + # disabled because this will break our own Python install - name: Python Setup + if: false uses: actions/setup-python@v4 with: python-version: 3.9 + + # disabled because the container has up-to-date packages - name: Update Packages + if: false run: sudo apt-get update + + # disabled as the dependencies are already installed - name: Install Dependencies + if: false run: | bash scripts/install-dependencies.sh --debug sudo apt-get install -y ccache + - name: Build Portable run: | bash --version diff --git a/scripts/appimage.sh b/scripts/appimage.sh index 03de616c..17551a48 100644 --- a/scripts/appimage.sh +++ b/scripts/appimage.sh @@ -181,7 +181,7 @@ generate_appimage() { version="${version}-addons" fi - ./appimagetool LiteXL.AppDir LiteXL${version}-${ARCH}.AppImage + ./appimagetool --appimage-extract-and-run LiteXL.AppDir LiteXL${version}-${ARCH}.AppImage } setup_appimagetool From e2a582d5fd0d2671e1cf252170b6fdcf12a51840 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Tue, 18 Apr 2023 02:56:04 +0800 Subject: [PATCH 071/176] Process API improvements (again) (#1370) * feat(process): add push_error * refactor(process): use push_error for better errors * style(process): consistent error messages * refactor(process): reimplement process.strerror() with push_error * refactor(process): implement close_fd only once * refactor(process): rename process_handle to process_handle_t * fix(process): prevent errors from a NULL error message * refactor(process): refactor push_error into 2 functions * fix(process): fix wrong error message * fix(process): check if push_error_string actually pushed something * refactor(process): make error messages descriptive * fix(process): check for empty table instead of aborting * refactor(process): make error messages descriptive on Windows * refactor(process): rename process_stream_handle to process_stream_t * refactor(process): fix wrong usage of process_handle_t * fix(process): fix wrong type name * refactor(process): incoporate kill_list_thread into process_kill_list_t * refactor(process): make kill_list per-state data --- src/api/process.c | 181 +++++++++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 60 deletions(-) diff --git a/src/api/process.c b/src/api/process.c index 2b0a5008..2e343c6c 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -24,13 +24,28 @@ #define READ_BUF_SIZE 2048 #define PROCESS_TERM_TRIES 3 #define PROCESS_TERM_DELAY 50 +#define PROCESS_KILL_LIST_NAME "__process_kill_list__" #if _WIN32 -typedef HANDLE process_stream_handle; -typedef HANDLE process_handle; + +typedef DWORD process_error_t; +typedef HANDLE process_stream_t; +typedef HANDLE process_handle_t; + +#define HANDLE_INVALID (INVALID_HANDLE_VALUE) +#define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess) + +static volatile long PipeSerialNumber; + #else -typedef int process_stream_handle; -typedef pid_t process_handle; + +typedef int process_error_t; +typedef int process_stream_t; +typedef pid_t process_handle_t; + +#define HANDLE_INVALID (0) +#define PROCESS_GET_HANDLE(P) ((P)->pid) + #endif typedef struct { @@ -43,13 +58,13 @@ typedef struct { bool reading[2]; char buffer[2][READ_BUF_SIZE]; #endif - process_stream_handle child_pipes[3][2]; + process_stream_t child_pipes[3][2]; } process_t; typedef struct process_kill_s { int tries; uint32_t start_time; - process_handle handle; + process_handle_t handle; struct process_kill_s *next; } process_kill_t; @@ -57,6 +72,7 @@ typedef struct { bool stop; SDL_mutex *mutex; SDL_cond *has_work, *work_done; + SDL_Thread *worker_thread; process_kill_t *head; process_kill_t *tail; } process_kill_list_t; @@ -83,21 +99,24 @@ typedef enum { REDIRECT_PARENT = -3, } filed_e; -static process_kill_list_t kill_list = { 0 }; -static SDL_Thread *kill_list_thread = NULL; - +static void close_fd(process_stream_t *handle) { + if (*handle) { #ifdef _WIN32 - static volatile long PipeSerialNumber; - static void close_fd(HANDLE* handle) { if (*handle) CloseHandle(*handle); *handle = INVALID_HANDLE_VALUE; } - #define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess) + CloseHandle(*handle); #else - static void close_fd(int* fd) { if (*fd) close(*fd); *fd = 0; } - #define PROCESS_GET_HANDLE(P) ((P)->pid) + close(*handle); #endif + *handle = HANDLE_INVALID; + } +} + + +static int kill_list_worker(void *ud); static void kill_list_free(process_kill_list_t *list) { process_kill_t *node, *temp; + SDL_WaitThread(list->worker_thread, NULL); SDL_DestroyMutex(list->mutex); SDL_DestroyCond(list->has_work); SDL_DestroyCond(list->work_done); @@ -107,10 +126,12 @@ static void kill_list_free(process_kill_list_t *list) { node = node->next; free(temp); } + memset(list, 0, sizeof(process_kill_list_t)); } static bool kill_list_init(process_kill_list_t *list) { + memset(list, 0, sizeof(process_kill_list_t)); list->mutex = SDL_CreateMutex(); list->has_work = SDL_CreateCond(); list->work_done = SDL_CreateCond(); @@ -120,6 +141,11 @@ static bool kill_list_init(process_kill_list_t *list) { kill_list_free(list); return false; } + list->worker_thread = SDL_CreateThread(kill_list_worker, "process_kill", list); + if (!list->worker_thread) { + kill_list_free(list); + return false; + } return true; } @@ -157,7 +183,7 @@ static void kill_list_wait_all(process_kill_list_t *list) { } -static void process_handle_close(process_handle *handle) { +static void process_handle_close(process_handle_t *handle) { #ifdef _WIN32 if (*handle) { CloseHandle(*handle); @@ -168,7 +194,7 @@ static void process_handle_close(process_handle *handle) { } -static bool process_handle_is_running(process_handle handle, int *status) { +static bool process_handle_is_running(process_handle_t handle, int *status) { #ifdef _WIN32 DWORD s; if (GetExitCodeProcess(handle, &s) && s != STILL_ACTIVE) { @@ -188,7 +214,7 @@ static bool process_handle_is_running(process_handle handle, int *status) { } -static bool process_handle_signal(process_handle handle, signal_e sig) { +static bool process_handle_signal(process_handle_t handle, signal_e sig) { #if _WIN32 switch(sig) { case SIGNAL_TERM: return GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetProcessId(handle)); @@ -252,6 +278,37 @@ static int kill_list_worker(void *ud) { } +static int push_error_string(lua_State *L, process_error_t err) { +#ifdef _WIN32 + char *msg = NULL; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char *) &msg, + 0, + NULL); + if (!msg) + return 0; + + lua_pushstring(L, msg); + LocalFree(msg); +#else + lua_pushstring(L, strerror(err)); +#endif + return 1; +} + +static void push_error(lua_State *L, const char *extra, process_error_t err) { + const char *msg = "unknown error"; + extra = extra != NULL ? extra : "error"; + if (push_error_string(L, err)) + msg = lua_tostring(L, -1); + lua_pushfstring(L, "%s: %s (%d)", extra, msg, err); +} + static bool poll_process(process_t* proc, int timeout) { uint32_t ticks; @@ -296,6 +353,10 @@ static int process_start(lua_State* L) { lua_pushinteger(L, (int)lua_objlen(L, 1)); #endif cmd_len = luaL_checknumber(L, -1); lua_pop(L, 1); + if (!cmd_len) + // we have not allocated anything here yet, so we can skip cleanup code + // don't do this anywhere else! + return luaL_argerror(L, 1,"table cannot be empty"); for (size_t i = 1; i <= cmd_len; ++i) { lua_pushinteger(L, i); lua_rawget(L, 1); @@ -306,9 +367,6 @@ static int process_start(lua_State* L) { cmd[0] = luaL_checkstring(L, 1); cmd_len = 1; } - // this should never trip - // but if it does we are in deep trouble - assert(cmd[0]); if (arg_len > 1) { lua_getfield(L, 2, "env"); @@ -334,7 +392,7 @@ static int process_start(lua_State* L) { lua_getfield(L, 2, "stderr"); new_fds[STDERR_FD] = luaL_optnumber(L, -1, STDERR_FD); for (int stream = STDIN_FD; stream <= STDERR_FD; ++stream) { if (new_fds[stream] > STDERR_FD || new_fds[stream] < REDIRECT_PARENT) { - lua_pushfstring(L, "redirect to handles, FILE* and paths are not supported"); + lua_pushfstring(L, "error: redirect to handles, FILE* and paths are not supported"); retval = -1; goto cleanup; } @@ -368,20 +426,22 @@ static int process_start(lua_State* L) { self->child_pipes[i][0] = CreateNamedPipeA(pipeNameBuffer, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, 1, READ_BUF_SIZE, READ_BUF_SIZE, 0, NULL); if (self->child_pipes[i][0] == INVALID_HANDLE_VALUE) { - lua_pushfstring(L, "Error creating read pipe: %d.", GetLastError()); + push_error(L, "cannot create pipe", GetLastError()); retval = -1; goto cleanup; } self->child_pipes[i][1] = CreateFileA(pipeNameBuffer, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (self->child_pipes[i][1] == INVALID_HANDLE_VALUE) { + // prevent CloseHandle from messing up error codes + DWORD err = GetLastError(); CloseHandle(self->child_pipes[i][0]); - lua_pushfstring(L, "Error creating write pipe: %d.", GetLastError()); + push_error(L, "cannot open pipe", err); retval = -1; goto cleanup; } if (!SetHandleInformation(self->child_pipes[i][i == STDIN_FD ? 1 : 0], HANDLE_FLAG_INHERIT, 0) || !SetHandleInformation(self->child_pipes[i][i == STDIN_FD ? 0 : 1], HANDLE_FLAG_INHERIT, 1)) { - lua_pushfstring(L, "Error inheriting pipes: %d.", GetLastError()); + push_error(L, "cannot set pipe permission", GetLastError()); retval = -1; goto cleanup; } @@ -445,7 +505,7 @@ static int process_start(lua_State* L) { if (env_len > 0) MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, environmentBlock, offset, (LPWSTR)wideEnvironmentBlock, sizeof(wideEnvironmentBlock)); if (!CreateProcess(NULL, commandLine, NULL, NULL, true, (detach ? DETACHED_PROCESS : CREATE_NO_WINDOW) | CREATE_UNICODE_ENVIRONMENT, env_len > 0 ? wideEnvironmentBlock : NULL, cwd, &siStartInfo, &self->process_information)) { - lua_pushfstring(L, "Error creating a process: %d.", GetLastError()); + push_error(L, NULL, GetLastError()); retval = -1; goto cleanup; } @@ -457,7 +517,7 @@ static int process_start(lua_State* L) { int control_pipe[2] = { 0 }; for (int i = 0; i < 3; ++i) { // Make only the parents fd's non-blocking. Children should block. if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1) { - lua_pushfstring(L, "Error creating pipes: %s", strerror(errno)); + push_error(L, "cannot create pipe", errno); retval = -1; goto cleanup; } @@ -476,7 +536,7 @@ static int process_start(lua_State* L) { self->pid = (long)fork(); if (self->pid < 0) { - lua_pushfstring(L, "Error running fork: %s.", strerror(errno)); + push_error(L, "cannot create child process", errno); retval = -1; goto cleanup; } else if (!self->pid) { @@ -533,7 +593,7 @@ static int process_start(lua_State* L) { free((char*)env_values[i]); } for (int stream = 0; stream < 3; ++stream) { - process_stream_handle* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; + process_stream_t* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; if (*pipe) { close_fd(pipe); } @@ -549,7 +609,7 @@ static int g_read(lua_State* L, int stream, unsigned long read_size) { process_t* self = (process_t*) luaL_checkudata(L, 1, API_TYPE_PROCESS); long length = 0; if (stream != STDOUT_FD && stream != STDERR_FD) - return luaL_error(L, "redirect to handles, FILE* and paths are not supported"); + return luaL_error(L, "error: redirect to handles, FILE* and paths are not supported"); #if _WIN32 int writable_stream_idx = stream - 1; if (self->reading[writable_stream_idx] || !ReadFile(self->child_pipes[stream][0], self->buffer[writable_stream_idx], READ_BUF_SIZE, NULL, &self->overlapped[writable_stream_idx])) { @@ -597,9 +657,9 @@ static int f_write(lua_State* L) { #if _WIN32 DWORD dwWritten; if (!WriteFile(self->child_pipes[STDIN_FD][1], data, data_size, &dwWritten, NULL)) { - int lastError = GetLastError(); + push_error(L, NULL, GetLastError()); signal_process(self, SIGNAL_TERM); - return luaL_error(L, "error writing to process: %d", lastError); + return lua_error(L); } length = dwWritten; #else @@ -607,9 +667,9 @@ static int f_write(lua_State* L) { if (length < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) length = 0; else if (length < 0) { - const char* lastError = strerror(errno); + push_error(L, "cannot write to child process", errno); signal_process(self, SIGNAL_TERM); - return luaL_error(L, "error writing to process: %s", lastError); + return lua_error(L); } #endif lua_pushinteger(L, length); @@ -626,15 +686,7 @@ static int f_close_stream(lua_State* L) { // Generic stuff below here. static int process_strerror(lua_State* L) { - #if _WIN32 - return 1; - #endif - int error_code = luaL_checknumber(L, 1); - if (error_code < 0) - lua_pushstring(L, strerror(error_code)); - else - lua_pushnil(L); - return 1; + return push_error_string(L, luaL_checknumber(L, 1)); } static int f_tostring(lua_State* L) { @@ -688,30 +740,32 @@ static int f_kill(lua_State* L) { return self_signal(L, SIGNAL_KILL); } static int f_interrupt(lua_State* L) { return self_signal(L, SIGNAL_INTERRUPT); } static int f_gc(lua_State* L) { + process_kill_list_t *list = NULL; + process_kill_t *p = NULL; process_t* self = (process_t*) luaL_checkudata(L, 1, API_TYPE_PROCESS); - if (poll_process(self, 0) && !self->detached) { - // attempt to kill the process if not detached - process_kill_t *p; + // get the kill_list for the lua_State + if (lua_getfield(L, LUA_REGISTRYINDEX, PROCESS_KILL_LIST_NAME) == LUA_TUSERDATA) + list = (process_kill_list_t *) lua_touserdata(L, -1); + if (poll_process(self, 0) && !self->detached) { + // attempt to kill the process if still running and not detached signal_process(self, SIGNAL_TERM); - p = malloc(sizeof(process_kill_t)); - if (!p || !kill_list_thread) { - // if we can't allocate, we'll use the old method - poll_process(self, PROCESS_TERM_DELAY); - if (self->running) { + if (!list || !list->worker_thread || !(p = malloc(sizeof(process_kill_t)))) { + // use synchronous waiting + if (poll_process(self, PROCESS_TERM_DELAY)) { signal_process(self, SIGNAL_KILL); poll_process(self, PROCESS_TERM_DELAY); } } else { - // send the handle to a queue for asynchronous waiting + // put the handle into a queue for asynchronous waiting p->handle = PROCESS_GET_HANDLE(self); p->start_time = SDL_GetTicks(); p->tries = 1; - SDL_LockMutex(kill_list.mutex); - kill_list_push(&kill_list, p); - SDL_CondSignal(kill_list.has_work); - SDL_UnlockMutex(kill_list.mutex); + SDL_LockMutex(list->mutex); + kill_list_push(list, p); + SDL_CondSignal(list->has_work); + SDL_UnlockMutex(list->mutex); } } close_fd(&self->child_pipes[STDIN_FD ][1]); @@ -727,9 +781,13 @@ static int f_running(lua_State* L) { } static int process_gc(lua_State *L) { - kill_list_wait_all(&kill_list); - SDL_WaitThread(kill_list_thread, NULL); - kill_list_free(&kill_list); + process_kill_list_t *list = NULL; + // get the kill_list for the lua_State + if (lua_getfield(L, LUA_REGISTRYINDEX, PROCESS_KILL_LIST_NAME) == LUA_TUSERDATA) { + list = (process_kill_list_t *) lua_touserdata(L, -1); + kill_list_wait_all(list); + kill_list_free(list); + } return 0; } @@ -758,8 +816,11 @@ static const struct luaL_Reg lib[] = { }; int luaopen_process(lua_State *L) { - if (kill_list_init(&kill_list)) - kill_list_thread = SDL_CreateThread(kill_list_worker, "process_kill", &kill_list); + process_kill_list_t *list = lua_newuserdata(L, sizeof(process_kill_list_t)); + if (kill_list_init(list)) + lua_setfield(L, LUA_REGISTRYINDEX, PROCESS_KILL_LIST_NAME); + else + lua_pop(L, 1); // discard the list // create the process metatable luaL_newmetatable(L, API_TYPE_PROCESS); From ff4364b0ff5b3b1a683d55948a4bd74125bc4f77 Mon Sep 17 00:00:00 2001 From: jgmdev Date: Mon, 17 Apr 2023 17:26:24 -0400 Subject: [PATCH 072/176] StatusView compat fix with older Lua runtimes --- data/core/statusview.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 35fff21b..930c7aef 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -247,7 +247,7 @@ function StatusView:register_docview_items() alignment = StatusView.Item.LEFT, get_item = function() local dv = core.active_view - local nsel = #dv.doc.selections // 4 + local nsel = math.floor(#dv.doc.selections / 4) if nsel > 1 then return { style.text, nsel, " selections" } end From 0fae012c68f597504b4394f71d286bf265c67a99 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 18 Apr 2023 20:55:25 +0200 Subject: [PATCH 073/176] Make `system.path_compare` more digit-aware (#1474) This allows a human friendly sorting filenames with numbers in them So - asd1 - asd10 - asd2 becomes - asd1 - asd2 - asd10 --- src/api/system.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index 66a46092..51978018 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -1067,9 +1067,10 @@ static int f_path_compare(lua_State *L) { int type1 = strcmp(type1_s, "dir") != 0; int type2 = strcmp(type2_s, "dir") != 0; /* Find the index of the common part of the path. */ - int offset = 0, i; + size_t offset = 0, i, j; for (i = 0; i < len1 && i < len2; i++) { if (path1[i] != path2[i]) break; + if (isdigit(path1[i])) break; if (path1[i] == PATHSEP) { offset = i + 1; } @@ -1089,21 +1090,37 @@ static int f_path_compare(lua_State *L) { } /* If types are the same compare the files' path alphabetically. */ int cfr = -1; - int len_min = (len1 < len2 ? len1 : len2); bool same_len = len1 == len2; - for (int j = offset; j <= len_min; j++) { - if (path1[j] == 0 || path2[j] == 0) { + for (i = offset, j = offset; i <= len1 && j <= len2; i++, j++) { + if (path1[i] == 0 || path2[j] == 0) { if (cfr < 0) cfr = 0; // The strings are equal if (!same_len) { - cfr = (path1[j] == 0); + cfr = (path1[i] == 0); } - } else if (path1[j] == path2[j]) { + } else if (isdigit(path1[i]) && isdigit(path2[j])) { + size_t ii = 0, ij = 0; + while (isdigit(path1[i+ii])) { ii++; } + while (isdigit(path2[j+ij])) { ij++; } + + size_t di = 0, dj = 0; + for (size_t ai = 0; ai < ii; ++ai) { + di = di * 10 + (path1[i+ai] - '0'); + } + for (size_t aj = 0; aj < ij; ++aj) { + dj = dj * 10 + (path2[j+aj] - '0'); + } + + if (di == dj) { + continue; + } + cfr = (di < dj); + } else if (path1[i] == path2[j]) { continue; - } else if (path1[j] == PATHSEP || path2[j] == PATHSEP) { + } else if (path1[i] == PATHSEP || path2[j] == PATHSEP) { /* For comparison we treat PATHSEP as if it was the string terminator. */ - cfr = (path1[j] == PATHSEP); + cfr = (path1[i] == PATHSEP); } else { - char a = path1[j], b = path2[j]; + char a = path1[i], b = path2[j]; if (a >= 'A' && a <= 'Z') a += 32; if (b >= 'A' && b <= 'Z') b += 32; if (a == b) { @@ -1111,7 +1128,7 @@ static int f_path_compare(lua_State *L) { to keep the first case sensitive difference. */ if (same_len && cfr < 0) { /* Give priority to lower-case characters */ - cfr = (path1[j] > path2[j]); + cfr = (path1[i] > path2[j]); } continue; } From 46260b8073c1fe828cceb96112ed6d860bb19d0d Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Wed, 19 Apr 2023 09:02:10 +0800 Subject: [PATCH 074/176] fix(process): check for HANDLE_INVALID (#1475) --- src/api/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/process.c b/src/api/process.c index 2e343c6c..d7bfeb72 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -100,7 +100,7 @@ typedef enum { } filed_e; static void close_fd(process_stream_t *handle) { - if (*handle) { + if (*handle && *handle != HANDLE_INVALID) { #ifdef _WIN32 CloseHandle(*handle); #else From 2090afcccad13d1e6661b44d28a04051128dc93c Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Wed, 19 Apr 2023 09:14:03 +0800 Subject: [PATCH 075/176] ci(build): update action dependencies --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0dabaaa5..398aae67 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,7 +110,7 @@ jobs: run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-universal" >> "$GITHUB_ENV" - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Download artifacts uses: actions/download-artifact@v3 id: download @@ -124,7 +124,7 @@ jobs: bash --version bash scripts/make-universal-binaries.sh ${{ steps.download.outputs.download-path }} "${INSTALL_NAME}" - name: Upload DMG Image - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: macOS Universal DMG Images path: ${{ env.INSTALL_NAME }}.dmg @@ -191,7 +191,7 @@ jobs: - uses: ilammy/msvc-dev-cmd@v1 with: arch: ${{ matrix.arch.target }} - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install meson and ninja From aa2ac0a4ce7c94373c571056cd77028f784b1a14 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 22 Apr 2023 13:24:54 -0400 Subject: [PATCH 076/176] Added in double-clicking on emptyview and tab bar. (#1478) * Added in double-clicking on emptyview and tab bar. * Fixed issue with split tabs. * Early exit if no overlapping node. * Changed category of command to tabbar. * Additional cleanup. * Changed for whether we should show tabs. * Fixed erroneous hover. --- data/core/commands/root.lua | 15 +++++++++++++++ data/core/keymap.lua | 2 +- data/core/node.lua | 9 ++++++++- data/core/rootview.lua | 10 ++++------ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua index acbd697c..0ae4c68e 100644 --- a/data/core/commands/root.lua +++ b/data/core/commands/root.lua @@ -176,3 +176,18 @@ command.add(function() end } ) + +-- double clicking the tab bar, or on the emptyview should open a new doc +command.add(function(x, y) + local node = x and y and core.root_view.root_node:get_child_overlapping_point(x, y) + return node and node:is_in_tab_area(x, y) +end, { + ["tabbar:new-doc"] = function() + command.perform("core:new-doc") + end +}) +command.add("core.emptyview", { + ["emptyview:new-doc"] = function() + command.perform("core:new-doc") + end +}) diff --git a/data/core/keymap.lua b/data/core/keymap.lua index c0a78dd3..f2257a3e 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -369,7 +369,7 @@ keymap.add_direct { ["shift+1lclick"] = "doc:select-to-cursor", ["ctrl+1lclick"] = "doc:split-cursor", ["1lclick"] = "doc:set-cursor", - ["2lclick"] = "doc:set-cursor-word", + ["2lclick"] = { "doc:set-cursor-word", "emptyview:new-doc", "tabbar:new-doc" }, ["3lclick"] = "doc:set-cursor-line", ["shift+left"] = "doc:select-to-previous-char", ["shift+right"] = "doc:select-to-next-char", diff --git a/data/core/node.lua b/data/core/node.lua index aff4bb11..e282882c 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -308,7 +308,7 @@ function Node:tab_hovered_update(px, py) if px >= cx and px < cx + cw and py >= y and py < y + h and config.tab_close_button then self.hovered_close = tab_index end - else + elseif #self.views > self:get_visible_tabs_number() then self.hovered_scroll_button = self:get_scroll_button_index(px, py) or 0 end end @@ -615,6 +615,13 @@ function Node:is_empty() end +function Node:is_in_tab_area(x, y) + if not self:should_show_tabs() then return false end + local _, ty, _, th = self:get_scroll_button_rect(1) + return y >= ty and y < ty + th +end + + function Node:close_all_docviews(keep_active) local node_active_view = self.active_view local lost_active_view = false diff --git a/data/core/rootview.lua b/data/core/rootview.lua index f9bde17e..c6b18c47 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -291,16 +291,14 @@ function RootView:on_mouse_moved(x, y, dx, dy) if last_overlapping_node and last_overlapping_node ~= self.overlapping_node then last_overlapping_node:on_mouse_left() end + if not self.overlapping_node then return end local div = self.root_node:get_divider_overlapping_point(x, y) - local tab_index = self.overlapping_node and self.overlapping_node:get_tab_overlapping_point(x, y) - if self.overlapping_node and self.overlapping_node:get_scroll_button_index(x, y) then + if self.overlapping_node:get_scroll_button_index(x, y) or self.overlapping_node:is_in_tab_area(x, y) then core.request_cursor("arrow") - elseif div and (self.overlapping_node and not self.overlapping_node.active_view:scrollbar_overlaps_point(x, y)) then + elseif div and not self.overlapping_node.active_view:scrollbar_overlaps_point(x, y) then core.request_cursor(div.type == "hsplit" and "sizeh" or "sizev") - elseif tab_index then - core.request_cursor("arrow") - elseif self.overlapping_node then + else core.request_cursor(self.overlapping_node.active_view.cursor) end end From 67147322227a7b0e9ba9c693a36370ff3c40a28f Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Sat, 22 Apr 2023 14:54:42 -0400 Subject: [PATCH 077/176] Fixing linewrapping bug to do with wordwrapping. --- data/plugins/linewrapping.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data/plugins/linewrapping.lua b/data/plugins/linewrapping.lua index b287c523..e461ae52 100644 --- a/data/plugins/linewrapping.lua +++ b/data/plugins/linewrapping.lua @@ -485,7 +485,7 @@ local old_draw_line_body = DocView.draw_line_body function DocView:draw_line_body(line, x, y) if not self.wrapped_settings then return old_draw_line_body(self, line, x, y) end local lh = self:get_line_height() - local idx0 = get_line_idx_col_count(self, line) + local idx0, _, count = get_line_idx_col_count(self, line) for lidx, line1, col1, line2, col2 in self.doc:get_selections(true) do if line >= line1 and line <= line2 then if line1 ~= line then col1 = 1 end @@ -493,12 +493,14 @@ function DocView:draw_line_body(line, x, y) if col1 ~= col2 then local idx1, ncol1 = get_line_idx_col_count(self, line, col1) local idx2, ncol2 = get_line_idx_col_count(self, line, col2) + local start = 0 for i = idx1, idx2 do local x1, x2 = x + (idx1 == i and self:get_col_x_offset(line1, col1) or 0) if idx2 == i then x2 = x + self:get_col_x_offset(line, col2) else - x2 = x + self:get_col_x_offset(line, get_idx_line_length(self, i, line) + 1, true) + start = start + get_idx_line_length(self, i, line) + x2 = x + self:get_col_x_offset(line, start + 1, true) end renderer.draw_rect(x1, y + (i - idx0) * lh, x2 - x1, lh, style.selection) end @@ -514,7 +516,6 @@ function DocView:draw_line_body(line, x, y) end end if draw_highlight then - local _, _, count = get_line_idx_col_count(self, line) for i=1,count do self:draw_line_highlight(x + self.scroll.x, y + lh * (i - 1)) end From a007a190ef0763db38dd0de26e9c7eb48c676267 Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Sun, 23 Apr 2023 16:35:40 +0800 Subject: [PATCH 078/176] fix(rencache): fix compiler warning for printing size_t --- src/rencache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rencache.c b/src/rencache.c index 928d0b0d..52527969 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -142,7 +142,7 @@ static void* push_command(enum CommandType type, int size) { int n = command_buf_idx + size; while (n > command_buf_size) { if (!expand_command_buffer()) { - fprintf(stderr, "Warning: (" __FILE__ "): unable to resize command buffer (%ld)\n", + fprintf(stderr, "Warning: (" __FILE__ "): unable to resize command buffer (%zu)\n", (size_t)(command_buf_size * CMD_BUF_RESIZE_RATE)); resize_issue = true; return NULL; From c255e53d378f6419df3576ce65b2a64e92014e7c Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Wed, 26 Apr 2023 08:29:57 +0800 Subject: [PATCH 079/176] feat(bootstrap): return error string from C searcher --- data/core/start.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/start.lua b/data/core/start.lua index 2ad71d54..f85d4087 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -38,8 +38,8 @@ package.cpath = package.native_plugins = {} package.searchers = { package.searchers[1], package.searchers[2], function(modname) - local path = package.searchpath(modname, package.cpath) - if not path then return nil end + local path, err = package.searchpath(modname, package.cpath) + if not path then return err end return system.load_native_plugin, path end } From e7168a1e00c1fb3890dcf67d2c4c4c6945793bc9 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 29 Apr 2023 18:50:39 +0200 Subject: [PATCH 080/176] Restore horizontal scroll position after scale change (#494) * Restore horizontal scroll position after scale change * Consider `View` horizontal size when restoring horizontal scroll This is needed because `View:get_h_scrollable_size` includes the horizontal size, while `View.scroll.x` doesn't. --- data/plugins/scale.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/data/plugins/scale.lua b/data/plugins/scale.lua index 7c9e6d4c..89a016b7 100644 --- a/data/plugins/scale.lua +++ b/data/plugins/scale.lua @@ -25,11 +25,16 @@ local function set_scale(scale) scale = common.clamp(scale, 0.2, 6) -- save scroll positions - local scrolls = {} + local v_scrolls = {} + local h_scrolls = {} for _, view in ipairs(core.root_view.root_node:get_children()) do local n = view:get_scrollable_size() - if n ~= math.huge and not view:is(CommandView) and n > view.size.y then - scrolls[view] = view.scroll.y / (n - view.size.y) + if n ~= math.huge and n > view.size.y then + v_scrolls[view] = view.scroll.y / (n - view.size.y) + end + local hn = view:get_h_scrollable_size() + if hn ~= math.huge and hn > view.size.x then + h_scrolls[view] = view.scroll.x / (hn - view.size.x) end end @@ -59,10 +64,14 @@ local function set_scale(scale) end -- restore scroll positions - for view, n in pairs(scrolls) do + for view, n in pairs(v_scrolls) do view.scroll.y = n * (view:get_scrollable_size() - view.size.y) view.scroll.to.y = view.scroll.y end + for view, hn in pairs(h_scrolls) do + view.scroll.x = hn * (view:get_h_scrollable_size() - view.size.x) + view.scroll.to.x = view.scroll.x + end core.redraw = true end From 21db8313c161a051cc74b1a10b266066862ceeab Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 6 May 2023 21:36:30 -0400 Subject: [PATCH 081/176] Allowed for overrides of toolbar items, so plugins can add things if they want to with different fonts. (#1157) --- data/plugins/toolbarview.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/plugins/toolbarview.lua b/data/plugins/toolbarview.lua index 9cfa15e8..caf86d71 100644 --- a/data/plugins/toolbarview.lua +++ b/data/plugins/toolbarview.lua @@ -48,7 +48,7 @@ end function ToolbarView:get_icon_width() local max_width = 0 - for i,v in ipairs(self.toolbar_commands) do max_width = math.max(max_width, self.toolbar_font:get_width(v.symbol)) end + for i,v in ipairs(self.toolbar_commands) do max_width = math.max(max_width, (v.font or self.toolbar_font):get_width(v.symbol)) end return max_width end @@ -83,7 +83,7 @@ function ToolbarView:draw() for item, x, y, w, h in self:each_item() do local color = item == self.hovered_item and command.is_valid(item.command) and style.text or style.dim - common.draw_text(self.toolbar_font, color, item.symbol, nil, x, y, 0, h) + common.draw_text(item.font or self.toolbar_font, color, item.symbol, nil, x, y, 0, h) end end From 431c8f4a3636aa659f179b11c6a0392ea0bc51af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Tue, 9 May 2023 10:51:20 -0700 Subject: [PATCH 082/176] detectindent: fix wrong detection reported by Adam (#1500) * The comment patterns had to come before the string ones * The smallest indentation size is now taken into consideration even if it only occurs once, we just make sure its size is more than 1 space. --- data/plugins/detectindent.lua | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/data/plugins/detectindent.lua b/data/plugins/detectindent.lua index f2589ead..8fad044b 100644 --- a/data/plugins/detectindent.lua +++ b/data/plugins/detectindent.lua @@ -37,7 +37,11 @@ local function optimal_indent_from_stat(stat) elseif indent > stat[y] and - indent_occurrences_more_than_once(stat, y) + ( + indent_occurrences_more_than_once(stat, y) + or + (y == count and stat[y] > 1) + ) then score = 0 break @@ -118,10 +122,10 @@ local function get_comment_patterns(syntax, _loop) end if type(pattern.regex) == "table" then table.insert(comments, { - "r", regex.compile(startp), regex.compile(pattern.regex[2]) + "r", regex.compile(startp), regex.compile(pattern.regex[2]), r=startp }) elseif not_is_string then - table.insert(comments, {"r", regex.compile(startp)}) + table.insert(comments, {"r", regex.compile(startp), r=startp}) end end elseif pattern.syntax then @@ -152,6 +156,25 @@ local function get_comment_patterns(syntax, _loop) table.insert(comments, {"p", "^%s*" .. block_comment[1], block_comment[2]}) end end + -- Put comments first and strings last + table.sort(comments, function(c1, c2) + local comment1, comment2 = false, false + if + (c1[1] == "p" and string.find(c1[2], "^%s*", 1, true)) + or + (c1[1] == "r" and string.find(c1["r"], "^\\s*", 1, true)) + then + comment1 = true + end + if + (c2[1] == "p" and string.find(c2[2], "^%s*", 1, true)) + or + (c2[1] == "r" and string.find(c2["r"], "^\\s*", 1, true)) + then + comment2 = true + end + return comment1 and not comment2 + end) comments_cache[syntax] = comments if #comments > 0 then return comments From 252bf87eadf6d967c887c0294f48e4a3ea6867ab Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Sat, 13 May 2023 18:29:20 +0800 Subject: [PATCH 083/176] docs(system): make all parameters for set_window_hit_test optional --- docs/api/system.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/api/system.lua b/docs/api/system.lua index 17c379fa..ffbc6f42 100644 --- a/docs/api/system.lua +++ b/docs/api/system.lua @@ -107,10 +107,12 @@ function system.set_window_bordered(bordered) end ---When then window is run borderless (without system decorations), this ---function allows to set the size of the different regions that allow ---for custom window management. +---To disable custom window management, call this function without any +---arguments --- ----@param title_height number ----@param controls_width number Width of window controls (maximize,minimize and close buttons, etc). ----@param resize_border number The amount of pixels reserved for resizing +---@param title_height? number Height of the window decoration +---@param controls_width? number Width of window controls (maximize,minimize and close buttons, etc). +---@param resize_border? number The amount of pixels reserved for resizing function system.set_window_hit_test(title_height, controls_width, resize_border) end --- From 363b102abc84799ceca0216dfe9068f5a9718269 Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Tue, 16 May 2023 21:18:04 +0800 Subject: [PATCH 084/176] fix(renderer): fix memory leak when freeing glyphsets --- src/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.c b/src/renderer.c index e9e715ef..6d14ea44 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -203,7 +203,7 @@ static RenFont* font_group_get_glyph(GlyphSet** set, GlyphMetric** metric, RenFo static void font_clear_glyph_cache(RenFont* font) { for (int i = 0; i < SUBPIXEL_BITMAPS_CACHED; ++i) { - for (int j = 0; j < MAX_GLYPHSET; ++j) { + for (int j = 0; j < MAX_LOADABLE_GLYPHSETS; ++j) { if (font->sets[i][j]) { if (font->sets[i][j]->surface) SDL_FreeSurface(font->sets[i][j]->surface); From ba753593f363219af680d0620c67d2643a2a1760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Wed, 17 May 2023 07:14:28 -0700 Subject: [PATCH 085/176] Move lineguide below blinking cursor, fixes #1488 (#1511) * Move lineguide below blinking cursor, fixes #1488 * Added config_spec custom color --- data/plugins/lineguide.lua | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/data/plugins/lineguide.lua b/data/plugins/lineguide.lua index 63f9a9ca..5c4a9204 100644 --- a/data/plugins/lineguide.lua +++ b/data/plugins/lineguide.lua @@ -15,6 +15,8 @@ config.plugins.lineguide = common.merge({ -- 120, config.line_limit }, + use_custom_color = false, + custom_color = style.selection, -- The config specification used by gui generators config_spec = { name = "Line Guide", @@ -63,7 +65,21 @@ config.plugins.lineguide = common.merge({ end return new_rulers end - } + }, + { + label = "Use Custom Color", + description = "Enable the utilization of a custom line color.", + path = "use_custom_color", + type = "toggle", + default = false + }, + { + label = "Custom Color", + description = "Applied when the above toggle is enabled.", + path = "custom_color", + type = "color", + default = style.selection + }, } }, config.plugins.lineguide) @@ -79,8 +95,6 @@ end local draw_overlay = DocView.draw_overlay function DocView:draw_overlay(...) - draw_overlay(self, ...) - if type(config.plugins.lineguide) == "table" and @@ -88,10 +102,12 @@ function DocView:draw_overlay(...) and self:is(DocView) then + local conf = config.plugins.lineguide local line_x = self:get_line_screen_position(1) local character_width = self:get_font():get_width("n") local ruler_width = config.plugins.lineguide.width - local ruler_color = style.guide or style.selection + local ruler_color = conf.use_custom_color and conf.custom_color + or (style.guide or style.selection) for k,v in ipairs(config.plugins.lineguide.rulers) do local ruler = get_ruler(v) @@ -106,6 +122,8 @@ function DocView:draw_overlay(...) end end end + -- everything else like the cursor above the line guides + draw_overlay(self, ...) end command.add(nil, { From 35647067d8207dd35e0c08ea3265d887feee701f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Fri, 19 May 2023 10:28:39 -0700 Subject: [PATCH 086/176] Close lua state when exiting on a runtime error (#1487) * Close lua state when exiting on a runtime error * This change allows calling the garbage collector before exiting the application for a cleaner shutdown. * Components like the shared memory object on #1486 will have a better chance at destroying no longer needed resources. * Overriden os.exit to always close the state * Allow setting close param on os.exit override * Simplified the os.exit override a bit more Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.c b/src/main.c index e3a9b1ac..1d1b78ee 100644 --- a/src/main.c +++ b/src/main.c @@ -227,6 +227,10 @@ init_lua: const char *init_lite_code = \ "local core\n" + "local os_exit = os.exit\n" + "os.exit = function(code, close)\n" + " os_exit(code, close == nil and true or close)\n" + "end\n" "xpcall(function()\n" " local match = require('utf8extra').match\n" " HOME = os.getenv('" LITE_OS_HOME "')\n" From 528e5641fba79bd66a610aa94e65b404309415cd Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 20 May 2023 19:54:58 +0200 Subject: [PATCH 087/176] Add mouse grab (#1501) * Add mouse grab We now also send mouse movement events only to the interested view. * Add deprecation messages handler * Make various `View`s respect `on_mouse_left` * `StatusView` * `TitleView` * `TreeView` * `ToolbarView` * Fix scrollbar in `TreeView` not updating We were in some cases sending outdated mouse positions to the scrollbar, which made it think that the mouse was hovering it. This also updates the hovered item more responsively during scroll. --- data/core/commands/root.lua | 6 +-- data/core/init.lua | 11 ++++ data/core/node.lua | 14 ++++-- data/core/rootview.lua | 98 ++++++++++++++++++++++++++++-------- data/core/statusview.lua | 6 +++ data/core/titleview.lua | 6 +++ data/plugins/toolbarview.lua | 10 ++++ data/plugins/treeview.lua | 21 +++++--- 8 files changed, 137 insertions(+), 35 deletions(-) diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua index 0ae4c68e..03f22c25 100644 --- a/data/core/commands/root.lua +++ b/data/core/commands/root.lua @@ -104,7 +104,7 @@ end, t) command.add(nil, { ["root:scroll"] = function(delta) - local view = (core.root_view.overlapping_node and core.root_view.overlapping_node.active_view) or core.active_view + local view = core.root_view.overlapping_view or core.active_view if view and view.scrollable then view.scroll.to.y = view.scroll.to.y + delta * -config.mouse_wheel_scroll return true @@ -112,7 +112,7 @@ command.add(nil, { return false end, ["root:horizontal-scroll"] = function(delta) - local view = (core.root_view.overlapping_node and core.root_view.overlapping_node.active_view) or core.active_view + local view = core.root_view.overlapping_view or core.active_view if view and view.scrollable then view.scroll.to.x = view.scroll.to.x + delta * -config.mouse_wheel_scroll return true @@ -154,7 +154,7 @@ command.add(function(node) ) command.add(function() - local node = core.root_view.overlapping_node + local node = core.root_view.root_node:get_child_overlapping_point(core.root_view.mouse.x, core.root_view.mouse.y) if not node then return false end return (node.hovered_tab or node.hovered_scroll_button > 0) and true, node end, diff --git a/data/core/init.lua b/data/core/init.lua index 050a8ee2..2b9be2a1 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1490,4 +1490,15 @@ function core.on_error(err) end +local alerted_deprecations = {} +---Show deprecation notice once per `kind`. +--- +---@param kind string +function core.deprecation_log(kind) + if alerted_deprecations[kind] then return end + alerted_deprecations[kind] = true + core.warn("Used deprecated functionality [%s]. Check if your plugins are up to date.", kind) +end + + return core diff --git a/data/core/node.lua b/data/core/node.lua index e282882c..0ea2c07e 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -18,7 +18,6 @@ function Node:new(type) if self.type == "leaf" then self:add_view(EmptyView()) end - self.hovered = {x = -1, y = -1 } self.hovered_close = 0 self.tab_shift = 0 self.tab_offset = 1 @@ -33,9 +32,10 @@ function Node:propagate(fn, ...) end +---@deprecated function Node:on_mouse_moved(x, y, ...) + core.deprecation_log("Node:on_mouse_moved") if self.type == "leaf" then - self.hovered.x, self.hovered.y = x, y self.active_view:on_mouse_moved(x, y, ...) else self:propagate("on_mouse_moved", x, y, ...) @@ -43,7 +43,9 @@ function Node:on_mouse_moved(x, y, ...) end +---@deprecated function Node:on_mouse_released(...) + core.deprecation_log("Node:on_mouse_released") if self.type == "leaf" then self.active_view:on_mouse_released(...) else @@ -52,7 +54,9 @@ function Node:on_mouse_released(...) end +---@deprecated function Node:on_mouse_left() + core.deprecation_log("Node:on_mouse_left") if self.type == "leaf" then self.active_view:on_mouse_left() else @@ -60,7 +64,10 @@ function Node:on_mouse_left() end end + +---@deprecated function Node:on_touch_moved(...) + core.deprecation_log("Node:on_touch_moved") if self.type == "leaf" then self.active_view:on_touch_moved(...) else @@ -68,6 +75,7 @@ function Node:on_touch_moved(...) end end + function Node:consume(node) for k, _ in pairs(self) do self[k] = nil end for k, v in pairs(node) do self[k] = v end @@ -489,7 +497,7 @@ function Node:update() for _, view in ipairs(self.views) do view:update() end - self:tab_hovered_update(self.hovered.x, self.hovered.y) + self:tab_hovered_update(core.root_view.mouse.x, core.root_view.mouse.y) local tab_width = self:target_tab_width() self:move_towards("tab_shift", tab_width * (self.tab_offset - 1), nil, "tabs") self:move_towards("tab_width", tab_width, nil, "tabs") diff --git a/data/core/rootview.lua b/data/core/rootview.lua index c6b18c47..18ae40ab 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -24,6 +24,9 @@ function RootView:new() base_color = style.drag_overlay_tab, color = { table.unpack(style.drag_overlay_tab) } } self.drag_overlay_tab.to = { x = 0, y = 0, w = 0, h = 0 } + self.grab = nil -- = {view = nil, button = nil} + self.overlapping_view = nil + self.touched_view = nil end @@ -116,6 +119,31 @@ function RootView:close_all_docviews(keep_active) end +---Obtain mouse grab. +--- +---This means that mouse movements will be sent to the specified view, even when +---those occur outside of it. +---There can't be multiple mouse grabs, even for different buttons. +---@see RootView:ungrab_mouse +---@param button core.view.mousebutton +---@param view core.view +function RootView:grab_mouse(button, view) + assert(self.grab == nil) + self.grab = {view = view, button = button} +end + + +---Release mouse grab. +--- +---The specified button *must* be the last button that grabbed the mouse. +---@see RootView:grab_mouse +---@param button core.view.mousebutton +function RootView:ungrab_mouse(button) + assert(self.grab and self.grab.button == button) + self.grab = nil +end + + ---Function to intercept mouse pressed events on the active view. ---Do nothing by default. ---@param button core.view.mousebutton @@ -132,6 +160,10 @@ end ---@param clicks integer ---@return boolean function RootView:on_mouse_pressed(button, x, y, clicks) + -- If there is a grab, release it first + if self.grab then + self:on_mouse_released(self.grab.button, x, y) + end local div = self.root_node:get_divider_overlapping_point(x, y) local node = self.root_node:get_child_overlapping_point(x, y) if div and (node and not node.active_view:scrollbar_overlaps_point(x, y)) then @@ -156,6 +188,7 @@ function RootView:on_mouse_pressed(button, x, y, clicks) end elseif not self.dragged_node then -- avoid sending on_mouse_pressed events when dragging tabs core.set_active_view(node.active_view) + self:grab_mouse(button, node.active_view) return self.on_view_mouse_pressed(button, x, y, clicks) or node.active_view:on_mouse_pressed(button, x, y, clicks) end end @@ -188,6 +221,21 @@ end ---@param x number ---@param y number function RootView:on_mouse_released(button, x, y, ...) + if self.grab then + if self.grab.button == button then + local grabbed_view = self.grab.view + grabbed_view:on_mouse_released(button, x, y, ...) + self:ungrab_mouse(button) + + -- If the mouse was released over a different view, send it the mouse position + local hovered_view = self.root_node:get_child_overlapping_point(x, y) + if grabbed_view ~= hovered_view then + self:on_mouse_moved(x, y, 0, 0) + end + end + return + end + if self.dragged_divider then self.dragged_divider = nil end @@ -228,8 +276,6 @@ function RootView:on_mouse_released(button, x, y, ...) end self.dragged_node = nil end - else -- avoid sending on_mouse_released events when dragging tabs - self.root_node:on_mouse_released(button, x, y, ...) end end @@ -250,6 +296,14 @@ end ---@param dx number ---@param dy number function RootView:on_mouse_moved(x, y, dx, dy) + self.mouse.x, self.mouse.y = x, y + + if self.grab then + self.grab.view:on_mouse_moved(x, y, dx, dy) + core.request_cursor(self.grab.view.cursor) + return + end + if core.active_view == core.nag_view then core.request_cursor("arrow") core.active_view:on_mouse_moved(x, y, dx, dy) @@ -269,8 +323,6 @@ function RootView:on_mouse_moved(x, y, dx, dy) return end - self.mouse.x, self.mouse.y = x, y - local dn = self.dragged_node if dn and not dn.dragging then -- start dragging only after enough movement @@ -283,30 +335,33 @@ function RootView:on_mouse_moved(x, y, dx, dy) -- avoid sending on_mouse_moved events when dragging tabs if dn then return end - self.root_node:on_mouse_moved(x, y, dx, dy) + local last_overlapping_view = self.overlapping_view + local overlapping_node = self.root_node:get_child_overlapping_point(x, y) + self.overlapping_view = overlapping_node and overlapping_node.active_view - local last_overlapping_node = self.overlapping_node - self.overlapping_node = self.root_node:get_child_overlapping_point(x, y) - - if last_overlapping_node and last_overlapping_node ~= self.overlapping_node then - last_overlapping_node:on_mouse_left() + if last_overlapping_view and last_overlapping_view ~= self.overlapping_view then + last_overlapping_view:on_mouse_left() end - if not self.overlapping_node then return end + + if not self.overlapping_view then return end + + self.overlapping_view:on_mouse_moved(x, y, dx, dy) + core.request_cursor(self.overlapping_view.cursor) + + if not overlapping_node then return end local div = self.root_node:get_divider_overlapping_point(x, y) - if self.overlapping_node:get_scroll_button_index(x, y) or self.overlapping_node:is_in_tab_area(x, y) then + if overlapping_node:get_scroll_button_index(x, y) or overlapping_node:is_in_tab_area(x, y) then core.request_cursor("arrow") - elseif div and not self.overlapping_node.active_view:scrollbar_overlaps_point(x, y) then + elseif div and not self.overlapping_view:scrollbar_overlaps_point(x, y) then core.request_cursor(div.type == "hsplit" and "sizeh" or "sizev") - else - core.request_cursor(self.overlapping_node.active_view.cursor) end end function RootView:on_mouse_left() - if self.overlapping_node then - self.overlapping_node:on_mouse_left() + if self.overlapping_view then + self.overlapping_view:on_mouse_left() end end @@ -333,15 +388,16 @@ function RootView:on_text_input(...) end function RootView:on_touch_pressed(x, y, ...) - self.touched_node = self.root_node:get_child_overlapping_point(x, y) + local touched_node = self.root_node:get_child_overlapping_point(x, y) + self.touched_view = touched_node and touched_node.active_view end function RootView:on_touch_released(x, y, ...) - self.touched_node = nil + self.touched_view = nil end function RootView:on_touch_moved(x, y, dx, dy, ...) - if not self.touched_node then return end + if not self.touched_view then return end if core.active_view == core.nag_view then core.active_view:on_touch_moved(x, y, dx, dy, ...) return @@ -372,7 +428,7 @@ function RootView:on_touch_moved(x, y, dx, dy, ...) -- avoid sending on_touch_moved events when dragging tabs if dn then return end - self.touched_node:on_touch_moved(x, y, dx, dy, ...) + self.touched_view:on_touch_moved(x, y, dx, dy, ...) end function RootView:on_ime_text_editing(...) diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 930c7aef..731c0552 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -989,6 +989,12 @@ function StatusView:on_mouse_pressed(button, x, y, clicks) end +function StatusView:on_mouse_left() + StatusView.super.on_mouse_left(self) + self.hovered_item = {} +end + + function StatusView:on_mouse_moved(x, y, dx, dy) if not self.visible then return end StatusView.super.on_mouse_moved(self, x, y, dx, dy) diff --git a/data/core/titleview.lua b/data/core/titleview.lua index 69315be1..482d6c8e 100644 --- a/data/core/titleview.lua +++ b/data/core/titleview.lua @@ -112,6 +112,12 @@ function TitleView:on_mouse_pressed(button, x, y, clicks) end +function TitleView:on_mouse_left() + TitleView.super.on_mouse_left(self) + self.hovered_item = nil +end + + function TitleView:on_mouse_moved(px, py, ...) if self.size.y == 0 then return end TitleView.super.on_mouse_moved(self, px, py, ...) diff --git a/data/plugins/toolbarview.lua b/data/plugins/toolbarview.lua index caf86d71..ddc0f39d 100644 --- a/data/plugins/toolbarview.lua +++ b/data/plugins/toolbarview.lua @@ -100,6 +100,16 @@ function ToolbarView:on_mouse_pressed(button, x, y, clicks) end +function ToolbarView:on_mouse_left() + ToolbarView.super.on_mouse_left(self) + if self.tooltip then + core.status_view:remove_tooltip() + self.tooltip = false + end + self.hovered_item = nil +end + + function ToolbarView:on_mouse_moved(px, py, ...) if not self.visible then return end ToolbarView.super.on_mouse_moved(self, px, py, ...) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index cab3d410..b27ba554 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -51,7 +51,7 @@ function TreeView:new() self.target_size = config.plugins.treeview.size self.cache = {} self.tooltip = { x = 0, y = 0, begin = 0, alpha = 0 } - self.cursor_pos = { x = 0, y = 0 } + self.last_scroll_y = 0 self.item_icon_width = 0 self.item_text_spacing = 0 @@ -251,10 +251,9 @@ function TreeView:get_text_bounding_box(item, x, y, w, h) end + function TreeView:on_mouse_moved(px, py, ...) if not self.visible then return end - self.cursor_pos.x = px - self.cursor_pos.y = py if TreeView.super.on_mouse_moved(self, px, py, ...) then -- mouse movement handled by the View (scrollbar) self.hovered_item = nil @@ -281,6 +280,12 @@ function TreeView:on_mouse_moved(px, py, ...) end +function TreeView:on_mouse_left() + TreeView.super.on_mouse_left(self) + self.hovered_item = nil +end + + function TreeView:update() -- update width local dest = self.visible and self.target_size or 0 @@ -304,10 +309,10 @@ function TreeView:update() self.item_text_spacing = style.icon_font:get_width("f") / 2 -- this will make sure hovered_item is updated - -- we don't want events when the thing is scrolling fast - local dy = math.abs(self.scroll.to.y - self.scroll.y) - if self.scroll.to.y ~= 0 and dy < self:get_item_height() then - self:on_mouse_moved(self.cursor_pos.x, self.cursor_pos.y, 0, 0) + local dy = math.abs(self.last_scroll_y - self.scroll.y) + if dy > 0 then + self:on_mouse_moved(core.root_view.mouse.x, core.root_view.mouse.y, 0, 0) + self.last_scroll_y = self.scroll.y end local config = config.plugins.treeview @@ -751,7 +756,7 @@ command.add( ["treeview-context:show"] = function() if view.hovered_item then - menu:show(view.cursor_pos.x, view.cursor_pos.y) + menu:show(core.root_view.mouse.x, core.root_view.mouse.y) return end From 862aba0f9143a5713603ebffe55155898e6a467b Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 24 May 2023 04:23:27 +0200 Subject: [PATCH 088/176] Mark `linewrapping` `open_files` table as weak We weren't correctly garbage-collecting `Doc`s, so we had `Highlighter`s stay alive over their due time. --- data/plugins/linewrapping.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/plugins/linewrapping.lua b/data/plugins/linewrapping.lua index e461ae52..62412720 100644 --- a/data/plugins/linewrapping.lua +++ b/data/plugins/linewrapping.lua @@ -310,7 +310,7 @@ local function get_line_col_from_index_and_x(docview, idx, x) end -local open_files = {} +local open_files = setmetatable({ }, { __mode = "k" }) local old_doc_insert = Doc.raw_insert function Doc:raw_insert(line, col, text, undo_stack, time) From f80a4563be9af2b211924a73abcfe5827cb66a71 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 9 Jun 2023 03:50:34 +0200 Subject: [PATCH 089/176] When logging don't use `core.status_view` if not yet initialized --- data/core/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/core/init.lua b/data/core/init.lua index 2b9be2a1..9aba4c70 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1197,7 +1197,9 @@ function core.custom_log(level, show, backtrace, fmt, ...) local text = string.format(fmt, ...) if show then local s = style.log[level] - core.status_view:show_message(s.icon, s.color, text) + if core.status_view then + core.status_view:show_message(s.icon, s.color, text) + end end local info = debug.getinfo(2, "Sl") From 122b72ed9004c4aaf60809ceb1449092f37f9fac Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 9 Jun 2023 15:18:02 +0200 Subject: [PATCH 090/176] Change AppID (#1187) This ID reflects our domain (lite-xl.com). --- README.md | 4 ++-- meson.build | 4 ++-- resources/README.md | 4 ++-- ..._xl.lite_xl.appdata.xml => com.lite_xl.LiteXL.appdata.xml} | 4 ++-- ...org.lite_xl.lite_xl.desktop => com.lite_xl.LiteXL.desktop} | 0 scripts/appimage.sh | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) rename resources/linux/{org.lite_xl.lite_xl.appdata.xml => com.lite_xl.LiteXL.appdata.xml} (89%) rename resources/linux/{org.lite_xl.lite_xl.desktop => com.lite_xl.LiteXL.desktop} (100%) diff --git a/README.md b/README.md index 5d7e947b..f8f701b6 100644 --- a/README.md +++ b/README.md @@ -122,8 +122,8 @@ To uninstall just run: ```sh rm -f $HOME/.local/bin/lite-xl rm -rf $HOME/.local/share/icons/hicolor/scalable/apps/lite-xl.svg \ - $HOME/.local/share/applications/org.lite_xl.lite_xl.desktop \ - $HOME/.local/share/metainfo/org.lite_xl.lite_xl.appdata.xml \ + $HOME/.local/share/applications/com.lite_xl.LiteXL.desktop \ + $HOME/.local/share/metainfo/com.lite_xl.LiteXL.appdata.xml \ $HOME/.local/share/lite-xl ``` diff --git a/meson.build b/meson.build index cfef8ec8..c3b0569c 100644 --- a/meson.build +++ b/meson.build @@ -192,10 +192,10 @@ else install_data('resources/icons/lite-xl.svg', install_dir : 'share/icons/hicolor/scalable/apps' ) - install_data('resources/linux/org.lite_xl.lite_xl.desktop', + install_data('resources/linux/com.lite_xl.LiteXL.desktop', install_dir : 'share/applications' ) - install_data('resources/linux/org.lite_xl.lite_xl.appdata.xml', + install_data('resources/linux/com.lite_xl.LiteXL.appdata.xml', install_dir : 'share/metainfo' ) endif diff --git a/resources/README.md b/resources/README.md index cf30432c..4cd85256 100644 --- a/resources/README.md +++ b/resources/README.md @@ -9,8 +9,8 @@ This folder contains resources that is used for building or packaging the projec ### Packaging - `icons/icon.{icns,ico,inl,rc,svg}`: lite-xl icon in various formats. -- `linux/org.lite_xl.lite_xl.appdata.xml`: AppStream metadata. -- `linux/org.lite_xl.lite_xl.desktop`: Desktop file for Linux desktops. +- `linux/com.lite_xl.LiteXL.appdata.xml`: AppStream metadata. +- `linux/com.lite_xl.LiteXL.desktop`: Desktop file for Linux desktops. - `macos/appdmg.png`: Background image for packaging MacOS DMGs. - `macos/Info.plist.in`: Template for generating `info.plist` on MacOS. See `macos/macos-retina-display.md` for details. - `windows/001-lua-unicode.diff`: Patch for allowing Lua to load files with UTF-8 filenames on Windows. diff --git a/resources/linux/org.lite_xl.lite_xl.appdata.xml b/resources/linux/com.lite_xl.LiteXL.appdata.xml similarity index 89% rename from resources/linux/org.lite_xl.lite_xl.appdata.xml rename to resources/linux/com.lite_xl.LiteXL.appdata.xml index b707ebe1..8e033d03 100644 --- a/resources/linux/org.lite_xl.lite_xl.appdata.xml +++ b/resources/linux/com.lite_xl.LiteXL.appdata.xml @@ -1,12 +1,12 @@ - org.lite_xl.lite_xl + com.lite_xl.LiteXL MIT MIT Lite XL A lightweight text editor written in Lua - org.lite_xl.lite_xl.desktop + com.lite_xl.LiteXL.desktop

diff --git a/resources/linux/org.lite_xl.lite_xl.desktop b/resources/linux/com.lite_xl.LiteXL.desktop similarity index 100% rename from resources/linux/org.lite_xl.lite_xl.desktop rename to resources/linux/com.lite_xl.LiteXL.desktop diff --git a/scripts/appimage.sh b/scripts/appimage.sh index 17551a48..0548450d 100644 --- a/scripts/appimage.sh +++ b/scripts/appimage.sh @@ -138,7 +138,7 @@ generate_appimage() { mv AppRun LiteXL.AppDir/ # These could be symlinks but it seems they doesn't work with AppimageLauncher cp resources/icons/lite-xl.svg LiteXL.AppDir/ - cp resources/linux/org.lite_xl.lite_xl.desktop LiteXL.AppDir/ + cp resources/linux/com.lite_xl.LiteXL.desktop LiteXL.AppDir/ if [[ $ADDONS == true ]]; then addons_download "${BUILD_DIR}" From ff38e449d1304b751271ba4850424dce17f4feac Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 9 Jun 2023 15:31:59 +0200 Subject: [PATCH 091/176] Revert "core syntax: strip the path from filename on syntax.get (#1168)" (#1322) * Revert "core syntax: strip the path from filename on syntax.get (#1168)" This reverts commit af6c4bc152234e13f3e12819e361e1b92a387013. The previous behavior was correct and allowed access to the full path for path-dependant syntaxes. * Use `Doc.abs_filename` to obtain syntax when possible This allows matching full paths in language syntaxes, but we lose the possibility of matching the project root. --- data/core/doc/init.lua | 7 ++++++- data/core/syntax.lua | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 74116fd5..572b2d78 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -44,7 +44,12 @@ end function Doc:reset_syntax() local header = self:get_text(1, 1, self:position_offset(1, 1, 128)) - local syn = syntax.get(self.filename or "", header) + local path = self.abs_filename + if not path and self.filename then + path = core.project_dir .. PATHSEP .. self.filename + end + if path then path = common.normalize_path(path) end + local syn = syntax.get(path or "", header) if self.syntax ~= syn then self.syntax = syn self.highlighter:soft_reset() diff --git a/data/core/syntax.lua b/data/core/syntax.lua index 6fe8984a..977983c1 100644 --- a/data/core/syntax.lua +++ b/data/core/syntax.lua @@ -44,7 +44,7 @@ local function find(string, field) end function syntax.get(filename, header) - return find(common.basename(filename), "files") + return find(filename, "files") or (header and find(header, "headers")) or plain_text_syntax end From 12a552931e1312517cb52a1325e3d002361eca44 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 9 Jun 2023 15:34:34 +0200 Subject: [PATCH 092/176] Make `Doc:sanitize_position` return a more appropriate `col` (#1469) If `line` is out of range, return the `col` "closest" to the original values. --- data/core/doc/init.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 572b2d78..bf5895fb 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -281,9 +281,13 @@ end -- End of cursor seciton. function Doc:sanitize_position(line, col) - line = common.clamp(line, 1, #self.lines) - col = common.clamp(col, 1, #self.lines[line]) - return line, col + local nlines = #self.lines + if line > nlines then + return nlines, #self.lines[nlines] + elseif line < 1 then + return 1, 1 + end + return line, common.clamp(col, 1, #self.lines[line]) end From 94b4825754bf3631c0618c32a1b82287cf999332 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 9 Jun 2023 15:37:08 +0200 Subject: [PATCH 093/176] Show cursor at the start of the next line when selecting full lines (#761) This was the previous behavior that regressed with the keymap clicks. This also better shows that the selection extends to the next line. --- data/core/commands/doc.lua | 2 +- data/core/docview.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 0530f6e9..aa73a2c0 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -359,7 +359,7 @@ local commands = { ["doc:select-lines"] = function(dv) for idx, line1, _, line2 in dv.doc:get_selections(true) do append_line_if_last_line(line2) - dv.doc:set_selections(idx, line1, 1, line2 + 1, 1) + dv.doc:set_selections(idx, line2 + 1, 1, line1, 1) end end, diff --git a/data/core/docview.lua b/data/core/docview.lua index 7b04dba4..d8ba562c 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -317,7 +317,7 @@ function DocView:mouse_selection(doc, snap_type, line1, col1, line2, col2) line1, col1 = translate.start_of_word(doc, line1, col1) line2, col2 = translate.end_of_word(doc, line2, col2) elseif snap_type == "lines" then - col1, col2 = 1, math.huge + col1, col2, line2 = 1, 1, line2 + 1 end if swap then return line2, col2, line1, col1 From e6c7001b5a1c3bead3af61dc9102d6267b2796bf Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 9 Jun 2023 15:44:20 +0200 Subject: [PATCH 094/176] Add top tab margins (#1479) adapted from #810 to allow styles to decide upon the top margin of the tab list --- data/core/node.lua | 21 +++++++++++++++------ data/core/style.lua | 12 +++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/data/core/node.lua b/data/core/node.lua index 0ea2c07e..3ae9b256 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -334,10 +334,17 @@ function Node:get_child_overlapping_point(x, y) return child:get_child_overlapping_point(x, y) end +-- returns: total height, text padding, top margin +local function get_tab_y_sizes() + local height = style.font:get_height() + local padding = style.padding.y + local margin = style.margin.tab.top + return height + (padding * 2) + margin, padding, margin +end function Node:get_scroll_button_rect(index) local w, pad = get_scroll_button_width() - local h = style.font:get_height() + style.padding.y * 2 + local h = get_tab_y_sizes() local x = self.position.x + (index == 1 and self.size.x - w * 2 or self.size.x - w) return x, self.position.y, w, h, pad end @@ -348,8 +355,8 @@ function Node:get_tab_rect(idx) local x0 = self.position.x local x1 = x0 + common.clamp(self.tab_width * (idx - 1) - self.tab_shift, 0, maxw) local x2 = x0 + common.clamp(self.tab_width * idx - self.tab_shift, 0, maxw) - local h = style.font:get_height() + style.padding.y * 2 - return x1, self.position.y, x2 - x1, h + local h, pad_y, margin_y = get_tab_y_sizes() + return x1, self.position.y, x2 - x1, h, margin_y end @@ -540,6 +547,7 @@ function Node:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalo if is_active then color = style.text renderer.draw_rect(x, y, w, h, style.background) + renderer.draw_rect(x, y, w, ds, style.divider) renderer.draw_rect(x + w, y, ds, h, style.divider) renderer.draw_rect(x - ds, y, ds, h, style.divider) end @@ -547,7 +555,8 @@ function Node:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalo end function Node:draw_tab(view, is_active, is_hovered, is_close_hovered, x, y, w, h, standalone) - x, y, w, h = self:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalone) + local _, padding_y, margin_y = get_tab_y_sizes() + x, y, w, h = self:draw_tab_borders(view, is_active, is_hovered, x, y + margin_y, w, h - margin_y, standalone) -- Close button local cx, cw, cpad = close_button_location(x, w) local show_close_button = ((is_active or is_hovered) and not standalone and config.tab_close_button) @@ -768,7 +777,7 @@ function Node:get_drag_overlay_tab_position(x, y, dragged_node, dragged_index) tab_index = self:get_visible_tabs_number() + (self.tab_offset - 1 or 0) end end - local tab_x, tab_y, tab_w, tab_h = self:get_tab_rect(tab_index) + local tab_x, tab_y, tab_w, tab_h, margin_y = self:get_tab_rect(tab_index) if x > tab_x + tab_w / 2 and tab_index <= #self.views then -- use next tab tab_x = tab_x + tab_w @@ -779,7 +788,7 @@ function Node:get_drag_overlay_tab_position(x, y, dragged_node, dragged_index) tab_index = tab_index - 1 tab_x = tab_x - tab_w end - return tab_index, tab_x, tab_y, tab_w, tab_h + return tab_index, tab_x, tab_y + margin_y, tab_w, tab_h - margin_y end return Node diff --git a/data/core/style.lua b/data/core/style.lua index 3e340c57..8f174315 100644 --- a/data/core/style.lua +++ b/data/core/style.lua @@ -1,13 +1,23 @@ local common = require "core.common" local style = {} -style.padding = { x = common.round(14 * SCALE), y = common.round(7 * SCALE) } style.divider_size = common.round(1 * SCALE) style.scrollbar_size = common.round(4 * SCALE) style.expanded_scrollbar_size = common.round(12 * SCALE) style.caret_width = common.round(2 * SCALE) style.tab_width = common.round(170 * SCALE) +style.padding = { + x = common.round(14 * SCALE), + y = common.round(7 * SCALE), +} + +style.margin = { + tab = { + top = common.round(-style.divider_size * SCALE) + } +} + -- The function renderer.font.load can accept an option table as a second optional argument. -- It shoud be like the following: -- From 9bb658979046bb9aee7d5bf36bd7fa703510f753 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 13 Jun 2023 22:45:43 +0200 Subject: [PATCH 095/176] Increase number of loadable glyphsets (#1524) This should be enough to load every unicode codepoint. --- src/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.c b/src/renderer.c index 6d14ea44..e10dd916 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -17,7 +17,7 @@ #include "renwindow.h" #define MAX_GLYPHSET 256 -#define MAX_LOADABLE_GLYPHSETS 1024 +#define MAX_LOADABLE_GLYPHSETS 4096 #define SUBPIXEL_BITMAPS_CACHED 3 RenWindow window_renderer = {0}; From 6e113cb15e8c53d9b6ede5090da2e415337f4ca6 Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 16 Jun 2023 16:19:52 +0200 Subject: [PATCH 096/176] Attach command buffer to Renderer Window (#1472) --- src/api/renderer.c | 4 ++-- src/rencache.c | 49 ++++++++++++++++++++++------------------------ src/rencache.h | 4 ++-- src/renderer.c | 9 ++++----- src/renwindow.c | 6 ++++++ src/renwindow.h | 4 ++++ 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index b619b586..901824fe 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -311,7 +311,7 @@ static int f_set_clip_rect(lua_State *L) { lua_Number w = luaL_checknumber(L, 3); lua_Number h = luaL_checknumber(L, 4); RenRect rect = rect_to_grid(x, y, w, h); - rencache_set_clip_rect(rect); + rencache_set_clip_rect(&window_renderer, rect); return 0; } @@ -323,7 +323,7 @@ static int f_draw_rect(lua_State *L) { lua_Number h = luaL_checknumber(L, 4); RenRect rect = rect_to_grid(x, y, w, h); RenColor color = checkcolor(L, 5, 255); - rencache_draw_rect(rect, color); + rencache_draw_rect(&window_renderer, rect, color); return 0; } diff --git a/src/rencache.c b/src/rencache.c index 52527969..d28ed543 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -65,10 +65,7 @@ static unsigned cells_buf2[CELLS_X * CELLS_Y]; static unsigned *cells_prev = cells_buf1; static unsigned *cells = cells_buf2; static RenRect rect_buf[CELLS_X * CELLS_Y / 2]; -size_t command_buf_size = 0; -uint8_t *command_buf = NULL; static bool resize_issue; -static int command_buf_idx; static RenRect screen_rect; static RenRect last_clip_rect; static bool show_debug; @@ -116,21 +113,21 @@ static RenRect merge_rects(RenRect a, RenRect b) { return (RenRect) { x1, y1, x2 - x1, y2 - y1 }; } -static bool expand_command_buffer() { - size_t new_size = command_buf_size * CMD_BUF_RESIZE_RATE; +static bool expand_command_buffer(RenWindow *window_renderer) { + size_t new_size = window_renderer->command_buf_size * CMD_BUF_RESIZE_RATE; if (new_size == 0) { new_size = CMD_BUF_INIT_SIZE; } - uint8_t *new_command_buf = realloc(command_buf, new_size); + uint8_t *new_command_buf = realloc(window_renderer->command_buf, new_size); if (!new_command_buf) { return false; } - command_buf_size = new_size; - command_buf = new_command_buf; + window_renderer->command_buf_size = new_size; + window_renderer->command_buf = new_command_buf; return true; } -static void* push_command(enum CommandType type, int size) { +static void* push_command(RenWindow *window_renderer, enum CommandType type, int size) { if (resize_issue) { // Don't push new commands as we had problems resizing the command buffer. // Let's wait for the next frame. @@ -139,17 +136,17 @@ static void* push_command(enum CommandType type, int size) { size_t alignment = alignof(max_align_t) - 1; size += COMMAND_BARE_SIZE; size = (size + alignment) & ~alignment; - int n = command_buf_idx + size; - while (n > command_buf_size) { - if (!expand_command_buffer()) { + int n = window_renderer->command_buf_idx + size; + while (n > window_renderer->command_buf_size) { + if (!expand_command_buffer(window_renderer)) { fprintf(stderr, "Warning: (" __FILE__ "): unable to resize command buffer (%zu)\n", - (size_t)(command_buf_size * CMD_BUF_RESIZE_RATE)); + (size_t)(window_renderer->command_buf_size * CMD_BUF_RESIZE_RATE)); resize_issue = true; return NULL; } } - Command *cmd = (Command*) (command_buf + command_buf_idx); - command_buf_idx = n; + Command *cmd = (Command*) (window_renderer->command_buf + window_renderer->command_buf_idx); + window_renderer->command_buf_idx = n; memset(cmd, 0, size); cmd->type = type; cmd->size = size; @@ -157,13 +154,13 @@ static void* push_command(enum CommandType type, int size) { } -static bool next_command(Command **prev) { +static bool next_command(RenWindow *window_renderer, Command **prev) { if (*prev == NULL) { - *prev = (Command*) command_buf; + *prev = (Command*) window_renderer->command_buf; } else { *prev = (Command*) (((char*) *prev) + (*prev)->size); } - return *prev != ((Command*) (command_buf + command_buf_idx)); + return *prev != ((Command*) (window_renderer->command_buf + window_renderer->command_buf_idx)); } @@ -172,8 +169,8 @@ void rencache_show_debug(bool enable) { } -void rencache_set_clip_rect(RenRect rect) { - SetClipCommand *cmd = push_command(SET_CLIP, sizeof(SetClipCommand)); +void rencache_set_clip_rect(RenWindow *window_renderer, RenRect rect) { + SetClipCommand *cmd = push_command(window_renderer, SET_CLIP, sizeof(SetClipCommand)); if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); last_clip_rect = cmd->rect; @@ -181,11 +178,11 @@ void rencache_set_clip_rect(RenRect rect) { } -void rencache_draw_rect(RenRect rect, RenColor color) { +void rencache_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { if (rect.width == 0 || rect.height == 0 || !rects_overlap(last_clip_rect, rect)) { return; } - DrawRectCommand *cmd = push_command(DRAW_RECT, sizeof(DrawRectCommand)); + DrawRectCommand *cmd = push_command(window_renderer, DRAW_RECT, sizeof(DrawRectCommand)); if (cmd) { cmd->rect = rect; cmd->color = color; @@ -198,7 +195,7 @@ double rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const cha RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; - DrawTextCommand *cmd = push_command(DRAW_TEXT, sizeof(DrawTextCommand) + sz); + DrawTextCommand *cmd = push_command(window_renderer, DRAW_TEXT, sizeof(DrawTextCommand) + sz); if (cmd) { memcpy(cmd->text, text, sz); cmd->color = color; @@ -265,7 +262,7 @@ void rencache_end_frame(RenWindow *window_renderer) { /* update cells from commands */ Command *cmd = NULL; RenRect cr = screen_rect; - while (next_command(&cmd)) { + while (next_command(window_renderer, &cmd)) { /* cmd->command[0] should always be the Command rect */ if (cmd->type == SET_CLIP) { cr = cmd->command[0]; } RenRect r = intersect_rects(cmd->command[0], cr); @@ -308,7 +305,7 @@ void rencache_end_frame(RenWindow *window_renderer) { ren_set_clip_rect(window_renderer, r); cmd = NULL; - while (next_command(&cmd)) { + while (next_command(window_renderer, &cmd)) { SetClipCommand *ccmd = (SetClipCommand*)&cmd->command; DrawRectCommand *rcmd = (DrawRectCommand*)&cmd->command; DrawTextCommand *tcmd = (DrawTextCommand*)&cmd->command; @@ -341,6 +338,6 @@ void rencache_end_frame(RenWindow *window_renderer) { unsigned *tmp = cells; cells = cells_prev; cells_prev = tmp; - command_buf_idx = 0; + window_renderer->command_buf_idx = 0; } diff --git a/src/rencache.h b/src/rencache.h index 2453d808..03963485 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -6,8 +6,8 @@ #include "renderer.h" void rencache_show_debug(bool enable); -void rencache_set_clip_rect(RenRect rect); -void rencache_draw_rect(RenRect rect, RenColor color); +void rencache_set_clip_rect(RenWindow *window_renderer, RenRect rect); +void rencache_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color); double rencache_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, double x, int y, RenColor color); void rencache_invalidate(void); void rencache_begin_frame(RenWindow *window_renderer); diff --git a/src/renderer.c b/src/renderer.c index e10dd916..7f2d74fa 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -506,13 +506,11 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) { /*************** Window Management ****************/ void ren_free_window_resources(RenWindow *window_renderer) { - extern uint8_t *command_buf; - extern size_t command_buf_size; renwin_free(window_renderer); SDL_FreeSurface(draw_rect_surface); - free(command_buf); - command_buf = NULL; - command_buf_size = 0; + free(window_renderer->command_buf); + window_renderer->command_buf = NULL; + window_renderer->command_buf_size = 0; } // TODO remove global and return RenWindow* @@ -525,6 +523,7 @@ void ren_init(SDL_Window *win) { } window_renderer.window = win; renwin_init_surface(&window_renderer); + renwin_init_command_buf(&window_renderer); renwin_clip_to_surface(&window_renderer); draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); diff --git a/src/renwindow.c b/src/renwindow.c index ba671404..fe40d009 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -45,6 +45,12 @@ void renwin_init_surface(UNUSED RenWindow *ren) { #endif } +void renwin_init_command_buf(RenWindow *ren) { + ren->command_buf = NULL; + ren->command_buf_idx = 0; + ren->command_buf_size = 0; +} + static RenRect scaled_rect(const RenRect rect, const int scale) { return (RenRect) {rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale}; diff --git a/src/renwindow.h b/src/renwindow.h index 6b0b9eaa..a80586a0 100644 --- a/src/renwindow.h +++ b/src/renwindow.h @@ -3,6 +3,9 @@ struct RenWindow { SDL_Window *window; + uint8_t *command_buf; + size_t command_buf_idx; + size_t command_buf_size; #ifdef LITE_USE_SDL_RENDERER SDL_Renderer *renderer; SDL_Texture *texture; @@ -12,6 +15,7 @@ struct RenWindow { typedef struct RenWindow RenWindow; void renwin_init_surface(RenWindow *ren); +void renwin_init_command_buf(RenWindow *ren); void renwin_clip_to_surface(RenWindow *ren); void renwin_set_clip_rect(RenWindow *ren, RenRect rect); void renwin_resize_surface(RenWindow *ren); From 39319e2ce9b6a14c7bd5bf31f75f182b812e1650 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Sun, 25 Jun 2023 04:09:27 +0200 Subject: [PATCH 097/176] comment typo in object.lua (#1541) --- data/core/object.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/core/object.lua b/data/core/object.lua index 7b712cff..5466cb01 100644 --- a/data/core/object.lua +++ b/data/core/object.lua @@ -70,7 +70,7 @@ function Object:__tostring() return "Object" end ----Methamethod to allow using the object call as a constructor. +---Metamethod to allow using the object call as a constructor. ---@return core.object function Object:__call(...) local obj = setmetatable({}, self) From 0e5f35ff9f1b26efb5d9e2bf9cd70d1eb2570f27 Mon Sep 17 00:00:00 2001 From: Luke aka SwissalpS Date: Wed, 28 Jun 2023 03:05:03 +0200 Subject: [PATCH 098/176] Fix #1538 log scrolls automatically (the real PR) (#1546) * fix #1538 log scrolls automatically adds: - when user scrolls, position is kept no matter how many new entries arrive - when user scrolls up to last entry, autoscroll is enabled again does not add buttons to jump up/down see #1538 * move scroll-test out of on_mouse_wheel * determine diff_index with loop * remove check at move_towards yoffset * use while loop instead of repeat loop * remove meaningless setter * remove stray var --- data/core/logview.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/data/core/logview.lua b/data/core/logview.lua index 15aec22e..0d102832 100644 --- a/data/core/logview.lua +++ b/data/core/logview.lua @@ -125,9 +125,19 @@ end function LogView:update() local item = core.log_items[#core.log_items] if self.last_item ~= item then + local lh = style.font:get_height() + style.padding.y + if 0 < self.scroll.to.y then + local index = #core.log_items + while index > 1 and self.last_item ~= core.log_items[index] do + index = index - 1 + end + local diff_index = #core.log_items - index + self.scroll.to.y = self.scroll.to.y + diff_index * lh + self.scroll.y = self.scroll.to.y + else + self.yoffset = -lh + end self.last_item = item - self.scroll.to.y = 0 - self.yoffset = -(style.font:get_height() + style.padding.y) end local expanding = self.expanding[1] From ca3acd4ee97ad583e55a6268aa3f12c47523084c Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 3 Jul 2023 22:39:54 +0200 Subject: [PATCH 099/176] Skip checking `files` if no filename was provided to `syntax.get` --- data/core/doc/init.lua | 2 +- data/core/syntax.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index bf5895fb..086e9f3e 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -49,7 +49,7 @@ function Doc:reset_syntax() path = core.project_dir .. PATHSEP .. self.filename end if path then path = common.normalize_path(path) end - local syn = syntax.get(path or "", header) + local syn = syntax.get(path, header) if self.syntax ~= syn then self.syntax = syn self.highlighter:soft_reset() diff --git a/data/core/syntax.lua b/data/core/syntax.lua index 977983c1..9862fbdf 100644 --- a/data/core/syntax.lua +++ b/data/core/syntax.lua @@ -44,7 +44,7 @@ local function find(string, field) end function syntax.get(filename, header) - return find(filename, "files") + return (filename and find(filename, "files")) or (header and find(header, "headers")) or plain_text_syntax end From 3775032c781a79e75cd26be4af80bae7940eceab Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 4 Jul 2023 05:50:28 +0200 Subject: [PATCH 100/176] Allow setting custom glyphset size (#1542) * Properly set glyphset size * Rename `MAX_GLYPHSET` to `GLYPHSET_SIZE` * Use more appropriate types for font metrics --- src/renderer.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/renderer.c b/src/renderer.c index 7f2d74fa..f8ae6302 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -16,8 +16,9 @@ #include "renderer.h" #include "renwindow.h" -#define MAX_GLYPHSET 256 -#define MAX_LOADABLE_GLYPHSETS 4096 +#define MAX_UNICODE 0x100000 +#define GLYPHSET_SIZE 256 +#define MAX_LOADABLE_GLYPHSETS (MAX_UNICODE / GLYPHSET_SIZE) #define SUBPIXEL_BITMAPS_CACHED 3 RenWindow window_renderer = {0}; @@ -37,14 +38,14 @@ static void* check_alloc(void *ptr) { /************************* Fonts *************************/ typedef struct { - unsigned short x0, x1, y0, y1, loaded; - short bitmap_left, bitmap_top; + unsigned int x0, x1, y0, y1, loaded; + int bitmap_left, bitmap_top; float xadvance; } GlyphMetric; typedef struct { SDL_Surface* surface; - GlyphMetric metrics[MAX_GLYPHSET]; + GlyphMetric metrics[GLYPHSET_SIZE]; } GlyphSet; typedef struct RenFont { @@ -128,14 +129,14 @@ static void font_load_glyphset(RenFont* font, int idx) { for (int j = 0, pen_x = 0; j < bitmaps_cached; ++j) { GlyphSet* set = check_alloc(calloc(1, sizeof(GlyphSet))); font->sets[j][idx] = set; - for (int i = 0; i < MAX_GLYPHSET; ++i) { - int glyph_index = FT_Get_Char_Index(font->face, i + idx * MAX_GLYPHSET); + for (int i = 0; i < GLYPHSET_SIZE; ++i) { + int glyph_index = FT_Get_Char_Index(font->face, i + idx * GLYPHSET_SIZE); if (!glyph_index || FT_Load_Glyph(font->face, glyph_index, load_option | FT_LOAD_BITMAP_METRICS_ONLY) || font_set_style(&font->face->glyph->outline, j * (64 / SUBPIXEL_BITMAPS_CACHED), font->style) || FT_Render_Glyph(font->face->glyph, render_option)) { continue; } FT_GlyphSlot slot = font->face->glyph; - int glyph_width = slot->bitmap.width / byte_width; + unsigned int glyph_width = slot->bitmap.width / byte_width; if (font->antialiasing == FONT_ANTIALIASING_NONE) glyph_width *= 8; set->metrics[i] = (GlyphMetric){ pen_x, pen_x + glyph_width, 0, slot->bitmap.rows, true, slot->bitmap_left, slot->bitmap_top, (slot->advance.x + slot->lsb_delta - slot->rsb_delta) / 64.0f}; @@ -153,8 +154,8 @@ static void font_load_glyphset(RenFont* font, int idx) { continue; set->surface = check_alloc(SDL_CreateRGBSurface(0, pen_x, font->max_height, font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? 24 : 8, 0, 0, 0, 0)); uint8_t* pixels = set->surface->pixels; - for (int i = 0; i < MAX_GLYPHSET; ++i) { - int glyph_index = FT_Get_Char_Index(font->face, i + idx * MAX_GLYPHSET); + for (int i = 0; i < GLYPHSET_SIZE; ++i) { + int glyph_index = FT_Get_Char_Index(font->face, i + idx * GLYPHSET_SIZE); if (!glyph_index || FT_Load_Glyph(font->face, glyph_index, load_option)) continue; FT_GlyphSlot slot = font->face->glyph; @@ -178,7 +179,7 @@ static void font_load_glyphset(RenFont* font, int idx) { } static GlyphSet* font_get_glyphset(RenFont* font, unsigned int codepoint, int subpixel_idx) { - int idx = (codepoint >> 8) % MAX_LOADABLE_GLYPHSETS; + int idx = (codepoint / GLYPHSET_SIZE) % MAX_LOADABLE_GLYPHSETS; if (!font->sets[font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? subpixel_idx : 0][idx]) font_load_glyphset(font, idx); return font->sets[font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? subpixel_idx : 0][idx]; @@ -192,7 +193,7 @@ static RenFont* font_group_get_glyph(GlyphSet** set, GlyphMetric** metric, RenFo bitmap_index += SUBPIXEL_BITMAPS_CACHED; for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { *set = font_get_glyphset(fonts[i], codepoint, bitmap_index); - *metric = &(*set)->metrics[codepoint % 256]; + *metric = &(*set)->metrics[codepoint % GLYPHSET_SIZE]; if ((*metric)->loaded || codepoint < 0xFF) return fonts[i]; } @@ -323,14 +324,16 @@ void ren_font_free(RenFont* font) { } void ren_font_group_set_tab_size(RenFont **fonts, int n) { + unsigned int tab_index = '\t' % GLYPHSET_SIZE; for (int j = 0; j < FONT_FALLBACK_MAX && fonts[j]; ++j) { for (int i = 0; i < (fonts[j]->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? SUBPIXEL_BITMAPS_CACHED : 1); ++i) - font_get_glyphset(fonts[j], '\t', i)->metrics['\t'].xadvance = fonts[j]->space_advance * n; + font_get_glyphset(fonts[j], '\t', i)->metrics[tab_index].xadvance = fonts[j]->space_advance * n; } } int ren_font_group_get_tab_size(RenFont **fonts) { - float advance = font_get_glyphset(fonts[0], '\t', 0)->metrics['\t'].xadvance; + unsigned int tab_index = '\t' % GLYPHSET_SIZE; + float advance = font_get_glyphset(fonts[0], '\t', 0)->metrics[tab_index].xadvance; if (fonts[0]->space_advance) { advance /= fonts[0]->space_advance; } From 74d9c15736610db736fa863106ce6811c9eb6be8 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 9 Jul 2023 08:42:40 +0800 Subject: [PATCH 101/176] style(src/renderer): use FreeType header names (#1554) --- src/renderer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer.c b/src/renderer.c index f8ae6302..6d95beeb 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -4,9 +4,9 @@ #include #include #include -#include -#include #include FT_FREETYPE_H +#include FT_LCD_FILTER_H +#include FT_OUTLINE_H #ifdef _WIN32 #include From 0ebf3c0393a7710cb2830c68aa6ef8c73f366062 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 9 Jul 2023 18:59:25 +0200 Subject: [PATCH 102/176] Return state when tokenizing plaintext syntaxes --- data/core/tokenizer.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index fe74ca6d..5f70fa20 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -133,12 +133,12 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) local res local i = 1 - if #incoming_syntax.patterns == 0 then - return { "normal", text } - end - state = state or string.char(0) + if #incoming_syntax.patterns == 0 then + return { "normal", text }, state + end + if resume then res = resume.res -- Remove "incomplete" tokens From 8c9620aaed1c1ee37122990f61c69fbb582462a3 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Tue, 11 Jul 2023 09:45:36 +0800 Subject: [PATCH 103/176] feat(src/renderer): stream fonts with SDL_RWops on all platforms (#1555) * feat(src/renderer): stream fonts with SDL_RWops on all platforms This fixes #1529 where the font itself carries the font file, which gets copied around. This commit streams the file, so the file is not entirely in memory. * style(src/renderer): use standard C types * refactor(src/renderer): implement FT_Stream.close * fix(src/renderer): fix SDL_RWops double free --- src/renderer.c | 111 +++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 63 deletions(-) diff --git a/src/renderer.c b/src/renderer.c index 6d95beeb..d08565ea 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -7,6 +7,7 @@ #include FT_FREETYPE_H #include FT_LCD_FILTER_H #include FT_OUTLINE_H +#include FT_SYSTEM_H #ifdef _WIN32 #include @@ -50,6 +51,7 @@ typedef struct { typedef struct RenFont { FT_Face face; + FT_StreamRec stream; GlyphSet* sets[SUBPIXEL_BITMAPS_CACHED][MAX_LOADABLE_GLYPHSETS]; float size, space_advance, tab_advance; unsigned short max_height, baseline, height; @@ -57,10 +59,6 @@ typedef struct RenFont { ERenFontHinting hinting; unsigned char style; unsigned short underline_thickness; -#ifdef _WIN32 - unsigned char *file; - HANDLE file_handle; -#endif char path[]; } RenFont; @@ -215,54 +213,49 @@ static void font_clear_glyph_cache(RenFont* font) { } } +// based on https://github.com/libsdl-org/SDL_ttf/blob/2a094959055fba09f7deed6e1ffeb986188982ae/SDL_ttf.c#L1735 +static unsigned long font_file_read(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { + uint64_t amount; + SDL_RWops *file = (SDL_RWops *) stream->descriptor.pointer; + SDL_RWseek(file, (int) offset, RW_SEEK_SET); + if (count == 0) + return 0; + amount = SDL_RWread(file, buffer, sizeof(char), count); + if (amount <= 0) + return 0; + return (unsigned long) amount; +} + +static void font_file_close(FT_Stream stream) { + if (stream && stream->descriptor.pointer) { + SDL_RWclose((SDL_RWops *) stream->descriptor.pointer); + stream->descriptor.pointer = NULL; + } +} + RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { + RenFont *font = NULL; FT_Face face = NULL; + + SDL_RWops *file = SDL_RWFromFile(path, "rb"); + if (!file) + goto rwops_failure; -#ifdef _WIN32 + int len = strlen(path); + font = check_alloc(calloc(1, sizeof(RenFont) + len + 1)); + font->stream.read = font_file_read; + font->stream.close = font_file_close; + font->stream.descriptor.pointer = file; + font->stream.pos = 0; + font->stream.size = (unsigned long) SDL_RWsize(file); - HANDLE file = INVALID_HANDLE_VALUE; - DWORD read; - int font_file_len = 0; - unsigned char *font_file = NULL; - wchar_t *wpath = NULL; - - if ((wpath = utfconv_utf8towc(path)) == NULL) - return NULL; - - if ((file = CreateFileW(wpath, - GENERIC_READ, - FILE_SHARE_READ, // or else we can't copy fonts - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)) == INVALID_HANDLE_VALUE) + if (FT_Open_Face(library, &(FT_Open_Args){ .flags = FT_OPEN_STREAM, .stream = &font->stream }, 0, &face)) goto failure; - if ((font_file_len = GetFileSize(file, NULL)) == INVALID_FILE_SIZE) - goto failure; - - font_file = check_alloc(malloc(font_file_len * sizeof(unsigned char))); - if (!ReadFile(file, font_file, font_file_len, &read, NULL) || read != font_file_len) - goto failure; - - free(wpath); - wpath = NULL; - - if (FT_New_Memory_Face(library, font_file, read, 0, &face)) - goto failure; - -#else - - if (FT_New_Face(library, path, 0, &face)) - return NULL; - -#endif - const int surface_scale = renwin_get_surface(window_renderer).scale; if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale))) goto failure; - int len = strlen(path); - RenFont* font = check_alloc(calloc(1, sizeof(RenFont) + len + 1)); + strcpy(font->path, path); font->face = face; font->size = size; @@ -272,32 +265,28 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, font->hinting = hinting; font->style = style; -#ifdef _WIN32 - // we need to keep this for freetype - font->file = font_file; - font->file_handle = file; -#endif - if(FT_IS_SCALABLE(face)) font->underline_thickness = (unsigned short)((face->underline_thickness / (float)face->units_per_EM) * font->size); - if(!font->underline_thickness) font->underline_thickness = ceil((double) font->height / 14.0); + if(!font->underline_thickness) + font->underline_thickness = ceil((double) font->height / 14.0); - if (FT_Load_Char(face, ' ', font_set_load_options(font))) { - free(font); + if (FT_Load_Char(face, ' ', font_set_load_options(font))) goto failure; - } + font->space_advance = face->glyph->advance.x / 64.0f; font->tab_advance = font->space_advance * 2; return font; failure: -#ifdef _WIN32 - free(wpath); - free(font_file); - if (file != INVALID_HANDLE_VALUE) CloseHandle(file); -#endif - if (face != NULL) + if (face) FT_Done_Face(face); + if (font) + free(font); + return NULL; + +rwops_failure: + if (file) + SDL_RWclose(file); return NULL; } @@ -316,10 +305,6 @@ const char* ren_font_get_path(RenFont *font) { void ren_font_free(RenFont* font) { font_clear_glyph_cache(font); FT_Done_Face(font->face); -#ifdef _WIN32 - free(font->file); - CloseHandle(font->file_handle); -#endif free(font); } From c4706830050af1e5e7dd73db01dbc591772ed849 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 19 Jul 2023 21:06:18 -0400 Subject: [PATCH 104/176] Updated extension for mac. (#1563) --- data/core/start.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/core/start.lua b/data/core/start.lua index f85d4087..c104cb13 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -25,7 +25,7 @@ package.path = DATADIR .. '/?/init.lua;' .. package.path package.path = USERDIR .. '/?.lua;' .. package.path package.path = USERDIR .. '/?/init.lua;' .. package.path -local suffix = PLATFORM == "Mac OS X" and 'lib' or (PLATFORM == "Windows" and 'dll' or 'so') +local suffix = PLATFORM == "Windows" and 'dll' or 'so' package.cpath = USERDIR .. '/?.' .. ARCH .. "." .. suffix .. ";" .. USERDIR .. '/?/init.' .. ARCH .. "." .. suffix .. ";" .. From ac3630c2ea171e3e829196fb859280e4355bdf87 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 23 Jul 2023 03:39:32 +0800 Subject: [PATCH 105/176] Documentation for core.common (#1510) * docs(core.common): add and improve documentation * refactor(core.common): remove unused variable to get_height() * docs(core.common): remove messy newlines * docs(core.common): fix wording * docs(core.common): use integer instead of number Co-authored-by: Guldoman * docs(core.common): update docs the docs now follow the style in docs/ directory. some of the changes suggested are also implemented. * docs(core.common): fix typo Co-authored-by: Guldoman * docs(core.common): restyle annoatations Extra whitespaces are removed and @overload is used whenever possible. * docs(core.common): fix various documentation errors * docs(core.common): simplify unicode description * docs(core.common): fix return value Co-authored-by: Guldoman * docs(core.common): clarify common.bench for not being a benchmark * docs(common): add disclaimer for numbers in common.serialize --------- Co-authored-by: Guldoman --- data/core/common.lua | 221 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 205 insertions(+), 16 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index b6c9db67..272f0d5d 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -1,22 +1,41 @@ local common = {} +---Checks if the byte at offset is a UTF-8 continuation byte. +--- +---UTF-8 encodes code points in 1 to 4 bytes. +---For a multi-byte sequence, each byte following the start byte is a continuation byte. +---@param s string +---@param offset? integer The offset of the string to start searching. Defaults to 1. +---@return boolean function common.is_utf8_cont(s, offset) local byte = s:byte(offset or 1) return byte >= 0x80 and byte < 0xc0 end +---Returns an iterator that yields a UTF-8 character on each iteration. +---@param text string +---@return fun(): string function common.utf8_chars(text) return text:gmatch("[\0-\x7f\xc2-\xf4][\x80-\xbf]*") end +---Clamps the number n between lo and hi. +---@param n number +---@param lo number +---@param hi number +---@return number function common.clamp(n, lo, hi) return math.max(math.min(n, hi), lo) end +---Returns a new table containing the contents of b merged into a. +---@param a table|nil +---@param b table? +---@return table function common.merge(a, b) a = type(a) == "table" and a or {} local t = {} @@ -32,11 +51,19 @@ function common.merge(a, b) end +---Returns the value of a number rounded to the nearest integer. +---@param n number +---@return number function common.round(n) return n >= 0 and math.floor(n + 0.5) or math.ceil(n - 0.5) end +---Returns the first index where a subtable in tbl has prop set. +---If none is found, nil is returned. +---@param tbl table +---@param prop any +---@return number|nil function common.find_index(tbl, prop) for i, o in ipairs(tbl) do if o[prop] then return i end @@ -44,6 +71,16 @@ function common.find_index(tbl, prop) end +---Returns a value between a and b on a linear scale, based on the +---interpolation point t. +--- +---If a and b are tables, a table containing the result for all the +---elements in a and b is returned. +---@param a number +---@param b number +---@param t number +---@return number +---@overload fun(a: table, b: table, t: number): table function common.lerp(a, b, t) if type(a) ~= "table" then return a + (b - a) * t @@ -56,11 +93,29 @@ function common.lerp(a, b, t) end +---Returns the euclidean distance between two points. +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@return number function common.distance(x1, y1, x2, y2) return math.sqrt(((x2-x1) ^ 2)+((y2-y1) ^ 2)) end +---Parses a CSS color string. +--- +---Only these formats are supported: +---* `rgb(r, g, b)` +---* `rgba(r, g, b, a)` +---* `#rrggbbaa` +---* `#rrggbb` +---@param str string +---@return number r +---@return number g +---@return number b +---@return number a function common.color(str) local r, g, b, a = str:match("^#(%x%x)(%x%x)(%x%x)(%x?%x?)$") if r then @@ -81,6 +136,12 @@ function common.color(str) end +---Splices a numerically indexed table. +---This function mutates the original table. +---@param t any[] +---@param at number Index at which to start splicing. +---@param remove number Number of elements to remove. +---@param insert? any[] A table containing elements to insert after splicing. function common.splice(t, at, remove, insert) assert(remove >= 0, "bad argument #3 to 'splice' (non-negative value expected)") insert = insert or {} @@ -110,6 +171,16 @@ local function fuzzy_match_items(items, needle, files) end +---Performs fuzzy matching. +--- +---If the haystack is a string, a score ranging from 0 to 1 is returned.
+---If the haystack is a table, a table containing the haystack sorted in ascending +---order of similarity is returned. +---@param haystack string +---@param needle string +---@param files boolean If true, the matching process will be performed in reverse to better match paths. +---@return number +---@overload fun(haystack: string[], needle: string, files: boolean): string[] function common.fuzzy_match(haystack, needle, files) if type(haystack) == "table" then return fuzzy_match_items(haystack, needle, files) @@ -118,6 +189,14 @@ function common.fuzzy_match(haystack, needle, files) end +---Performs fuzzy matching and returns recently used strings if needed. +--- +---If the needle is empty, then a list of recently used strings +---are added to the result, followed by strings from the haystack. +---@param haystack string[] +---@param recents string[] +---@param needle string +---@return string[] function common.fuzzy_match_with_recents(haystack, recents, needle) if needle == "" then local recents_ext = {} @@ -136,6 +215,13 @@ function common.fuzzy_match_with_recents(haystack, recents, needle) end +---Returns a list of paths that are relative to the input path. +--- +---If a root directory is specified, the function returns paths +---that are relative to the root directory. +---@param text string The input path. +---@param root? string The root directory. +---@return string[] function common.path_suggest(text, root) if root and root:sub(-1) ~= PATHSEP then root = root .. PATHSEP @@ -189,6 +275,9 @@ function common.path_suggest(text, root) end +---Returns a list of directories that are related to a path. +---@param text string The input path. +---@return string[] function common.dir_path_suggest(text) local path, name = text:match("^(.-)([^/\\]*)$") local files = system.list_dir(path == "" and "." or path) or {} @@ -204,6 +293,10 @@ function common.dir_path_suggest(text) end +---Filters a list of paths to find those that are related to the input path. +---@param text string The input path. +---@param dir_list string[] A list of paths to filter. +---@return string[] function common.dir_list_suggest(text, dir_list) local path, name = text:match("^(.-)([^/\\]*)$") local res = {} @@ -216,6 +309,15 @@ function common.dir_list_suggest(text, dir_list) end +---Matches a string against a list of patterns. +--- +---If a match was found, its start and end index is returned. +---Otherwise, false is returned. +---@param text string +---@param pattern string|string[] +---@param ... any Other options for string.find(). +---@return number|boolean start_index +---@return number|nil end_index function common.match_pattern(text, pattern, ...) if type(pattern) == "string" then return text:find(pattern, ...) @@ -228,8 +330,24 @@ function common.match_pattern(text, pattern, ...) end +---Draws text onto the window. +---The function returns the X and Y coordinates of the bottom-right +---corner of the text. +---@param font renderer.font +---@param color renderer.color +---@param text string +---@param align string +---| '"left"' # Align text to the left of the bounding box +---| '"right"' # Align text to the right of the bounding box +---| '"center"' # Center text in the bounding box +---@param x number +---@param y number +---@param w number +---@param h number +---@return number x_advance +---@return number y_advance function common.draw_text(font, color, text, align, x,y,w,h) - local tw, th = font:get_width(text), font:get_height(text) + local tw, th = font:get_width(text), font:get_height() if align == "center" then x = x + (w - tw) / 2 elseif align == "right" then @@ -240,6 +358,16 @@ function common.draw_text(font, color, text, align, x,y,w,h) end +---Prints the execution time of a function. +--- +---The execution time and percentage of frame time +---for the function is printed to standard output.
+---The frame rate is always assumed to be 60 FPS, thus +---a value of 100% would mean that the benchmark took +---1/60 of a second to execute. +---@param name string +---@param fn fun(...: any): any +---@return any # The result returned by the function function common.bench(name, fn, ...) local start = system.get_time() local res = fn(...) @@ -285,14 +413,28 @@ local function serialize(val, pretty, indent_str, escape, sort, limit, level) return tostring(val) end --- Serialize `val` into a parsable string. --- Available options --- * pretty: enable pretty printing --- * indent_str: indent to use (" " by default) --- * escape: use normal escape characters instead of the ones used by string.format("%q", ...) --- * sort: sort the keys inside tables --- * limit: limit how deep to serialize --- * initial_indent: the initial indentation level + +---@class common.serializeoptions +---@field pretty boolean Enables pretty printing. +---@field indent_str string The indentation character to use. Defaults to `" "`. +---@field escape boolean Uses normal escape characters ("\n") instead of decimal escape sequences ("\10"). +---@field limit number Limits the depth when serializing nested tables. Defaults to `math.huge`. +---@field sort boolean Sorts the output if it is a sortable table. +---@field initial_indent number The initial indentation level. Defaults to 0. + +---Serializes a value into a Lua string that is loadable with load(). +--- +---Only these basic types are supported: +---* nil +---* boolean +---* number (except very large numbers and special constants, e.g. `math.huge`, `inf` and `nan`) +---* integer +---* string +---* table +--- +---@param val any +---@param opts? common.serializeoptions +---@return string function common.serialize(val, opts) opts = opts or {} local indent_str = opts.indent_str or " " @@ -304,6 +446,9 @@ function common.serialize(val, opts) end +---Returns the last portion of a path. +---@param path string +---@return string function common.basename(path) -- a path should never end by / or \ except if it is '/' (unix root) or -- 'X:\' (windows drive) @@ -311,12 +456,18 @@ function common.basename(path) end --- can return nil if there is no directory part in the path +---Returns the directory name of a path. +---If the path doesn't have a directory, this function may return nil. +---@param path string +---@return string|nil function common.dirname(path) return path:match("(.+)[\\/][^\\/]+$") end +---Returns a path where the user's home directory is replaced by `"~"`. +---@param text string +---@return string function common.home_encode(text) if HOME and string.find(text, HOME, 1, true) == 1 then local dir_pos = #HOME + 1 @@ -330,6 +481,9 @@ function common.home_encode(text) end +---Returns a list of paths where the user's home directory is replaced by `"~"`. +---@param paths string[] A list of paths to encode +---@return string[] function common.home_encode_list(paths) local t = {} for i = 1, #paths do @@ -339,6 +493,10 @@ function common.home_encode_list(paths) end +---Expands the `"~"` prefix in a path into the user's home directory. +---This function is not guaranteed to return an absolute path. +---@param text string +---@return string function common.home_expand(text) return HOME and text:gsub("^~", HOME) or text end @@ -356,12 +514,13 @@ local function split_on_slash(s, sep_pattern) end --- The filename argument given to the function is supposed to --- come from system.absolute_path and as such should be an --- absolute path without . or .. elements. --- This function exists because on Windows the drive letter returned --- by system.absolute_path is sometimes with a lower case and sometimes --- with an upper case so we normalize to upper case. +---Normalizes the drive letter in a Windows path to uppercase. +---This function expects an absolute path, e.g. a path from `system.absolute_path`. +--- +---This function is needed because the path returned by `system.absolute_path` +---may contain drive letters in upper or lowercase. +---@param filename string|nil The input path. +---@return string|nil function common.normalize_volume(filename) if not filename then return end if PATHSEP == '\\' then @@ -374,6 +533,13 @@ function common.normalize_volume(filename) end +---Normalizes a path into the same format across platforms. +--- +---On Windows, all drive letters are converted to uppercase. +---UNC paths with drive letters are converted back to ordinary Windows paths. +---All path separators (`"/"`, `"\\"`) are converted to platform-specific ones. +---@param filename string|nil +---@return string|nil function common.normalize_path(filename) if not filename then return end local volume @@ -414,16 +580,27 @@ function common.normalize_path(filename) end +---Checks whether a path is absolute or relative. +---@param path string +---@return boolean function common.is_absolute_path(path) return path:sub(1, 1) == PATHSEP or path:match("^(%a):\\") end +---Checks whether a path belongs to a parent directory. +---@param filename string The path to check. +---@param path string The parent path. +---@return boolean function common.path_belongs_to(filename, path) return string.find(filename, path .. PATHSEP, 1, true) == 1 end +---Checks whether a path is relative to another path. +---@param ref_dir string The path to check against. +---@param dir string The input path. +---@return boolean function common.relative_path(ref_dir, dir) local drive_pattern = "^(%a):\\" local drive, ref_drive = dir:match(drive_pattern), ref_dir:match(drive_pattern) @@ -449,6 +626,11 @@ function common.relative_path(ref_dir, dir) end +---Creates a directory recursively if necessary. +---@param path string +---@return boolean success +---@return string|nil error +---@return string|nil path The path where an error occured. function common.mkdirp(path) local stat = system.get_file_info(path) if stat and stat.type then @@ -471,6 +653,13 @@ function common.mkdirp(path) return true end + +---Removes a path. +---@param path string +---@param recursively boolean If true, the function will attempt to remove everything in the specified path. +---@return boolean success +---@return string|nil error +---@return string|nil path The path where the error occured. function common.rm(path, recursively) local stat = system.get_file_info(path) if not stat or (stat.type ~= "file" and stat.type ~= "dir") then From 7ba1d1ba8e8e2005130a5a567e4e99d4a6933571 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:17:45 +0800 Subject: [PATCH 106/176] docs(system): fix missing parameter for system.path_compare (#1566) * docs(system): fix missing parameter for system.path_compare * docs(system): fix missing parameter in function prototype --- docs/api/system.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/system.lua b/docs/api/system.lua index ffbc6f42..9e5ef289 100644 --- a/docs/api/system.lua +++ b/docs/api/system.lua @@ -318,9 +318,11 @@ function system.load_native_plugin(name, path) end ---Compares two paths in the order used by TreeView. --- ---@param path1 string +---@param type1 system.fileinfotype ---@param path2 string +---@param type2 system.fileinfotype ---@return boolean compare_result True if path1 < path2 -function system.path_compare(path1, path2) end +function system.path_compare(path1, type1, path2, type2) end return system From 6ad67c18f02709f5ede5e853cdce0f1778c32206 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:04:44 +0800 Subject: [PATCH 107/176] Documentation for core.command (#1564) * docs(core.command): add documentation * fix(core.common): fix warnings * docs(core.command): add "core." prefix to all custom types * docs(core.command); add name as parameter to command.perform * docs(core.command): fix typo and wording * docs(core.command): add disclaimer to command.generate_predicate * docs(core.command): fix wording for predicate * docs(core.command): document command name * docs(core.command): document the always_true predicate --- data/core/command.lua | 98 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/data/core/command.lua b/data/core/command.lua index faf872e2..2b28f63b 100644 --- a/data/core/command.lua +++ b/data/core/command.lua @@ -1,25 +1,55 @@ local core = require "core" local command = {} +---A predicate function accepts arguments from `command.perform()` and evaluates to a boolean.
+---If the function returns true, then the function associated with the command is executed. +--- +---The predicate function can also return other values after the boolean, which will +---be passed into the function associated with the command. +---@alias core.command.predicate_function fun(...: any): boolean, ... + +---A predicate is a string, an Object or a function, that is used to determine +---whether a command should be executed. +--- +---If the predicate is a string, it is resolved into an `Object` via `require()` +---and checked against the active view with `Object:extends()`.
+---For example, `"core.docview"` will match any view that inherits from `DocView`.
+---A `!` can be appended to the predicate to strictly match the current view via `Object:is()`, +---instead of matching any view that inherits the predicate. +--- +---If the predicate is a table, it is checked against the active view with `Object:extends()`. +---Strict matching via `Object:is()` is not available. +--- +---If the predicate is a function, it must behave like a predicate function. +---@see core.command.predicate_function +---@alias core.command.predicate string|core.object|core.command.predicate_function + +---A command is identified by a command name. +---The command name contains a category and the name itself, separated by a colon (':'). +--- +---All commands should be in lowercase and should not contain whitespaces; instead +---they should be replaced by a dash ('-'). +---@alias core.command.command_name string + +---The predicate and its associated function. +---@class core.command.command +---@field predicate core.command.predicate_function +---@field perform fun(...: any) + +---@type { [string]: core.command.command } command.map = {} +---@type core.command.predicate_function local always_true = function() return true end ----Used iternally by command.add, statusview, and contextmenu to generate a ----function with a condition to evaluate returning the boolean result of this ----evaluation. +---This function takes in a predicate and produces a predicate function +---that is internally used to dispatch and execute commands. --- ----If a string predicate is given it is treated as a require import that should ----return a valid object which is checked against the current active view, ----eg: "core.docview" will match any view that inherits from DocView. Appending ----a `!` at the end of the string means we want to match the given object ----from the import strcitly eg: "core.docview!" only DocView is matched. ----A function that returns a boolean can be used instead to perform a custom ----evaluation, setting to nil means always evaluates to true. ---- ----@param predicate string | table | function ----@return function +---This function should not be called manually. +---@see core.command.predicate +---@param predicate core.command.predicate|nil If nil, the predicate always evaluates to true. +---@return core.command.predicate_function function command.generate_predicate(predicate) predicate = predicate or always_true local strict = false @@ -38,10 +68,20 @@ function command.generate_predicate(predicate) predicate = function(...) return core.active_view:is(class), core.active_view, ... end end end + ---@cast predicate core.command.predicate_function return predicate end +---Adds commands to the map. +--- +---The function accepts a table containing a list of commands +---and their functions.
+---If a command already exists, it will be replaced. +---@see core.command.predicate +---@see core.command.command_name +---@param predicate core.command.predicate +---@param map { [core.command.command_name]: fun(...: any) } function command.add(predicate, map) predicate = command.generate_predicate(predicate) for name, fn in pairs(map) do @@ -57,11 +97,21 @@ local function capitalize_first(str) return str:sub(1, 1):upper() .. str:sub(2) end +---Prettifies the command name. +--- +---This function adds a space between the colon and the command name, +---replaces dashes with spaces and capitalizes the command appropriately. +---@see core.command.command_name +---@param name core.command.command_name +---@return string function command.prettify_name(name) + ---@diagnostic disable-next-line: redundant-return-value return name:gsub(":", ": "):gsub("-", " "):gsub("%S+", capitalize_first) end +---Returns all the commands that can be executed (their predicates evaluate to true). +---@return core.command.command_name[] function command.get_all_valid() local res = {} local memoized_predicates = {} @@ -76,6 +126,10 @@ function command.get_all_valid() return res end +---Checks whether a command can be executed (its predicate evaluates to true). +---@param name core.command.command_name +---@param ... any +---@return boolean function command.is_valid(name, ...) return command.map[name] and command.map[name].predicate(...) end @@ -98,12 +152,26 @@ local function perform(name, ...) end -function command.perform(...) - local ok, res = core.try(perform, ...) +---Performs a command. +--- +---The arguments passed into this function are forwarded to the predicate function.
+---If the predicate function returns more than 1 value, the other values are passed +---to the command. +--- +---Otherwise, the arguments passed into this function are passed directly +---to the command. +---@see core.command.predicate +---@see core.command.predicate_function +---@param name core.command.command_name +---@param ... any +---@return boolean # true if the command is performed successfully. +function command.perform(name, ...) + local ok, res = core.try(perform, name, ...) return not ok or res end +---Inserts the default commands for Lite XL into the map. function command.add_defaults() local reg = { "core", "root", "command", "doc", "findreplace", From 5145194f1f097becc5280a7109c772f44e2d7117 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 1 Aug 2023 15:38:24 -0400 Subject: [PATCH 108/176] Fixed things for when a thread requests a redraw. (#1570) * Fixed things for when a thread requests a redraw. * @guldoman's changes. * Whoops. --- data/core/init.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 9aba4c70..16cb265e 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1429,12 +1429,17 @@ end) function core.run() local next_step + local last_frame_time while true do core.frame_start = system.get_time() local time_to_wake = run_threads() local did_redraw = false - if not next_step or system.get_time() >= next_step then - did_redraw = core.step() + local force_draw = core.redraw and last_frame_time and core.frame_start - last_frame_time > (1 / config.fps) + if force_draw or not next_step or system.get_time() >= next_step then + if core.step() then + did_redraw = true + last_frame_time = core.frame_start + end next_step = nil end if core.restart_request or core.quit_request then break end From 8daf7dc92689e1a165e1352a0c408528748baefe Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 4 Aug 2023 02:03:33 +0800 Subject: [PATCH 109/176] feat(src/renderer): unify fontgroup baseline (#1560) * feat(src/renderer): unify fontgroup baseline * fix(src/renderer): use the first font's baseline for the text run --- src/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.c b/src/renderer.c index d08565ea..f4dbcc78 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -397,7 +397,7 @@ double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t l if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) { uint8_t* source_pixels = set->surface->pixels; for (int line = metric->y0; line < metric->y1; ++line) { - int target_y = line + y - metric->bitmap_top + font->baseline * surface_scale; + int target_y = line + y - metric->bitmap_top + fonts[0]->baseline * surface_scale; if (target_y < clip.y) continue; if (target_y >= clip_end_y) From 9c9f2dace04cb15010547379a63653c33bc7b0c5 Mon Sep 17 00:00:00 2001 From: Delta-official Date: Fri, 4 Aug 2023 13:38:33 +0000 Subject: [PATCH 110/176] Normalize stroke before adding keybind (#1334) * Normalize stroke before adding keybind * improve normalization algorithm and implement normalization in several functions Signed-off-by: delta --------- Signed-off-by: delta --- data/core/keymap.lua | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/data/core/keymap.lua b/data/core/keymap.lua index f2257a3e..bae1e63a 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -35,6 +35,23 @@ local modkey_map = modkeys_os.map local modkeys = modkeys_os.keys +---Normalizes a stroke sequence to follow the modkeys table +---@param stroke string +---@return string +local function normalize_stroke(stroke) + local stroke_table = {} + for modkey in stroke:gmatch("(%w+)%+") do + table.insert(stroke_table, modkey) + end + if not next(stroke_table) then + return stroke + end + table.sort(stroke_table) + local new_stroke = table.concat(stroke_table, "+") .. "+" + return new_stroke .. stroke:sub(new_stroke:len() + 1) +end + + ---Generates a stroke sequence including currently pressed mod keys. ---@param key string ---@return string @@ -45,10 +62,9 @@ local function key_to_stroke(key) stroke = stroke .. mk .. "+" end end - return stroke .. key + return normalize_stroke(stroke) .. key end - ---Remove the given value from an array associated to a key in a table. ---@param tbl table The table containing the key ---@param k string The key containing the array @@ -74,6 +90,7 @@ end ---@param map keymap.map local function remove_duplicates(map) for stroke, commands in pairs(map) do + stroke = normalize_stroke(stroke) if type(commands) == "string" or type(commands) == "function" then commands = { commands } end @@ -96,11 +113,12 @@ local function remove_duplicates(map) end end - ---Add bindings by replacing commands that were previously assigned to a shortcut. ---@param map keymap.map function keymap.add_direct(map) for stroke, commands in pairs(map) do + stroke = normalize_stroke(stroke) + if type(commands) == "string" or type(commands) == "function" then commands = { commands } end @@ -128,6 +146,7 @@ function keymap.add(map, overwrite) if macos then stroke = stroke:gsub("%f[%a]ctrl%f[%A]", "cmd") end + stroke = normalize_stroke(stroke) if overwrite then if keymap.map[stroke] then for _, cmd in ipairs(keymap.map[stroke]) do @@ -153,7 +172,7 @@ end ---@param shortcut string ---@param cmd string function keymap.unbind(shortcut, cmd) - remove_only(keymap.map, shortcut, cmd) + remove_only(keymap.map, normalize_stroke(shortcut), cmd) remove_only(keymap.reverse_map, cmd, shortcut) end From 16bfa6d958fd0e9c91d5eeb17ea90ce802e7be1b Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 4 Aug 2023 15:40:02 +0200 Subject: [PATCH 111/176] Use proper timeouts for coroutines that don't need to wait (#1467) --- data/core/doc/highlighter.lua | 2 +- data/plugins/projectsearch.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua index b1367049..14868674 100644 --- a/data/core/doc/highlighter.lua +++ b/data/core/doc/highlighter.lua @@ -48,7 +48,7 @@ function Highlighter:start() self:update_notify(retokenized_from, max - retokenized_from) end core.redraw = true - coroutine.yield() + coroutine.yield(0) end self.max_wanted_line = 0 self.running = false diff --git a/data/plugins/projectsearch.lua b/data/plugins/projectsearch.lua index cc5e1324..8c8dfd95 100644 --- a/data/plugins/projectsearch.lua +++ b/data/plugins/projectsearch.lua @@ -37,7 +37,7 @@ local function find_all_matches_in_file(t, filename, fn) table.insert(t, { file = filename, text = (start_index > 1 and "..." or "") .. line:sub(start_index, 256 + start_index), line = n, col = s }) core.redraw = true end - if n % 100 == 0 then coroutine.yield() end + if n % 100 == 0 then coroutine.yield(0) end n = n + 1 core.redraw = true end From 02e421149b09986948142674385776c992e9f0b0 Mon Sep 17 00:00:00 2001 From: Shreyas A S <137637016+shreyas-a-s@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:11:49 +0530 Subject: [PATCH 112/176] Updating the *Installing prebuild* section in README.md (#1548) Sub sections that I've updated: *To run lite-xl without installing:* *To install lite-xl copy files over into appropriate directories:* I think the directory structure of prebuilt packages has changed since when README.md was last updated. I've just updated it. Just that. Co-authored-by: Shreyas A S <137637016+shreyasastech@users.noreply.github.com> --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f8f701b6..b0163ec9 100644 --- a/README.md +++ b/README.md @@ -92,15 +92,14 @@ cd lite-xl To run lite-xl without installing: ```sh -cd bin ./lite-xl ``` To install lite-xl copy files over into appropriate directories: ```sh -mkdir -p $HOME/.local/bin && cp bin/lite-xl $HOME/.local/bin -cp -r share $HOME/.local +mkdir -p $HOME/.local/bin && cp lite-xl $HOME/.local/bin/ +mkdir -p $HOME/.local/share/lite-xl && cp -r data/* $HOME/.local/share/lite-xl/ ``` If `$HOME/.local/bin` is not in PATH: From 6bb9a89a8bfde74c098b27c57a6953837134db1b Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Fri, 4 Aug 2023 09:46:35 -0400 Subject: [PATCH 113/176] Updated README.md as per PR comittee meeting #8. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b0163ec9..d7c7e3c3 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ To run lite-xl without installing: To install lite-xl copy files over into appropriate directories: ```sh +rm -rf $HOME/.local/share/lite-xl $HOME/.local/bin/lite-xl mkdir -p $HOME/.local/bin && cp lite-xl $HOME/.local/bin/ mkdir -p $HOME/.local/share/lite-xl && cp -r data/* $HOME/.local/share/lite-xl/ ``` From 6d5c6051cd2f28745e6f48b50d1322a90b626424 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 4 Aug 2023 16:56:49 +0200 Subject: [PATCH 114/176] Make `DocView` aware of scrollbars sizes (#1177) * Make `DocView:scroll_to_make_visible` aware of vertical scrollbar width * Make `DocView` aware of horizontal scrollbar size --- data/core/docview.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/data/core/docview.lua b/data/core/docview.lua index d8ba562c..e2da6dfc 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -112,7 +112,8 @@ end function DocView:get_scrollable_size() if not config.scroll_past_end then - return self:get_line_height() * (#self.doc.lines) + style.padding.y * 2 + local _, _, _, h_scroll = self.h_scrollbar:get_track_rect() + return self:get_line_height() * (#self.doc.lines) + style.padding.y * 2 + h_scroll end return self:get_line_height() * (#self.doc.lines - 1) + self.size.y end @@ -244,7 +245,8 @@ function DocView:scroll_to_line(line, ignore_if_visible, instant) if not (ignore_if_visible and line > min and line < max) then local x, y = self:get_line_screen_position(line) local ox, oy = self:get_content_offset() - self.scroll.to.y = math.max(0, y - oy - self.size.y / 2) + local _, _, _, scroll_h = self.h_scrollbar:get_track_rect() + self.scroll.to.y = math.max(0, y - oy - (self.size.y - scroll_h) / 2) if instant then self.scroll.y = self.scroll.to.y end @@ -258,17 +260,20 @@ end function DocView:scroll_to_make_visible(line, col) - local ox, oy = self:get_content_offset() + local _, oy = self:get_content_offset() local _, ly = self:get_line_screen_position(line, col) local lh = self:get_line_height() - self.scroll.to.y = common.clamp(self.scroll.to.y, ly - oy - self.size.y + lh * 2, ly - oy - lh) + local _, _, _, scroll_h = self.h_scrollbar:get_track_rect() + self.scroll.to.y = common.clamp(self.scroll.to.y, ly - oy - self.size.y + scroll_h + lh * 2, ly - oy - lh) local gw = self:get_gutter_width() local xoffset = self:get_col_x_offset(line, col) local xmargin = 3 * self:get_font():get_width(' ') local xsup = xoffset + gw + xmargin local xinf = xoffset - xmargin - if xsup > self.scroll.x + self.size.x then - self.scroll.to.x = xsup - self.size.x + local _, _, scroll_w = self.v_scrollbar:get_track_rect() + local size_x = math.max(0, self.size.x - scroll_w) + if xsup > self.scroll.x + size_x then + self.scroll.to.x = xsup - size_x elseif xinf < self.scroll.x then self.scroll.to.x = math.max(0, xinf) end From 8c8635146e61b75dae4236c6129a99d196748c43 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 5 Aug 2023 09:00:17 +0800 Subject: [PATCH 115/176] ci(release): use lite-xl org (#1571) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 581b6469..edf66372 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: name: Linux needs: release runs-on: ubuntu-latest - container: ghcr.io/takase1121/lite-xl-build-box:latest + container: ghcr.io/lite-xl/lite-xl-build-box:latest env: CC: gcc CXX: g++ From f820b9301f04029a4956aaff841f95fd94b2d37c Mon Sep 17 00:00:00 2001 From: Velosofy <61261357+Velosofy@users.noreply.github.com> Date: Fri, 20 Jan 2023 07:46:19 +0700 Subject: [PATCH 116/176] Add "Open with Lite XL" to windows' context menu (#1333) Closes #423 --- scripts/innosetup/innosetup.iss.in | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/scripts/innosetup/innosetup.iss.in b/scripts/innosetup/innosetup.iss.in index 628733ff..566abe5d 100644 --- a/scripts/innosetup/innosetup.iss.in +++ b/scripts/innosetup/innosetup.iss.in @@ -1,7 +1,7 @@ #define MyAppName "Lite XL" #define MyAppVersion "@PROJECT_VERSION@" #define MyAppPublisher "Lite XL Team" -#define MyAppURL "https://lite-xl.github.io" +#define MyAppURL "https://lite-xl.com" #define MyAppExeName "lite-xl.exe" #define BuildDir "@PROJECT_BUILD_DIR@" #define SourceDir "@PROJECT_SOURCE_DIR@" @@ -69,9 +69,7 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip Name: "portablemode"; Description: "Portable Mode"; Flags: unchecked [Files] -Source: "{#BuildDir}/src/lite-xl.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "{#BuildDir}/mingwLibs{#Arch}/*"; DestDir: "{app}"; Flags: ignoreversion ; Check: DirExists(ExpandConstant('{#BuildDir}/mingwLibs{#Arch}')) -Source: "{#SourceDir}/data/*"; DestDir: "{app}/data"; Flags: ignoreversion recursesubdirs +Source: "{#SourceDir}/lite-xl/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] @@ -81,6 +79,17 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"; Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon; Check: not WizardIsTaskSelected('portablemode') ; Name: "{usersendto}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +[Registry] +Root: "HKA"; Subkey: "Software\Classes\*\shell\{#MyAppName}"; ValueType: string; ValueName: ""; ValueData: "Open with {#MyAppName}"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\*\shell\{#MyAppName}"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\{#MyAppExeName}, 0"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\*\shell\{#MyAppName}\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExename}"" ""%1"""; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\shell\{#MyAppName}"; ValueType: string; ValueName: ""; ValueData: "Open with {#MyAppName}"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\shell\{#MyAppName}"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\{#MyAppExeName}, 0"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\shell\{#MyAppName}\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExename}"" ""%1"""; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\background\shell\{#MyAppName}"; ValueType: string; ValueName: ""; ValueData: "Open with {#MyAppName}"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\background\shell\{#MyAppName}"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\{#MyAppExeName}, 0"; Flags: uninsdeletekey +Root: "HKA"; Subkey: "Software\Classes\directory\background\shell\{#MyAppName}\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExename}"" ""%V"""; Flags: uninsdeletekey + [Run] Filename: "{app}/{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent From eb306a2ff0fcfa9fa5b057a7c2200d324a8070d8 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 22 Jun 2023 18:03:51 -0400 Subject: [PATCH 117/176] Windows Installer Path Modification (#1536) * innosetup: installation path to environment task Also set the uninstall icon shown on add/remove programs. * Improved path description. --------- Co-authored-by: jgmdev --- scripts/innosetup/innosetup.iss.in | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/scripts/innosetup/innosetup.iss.in b/scripts/innosetup/innosetup.iss.in index 566abe5d..ff1cf425 100644 --- a/scripts/innosetup/innosetup.iss.in +++ b/scripts/innosetup/innosetup.iss.in @@ -57,9 +57,13 @@ OutputBaseFilename=LiteXL-{#MyAppVersion}-{#ArchInternal}-setup LicenseFile={#SourceDir}/LICENSE SetupIconFile={#SourceDir}/resources/icons/icon.ico +UninstallDisplayIcon={app}\{#MyAppExeName}, 0 WizardImageFile="{#SourceDir}/scripts/innosetup/wizard-modern-image.bmp" WizardSmallImageFile="{#SourceDir}/scripts/innosetup/litexl-55px.bmp" +; Required for the add to path option to refresh environment +ChangesEnvironment=yes + [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" @@ -67,6 +71,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 6.1; Check: not IsAdminInstallMode Name: "portablemode"; Description: "Portable Mode"; Flags: unchecked +Name: "envPath"; Description: "Add lite-xl to the PATH variable, allowing it to be run from a command line." [Files] Source: "{#SourceDir}/lite-xl/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs @@ -95,3 +100,62 @@ Filename: "{app}/{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChang [Setup] Uninstallable=not WizardIsTaskSelected('portablemode') + +; Code to add installation path to environment taken from: +; https://stackoverflow.com/a/46609047 +[Code] +const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + +procedure EnvAddPath(Path: string); +var + Paths: string; +begin + { Retrieve current path (use empty string if entry not exists) } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Paths := ''; + + { Skip if string already found in path } + if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; + + { App string to the end of the path variable } + Paths := Paths + ';'+ Path +';' + + { Overwrite (or create if missing) path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths])) + else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths])); +end; + +procedure EnvRemovePath(Path: string); +var + Paths: string; + P: Integer; +begin + { Skip if registry entry not exists } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then + exit; + + { Skip if string not found in path } + P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';'); + if P = 0 then exit; + + { Update path variable } + Delete(Paths, P - 1, Length(Path) + 1); + + { Overwrite path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths])) + else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths])); +end; + +procedure CurStepChanged(CurStep: TSetupStep); +begin + if (CurStep = ssPostInstall) and WizardIsTaskSelected('envPath') + then EnvAddPath(ExpandConstant('{app}')); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +begin + if CurUninstallStep = usPostUninstall + then EnvRemovePath(ExpandConstant('{app}')); +end; From dc148601662c37cfd305b81d4dce1eb6a10e656b Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 18 Aug 2023 21:25:10 +0800 Subject: [PATCH 118/176] fix(core): defer core:open-log until everything is loaded (#1585) * fix(core): defer core:open-log until everything is loaded * docs(core): document why core:open-log is opened in a thread --- data/core/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/core/init.lua b/data/core/init.lua index 16cb265e..890d79c5 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -810,7 +810,11 @@ function core.init() end if not plugins_success or got_user_error or got_project_error then - command.perform("core:open-log") + -- defer LogView to after everything is initialized, + -- so that EmptyView won't be added after LogView. + core.add_thread(function() + command.perform("core:open-log") + end) end core.configure_borderless_window() From 50102fdc3a34f7efd057b71bcad94ddf6b26cb2d Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 20 Aug 2023 16:28:49 +0200 Subject: [PATCH 119/176] Fix `scrollbar` misinterpreting `percent` (#1587) --- data/core/scrollbar.lua | 7 ++++--- data/core/view.lua | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/data/core/scrollbar.lua b/data/core/scrollbar.lua index d2bb0562..05df0afa 100644 --- a/data/core/scrollbar.lua +++ b/data/core/scrollbar.lua @@ -121,7 +121,7 @@ function Scrollbar:_get_thumb_rect_normal() across_size = across_size + (expanded_scrollbar_size - scrollbar_size) * self.expand_percent return nr.across + nr.across_size - across_size, - nr.along + self.percent * nr.scrollable * (nr.along_size - along_size) / (sz - nr.along_size), + nr.along + self.percent * (nr.along_size - along_size), across_size, along_size end @@ -237,7 +237,8 @@ end function Scrollbar:_on_mouse_moved_normal(x, y, dx, dy) if self.dragging then local nr = self.normal_rect - return common.clamp((y - nr.along + self.drag_start_offset) / nr.along_size, 0, 1) + local _, _, _, along_size = self:_get_thumb_rect_normal() + return common.clamp((y - nr.along + self.drag_start_offset) / (nr.along_size - along_size), 0, 1) end return self:_update_hover_status_normal(x, y) end @@ -280,7 +281,7 @@ function Scrollbar:set_size(x, y, w, h, scrollable) end ---Updates the scrollbar location ----@param percent number @number between 0 and 1 representing the position of the middle part of the thumb +---@param percent number @number between 0 and 1 where 0 means thumb at the top and 1 at the bottom function Scrollbar:set_percent(percent) self.percent = percent end diff --git a/data/core/view.lua b/data/core/view.lua index 02560ff8..b204afdc 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -142,14 +142,14 @@ function View:on_mouse_pressed(button, x, y, clicks) local result = self.v_scrollbar:on_mouse_pressed(button, x, y, clicks) if result then if result ~= true then - self.scroll.to.y = result * self:get_scrollable_size() + self.scroll.to.y = result * (self:get_scrollable_size() - self.size.y) end return true end result = self.h_scrollbar:on_mouse_pressed(button, x, y, clicks) if result then if result ~= true then - self.scroll.to.x = result * self:get_h_scrollable_size() + self.scroll.to.x = result * (self:get_h_scrollable_size() - self.size.x) end return true end @@ -177,7 +177,7 @@ function View:on_mouse_moved(x, y, dx, dy) result = self.v_scrollbar:on_mouse_moved(x, y, dx, dy) if result then if result ~= true then - self.scroll.to.y = result * self:get_scrollable_size() + self.scroll.to.y = result * (self:get_scrollable_size() - self.size.y) if not config.animate_drag_scroll then self:clamp_scroll_position() self.scroll.y = self.scroll.to.y @@ -191,7 +191,7 @@ function View:on_mouse_moved(x, y, dx, dy) result = self.h_scrollbar:on_mouse_moved(x, y, dx, dy) if result then if result ~= true then - self.scroll.to.x = result * self:get_h_scrollable_size() + self.scroll.to.x = result * (self:get_h_scrollable_size() - self.size.x) if not config.animate_drag_scroll then self:clamp_scroll_position() self.scroll.x = self.scroll.to.x @@ -287,12 +287,12 @@ end function View:update_scrollbar() local v_scrollable = self:get_scrollable_size() self.v_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, v_scrollable) - self.v_scrollbar:set_percent(self.scroll.y/v_scrollable) + self.v_scrollbar:set_percent(self.scroll.y/(v_scrollable - self.size.y)) self.v_scrollbar:update() local h_scrollable = self:get_h_scrollable_size() self.h_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, h_scrollable) - self.h_scrollbar:set_percent(self.scroll.x/h_scrollable) + self.h_scrollbar:set_percent(self.scroll.x/(h_scrollable - self.size.x)) self.h_scrollbar:update() end From 9bc44e2b450f9c0cf7e44dd6d0d62a8a2e1b3127 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 23 Aug 2023 19:07:52 +0200 Subject: [PATCH 120/176] Fix returned `percent` when clicking the `Scrollbar` `track` --- data/core/scrollbar.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/core/scrollbar.lua b/data/core/scrollbar.lua index 05df0afa..c7590b8c 100644 --- a/data/core/scrollbar.lua +++ b/data/core/scrollbar.lua @@ -189,8 +189,9 @@ function Scrollbar:_on_mouse_pressed_normal(button, x, y, clicks) self.drag_start_offset = along - y return true elseif overlaps == "track" then + local nr = self.normal_rect self.drag_start_offset = - along_size / 2 - return (y - self.normal_rect.along - along_size / 2) / self.normal_rect.along_size + return common.clamp((y - nr.along - along_size / 2) / (nr.along_size - along_size), 0, 1) end end end From 3f3b4d52b47fb63f83b44ec4617292871aab00b3 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:32:07 +0800 Subject: [PATCH 121/176] docs(core.contextmenu): add documentation for contextmenu (#1567) --- data/core/contextmenu.lua | 56 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/data/core/contextmenu.lua b/data/core/contextmenu.lua index 4b466907..d59609d7 100644 --- a/data/core/contextmenu.lua +++ b/data/core/contextmenu.lua @@ -12,11 +12,31 @@ local divider_width = 1 local divider_padding = 5 local DIVIDER = {} +---An item in the context menu. +---@class core.contextmenu.item +---@field text string +---@field info string|nil If provided, this text is displayed on the right side of the menu. +---@field command string|fun() + +---A list of items with the same predicate. +---@see core.command.predicate +---@class core.contextmenu.itemset +---@field predicate core.command.predicate +---@field items core.contextmenu.item[] + +---A context menu. ---@class core.contextmenu : core.object +---@field itemset core.contextmenu.itemset[] +---@field show_context_menu boolean +---@field selected number +---@field position core.view.position +---@field current_scale number local ContextMenu = Object:extend() +---A unique value representing the divider in a context menu. ContextMenu.DIVIDER = DIVIDER +---Creates a new context menu. function ContextMenu:new() self.itemset = {} self.show_context_menu = false @@ -55,12 +75,19 @@ local function update_items_size(items, update_binding) items.width, items.height = width, height end +---Registers a list of items into the context menu with a predicate. +---@param predicate core.command.predicate +---@param items core.contextmenu.item[] function ContextMenu:register(predicate, items) predicate = command.generate_predicate(predicate) update_items_size(items, true) table.insert(self.itemset, { predicate = predicate, items = items }) end +---Shows the context menu. +---@param x number +---@param y number +---@return boolean # If true, the context menu is shown. function ContextMenu:show(x, y) self.items = nil local items_list = { width = 0, height = 0 } @@ -94,6 +121,7 @@ function ContextMenu:show(x, y) return false end +---Hides the context menu. function ContextMenu:hide() self.show_context_menu = false self.items = nil @@ -102,6 +130,8 @@ function ContextMenu:hide() core.request_cursor(core.active_view.cursor) end +---Returns an iterator that iterates over each context menu item and their dimensions. +---@return fun(): number, core.contextmenu.item, number, number, number, number function ContextMenu:each_item() local x, y, w = self.position.x, self.position.y, self.items.width local oy = y @@ -115,8 +145,12 @@ function ContextMenu:each_item() end) end +---Event handler for mouse movements. +---@param px any +---@param py any +---@return boolean # true if the event is caught. function ContextMenu:on_mouse_moved(px, py) - if not self.show_context_menu then return end + if not self.show_context_menu then return false end self.selected = -1 for i, item, x, y, w, h in self:each_item() do @@ -128,6 +162,8 @@ function ContextMenu:on_mouse_moved(px, py) return true end +---Event handler for when the selection is confirmed. +---@param item core.contextmenu.item function ContextMenu:on_selected(item) if type(item.command) == "string" then command.perform(item.command) @@ -140,6 +176,7 @@ local function change_value(value, change) return value + change end +---Selects the the previous item. function ContextMenu:focus_previous() self.selected = (self.selected == -1 or self.selected == 1) and #self.items or change_value(self.selected, -1) if self:get_item_selected() == DIVIDER then @@ -147,6 +184,7 @@ function ContextMenu:focus_previous() end end +---Selects the next item. function ContextMenu:focus_next() self.selected = (self.selected == -1 or self.selected == #self.items) and 1 or change_value(self.selected, 1) if self:get_item_selected() == DIVIDER then @@ -154,10 +192,13 @@ function ContextMenu:focus_next() end end +---Gets the currently selected item. +---@return core.contextmenu.item|nil function ContextMenu:get_item_selected() return (self.items or {})[self.selected] end +---Hides the context menu and performs the command if an item is selected. function ContextMenu:call_selected_item() local selected = self:get_item_selected() self:hide() @@ -166,6 +207,12 @@ function ContextMenu:call_selected_item() end end +---Event handler for mouse press. +---@param button core.view.mousebutton +---@param px number +---@param py number +---@param clicks number +---@return boolean # true if the event is caught. function ContextMenu:on_mouse_pressed(button, px, py, clicks) local caught = false @@ -186,14 +233,20 @@ function ContextMenu:on_mouse_pressed(button, px, py, clicks) return caught end +---@type fun(self: table, k: string, dest: number, rate?: number, name?: string) ContextMenu.move_towards = View.move_towards +---Event handler for content update. function ContextMenu:update() if self.show_context_menu then self:move_towards("height", self.items.height, nil, "contextmenu") end end +---Draws the context menu. +--- +---This wraps `ContextMenu:draw_context_menu()`. +---@see core.contextmenu.draw_context_menu function ContextMenu:draw() if not self.show_context_menu then return end if self.current_scale ~= SCALE then @@ -206,6 +259,7 @@ function ContextMenu:draw() core.root_view:defer_draw(self.draw_context_menu, self) end +---Draws the context menu. function ContextMenu:draw_context_menu() if not self.items then return end local bx, by, bw, bh = self.position.x, self.position.y, self.items.width, self.height From 3993d689fb474b377185b306126f0118e14b8b3e Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 25 Aug 2023 04:33:39 +0200 Subject: [PATCH 122/176] Use Lua wrap by default (#1481) Debian and all its derivatives ship a broken Lua 5.4 that is missing some symbols. To work around broken distros and make development and distribution easier use the wrap by default and add an option to use the system version. --- meson.build | 37 ++++++++++++++++++++----------------- meson_options.txt | 3 ++- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/meson.build b/meson.build index c3b0569c..3cfec808 100644 --- a/meson.build +++ b/meson.build @@ -4,8 +4,7 @@ project('lite-xl', license : 'MIT', meson_version : '>= 0.56', default_options : [ - 'c_std=gnu11', - 'wrap_mode=nofallback' + 'c_std=gnu11' ] ) @@ -84,23 +83,27 @@ if not get_option('source-only') 'lua', # Fedora ] - foreach lua : lua_names - last_lua = (lua == lua_names[-1] or get_option('wrap_mode') == 'forcefallback') - lua_dep = dependency(lua, fallback: last_lua ? ['lua', 'lua_dep'] : [], required : false, - version: '>= 5.4', + if get_option('use_system_lua') + foreach lua : lua_names + last_lua = (lua == lua_names[-1] or get_option('wrap_mode') == 'forcefallback') + lua_dep = dependency(lua, required : false, + ) + if lua_dep.found() + break + endif + + if last_lua + # If we could not find lua on the system and fallbacks are disabled + # try the compiler as a last ditch effort, since Lua has no official + # pkg-config support. + lua_dep = cc.find_library('lua', required : true) + endif + endforeach + else + lua_dep = dependency('', fallback: ['lua', 'lua_dep'], required : true, default_options: default_fallback_options + ['default_library=static', 'line_editing=false', 'interpreter=false'] ) - if lua_dep.found() - break - endif - - if last_lua - # If we could not find lua on the system and fallbacks are disabled - # try the compiler as a last ditch effort, since Lua has no official - # pkg-config support. - lua_dep = cc.find_library('lua', required : true) - endif - endforeach + endif pcre2_dep = dependency('libpcre2-8', fallback: ['pcre2', 'libpcre2_8'], default_options: default_fallback_options + ['default_library=static', 'grep=false', 'test=false'] diff --git a/meson_options.txt b/meson_options.txt index 9cfcc353..ae9d8c6b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,4 +3,5 @@ option('source-only', type : 'boolean', value : false, description: 'Configure s option('portable', type : 'boolean', value : false, description: 'Portable install') option('renderer', type : 'boolean', value : false, description: 'Use SDL renderer') option('dirmonitor_backend', type : 'combo', value : '', choices : ['', 'inotify', 'fsevents', 'kqueue', 'win32', 'dummy'], description: 'define what dirmonitor backend to use') -option('arch_tuple', type : 'string', value : '', description: 'Specify a custom architecture tuple') \ No newline at end of file +option('arch_tuple', type : 'string', value : '', description: 'Specify a custom architecture tuple') +option('use_system_lua', type : 'boolean', value : false, description: 'Prefer System Lua over a the meson wrap') From 2ed17dd03ff0411c91ece13461863b1bdeb46da3 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 25 Aug 2023 20:03:23 +0200 Subject: [PATCH 123/176] Normalize strokes in fixed order (#1572) * Use normalized strokes when removing duplicates only when appropriate * Use normalized stroke in `keymap.unbind` * Normalize strokes by sorting the modifiers before the keys This also sorts the modifiers in a fixed manner, decided by `modkeys.keys`. We need to do this because we display the strokes in a few places like the command palette. --- data/core/keymap.lua | 38 ++++++++++++++++++++--------------- data/core/modkeys-generic.lua | 2 +- data/core/modkeys-macos.lua | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/data/core/keymap.lua b/data/core/keymap.lua index bae1e63a..3ab0c360 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -40,15 +40,19 @@ local modkeys = modkeys_os.keys ---@return string local function normalize_stroke(stroke) local stroke_table = {} - for modkey in stroke:gmatch("(%w+)%+") do - table.insert(stroke_table, modkey) + for key in stroke:gmatch("[^+]+") do + table.insert(stroke_table, key) end - if not next(stroke_table) then - return stroke - end - table.sort(stroke_table) - local new_stroke = table.concat(stroke_table, "+") .. "+" - return new_stroke .. stroke:sub(new_stroke:len() + 1) + table.sort(stroke_table, function(a, b) + if a == b then return false end + for _, mod in ipairs(modkeys) do + if a == mod or b == mod then + return a == mod + end + end + return a < b + end) + return table.concat(stroke_table, "+") end @@ -56,15 +60,16 @@ end ---@param key string ---@return string local function key_to_stroke(key) - local stroke = "" + local keys = { key } for _, mk in ipairs(modkeys) do if keymap.modkeys[mk] then - stroke = stroke .. mk .. "+" + table.insert(keys, mk) end end - return normalize_stroke(stroke) .. key + return normalize_stroke(table.concat(keys, "+")) end + ---Remove the given value from an array associated to a key in a table. ---@param tbl table The table containing the key ---@param k string The key containing the array @@ -90,12 +95,12 @@ end ---@param map keymap.map local function remove_duplicates(map) for stroke, commands in pairs(map) do - stroke = normalize_stroke(stroke) + local normalized_stroke = normalize_stroke(stroke) if type(commands) == "string" or type(commands) == "function" then commands = { commands } end - if keymap.map[stroke] then - for _, registered_cmd in ipairs(keymap.map[stroke]) do + if keymap.map[normalized_stroke] then + for _, registered_cmd in ipairs(keymap.map[normalized_stroke]) do local j = 0 for i=1, #commands do while commands[i + j] == registered_cmd do @@ -118,7 +123,7 @@ end function keymap.add_direct(map) for stroke, commands in pairs(map) do stroke = normalize_stroke(stroke) - + if type(commands) == "string" or type(commands) == "function" then commands = { commands } end @@ -172,7 +177,8 @@ end ---@param shortcut string ---@param cmd string function keymap.unbind(shortcut, cmd) - remove_only(keymap.map, normalize_stroke(shortcut), cmd) + shortcut = normalize_stroke(shortcut) + remove_only(keymap.map, shortcut, cmd) remove_only(keymap.reverse_map, cmd, shortcut) end diff --git a/data/core/modkeys-generic.lua b/data/core/modkeys-generic.lua index 6e264061..e239d8a9 100644 --- a/data/core/modkeys-generic.lua +++ b/data/core/modkeys-generic.lua @@ -9,6 +9,6 @@ modkeys.map = { ["right alt"] = "altgr", } -modkeys.keys = { "ctrl", "alt", "altgr", "shift" } +modkeys.keys = { "ctrl", "shift", "alt", "altgr" } return modkeys diff --git a/data/core/modkeys-macos.lua b/data/core/modkeys-macos.lua index e9fd0665..86b28de0 100644 --- a/data/core/modkeys-macos.lua +++ b/data/core/modkeys-macos.lua @@ -13,6 +13,6 @@ modkeys.map = { ["right alt"] = "altgr", } -modkeys.keys = { "cmd", "ctrl", "alt", "option", "altgr", "shift" } +modkeys.keys = { "ctrl", "alt", "option", "altgr", "shift", "cmd" } return modkeys From b0e1469a8743a93c3a23b85898bb2e46a50860d7 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Aug 2023 14:34:51 -0400 Subject: [PATCH 124/176] Adds super as a modkey. (#1590) * Adds super as a modkey. * Added in super designation for windows. --- data/core/modkeys-generic.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/core/modkeys-generic.lua b/data/core/modkeys-generic.lua index e239d8a9..613813dc 100644 --- a/data/core/modkeys-generic.lua +++ b/data/core/modkeys-generic.lua @@ -7,8 +7,12 @@ modkeys.map = { ["right shift"] = "shift", ["left alt"] = "alt", ["right alt"] = "altgr", + ["left gui"] = "super", + ["left windows"] = "super", + ["right gui"] = "super", + ["right windows"] = "super" } -modkeys.keys = { "ctrl", "shift", "alt", "altgr" } +modkeys.keys = { "ctrl", "shift", "alt", "altgr", "super" } return modkeys From 25a0943087ddd9b70e6bb6b7b6bbfcf5088a6ca5 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 26 Aug 2023 05:11:10 +0200 Subject: [PATCH 125/176] Add `NaN` guard to `View:update_scrollbar` --- data/core/view.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data/core/view.lua b/data/core/view.lua index b204afdc..bab75b01 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -287,12 +287,16 @@ end function View:update_scrollbar() local v_scrollable = self:get_scrollable_size() self.v_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, v_scrollable) - self.v_scrollbar:set_percent(self.scroll.y/(v_scrollable - self.size.y)) + local v_percent = self.scroll.y/(v_scrollable - self.size.y) + -- Avoid setting nan percent + self.v_scrollbar:set_percent(v_percent == v_percent and v_percent or 0) self.v_scrollbar:update() local h_scrollable = self:get_h_scrollable_size() self.h_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, h_scrollable) - self.h_scrollbar:set_percent(self.scroll.x/(h_scrollable - self.size.x)) + local h_percent = self.scroll.x/(h_scrollable - self.size.x) + -- Avoid setting nan percent + self.h_scrollbar:set_percent(h_percent == h_percent and h_percent or 0) self.h_scrollbar:update() end From 27f24701c4ebf084a8b7cc9a42d13a22932ebbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jefferson=20Gonz=C3=A1lez?= Date: Sat, 26 Aug 2023 10:50:48 -0400 Subject: [PATCH 126/176] Autocomplete plugin improvements (#1519) * Add icons support to autocomplete plugin * Removed redundant flag check * Added support for non syntax colors * Assert if color name not in style.syntax * Autocomplete plugin improvements * Support suggestion symbols scoping - global: all open documents - local: current document - related: all open documents with same syntax - none: language syntax symbols only * Register style.syntax[] entries as icons * Other related fixes --- data/plugins/autocomplete.lua | 218 ++++++++++++++++++++++++++++++---- 1 file changed, 198 insertions(+), 20 deletions(-) diff --git a/data/plugins/autocomplete.lua b/data/plugins/autocomplete.lua index cf228b6e..98b2dcd0 100644 --- a/data/plugins/autocomplete.lua +++ b/data/plugins/autocomplete.lua @@ -10,6 +10,10 @@ local RootView = require "core.rootview" local DocView = require "core.docview" local Doc = require "core.doc" +---Symbols cache of all open documents +---@type table +local cache = setmetatable({}, { __mode = "k" }) + config.plugins.autocomplete = common.merge({ -- Amount of characters that need to be written for autocomplete min_len = 3, @@ -19,8 +23,16 @@ config.plugins.autocomplete = common.merge({ max_suggestions = 100, -- Maximum amount of symbols to cache per document max_symbols = 4000, + -- Which symbols to show on the suggestions list: global, local, related, none + suggestions_scope = "global", -- Font size of the description box desc_font_size = 12, + -- Do not show the icons associated to the suggestions + hide_icons = false, + -- Position where icons will be displayed on the suggestions list + icon_position = "left", + -- Do not show the additional information related to a suggestion + hide_info = false, -- The config specification used by gui generators config_spec = { name = "Autocomplete", @@ -60,6 +72,26 @@ config.plugins.autocomplete = common.merge({ min = 1000, max = 10000 }, + { + label = "Suggestions Scope", + description = "Which symbols to show on the suggestions list.", + path = "suggestions_scope", + type = "selection", + default = "global", + values = { + {"All Documents", "global"}, + {"Current Document", "local"}, + {"Related Documents", "related"}, + {"Known Symbols", "none"} + }, + on_apply = function(value) + if value == "global" then + for _, doc in ipairs(core.docs) do + if cache[doc] then cache[doc] = nil end + end + end + end + }, { label = "Description Font Size", description = "Font size of the description box.", @@ -67,6 +99,31 @@ config.plugins.autocomplete = common.merge({ type = "number", default = 12, min = 8 + }, + { + label = "Hide Icons", + description = "Do not show icons on the suggestions list.", + path = "hide_icons", + type = "toggle", + default = false + }, + { + label = "Icons Position", + description = "Position to display icons on the suggestions list.", + path = "icon_position", + type = "selection", + default = "left", + values = { + {"Left", "left"}, + {"Right", "Right"} + } + }, + { + label = "Hide Items Info", + description = "Do not show the additional info related to each suggestion.", + path = "hide_info", + type = "toggle", + default = false } } }, config.plugins.autocomplete) @@ -76,6 +133,7 @@ local autocomplete = {} autocomplete.map = {} autocomplete.map_manually = {} autocomplete.on_close = nil +autocomplete.icons = {} -- Flag that indicates if the autocomplete box was manually triggered -- with the autocomplete.complete() function to prevent the suggestions @@ -95,6 +153,7 @@ function autocomplete.add(t, manually_triggered) { text = text, info = info.info, + icon = info.icon, -- Name of icon to show desc = info.desc, -- Description shown on item selected onhover = info.onhover, -- A callback called once when item is hovered onselect = info.onselect, -- A callback called when item is selected @@ -119,28 +178,35 @@ end -- -- Thread that scans open document symbols and cache them -- -local max_symbols = config.plugins.autocomplete.max_symbols +local global_symbols = {} core.add_thread(function() - local cache = setmetatable({}, { __mode = "k" }) - - local function get_syntax_symbols(symbols, doc) - if doc.syntax then - for sym in pairs(doc.syntax.symbols) do - symbols[sym] = true + local function load_syntax_symbols(doc) + if doc.syntax and not autocomplete.map["language_"..doc.syntax.name] then + local symbols = { + name = "language_"..doc.syntax.name, + files = doc.syntax.files, + items = {} + } + for name, type in pairs(doc.syntax.symbols) do + symbols.items[name] = type end + autocomplete.add(symbols) + return symbols.items end + return {} end local function get_symbols(doc) local s = {} - get_syntax_symbols(s, doc) + local syntax_symbols = load_syntax_symbols(doc) + local max_symbols = config.plugins.autocomplete.max_symbols if doc.disable_symbols then return s end local i = 1 local symbols_count = 0 while i <= #doc.lines do for sym in doc.lines[i]:gmatch(config.symbol_pattern) do - if not s[sym] then + if not s[sym] and not syntax_symbols[sym] then symbols_count = symbols_count + 1 if symbols_count > max_symbols then s = nil @@ -186,14 +252,18 @@ core.add_thread(function() } end -- update symbol set with doc's symbol set - for sym in pairs(cache[doc].symbols) do - symbols[sym] = true + if config.plugins.autocomplete.suggestions_scope == "global" then + for sym in pairs(cache[doc].symbols) do + symbols[sym] = true + end end coroutine.yield() end - -- update symbols list - autocomplete.add { name = "open-docs", items = symbols } + -- update global symbols list + if config.plugins.autocomplete.suggestions_scope == "global" then + global_symbols = symbols + end -- wait for next scan local valid = true @@ -240,12 +310,50 @@ local function update_suggestions() map = autocomplete.map_manually end + local assigned_sym = {} + -- get all relevant suggestions for given filename local items = {} for _, v in pairs(map) do if common.match_pattern(filename, v.files) then for _, item in pairs(v.items) do table.insert(items, item) + assigned_sym[item.text] = true + end + end + end + + -- Append the global, local or related text symbols if applicable + local scope = config.plugins.autocomplete.suggestions_scope + + if not triggered_manually then + local text_symbols = nil + + if scope == "global" then + text_symbols = global_symbols + elseif scope == "local" and cache[doc] and cache[doc].symbols then + text_symbols = cache[doc].symbols + elseif scope == "related" then + for _, d in ipairs(core.docs) do + if doc.syntax == d.syntax then + if cache[d].symbols then + for name in pairs(cache[d].symbols) do + if not assigned_sym[name] then + table.insert(items, setmetatable( + {text = name, info = "normal"}, mt + )) + end + end + end + end + end + end + + if text_symbols then + for name in pairs(text_symbols) do + if not assigned_sym[name] then + table.insert(items, setmetatable({text = name, info = "normal"}, mt)) + end end end end @@ -286,13 +394,23 @@ local function get_suggestions_rect(av) y = y + av:get_line_height() + style.padding.y local font = av:get_font() local th = font:get_height() + local has_icons = false + local hide_info = config.plugins.autocomplete.hide_info + local hide_icons = config.plugins.autocomplete.hide_icons local max_width = 0 for _, s in ipairs(suggestions) do local w = font:get_width(s.text) - if s.info then + if s.info and not hide_info then w = w + style.font:get_width(s.info) + style.padding.x end + local icon = s.icon or s.info + if not hide_icons and icon and autocomplete.icons[icon] then + w = w + autocomplete.icons[icon].font:get_width( + autocomplete.icons[icon].char + ) + (style.padding.x / 2) + has_icons = true + end max_width = math.max(max_width, w) end @@ -319,7 +437,8 @@ local function get_suggestions_rect(av) x - style.padding.x, y - style.padding.y, max_width + style.padding.x * 2, - max_items * (th + style.padding.y) + style.padding.y + max_items * (th + style.padding.y) + style.padding.y, + has_icons end local function wrap_line(line, max_chars) @@ -439,7 +558,7 @@ local function draw_suggestions_box(av) local ah = config.plugins.autocomplete.max_height -- draw background rect - local rx, ry, rw, rh = get_suggestions_rect(av) + local rx, ry, rw, rh, has_icons = get_suggestions_rect(av) renderer.draw_rect(rx, ry, rw, rh, style.background3) -- draw text @@ -448,17 +567,52 @@ local function draw_suggestions_box(av) local y = ry + style.padding.y / 2 local show_count = #suggestions <= ah and #suggestions or ah local start_index = suggestions_idx > ah and (suggestions_idx-(ah-1)) or 1 + local hide_info = config.plugins.autocomplete.hide_info for i=start_index, start_index+show_count-1, 1 do if not suggestions[i] then break end local s = suggestions[i] + + local icon_l_padding, icon_r_padding = 0, 0 + + if has_icons then + local icon = s.icon or s.info + if icon and autocomplete.icons[icon] then + local ifont = autocomplete.icons[icon].font + local itext = autocomplete.icons[icon].char + local icolor = autocomplete.icons[icon].color + if i == suggestions_idx then + icolor = style.accent + elseif type(icolor) == "string" then + icolor = style.syntax[icolor] + end + if config.plugins.autocomplete.icon_position == "left" then + common.draw_text( + ifont, icolor, itext, "left", rx + style.padding.x, y, rw, lh + ) + icon_l_padding = ifont:get_width(itext) + (style.padding.x / 2) + else + common.draw_text( + ifont, icolor, itext, "right", rx, y, rw - style.padding.x, lh + ) + icon_r_padding = ifont:get_width(itext) + (style.padding.x / 2) + end + end + end + local color = (i == suggestions_idx) and style.accent or style.text - common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh) - if s.info then + common.draw_text( + font, color, s.text, "left", + rx + icon_l_padding + style.padding.x, y, rw, lh + ) + if s.info and not hide_info then color = (i == suggestions_idx) and style.text or style.dim - common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh) + common.draw_text( + style.font, color, s.info, "right", + rx, y, rw - icon_r_padding - style.padding.x, lh + ) end y = y + lh if suggestions_idx == i then @@ -619,6 +773,31 @@ function autocomplete.can_complete() return false end +---Register a font icon that can be assigned to completion items. +---@param name string +---@param character string +---@param font? renderer.font +---@param color? string | renderer.color A style.syntax[] name or specific color +function autocomplete.add_icon(name, character, font, color) + local color_type = type(color) + assert( + not color or color_type == "table" + or (color_type == "string" and style.syntax[color]), + "invalid icon color given" + ) + autocomplete.icons[name] = { + char = character, + font = font or style.code_font, + color = color or "keyword" + } +end + +-- +-- Register built-in syntax symbol types icon +-- +for name, _ in pairs(style.syntax) do + autocomplete.add_icon(name, "M", style.icon_font, name) +end -- -- Commands @@ -632,7 +811,6 @@ command.add(predicate, { ["autocomplete:complete"] = function(dv) local doc = dv.doc local item = suggestions[suggestions_idx] - local text = item.text local inserted = false if item.onselect then inserted = item.onselect(suggestions_idx, item) From 1d5f7ae9b0d915d69296e599786bcdf977238b1d Mon Sep 17 00:00:00 2001 From: sammyette Date: Sat, 26 Aug 2023 08:19:12 -0700 Subject: [PATCH 127/176] feat(statusview): make a separate item for doc position percent (#1579) * feat(statusview): make a separate item for doc position percent * chore: remove unused variable * fix(statusview): remove command for percent doc item * fix(statusview): change doc percent tooltip * fix(statusview): change percent tooltip message --- data/core/statusview.lua | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 731c0552..3ef40d82 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -232,15 +232,27 @@ function StatusView:register_docview_items() return { style.text, line, ":", col > config.line_limit and style.accent or style.text, col, - style.text, - self.separator, - string.format("%.f%%", line / #dv.doc.lines * 100) + style.text } end, command = "doc:go-to-line", tooltip = "line : column" }) + self:add_item({ + predicate = predicate_docview, + name = "doc:position-percent", + alignment = StatusView.Item.LEFT, + get_item = function() + local dv = core.active_view + local line = dv.doc:get_selection() + return { + string.format("%.f%%", line / #dv.doc.lines * 100) + } + end, + tooltip = "caret position" + }) + self:add_item({ predicate = predicate_docview, name = "doc:selections", From 15e05aaf038eecff5bdf38cdb61455519dbf57d7 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sat, 26 Aug 2023 23:32:39 +0800 Subject: [PATCH 128/176] docs(core.config): add documentation for config options (#1512) * docs(core.config): add documentation for config options * docs(core.config): remove wrong newline * docs(core.config): remove trailing whitespace * docs(core.config): add missing whitespace * docs(core.config): add disclaimer for core.file_size_limit * docs(core.config): fix wrong description of the pattern * docs(core.config): fix wrong description * docs(core.config): fix wrong description for transitions * docs(core.config): guide user to drawwhitespace plugin * docs(core.config): clarify libdecor usage * docs(core.config): clarify various things * docs(core.config): clarify more about libdecor support * docs(core.config): fix missing enum separator * docs(core.config): remove wayland-specific advice on config.borderless --- data/core/config.lua | 206 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 4 deletions(-) diff --git a/data/core/config.lua b/data/core/config.lua index c1a16b11..2381639f 100644 --- a/data/core/config.lua +++ b/data/core/config.lua @@ -2,15 +2,71 @@ local common = require "core.common" local config = {} +---The frame rate of Lite XL. +---Note that setting this value to the screen's refresh rate +---does not eliminate screen tearing. +--- +---Defaults to 60. +---@type number config.fps = 60 + +---Maximum number of log items that will be stored. +---When the number of log items exceed this value, old items will be discarded. +--- +---Defaults to 800. +---@type number config.max_log_items = 800 + +---The timeout, in seconds, before a message dissapears from StatusView. +--- +---Defaults to 5. +---@type number config.message_timeout = 5 + +---The number of pixels scrolled per-step. +--- +---Defaults to 50 * SCALE. +---@type number config.mouse_wheel_scroll = 50 * SCALE + +---Enables/disables transitions when scrolling with the scrollbar. +---When enabled, the scrollbar will have inertia and slowly move towards the cursor. +---Otherwise, the scrollbar will immediately follow the cursor. +--- +---Defaults to false. +---@type boolean config.animate_drag_scroll = false + +---Enables/disables scrolling past the end of a document. +--- +---Defaults to true. +---@type boolean config.scroll_past_end = true ----@type "expanded" | "contracted" | false @Force the scrollbar status of the DocView + +---@alias config.scrollbartype +---| "expanded" # A thicker scrollbar is shown at all times. +---| "contracted" # A thinner scrollbar is shown at all times. +---| false # The scrollbar expands when the cursor hovers over it. + +---Controls whether the DocView scrollbar is always shown or hidden. +---This option does not affect other View's scrollbars. +--- +---Defaults to false. +---@type config.scrollbartype config.force_scrollbar_status = false + +---The file size limit, in megabytes. +---Files larger than this size will not be shown in the file picker. +--- +---Defaults to 10. +---@type number config.file_size_limit = 10 + +---A list of files and directories to ignore. +---Each element is a Lua pattern, where patterns ending with a forward slash +---are recognized as directories while patterns ending with an anchor ("$") are +---recognized as files. +---@type string[] config.ignore_files = { -- folders "^%.svn/", "^%.git/", "^%.hg/", "^CVS/", "^%.Trash/", "^%.Trash%-.*/", @@ -21,46 +77,188 @@ config.ignore_files = { "%.suo$", "%.pdb$", "%.idb$", "%.class$", "%.psd$", "%.db$", "^desktop%.ini$", "^%.DS_Store$", "^%.directory$", } + +---Lua pattern used to find symbols when advanced syntax highlighting +---is not available. +---This pattern is also used for navigation, e.g. move to next word. +--- +---The default pattern matches all letters, followed by any number +---of letters and digits. +---@type string config.symbol_pattern = "[%a_][%w_]*" + +---A list of characters that delimits a word. +--- +---The default is ``" \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"`` +---@type string config.non_word_chars = " \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" + +---The timeout, in seconds, before several consecutive actions +---are merged as a single undo step. +--- +---The default is 0.3 seconds. +---@type number config.undo_merge_timeout = 0.3 + +---The maximum number of undo steps per-document. +--- +---The default is 10000. +---@type number config.max_undos = 10000 + +---The maximum number of tabs shown at a time. +--- +---The default is 8. +---@type number config.max_tabs = 8 + +---Shows/hides the tab bar when there is only one tab open. +--- +---The tab bar is always shown by default. +---@type boolean config.always_show_tabs = true --- Possible values: false, true, "no_selection" + +---@alias config.highlightlinetype +---| true # Always highlight the current line. +---| false # Never highlight the current line. +---| "no_selection" # Highlight the current line if no text is selected. + +---Highlights the current line. +--- +---The default is true. +---@type config.highlightlinetype config.highlight_current_line = true + +---The spacing between each line of text. +--- +---The default is 120% of the height of the text (1.2). +---@type number config.line_height = 1.2 + +---The number of spaces each level of indentation represents. +--- +---The default is 2. +---@type number config.indent_size = 2 + +---The type of indentation. +--- +---The default is "soft" (spaces). +---@type "soft" | "hard" config.tab_type = "soft" + +---Do not remove whitespaces when advancing to the next line. +--- +---Defaults to false. +---@type boolean config.keep_newline_whitespace = false + +---Maximum number of characters per-line for the line guide. +--- +---Defaults to 80. +---@type number config.line_limit = 80 + +---Maximum number of project files to keep track of. +---If the number of files in the project exceeds this number, +---Lite XL will not be able to keep track of them. +---They will be not be searched when searching for files or text. +--- +---Defaults to 2000. +---@type number config.max_project_files = 2000 + +---Enables/disables all transitions. +--- +---Defaults to true. +---@type boolean config.transitions = true + +---Enable/disable individual transitions. +---These values are overriden by `config.transitions`. config.disabled_transitions = { + ---Disables scrolling transitions. scroll = false, + ---Disables transitions for CommandView's suggestions list. commandview = false, + ---Disables transitions for showing/hiding the context menu. contextmenu = false, + ---Disables transitions when clicking on log items in LogView. logview = false, + ---Disables transitions for showing/hiding the Nagbar. nagbar = false, + ---Disables transitions when scrolling the tab bar. tabs = false, + ---Disables transitions when a tab is being dragged. tab_drag = false, + ---Disables transitions when a notification is shown. statusbar = false, } + +---The rate of all transitions. +--- +---Defaults to 1. +---@type number config.animation_rate = 1.0 + +---The caret's blinking period, in seconds. +--- +---Defaults to 0.8. +---@type number config.blink_period = 0.8 + +---Disables caret blinking. +--- +---Defaults to false. +---@type boolean config.disable_blink = false + +---Draws whitespaces as dots. +---This option is deprecated. +---Please use the drawwhitespace plugin instead. +---@deprecated config.draw_whitespace = false + +---Disables system-drawn window borders. +--- +---When set to true, Lite XL draws its own window decorations, +---which can be useful for certain setups. +--- +---Defaults to false. +---@type boolean config.borderless = false + +---Shows/hides the close buttons on tabs. +---When hidden, users can close tabs via keyboard shortcuts or commands. +--- +---Defaults to true. +---@type boolean config.tab_close_button = true + +---Maximum number of clicks recognized by Lite XL. +--- +---Defaults to 3. +---@type number config.max_clicks = 3 --- set as true to be able to test non supported plugins +---Disables plugin version checking. +---Do not change this unless you know what you are doing. +--- +---Defaults to false. +---@type boolean config.skip_plugins_version = false -- holds the plugins real config table local plugins_config = {} --- virtual representation of plugins config table +---A table containing configuration for all the plugins. +--- +---This is a metatable that automaticaly creates a minimal +---configuration when a plugin is initially configured. +---Each plugins will then call `common.merge()` to get the finalized +---plugin config. +---Do not use raw operations on this table. +---@type table config.plugins = {} -- allows virtual access to the plugins config table From 351ef1ecea31ccb8e52e24b7e76b4921bd5c8f1f Mon Sep 17 00:00:00 2001 From: Robert Hildebrandt Date: Thu, 7 Sep 2023 01:54:52 +0200 Subject: [PATCH 129/176] Fixed C++14 digit separators (#1593) --- data/plugins/language_cpp.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/plugins/language_cpp.lua b/data/plugins/language_cpp.lua index a26ce868..70489713 100644 --- a/data/plugins/language_cpp.lua +++ b/data/plugins/language_cpp.lua @@ -14,9 +14,9 @@ syntax.add { { pattern = { "/%*", "%*/" }, type = "comment" }, { pattern = { '"', '"', '\\' }, type = "string" }, { pattern = { "'", "'", '\\' }, type = "string" }, - { pattern = "0x%x+", type = "number" }, + { pattern = "0x%x+[%x']*", type = "number" }, { pattern = "%d+[%d%.'eE]*f?", type = "number" }, - { pattern = "%.?%d+f?", type = "number" }, + { pattern = "%.?%d+[%d']*f?", type = "number" }, { pattern = "[%+%-=/%*%^%%<>!~|:&]", type = "operator" }, { pattern = "##", type = "operator" }, { pattern = "struct%s()[%a_][%w_]*", type = {"keyword", "keyword2"} }, From e5c17ed3ec625604a2c1bc5d3fd3700a384b401c Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 7 Sep 2023 04:04:24 +0200 Subject: [PATCH 130/176] Fix `Scrollbar.{expanded,contracted}_size` documentation --- data/core/scrollbar.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/scrollbar.lua b/data/core/scrollbar.lua index c7590b8c..29352dd4 100644 --- a/data/core/scrollbar.lua +++ b/data/core/scrollbar.lua @@ -58,9 +58,9 @@ function Scrollbar:new(options) ---@type "expanded" | "contracted" | false @Force the scrollbar status self.force_status = options.force_status self:set_forced_status(options.force_status) - ---@type number? @Override the default value specified by `style.expanded_scrollbar_size` - self.contracted_size = options.contracted_size ---@type number? @Override the default value specified by `style.scrollbar_size` + self.contracted_size = options.contracted_size + ---@type number? @Override the default value specified by `style.expanded_scrollbar_size` self.expanded_size = options.expanded_size end From febfcb5757c1e7e7be7004e03a289773dc15702d Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 7 Sep 2023 04:07:21 +0200 Subject: [PATCH 131/176] Make `linewrapping` consider the expanded `Scrollbar` size This avoids reflowing the text when hovering the scrollbar. --- data/plugins/linewrapping.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/plugins/linewrapping.lua b/data/plugins/linewrapping.lua index 62412720..0b9f0b76 100644 --- a/data/plugins/linewrapping.lua +++ b/data/plugins/linewrapping.lua @@ -219,7 +219,7 @@ function LineWrapping.draw_guide(docview) end function LineWrapping.update_docview_breaks(docview) - local x,y,w,h = docview.v_scrollbar:get_thumb_rect() + local w = docview.v_scrollbar.expanded_size or style.expanded_scrollbar_size local width = (type(config.plugins.linewrapping.width_override) == "function" and config.plugins.linewrapping.width_override(docview)) or config.plugins.linewrapping.width_override or (docview.size.x - docview:get_gutter_width() - w) if (not docview.wrapped_settings or docview.wrapped_settings.width == nil or width ~= docview.wrapped_settings.width) then From 4f28f718a9f235179ce92e0e2b06ceb3a074934f Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:16:13 +0800 Subject: [PATCH 132/176] docs: update invite link on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d7c7e3c3..c6b21e85 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Lite XL [![CI]](https://github.com/lite-xl/lite-xl/actions/workflows/build.yml) -[![Discord Badge Image]](https://discord.gg/RWzqC3nx7K) +[![Discord Badge Image]](https://discord.gg/UQKnzBhY5H) ![screenshot-dark] From 17cb2e86ed75a3ac9702bac9b4d92027b3192a1a Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 30 Sep 2023 16:48:38 +0200 Subject: [PATCH 133/176] Remove DPI detection for default `SCALE` This often leads to `SCALE` values that are way off, and makes Lite XL unusable, so we now just default it to 1. --- data/core/start.lua | 2 +- src/main.c | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/data/core/start.lua b/data/core/start.lua index c104cb13..07e1e385 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -5,7 +5,7 @@ MOD_VERSION_MINOR = 0 MOD_VERSION_PATCH = 0 MOD_VERSION_STRING = string.format("%d.%d.%d", MOD_VERSION_MAJOR, MOD_VERSION_MINOR, MOD_VERSION_PATCH) -SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or SCALE +SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or 1 PATHSEP = package.config:sub(1, 1) EXEDIR = EXEFILE:match("^(.+)[/\\][^/\\]+$") diff --git a/src/main.c b/src/main.c index 1d1b78ee..7cba80c1 100644 --- a/src/main.c +++ b/src/main.c @@ -20,16 +20,6 @@ static SDL_Window *window; -static double get_scale(void) { -#ifndef __APPLE__ - float dpi; - if (SDL_GetDisplayDPI(0, NULL, &dpi, NULL) == 0) - return dpi / 96.0; -#endif - return 1.0; -} - - static void get_exe_filename(char *buf, int sz) { #if _WIN32 int len; @@ -203,9 +193,6 @@ init_lua: lua_pushstring(L, LITE_ARCH_TUPLE); lua_setglobal(L, "ARCH"); - lua_pushnumber(L, get_scale()); - lua_setglobal(L, "SCALE"); - char exename[2048]; get_exe_filename(exename, sizeof(exename)); if (*exename) { From 9017fadba6d940095a36e59d0ca4c053dfa77e85 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 12 Oct 2023 00:24:42 +0800 Subject: [PATCH 134/176] docs: fix prebuilt install instructions (#1637) * docs: fix prebuilt install instructions Added missing documentation for Windows and macOS. Also updated the Linux instruction for creating desktop entries. * docs: more clarification and grammar fixes * docs: clarify plugin and config load in portable mode * docs: better phrasing Co-authored-by: Guldoman * docs: better phrasing Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c6b21e85..0bd00e48 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,29 @@ affects only the place where the application is actually installed. Head over to [releases](https://github.com/lite-xl/lite-xl/releases) and download the version for your operating system. +### Windows + +Lite XL comes with installers on Windows for typical installations. +Alternatively, we provide ZIP archives that you can download and extract anywhere and run directly. + +To make Lite XL portable (e.g. running Lite XL from a thumb drive), +simply create a `user` folder where `lite-xl.exe` is located. +Lite XL will load and store all your configurations and plugins in the folder. + +### macOS + +We provide DMG files for macOS. Simply drag the program into your Applications folder. + +> **Important** +> Since Lite XL is not signed, you **must** run this command before starting Lite XL: +> +> ```sh +> # clears attributes from the directory +> xattr -cr /Applications/Lite\ XL.app +> ``` +> +> Otherwise, macOS will display a **very misleading error** saying that the application is damaged. + ### Linux Unzip the file and `cd` into the `lite-xl` directory: @@ -91,6 +114,7 @@ cd lite-xl ``` To run lite-xl without installing: + ```sh ./lite-xl ``` @@ -103,21 +127,59 @@ mkdir -p $HOME/.local/bin && cp lite-xl $HOME/.local/bin/ mkdir -p $HOME/.local/share/lite-xl && cp -r data/* $HOME/.local/share/lite-xl/ ``` +#### Add Lite XL to PATH + +To run Lite XL from the command line, you must add it to PATH. + If `$HOME/.local/bin` is not in PATH: ```sh echo -e 'export PATH=$PATH:$HOME/.local/bin' >> $HOME/.bashrc ``` -To get the icon to show up in app launcher: +Alternatively on recent versions of GNOME and KDE Plasma, +you can add `$HOME/.local/bin` to PATH via `~/.config/environment.d/envvars.conf`: + +```ini +PATH=$HOME/.local/bin:$PATH +``` + +> **Note** +> Some systems might not load `.bashrc` when logging in. +> This can cause problems with launching applications from the desktop / menu. + +#### Add Lite XL to application launchers + +To get the icon to show up in app launcher, you need to create a desktop +entry and put it into `/usr/share/applications` or `~/.local/share/applications`. + +Here is an example for a desktop entry in `~/.local/share/applications/com.lite_xl.LiteXL.desktop`, +assuming Lite XL is in PATH: + +```ini +[Desktop Entry] +Type=Application +Name=Lite XL +Comment=A lightweight text editor written in Lua +Exec=lite-xl %F +Icon=lite-xl +Terminal=false +StartupWMClass=lite-xl +Categories=Development;IDE; +MimeType=text/plain;inode/directory; +``` + +To get the icon to show up in app launcher immediately, run: ```sh xdg-desktop-menu forceupdate ``` -You may need to logout and login again to see icon in app launcher. +Alternatively, you may log out and log in again. -To uninstall just run: +#### Uninstall + +To uninstall Lite XL, run: ```sh rm -f $HOME/.local/bin/lite-xl @@ -127,7 +189,6 @@ rm -rf $HOME/.local/share/icons/hicolor/scalable/apps/lite-xl.svg \ $HOME/.local/share/lite-xl ``` - ## Contributing Any additional functionality that can be added through a plugin should be done From 1196bf355c5bb16f39bafcb45b221502fb3656d8 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 15 Oct 2023 04:16:36 +0800 Subject: [PATCH 135/176] fix: dim rendering when antialiasing is turned off (#1641) --- src/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer.c b/src/renderer.c index f4dbcc78..0e36aaa1 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -167,7 +167,7 @@ static void font_load_glyphset(RenFont* font, int idx) { for (unsigned int column = 0; column < slot->bitmap.width; ++column) { int current_source_offset = source_offset + (column / 8); int source_pixel = slot->bitmap.buffer[current_source_offset]; - pixels[++target_offset] = ((source_pixel >> (7 - (column % 8))) & 0x1) << 7; + pixels[++target_offset] = ((source_pixel >> (7 - (column % 8))) & 0x1) * 0xFF; } } else memcpy(&pixels[target_offset], &slot->bitmap.buffer[source_offset], slot->bitmap.width); From 16694096108b71c6a8f80abe1c359f6daf2b3fe1 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 18 Oct 2023 06:45:31 +0200 Subject: [PATCH 136/176] Mark unsaved named files as dirty (#1598) --- data/core/doc/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 086e9f3e..deeb3816 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -123,6 +123,7 @@ end function Doc:is_dirty() if self.new_file then + if self.filename then return true end return #self.lines > 1 or #self.lines[1] > 1 else return self.clean_change_id ~= self:get_change_id() From 9612f20685b21caf6cc2f90e6bd8dfa214d2c4e4 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 18 Oct 2023 06:45:52 +0200 Subject: [PATCH 137/176] Improve `common.serialize` (#1640) * Make `common.serialize` more locale-independent * Handle inf/nan numbers in `common.serialize` --- data/core/common.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index 272f0d5d..a887c307 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -378,12 +378,15 @@ function common.bench(name, fn, ...) return res end +-- From gvx/Ser +local oddvals = {[tostring(1/0)] = "1/0", [tostring(-1/0)] = "-1/0", [tostring(-(0/0))] = "-(0/0)", [tostring(0/0)] = "0/0"} local function serialize(val, pretty, indent_str, escape, sort, limit, level) local space = pretty and " " or "" local indent = pretty and string.rep(indent_str, level) or "" local newline = pretty and "\n" or "" - if type(val) == "string" then + local ty = type(val) + if ty == "string" then local out = string.format("%q", val) if escape then out = string.gsub(out, "\\\n", "\\n") @@ -395,7 +398,7 @@ local function serialize(val, pretty, indent_str, escape, sort, limit, level) out = string.gsub(out, "\\13", "\\r") end return out - elseif type(val) == "table" then + elseif ty == "table" then -- early exit if level >= limit then return tostring(val) end local next_indent = pretty and (indent .. indent_str) or "" @@ -410,6 +413,12 @@ local function serialize(val, pretty, indent_str, escape, sort, limit, level) if sort then table.sort(t) end return "{" .. newline .. table.concat(t, "," .. newline) .. newline .. indent .. "}" end + if ty == "number" then + -- tostring is locale-dependent, so we need to replace an eventual `,` with `.` + local res, _ = tostring(val):gsub(",", ".") + -- handle inf/nan + return oddvals[res] or res + end return tostring(val) end From 7e20424b29f426b37315af07324be01671477b5d Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 18 Oct 2023 06:46:27 +0200 Subject: [PATCH 138/176] Ignore keypresses during IME composition (#1573) Some IMEs continue sending keypresses even during composition, so we just ignore them. --- data/core/init.lua | 3 +++ data/core/keymap.lua | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 890d79c5..8b43d8ed 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1278,6 +1278,9 @@ function core.on_event(type, ...) elseif type == "textediting" then ime.on_text_editing(...) elseif type == "keypressed" then + -- In some cases during IME composition input is still sent to us + -- so we just ignore it. + if ime.editing then return false end did_keymap = keymap.on_key_pressed(...) elseif type == "keyreleased" then keymap.on_key_released(...) diff --git a/data/core/keymap.lua b/data/core/keymap.lua index 3ab0c360..74e270d2 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -203,10 +203,6 @@ end -- Events listening -------------------------------------------------------------------------------- function keymap.on_key_pressed(k, ...) - -- In MacOS and Windows during IME composition input is still sent to us - -- so we just ignore it - if PLATFORM ~= "Linux" and ime.editing then return false end - local mk = modkey_map[k] if mk then keymap.modkeys[mk] = true From 9be4583f63e76565540dfd4884575aa0350ddfa7 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 18 Oct 2023 06:46:58 +0200 Subject: [PATCH 139/176] Save in the `workspace` unsaved named files and `crlf` status (#1597) * Save in the `workspace` unsaved named files * Save in the `workspace` the `crlf` status and restore it for "new" files --- data/plugins/workspace.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data/plugins/workspace.lua b/data/plugins/workspace.lua index 6426cbdb..3b3bd044 100644 --- a/data/plugins/workspace.lua +++ b/data/plugins/workspace.lua @@ -83,7 +83,8 @@ local function save_view(view) filename = view.doc.filename, selection = { view.doc:get_selection() }, scroll = { x = view.scroll.to.x, y = view.scroll.to.y }, - text = not view.doc.filename and view.doc:get_text(1, 1, math.huge, math.huge) + crlf = view.doc.crlf, + text = view.doc.new_file and view.doc:get_text(1, 1, math.huge, math.huge) } end if mt == LogView then return end @@ -106,7 +107,6 @@ local function load_view(t) if not t.filename then -- document not associated to a file dv = DocView(core.open_doc()) - if t.text then dv.doc:insert(1, 1, t.text) end else -- we have a filename, try to read the file local ok, doc = pcall(core.open_doc, t.filename) @@ -114,9 +114,11 @@ local function load_view(t) dv = DocView(doc) end end - -- doc view "dv" can be nil here if the filename associated to the document - -- cannot be read. if dv and dv.doc then + if dv.doc.new_file and t.text then + dv.doc:insert(1, 1, t.text) + dv.doc.crlf = t.crlf + end dv.doc:set_selection(table.unpack(t.selection)) dv.last_line1, dv.last_col1, dv.last_line2, dv.last_col2 = dv.doc:get_selection() dv.scroll.x, dv.scroll.to.x = t.scroll.x, t.scroll.x From e520227d358d24e949f651126e6e9c3dd5da7868 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:09:51 +0800 Subject: [PATCH 140/176] ci: fix diff files having "wrong" path separator (#1648) * ci: fix diff files having "wrong" path separator * ci(build): use git bash to apply patches * ci(build): fix step wording Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- .github/workflows/build.yml | 9 ++++---- resources/windows/001-lua-unicode.diff | 30 +++++++++++++------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 398aae67..461a9d16 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -201,12 +201,13 @@ jobs: "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV "INSTALL_REF=$($env:GITHUB_REF -replace ".*/")" >> $env:GITHUB_ENV "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV + - name: Download and patch subprojects + shell: bash + run: | + meson subprojects download + cat resources/windows/001-lua-unicode.diff | patch -Np1 -d "$LUA_SUBPROJECT_PATH" - name: Configure run: | - # Download the subprojects first so we can patch it before configuring. - # This avoids reconfiguring the subprojects when compiling. - meson subprojects download - Get-Content -Path resources/windows/001-lua-unicode.diff -Raw | patch -d $env:LUA_SUBPROJECT_PATH -p1 --forward meson setup --wrap-mode=forcefallback build - name: Build run: | diff --git a/resources/windows/001-lua-unicode.diff b/resources/windows/001-lua-unicode.diff index 31fec364..e6a2ae44 100644 --- a/resources/windows/001-lua-unicode.diff +++ b/resources/windows/001-lua-unicode.diff @@ -1,6 +1,6 @@ -diff -ruN lua-5.4.4\meson.build lua-5.4.4-patched\meson.build ---- lua-5.4.4\meson.build Wed Feb 22 18:16:56 2023 -+++ lua-5.4.4-patched\meson.build Wed Feb 22 04:10:01 2023 +diff -ruN lua-5.4.4/meson.build lua-5.4.4-patched/meson.build +--- lua-5.4.4/meson.build Wed Feb 22 18:16:56 2023 ++++ lua-5.4.4-patched/meson.build Wed Feb 22 04:10:01 2023 @@ -85,6 +85,7 @@ 'src/lutf8lib.c', 'src/lvm.c', @@ -9,9 +9,9 @@ diff -ruN lua-5.4.4\meson.build lua-5.4.4-patched\meson.build dependencies: lua_lib_deps, version: meson.project_version(), soversion: lua_versions[0] + '.' + lua_versions[1], -diff -ruN lua-5.4.4\src\luaconf.h lua-5.4.4-patched\src\luaconf.h ---- lua-5.4.4\src\luaconf.h Thu Jan 13 19:24:43 2022 -+++ lua-5.4.4-patched\src\luaconf.h Wed Feb 22 04:10:02 2023 +diff -ruN lua-5.4.4/src/luaconf.h lua-5.4.4-patched/src/luaconf.h +--- lua-5.4.4/src/luaconf.h Thu Jan 13 19:24:43 2022 ++++ lua-5.4.4-patched/src/luaconf.h Wed Feb 22 04:10:02 2023 @@ -782,5 +782,15 @@ @@ -28,9 +28,9 @@ diff -ruN lua-5.4.4\src\luaconf.h lua-5.4.4-patched\src\luaconf.h + #endif -diff -ruN lua-5.4.4\src\Makefile lua-5.4.4-patched\src\Makefile ---- lua-5.4.4\src\Makefile Thu Jul 15 22:01:52 2021 -+++ lua-5.4.4-patched\src\Makefile Wed Feb 22 04:10:02 2023 +diff -ruN lua-5.4.4/src/Makefile lua-5.4.4-patched/src/Makefile +--- lua-5.4.4/src/Makefile Thu Jul 15 22:01:52 2021 ++++ lua-5.4.4-patched/src/Makefile Wed Feb 22 04:10:02 2023 @@ -33,7 +33,7 @@ PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris @@ -40,9 +40,9 @@ diff -ruN lua-5.4.4\src\Makefile lua-5.4.4-patched\src\Makefile LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) -diff -ruN lua-5.4.4\src\utf8_wrappers.c lua-5.4.4-patched\src\utf8_wrappers.c ---- lua-5.4.4\src\utf8_wrappers.c Thu Jan 01 08:00:00 1970 -+++ lua-5.4.4-patched\src\utf8_wrappers.c Wed Feb 22 18:13:45 2023 +diff -ruN lua-5.4.4/src/utf8_wrappers.c lua-5.4.4-patched/src/utf8_wrappers.c +--- lua-5.4.4/src/utf8_wrappers.c Thu Jan 01 08:00:00 1970 ++++ lua-5.4.4-patched/src/utf8_wrappers.c Wed Feb 22 18:13:45 2023 @@ -0,0 +1,129 @@ +/** + * Wrappers to provide Unicode (UTF-8) support on Windows. @@ -173,9 +173,9 @@ diff -ruN lua-5.4.4\src\utf8_wrappers.c lua-5.4.4-patched\src\utf8_wrappers.c + return env_value; +} +#endif -diff -ruN lua-5.4.4\src\utf8_wrappers.h lua-5.4.4-patched\src\utf8_wrappers.h ---- lua-5.4.4\src\utf8_wrappers.h Thu Jan 01 08:00:00 1970 -+++ lua-5.4.4-patched\src\utf8_wrappers.h Wed Feb 22 18:09:48 2023 +diff -ruN lua-5.4.4/src/utf8_wrappers.h lua-5.4.4-patched/src/utf8_wrappers.h +--- lua-5.4.4/src/utf8_wrappers.h Thu Jan 01 08:00:00 1970 ++++ lua-5.4.4-patched/src/utf8_wrappers.h Wed Feb 22 18:09:48 2023 @@ -0,0 +1,46 @@ +/** + * Wrappers to provide Unicode (UTF-8) support on Windows. From 05e7fc4e439f9e01a15949fd7cea1e42da79f786 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 21 Oct 2023 08:16:32 +0200 Subject: [PATCH 141/176] Set SDL hint to prefer software render driver (#1646) --- src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.c b/src/main.c index 7cba80c1..252b0f45 100644 --- a/src/main.c +++ b/src/main.c @@ -160,6 +160,8 @@ int main(int argc, char **argv) { SDL_SetHint("SDL_MOUSE_DOUBLE_CLICK_RADIUS", "4"); #endif + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software"); + SDL_DisplayMode dm; SDL_GetCurrentDisplayMode(0, &dm); From 637096849496f45d8eb7821d744f584df4c668a8 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Sun, 22 Oct 2023 01:17:49 +0800 Subject: [PATCH 142/176] fix(dirmonitor): deadlock if error handler jumps somewhere else (#1647) * fix: deadlock if error handler jumps somewhere else * docs(dirmonitor): fix wrong data type in error callback * docs(dirmonitor): clarify coroutines and deadlocks * docs(dirmonitor): wording Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- data/core/dirwatch.lua | 4 ++++ docs/api/dirmonitor.lua | 6 +++++- src/api/dirmonitor.c | 22 +++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/data/core/dirwatch.lua b/data/core/dirwatch.lua index e3b6d61c..3b62fa24 100644 --- a/data/core/dirwatch.lua +++ b/data/core/dirwatch.lua @@ -91,6 +91,7 @@ end -- designed to be run inside a coroutine. function dirwatch:check(change_callback, scan_time, wait_time) local had_change = false + local last_error self.monitor:check(function(id) had_change = true if self.monitor:mode() == "single" then @@ -102,7 +103,10 @@ function dirwatch:check(change_callback, scan_time, wait_time) elseif self.reverse_watched[id] then change_callback(self.reverse_watched[id]) end + end, function(err) + last_error = err end) + if last_error ~= nil then error(last_error) end local start_time = system.get_time() for directory, old_modified in pairs(self.scanned) do if old_modified then diff --git a/docs/api/dirmonitor.lua b/docs/api/dirmonitor.lua index 439e0ec4..a12b61f1 100644 --- a/docs/api/dirmonitor.lua +++ b/docs/api/dirmonitor.lua @@ -45,10 +45,14 @@ function dirmonitor:unwatch(fd_or_path) end ---edited, removed or added. A file descriptor will be passed to the ---callback in "multiple" mode or a path in "single" mode. --- +---If an error occurred during the callback execution, the error callback will be called with the error object. +---This callback should not manipulate coroutines to avoid deadlocks. +--- ---@param callback dirmonitor.callback +---@param error_callback fun(error: any): nil --- ---@return boolean? changes True when changes were detected. -function dirmonitor:check(callback) end +function dirmonitor:check(callback, error_callback) end --- ---Get the working mode for the current file system monitoring backend. diff --git a/src/api/dirmonitor.c b/src/api/dirmonitor.c index 1bccfd13..320235a0 100644 --- a/src/api/dirmonitor.c +++ b/src/api/dirmonitor.c @@ -1,4 +1,5 @@ #include "api.h" +#include "lua.h" #include #include #include @@ -25,13 +26,16 @@ int get_mode_dirmonitor(); static int f_check_dir_callback(int watch_id, const char* path, void* L) { - lua_pushvalue(L, -1); + // using absolute indices from f_dirmonitor_check (2: callback, 3: error_callback) + lua_pushvalue(L, 2); if (path) lua_pushlstring(L, path, watch_id); else lua_pushnumber(L, watch_id); - lua_call(L, 1, 1); - int result = lua_toboolean(L, -1); + + int result = 0; + if (lua_pcall(L, 1, 1, 3) == LUA_OK) + result = lua_toboolean(L, -1); lua_pop(L, 1); return !result; } @@ -95,8 +99,20 @@ static int f_dirmonitor_unwatch(lua_State *L) { } +static int f_noop(lua_State *L) { return 0; } + + static int f_dirmonitor_check(lua_State* L) { struct dirmonitor* monitor = luaL_checkudata(L, 1, API_TYPE_DIRMONITOR); + luaL_checktype(L, 2, LUA_TFUNCTION); + if (!lua_isnoneornil(L, 3)) { + luaL_checktype(L, 3, LUA_TFUNCTION); + } else { + lua_settop(L, 2); + lua_pushcfunction(L, f_noop); + } + lua_settop(L, 3); + SDL_LockMutex(monitor->mutex); if (monitor->length < 0) lua_pushnil(L); From 05fbc48e03ef6461da63845bb978f37436bab914 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 23 Oct 2023 23:58:02 +0200 Subject: [PATCH 143/176] Sanitize tab index in `Node:add_view` (#1651) * Fix `Node:add_view` not adjusting tab index after removing `EmptyView` * Clamp tab index in `Node:add_view` --- data/core/node.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/core/node.lua b/data/core/node.lua index 3ae9b256..86d4e4e0 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -177,8 +177,12 @@ function Node:add_view(view, idx) assert(not self.locked, "Tried to add view to locked node") if self.views[1] and self.views[1]:is(EmptyView) then table.remove(self.views) + if idx and idx > 1 then + idx = idx - 1 + end end - table.insert(self.views, idx or (#self.views + 1), view) + idx = common.clamp(idx or (#self.views + 1), 1, (#self.views + 1)) + table.insert(self.views, idx, view) self:set_active_view(view) end From dc3716f1777c8818ade623e0d8b7774690c32dd6 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Fri, 27 Oct 2023 13:39:08 +0200 Subject: [PATCH 144/176] Make license time-independent (#1655) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index da7be0e2..387fd09d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2021 Lite XL Team +Copyright (c) 2020-present Lite XL Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in From df7cf7e270ae6ca6c41c0814c708627cbd9d7e53 Mon Sep 17 00:00:00 2001 From: ThaCuber <70547062+thacuber2a03@users.noreply.github.com> Date: Tue, 31 Oct 2023 16:24:36 -0400 Subject: [PATCH 145/176] ease transparency of nagbar dim (#1658) * ease transparency of nagbar dim * tiny changes * lerp alpha rather than the whole color --- data/core/nagview.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/core/nagview.lua b/data/core/nagview.lua index b66da75c..1a7fa193 100644 --- a/data/core/nagview.lua +++ b/data/core/nagview.lua @@ -24,6 +24,7 @@ function NagView:new() self.scrollable = true self.target_height = 0 self.on_mouse_pressed_root = nil + self.dim_alpha = 0 end function NagView:get_title() @@ -68,7 +69,9 @@ function NagView:dim_window_content() oy = oy + self.show_height local w, h = core.root_view.size.x, core.root_view.size.y - oy core.root_view:defer_draw(function() - renderer.draw_rect(ox, oy, w, h, style.nagbar_dim) + local dim_color = { table.unpack(style.nagbar_dim) } + dim_color[4] = style.nagbar_dim[4] * self.dim_alpha + renderer.draw_rect(ox, oy, w, h, dim_color) end) end @@ -172,10 +175,13 @@ function NagView:update() NagView.super.update(self) if self.visible and core.active_view == self and self.title then - self:move_towards(self, "show_height", self:get_target_height(), nil, "nagbar") + local target_height = self:get_target_height() + self:move_towards(self, "show_height", target_height, nil, "nagbar") self:move_towards(self, "underline_progress", 1, nil, "nagbar") + self:move_towards(self, "dim_alpha", self.show_height / target_height, nil, "nagbar") else self:move_towards(self, "show_height", 0, nil, "nagbar") + self:move_towards(self, "dim_alpha", 0, nil, "nagbar") if self.show_height <= 0 then self.title = nil self.message = nil From de05ec374efbb17c267df01a0597d46e4be0a7b6 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 10 Nov 2023 09:36:44 +0800 Subject: [PATCH 146/176] feat(package): ad-hoc sign macOS bundles (#1656) * feat(package): ad-hoc sign macOS bundles * fix(package.sh): syntax error * docs(readme): add instructions for self-signed builds * docs(readme): grammar Co-authored-by: Guldoman --------- Co-authored-by: Guldoman --- README.md | 12 +++++++++++- scripts/package.sh | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bd00e48..05949e80 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,17 @@ Lite XL will load and store all your configurations and plugins in the folder. We provide DMG files for macOS. Simply drag the program into your Applications folder. > **Important** -> Since Lite XL is not signed, you **must** run this command before starting Lite XL: +> Newer versions of Lite XL are signed with a self-signed certificate, +> so you'll have to follow these steps when running Lite XL for the first time. +> +> 1. Find Lite XL in Finder (do not open it in Launchpad). +> 2. Control-click Lite XL, then choose `Open` from the shortcut menu. +> 3. Click `Open` in the popup menu. +> +> The correct steps may vary between macOS versions, so you should refer to +> the [macOS User Guide](https://support.apple.com/en-my/guide/mac-help/mh40616/mac). +> +> On an older version of Lite XL, you will need to run these commands instead: > > ```sh > # clears attributes from the directory diff --git a/scripts/package.sh b/scripts/package.sh index d2346b76..1faba509 100644 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -264,6 +264,11 @@ main() { $stripcmd "${exe_file}" fi + if [[ $bundle == true ]]; then + # https://eclecticlight.co/2019/01/17/code-signing-for-the-concerned-3-signing-an-app/ + codesign --force --deep -s - "${dest_dir}" + fi + echo "Creating a compressed archive ${package_name}" if [[ $binary == true ]]; then rm -f "${package_name}".tar.gz From dc62c59705cd3990b7c246276e86e97fd4d9d6d0 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Fri, 10 Nov 2023 09:44:58 +0800 Subject: [PATCH 147/176] refactor(build): use dmgbuild to create dmgs (#1664) * refactor(appdmg): make dmgs with dmgbuild * fix(appdmg.sh): typo * refactor(appdmg.sh): don't generate config on the fly * fix(dmgbuild): icon file * fix(gitignore): dmgbuild settings * chore(resources): update readme with new files * chore(resources/macos): add missing newline --- .github/workflows/build.yml | 8 +++-- .github/workflows/release.yml | 4 +-- .gitignore | 1 + build-packages.sh | 2 +- resources/README.md | 5 ++-- resources/macos/{appdmg.png => dmg-cover.png} | Bin resources/macos/lite-xl-dmg.py | 28 ++++++++++++++++++ scripts/README.md | 4 +-- scripts/appdmg.sh | 23 +------------- scripts/install-dependencies.sh | 4 +-- scripts/package.sh | 2 +- 11 files changed, 46 insertions(+), 35 deletions(-) rename resources/macos/{appdmg.png => dmg-cover.png} (100%) create mode 100644 resources/macos/lite-xl-dmg.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 461a9d16..96db355f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,6 +110,12 @@ jobs: run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "INSTALL_NAME=lite-xl-${GITHUB_REF##*/}-macos-universal" >> "$GITHUB_ENV" + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Install dmgbuild + run: pip install dmgbuild - uses: actions/checkout@v3 - name: Download artifacts uses: actions/download-artifact@v3 @@ -117,8 +123,6 @@ jobs: with: name: macOS DMG Images path: dmgs-original - - name: Install appdmg - run: cd ~; npm i appdmg; cd - - name: Make universal bundles run: | bash --version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index edf66372..5d9a388c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -185,8 +185,8 @@ jobs: uses: actions/setup-python@v2 with: python-version: 3.9 - - name: Install appdmg - run: cd ~; npm i appdmg; cd - + - name: Install dmgbuild + run: pip install dmgbuild - name: Prepare DMG Images run: | mkdir -p dmgs-addons dmgs-normal diff --git a/.gitignore b/.gitignore index 9b248455..7b420ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ LiteXL* !resources/windows/*.diff !resources/windows/*.exe.manifest.in +!resources/macos/*.py diff --git a/build-packages.sh b/build-packages.sh index 96a7d11d..a95d3460 100755 --- a/build-packages.sh +++ b/build-packages.sh @@ -38,7 +38,7 @@ show_help() { echo "-v --version VERSION Sets the version on the package name." echo "-A --appimage Create an AppImage (Linux only)." echo "-D --dmg Create a DMG disk image (macOS only)." - echo " Requires NPM and AppDMG." + echo " Requires dmgbuild." echo "-I --innosetup Create an InnoSetup installer (Windows only)." echo "-r --release Compile in release mode." echo "-S --source Create a source code package," diff --git a/resources/README.md b/resources/README.md index 4cd85256..d6d80eec 100644 --- a/resources/README.md +++ b/resources/README.md @@ -11,8 +11,9 @@ This folder contains resources that is used for building or packaging the projec - `icons/icon.{icns,ico,inl,rc,svg}`: lite-xl icon in various formats. - `linux/com.lite_xl.LiteXL.appdata.xml`: AppStream metadata. - `linux/com.lite_xl.LiteXL.desktop`: Desktop file for Linux desktops. -- `macos/appdmg.png`: Background image for packaging MacOS DMGs. -- `macos/Info.plist.in`: Template for generating `info.plist` on MacOS. See `macos/macos-retina-display.md` for details. +- `macos/dmg-cover.png`: Background image for packaging macOS DMGs. +- `macos/Info.plist.in`: Template for generating `info.plist` on macOS. See `macos/macos-retina-display.md` for details. +- `macos/lite-xl-dmg.py`: Configuration options for dmgbuild for packaging macOS DMGs. - `windows/001-lua-unicode.diff`: Patch for allowing Lua to load files with UTF-8 filenames on Windows. ### Development diff --git a/resources/macos/appdmg.png b/resources/macos/dmg-cover.png similarity index 100% rename from resources/macos/appdmg.png rename to resources/macos/dmg-cover.png diff --git a/resources/macos/lite-xl-dmg.py b/resources/macos/lite-xl-dmg.py new file mode 100644 index 00000000..27b24417 --- /dev/null +++ b/resources/macos/lite-xl-dmg.py @@ -0,0 +1,28 @@ +# configuration for dmgbuild + +import os.path + +app_path = "Lite XL.app" +app_name = os.path.basename(app_path) + +# Image options +format = defines.get("format", "UDZO") + +# Content options +files = [(app_path, app_name)] +symlinks = { "Applications": "/Applications" } +icon = "resources/icons/icon.icns" +icon_locations = { + app_name: (144, 248), + "Applications": (336, 248) +} + +# Window options +background = "resources/macos/dmg-cover.png" +window_rect = ((360, 360), (480, 380)) +default_view = "coverflow" +include_icon_view_settings = True + +# Icon view options +icon_size = 80 +text_size = 11.0 diff --git a/scripts/README.md b/scripts/README.md index 478e461f..5910931c 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -10,7 +10,7 @@ Various scripts and configurations used to configure, build, and package Lite XL ### Package -- **appdmg.sh**: Create a macOS DMG image using [AppDMG][1]. +- **appdmg.sh**: Create a macOS DMG image using [dmgbuild][1]. - **appimage.sh**: [AppImage][2] builder. - **innosetup.sh**: Creates a 32/64 bit [InnoSetup][3] installer package. - **package.sh**: Creates all binary / DMG image / installer / source packages. @@ -25,6 +25,6 @@ Various scripts and configurations used to configure, build, and package Lite XL - **generate_header.sh**: Generates a header file for native plugin API - **keymap-generator**: Generates a JSON file containing the keymap -[1]: https://github.com/LinusU/node-appdmg +[1]: https://github.com/dmgbuild/dmgbuild [2]: https://docs.appimage.org/ [3]: https://jrsoftware.org/isinfo.php diff --git a/scripts/appdmg.sh b/scripts/appdmg.sh index 840f518b..5ce4fe71 100644 --- a/scripts/appdmg.sh +++ b/scripts/appdmg.sh @@ -6,25 +6,4 @@ if [ ! -e "src/api/api.h" ]; then exit 1 fi -cat > lite-xl-dmg.json << EOF -{ - "title": "Lite XL", - "icon": "$(pwd)/resources/icons/icon.icns", - "background": "$(pwd)/resources/macos/appdmg.png", - "window": { - "position": { - "x": 360, - "y": 360 - }, - "size": { - "width": 480, - "height": 360 - } - }, - "contents": [ - { "x": 144, "y": 248, "type": "file", "path": "$(pwd)/Lite XL.app" }, - { "x": 336, "y": 248, "type": "link", "path": "/Applications" } - ] -} -EOF -~/node_modules/appdmg/bin/appdmg.js lite-xl-dmg.json "$(pwd)/$1.dmg" +dmgbuild -s resources/macos/lite-xl-dmg.py "Lite XL" "$1.dmg" diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh index 1290cfcc..00606944 100644 --- a/scripts/install-dependencies.sh +++ b/scripts/install-dependencies.sh @@ -57,9 +57,7 @@ main() { else brew install bash ninja sdl2 fi - pip3 install meson - cd ~; npm install appdmg; cd - - ~/node_modules/appdmg/bin/appdmg.js --version + pip3 install meson dmgbuild elif [[ "$OSTYPE" == "msys" ]]; then if [[ $lhelper == true ]]; then pacman --noconfirm -S \ diff --git a/scripts/package.sh b/scripts/package.sh index 1faba509..d9a9c14c 100644 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -25,7 +25,7 @@ show_help() { echo "-A --appimage Create an AppImage (Linux only)." echo "-B --binary Create a normal / portable package or macOS bundle," echo " depending on how the build was configured. (Default.)" - echo "-D --dmg Create a DMG disk image with AppDMG (macOS only)." + echo "-D --dmg Create a DMG disk image with dmgbuild (macOS only)." echo "-I --innosetup Create a InnoSetup package (Windows only)." echo "-r --release Strip debugging symbols." echo "-S --source Create a source code package," From da64a99f18d44906dd05b33ca5329792e70d7555 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 28 Nov 2023 20:54:00 +0100 Subject: [PATCH 148/176] Avoid considering single spaces in `detectindent` (#1595) --- data/plugins/detectindent.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/plugins/detectindent.lua b/data/plugins/detectindent.lua index 8fad044b..9f22c66b 100644 --- a/data/plugins/detectindent.lua +++ b/data/plugins/detectindent.lua @@ -266,7 +266,7 @@ local function detect_indent_stat(doc) local max_lines = auto_detect_max_lines for i, text in get_non_empty_lines(doc.syntax, doc.lines) do local spaces = text:match("^ +") - if spaces then table.insert(stat, spaces:len()) end + if spaces and #spaces > 1 then table.insert(stat, #spaces) end local tabs = text:match("^\t+") if tabs then tab_count = tab_count + 1 end -- if nothing found for first lines try at least 4 more times From 3972f100599692cd1433799c109cb25ebb39aae0 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 28 Nov 2023 20:54:11 +0100 Subject: [PATCH 149/176] Fix deleting indentation with multiple cursors (#1670) --- data/core/commands/doc.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index aa73a2c0..c698d2cc 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -340,10 +340,11 @@ local commands = { local text = dv.doc:get_text(line1, 1, line1, col1) if #text >= indent_size and text:find("^ *$") then dv.doc:delete_to_cursor(idx, 0, -indent_size) - return + goto continue end end dv.doc:delete_to_cursor(idx, translate.previous_char) + ::continue:: end end, From 86b89c402d53b1dbdb4864b64c88810f5c22c637 Mon Sep 17 00:00:00 2001 From: Daniel Margarido Date: Tue, 28 Nov 2023 23:34:44 +0000 Subject: [PATCH 150/176] Fixed issue with set_target_size passing the wrong value to plugins (#1657) * Fixed issue with set_target_size passing the wrong value to plugins that are split on the right and activated from the settings UI. * Added position awareness for the all resize_child_node calls. --- data/core/rootview.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/core/rootview.lua b/data/core/rootview.lua index 18ae40ab..ec9d5e0e 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -313,10 +313,10 @@ function RootView:on_mouse_moved(x, y, dx, dy) if self.dragged_divider then local node = self.dragged_divider if node.type == "hsplit" then - x = common.clamp(x, 0, self.root_node.size.x * 0.95) + x = common.clamp(x - node.position.x, 0, self.root_node.size.x * 0.95) resize_child_node(node, "x", x, dx) elseif node.type == "vsplit" then - y = common.clamp(y, 0, self.root_node.size.y * 0.95) + y = common.clamp(y - node.position.y, 0, self.root_node.size.y * 0.95) resize_child_node(node, "y", y, dy) end node.divider = common.clamp(node.divider, 0.01, 0.99) @@ -406,10 +406,10 @@ function RootView:on_touch_moved(x, y, dx, dy, ...) if self.dragged_divider then local node = self.dragged_divider if node.type == "hsplit" then - x = common.clamp(x, 0, self.root_node.size.x * 0.95) + x = common.clamp(x - node.position.x, 0, self.root_node.size.x * 0.95) resize_child_node(node, "x", x, dx) elseif node.type == "vsplit" then - y = common.clamp(y, 0, self.root_node.size.y * 0.95) + y = common.clamp(y - node.position.y, 0, self.root_node.size.y * 0.95) resize_child_node(node, "y", y, dy) end node.divider = common.clamp(node.divider, 0.01, 0.99) From c4f9542509fb13fe8a8d586ffe7c6e022bc1b2e4 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 02:07:33 +0100 Subject: [PATCH 151/176] Limit `system.{sleep,wait_event}` to timeouts >= 0 (#1666) Otherwise we might wait forever by mistake. --- src/api/system.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api/system.c b/src/api/system.c index 51978018..2774a97a 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -386,6 +386,7 @@ static int f_wait_event(lua_State *L) { int nargs = lua_gettop(L); if (nargs >= 1) { double n = luaL_checknumber(L, 1); + if (n < 0) n = 0; lua_pushboolean(L, SDL_WaitEventTimeout(NULL, n * 1000)); } else { lua_pushboolean(L, SDL_WaitEvent(NULL)); @@ -861,6 +862,7 @@ static int f_get_time(lua_State *L) { static int f_sleep(lua_State *L) { double n = luaL_checknumber(L, 1); + if (n < 0) n = 0; SDL_Delay(n * 1000); return 0; } From 1dceaf65f5ce65dec0f5d4a3b104afd08cc67e40 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 12 Nov 2023 00:48:34 +0100 Subject: [PATCH 152/176] Fix running `core.step` when receiving an event while not waiting When `time_to_wake` was <= 0, so when a coroutine needed to be executed as soon as possible, we didn't check for events, so we only performed a `core.step` with the blink timer. This resulted in jerky reactions to input. --- data/core/init.lua | 2 +- docs/api/system.lua | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 8b43d8ed..61ee9b97 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1461,7 +1461,7 @@ function core.run() local cursor_time_to_wake = dt + 1 / config.fps next_step = now + cursor_time_to_wake end - if time_to_wake > 0 and system.wait_event(math.min(next_step - now, time_to_wake)) then + if system.wait_event(math.min(next_step - now, time_to_wake)) then next_step = nil -- if we've recevied an event, perform a step end else diff --git a/docs/api/system.lua b/docs/api/system.lua index 9e5ef289..ae0f7424 100644 --- a/docs/api/system.lua +++ b/docs/api/system.lua @@ -61,10 +61,10 @@ function system.poll_event() end --- ---Wait until an event is triggered. --- ----@param timeout number Amount of seconds, also supports fractions ----of a second, eg: 0.01 +---@param timeout? number Amount of seconds, also supports fractions +---of a second, eg: 0.01. If not provided, waits forever. --- ----@return boolean status True on success or false if there was an error. +---@return boolean status True on success or false if there was an error or if no event was received. function system.wait_event(timeout) end --- From 3ee903b16c256acebf8c695e93497275bb45b411 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 15:55:38 +0100 Subject: [PATCH 153/176] Fix `dirmonitor` sorting issues (#1599) * Use `PATHSEP` in path-related functions * Don't stop on digits when getting the common part in `system.path_compare` * Avoid sorting multiple times in `dirwatch.get_directory_files` This also fixes the timeout detection in `recurse_pred`. --- data/core/common.lua | 16 ++++++------- data/core/dirwatch.lua | 48 +++++++++++++++++++-------------------- data/core/init.lua | 10 ++++---- data/plugins/treeview.lua | 2 +- src/api/system.c | 3 +-- 5 files changed, 37 insertions(+), 42 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index a887c307..82f1ab6f 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -226,7 +226,7 @@ function common.path_suggest(text, root) if root and root:sub(-1) ~= PATHSEP then root = root .. PATHSEP end - local path, name = text:match("^(.-)([^/\\]*)$") + local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$") local clean_dotslash = false -- ignore root if path is absolute local is_absolute = common.is_absolute_path(text) @@ -279,7 +279,7 @@ end ---@param text string The input path. ---@return string[] function common.dir_path_suggest(text) - local path, name = text:match("^(.-)([^/\\]*)$") + local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$") local files = system.list_dir(path == "" and "." or path) or {} local res = {} for _, file in ipairs(files) do @@ -298,7 +298,7 @@ end ---@param dir_list string[] A list of paths to filter. ---@return string[] function common.dir_list_suggest(text, dir_list) - local path, name = text:match("^(.-)([^/\\]*)$") + local path, name = text:match("^(.-)([^"..PATHSEP.."]*)$") local res = {} for _, dir_path in ipairs(dir_list) do if dir_path:lower():find(text:lower(), nil, true) == 1 then @@ -461,7 +461,7 @@ end function common.basename(path) -- a path should never end by / or \ except if it is '/' (unix root) or -- 'X:\' (windows drive) - return path:match("[^\\/]+$") or path + return path:match("[^"..PATHSEP.."]+$") or path end @@ -470,7 +470,7 @@ end ---@param path string ---@return string|nil function common.dirname(path) - return path:match("(.+)[\\/][^\\/]+$") + return path:match("(.+)["..PATHSEP.."][^"..PATHSEP.."]+$") end @@ -513,10 +513,10 @@ end local function split_on_slash(s, sep_pattern) local t = {} - if s:match("^[/\\]") then + if s:match("^["..PATHSEP.."]") then t[#t + 1] = "" end - for fragment in string.gmatch(s, "([^/\\]+)") do + for fragment in string.gmatch(s, "([^"..PATHSEP.."]+)") do t[#t + 1] = fragment end return t @@ -649,7 +649,7 @@ function common.mkdirp(path) while path and path ~= "" do local success_mkdir = system.mkdir(path) if success_mkdir then break end - local updir, basedir = path:match("(.*)[/\\](.+)$") + local updir, basedir = path:match("(.*)["..PATHSEP.."](.+)$") table.insert(subdirs, 1, basedir or path) path = updir end diff --git a/data/core/dirwatch.lua b/data/core/dirwatch.lua index 3b62fa24..d9ac4523 100644 --- a/data/core/dirwatch.lua +++ b/data/core/dirwatch.lua @@ -190,49 +190,47 @@ end -- "root" will by an absolute path without trailing '/' -- "path" will be a path starting without '/' and without trailing '/' -- or the empty string. --- It will identifies a sub-path within "root. +-- It identifies a sub-path within "root". -- The current path location will therefore always be: root .. path. --- When recursing "root" will always be the same, only "path" will change. +-- When recursing, "root" will always be the same, only "path" will change. -- Returns a list of file "items". In each item the "filename" will be the -- complete file path relative to "root" *without* the trailing '/', and without the starting '/'. -function dirwatch.get_directory_files(dir, root, path, t, entries_count, recurse_pred) +function dirwatch.get_directory_files(dir, root, path, entries_count, recurse_pred) + local t = {} local t0 = system.get_time() - local t_elapsed = system.get_time() - t0 - local dirs, files = {}, {} local ignore_compiled = compile_ignore_files() - local all = system.list_dir(root .. PATHSEP .. path) if not all then return nil end - - for _, file in ipairs(all or {}) do + local entries = { } + for _, file in ipairs(all) do local info = get_project_file_info(root, (path ~= "" and (path .. PATHSEP) or "") .. file, ignore_compiled) if info then - table.insert(info.type == "dir" and dirs or files, info) - entries_count = entries_count + 1 + table.insert(entries, info) end end + table.sort(entries, compare_file) local recurse_complete = true - table.sort(dirs, compare_file) - for _, f in ipairs(dirs) do - table.insert(t, f) - if recurse_pred(dir, f.filename, entries_count, t_elapsed) then - local _, complete, n = dirwatch.get_directory_files(dir, root, f.filename, t, entries_count, recurse_pred) - recurse_complete = recurse_complete and complete - if n ~= nil then - entries_count = n + for _, info in ipairs(entries) do + table.insert(t, info) + entries_count = entries_count + 1 + if info.type == "dir" then + if recurse_pred(dir, info.filename, entries_count, system.get_time() - t0) then + local t_rec, complete, n = dirwatch.get_directory_files(dir, root, info.filename, entries_count, recurse_pred) + recurse_complete = recurse_complete and complete + if n ~= nil then + entries_count = n + for _, info_rec in ipairs(t_rec) do + table.insert(t, info_rec) + end + end + else + recurse_complete = false end - else - recurse_complete = false end end - table.sort(files, compare_file) - for _, f in ipairs(files) do - table.insert(t, f) - end - return t, recurse_complete, entries_count end diff --git a/data/core/init.lua b/data/core/init.lua index 61ee9b97..aee11529 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -102,7 +102,7 @@ local function strip_leading_path(filename) end local function strip_trailing_slash(filename) - if filename:match("[^:][/\\]$") then + if filename:match("[^:]["..PATHSEP.."]$") then return filename:sub(1, -2) end return filename @@ -120,9 +120,7 @@ local function show_max_files_warning(dir) "Too many files in project directory: stopped reading at ".. config.max_project_files.." files. For more information see ".. "usage.md at https://github.com/lite-xl/lite-xl." - if core.status_view then - core.status_view:show_message("!", style.accent, message) - end + core.warn(message) end @@ -184,7 +182,7 @@ local function refresh_directory(topdir, target) directory_start_idx = directory_start_idx + 1 end - local files = dirwatch.get_directory_files(topdir, topdir.name, (target or ""), {}, 0, function() return false end) + local files = dirwatch.get_directory_files(topdir, topdir.name, (target or ""), 0, function() return false end) local change = false -- If this file doesn't exist, we should be calling this on our parent directory, assume we'll do that. @@ -265,7 +263,7 @@ function core.add_project_directory(path) local fstype = PLATFORM == "Linux" and system.get_fs_type(topdir.name) or "unknown" topdir.force_scans = (fstype == "nfs" or fstype == "fuse") - local t, complete, entries_count = dirwatch.get_directory_files(topdir, topdir.name, "", {}, 0, timed_max_files_pred) + local t, complete, entries_count = dirwatch.get_directory_files(topdir, topdir.name, "", 0, timed_max_files_pred) topdir.files = t if not complete then topdir.slow_filesystem = not complete and (entries_count <= config.max_project_files) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index b27ba554..9037d51a 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -29,7 +29,7 @@ local tooltip_alpha_rate = 1 local function get_depth(filename) local n = 1 - for sep in filename:gmatch("[\\/]") do + for _ in filename:gmatch(PATHSEP) do n = n + 1 end return n diff --git a/src/api/system.c b/src/api/system.c index 2774a97a..32a06194 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -1058,7 +1058,7 @@ static int f_load_native_plugin(lua_State *L) { #endif /* Special purpose filepath compare function. Corresponds to the - order used in the TreeView view of the project's files. Returns true iff + order used in the TreeView view of the project's files. Returns true if path1 < path2 in the TreeView order. */ static int f_path_compare(lua_State *L) { size_t len1, len2; @@ -1072,7 +1072,6 @@ static int f_path_compare(lua_State *L) { size_t offset = 0, i, j; for (i = 0; i < len1 && i < len2; i++) { if (path1[i] != path2[i]) break; - if (isdigit(path1[i])) break; if (path1[i] == PATHSEP) { offset = i + 1; } From 52d224ac6b2323d4dc1e81e177ee42b541ecf1c7 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Wed, 29 Nov 2023 23:08:23 +0800 Subject: [PATCH 154/176] feat(subprojects): update wraps (#1577) * feat(subprojects): update SDL2 wrap * fix(meson.build): add sdl2main as dependency on Windows * fix(meson.build): don't load sdl2main on non-Windows platforms * feat(subprojects): update freetype version * feat(subprojects): update pcre2 to latest version * feat(subprojects): update lua to latest version * feat(lite_xl_plugin_api): add lua_closethread to symbols list * fix(meson.build): fix meson error with features and booleans * fix(meson.build): fix wrong variable name * feat(subprojects): update wraps again * ci(build): fix lua subproject not found * ci(build): use awk instead of grep and sed --- .github/workflows/build.yml | 2 +- meson.build | 17 +++++++++++++++-- resources/include/lite_xl_plugin_api.h | 12 +++++++++++- subprojects/freetype2.wrap | 11 ++++++----- subprojects/lua.wrap | 18 ++++++++++-------- subprojects/pcre2.wrap | 11 ++++++----- subprojects/sdl2.wrap | 19 +++++++++++-------- 7 files changed, 60 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96db355f..21f3a8b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,7 +204,7 @@ jobs: run: | "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV "INSTALL_REF=$($env:GITHUB_REF -replace ".*/")" >> $env:GITHUB_ENV - "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV + "LUA_SUBPROJECT_PATH=subprojects/$(awk -F ' *= *' '/directory/ { printf $2 }' subprojects/lua.wrap)" >> $env:GITHUB_ENV - name: Download and patch subprojects shell: bash run: | diff --git a/meson.build b/meson.build index 3cfec808..f0614cc8 100644 --- a/meson.build +++ b/meson.build @@ -101,7 +101,7 @@ if not get_option('source-only') endforeach else lua_dep = dependency('', fallback: ['lua', 'lua_dep'], required : true, - default_options: default_fallback_options + ['default_library=static', 'line_editing=false', 'interpreter=false'] + default_options: default_fallback_options + ['default_library=static', 'line_editing=disabled', 'interpreter=false'] ) endif @@ -123,6 +123,7 @@ if not get_option('source-only') sdl_options += 'use_atomic=enabled' sdl_options += 'use_threads=enabled' sdl_options += 'use_timers=enabled' + sdl_options += 'with_main=true' # investigate if this is truly needed # Do not remove before https://github.com/libsdl-org/SDL/issues/5413 is released sdl_options += 'use_events=enabled' @@ -155,12 +156,24 @@ if not get_option('source-only') sdl_options += 'use_video_vulkan=disabled' sdl_options += 'use_video_offscreen=disabled' sdl_options += 'use_power=disabled' + sdl_options += 'system_iconv=disabled' sdl_dep = dependency('sdl2', fallback: ['sdl2', 'sdl2_dep'], default_options: default_fallback_options + sdl_options ) - lite_deps = [lua_dep, sdl_dep, freetype_dep, pcre2_dep, libm, libdl] + if host_machine.system() == 'windows' + if sdl_dep.type_name() == 'internal' + sdlmain_dep = dependency('sdl2main', fallback: ['sdl2main_dep']) + else + sdlmain_dep = cc.find_library('SDL2main') + endif + else + sdlmain_dep = dependency('', required: false) + assert(not sdlmain_dep.found(), 'checking if fake dependency has been found') + endif + + lite_deps = [lua_dep, sdl_dep, sdlmain_dep, freetype_dep, pcre2_dep, libm, libdl] endif #=============================================================================== # Install Configuration diff --git a/resources/include/lite_xl_plugin_api.h b/resources/include/lite_xl_plugin_api.h index 0c5e93e9..0f500059 100644 --- a/resources/include/lite_xl_plugin_api.h +++ b/resources/include/lite_xl_plugin_api.h @@ -31,9 +31,14 @@ * An example command would be: gcc -shared -o xxxxx.so xxxxx.c * You must not link to ANY lua library to avoid symbol collision. * - * This file contains stock configuration for a typical installation of Lua 5.4. + * This file contains stock configuration for a typical installation of Lua 5.4.6. * DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK * COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS. + * + * For reference, here are a list of permalinks to previous version of this file that targets an older version of Lua. + * If you don't need functionalities offered by the new version, use the OLDEST FILE for backwards compatibility. + * + * - Lua 5.4.4: https://github.com/lite-xl/lite-xl/blob/397973067f14420b26e3b20a238a50016c0b75e2/resources/include/lite_xl_plugin_api.h **/ #ifndef LITE_XL_PLUGIN_API #define LITE_XL_PLUGIN_API @@ -1028,6 +1033,7 @@ extern const char lua_ident[]; SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) SYMBOL_DECLARE(void, lua_close, lua_State *L) SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) +SYMBOL_DECLARE(int, lua_closethread, lua_State *L, lua_State *from) SYMBOL_DECLARE(int, lua_resetthread, lua_State *L) SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) @@ -1739,6 +1745,9 @@ SYMBOL_WRAP_DECL(void, lua_close, lua_State *L) { SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_newthread, L); } +SYMBOL_WRAP_DECL(int, lua_closethread, lua_State *L, lua_State *from) { + return SYMBOL_WRAP_CALL(lua_closethread, L, from); +} SYMBOL_WRAP_DECL(int, lua_resetthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_resetthread, L); } @@ -2351,6 +2360,7 @@ void lite_xl_plugin_init(void *XL) { IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); IMPORT_SYMBOL(lua_close, void, lua_State *L); IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); + IMPORT_SYMBOL(lua_closethread, int, lua_State *L, lua_State *from); IMPORT_SYMBOL(lua_resetthread, int, lua_State *L); IMPORT_SYMBOL(lua_atpanic, lua_CFunction, lua_State *L, lua_CFunction panicf); IMPORT_SYMBOL(lua_version, lua_Number, lua_State *L); diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap index 1ff89ecd..e3554c9a 100644 --- a/subprojects/freetype2.wrap +++ b/subprojects/freetype2.wrap @@ -1,9 +1,10 @@ [wrap-file] -directory = freetype-2.12.1 -source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.xz -source_filename = freetype-2.12.1.tar.xz -source_hash = 4766f20157cc4cf0cd292f80bf917f92d1c439b243ac3018debf6b9140c41a7f -wrapdb_version = 2.12.1-2 +directory = freetype-2.13.2 +source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.2.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.2-1/freetype-2.13.2.tar.xz +source_filename = freetype-2.13.2.tar.xz +source_hash = 12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d +wrapdb_version = 2.13.2-1 [provide] freetype2 = freetype_dep diff --git a/subprojects/lua.wrap b/subprojects/lua.wrap index 5a2d615b..16502616 100644 --- a/subprojects/lua.wrap +++ b/subprojects/lua.wrap @@ -1,12 +1,14 @@ [wrap-file] -directory = lua-5.4.4 -source_url = https://www.lua.org/ftp/lua-5.4.4.tar.gz -source_filename = lua-5.4.4.tar.gz -source_hash = 164c7849653b80ae67bec4b7473b884bf5cc8d2dca05653475ec2ed27b9ebf61 -patch_filename = lua_5.4.4-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.4-1/get_patch -patch_hash = e61cd965c629d6543176f41a9f1cb9050edfd1566cf00ce768ff211086e40bdc +directory = lua-5.4.6 +source_url = https://www.lua.org/ftp/lua-5.4.6.tar.gz +source_filename = lua-5.4.6.tar.gz +source_hash = 7d5ea1b9cb6aa0b59ca3dde1c6adcb57ef83a1ba8e5432c0ecd06bf439b3ad88 +patch_filename = lua_5.4.6-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.6-3/get_patch +patch_hash = 9b72a95422fd47f79f969d9abdb589ee95712d5512a5246f94e7e4f63d2cb7b7 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lua_5.4.6-3/lua-5.4.6.tar.gz +wrapdb_version = 5.4.6-3 [provide] lua-5.4 = lua_dep - +lua = lua_dep diff --git a/subprojects/pcre2.wrap b/subprojects/pcre2.wrap index 8fada34e..6bfef6f3 100644 --- a/subprojects/pcre2.wrap +++ b/subprojects/pcre2.wrap @@ -1,12 +1,13 @@ [wrap-file] directory = pcre2-10.42 -source_url = https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 +source_url = https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 source_filename = pcre2-10.42.tar.bz2 source_hash = 8d36cd8cb6ea2a4c2bb358ff6411b0c788633a2a45dabbf1aeb4b701d1b5e840 -patch_filename = pcre2_10.42-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-1/get_patch -patch_hash = 06969e916dfee663c189810df57d98574f15e0754a44cd93f3f0bc7234b05d89 -wrapdb_version = 10.42-1 +patch_filename = pcre2_10.42-5_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-5/get_patch +patch_hash = 7ba1730a3786c46f41735658a9884b09bc592af3840716e0ccc552e7ddf5630c +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/pcre2_10.42-5/pcre2-10.42.tar.bz2 +wrapdb_version = 10.42-5 [provide] libpcre2-8 = libpcre2_8 diff --git a/subprojects/sdl2.wrap b/subprojects/sdl2.wrap index 53a71e2f..14c18533 100644 --- a/subprojects/sdl2.wrap +++ b/subprojects/sdl2.wrap @@ -1,12 +1,15 @@ [wrap-file] -directory = SDL2-2.26.0 -source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.26.0/SDL2-2.26.0.tar.gz -source_filename = SDL2-2.26.0.tar.gz -source_hash = 8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 -patch_filename = sdl2_2.26.0-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.26.0-1/get_patch -patch_hash = 6fcfd727d71cf7837332723518d5e47ffd64f1e7630681cf4b50e99f2bf7676f -wrapdb_version = 2.26.0-1 +directory = SDL2-2.28.1 +source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.28.1/SDL2-2.28.1.tar.gz +source_filename = SDL2-2.28.1.tar.gz +source_hash = 4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d +patch_filename = sdl2_2.28.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.28.1-2/get_patch +patch_hash = 2dd332226ba2a4373c6d4eb29fa915e9d5414cf7bb9fa2e4a5ef3b16a06e2736 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.28.1-2/SDL2-2.28.1.tar.gz +wrapdb_version = 2.28.1-2 [provide] sdl2 = sdl2_dep +sdl2main = sdl2main_dep +sdl2_test = sdl2_test_dep From 4e2f70e5eef2a1e8812cbb36bb63da556d859a71 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 16:21:58 +0100 Subject: [PATCH 155/176] Scale mouse coordinates by window scale (#1630) * Update window scale on resize * Scale mouse coordinates by window scale * Avoid scaling mouse coordinates while using `LITE_USE_SDL_RENDERER` --- src/api/system.c | 20 ++++++++++---------- src/renderer.c | 1 + src/renwindow.c | 13 ++++++++++++- src/renwindow.h | 3 +++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/api/system.c b/src/api/system.c index 32a06194..2a09621f 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -225,8 +225,8 @@ top: SDL_GetMouseState(&mx, &my); lua_pushstring(L, "filedropped"); lua_pushstring(L, e.drop.file); - lua_pushinteger(L, mx); - lua_pushinteger(L, my); + lua_pushinteger(L, mx * window_renderer.scale_x); + lua_pushinteger(L, my * window_renderer.scale_y); SDL_free(e.drop.file); return 4; @@ -283,8 +283,8 @@ top: if (e.button.button == 1) { SDL_CaptureMouse(1); } lua_pushstring(L, "mousepressed"); lua_pushstring(L, button_name(e.button.button)); - lua_pushinteger(L, e.button.x); - lua_pushinteger(L, e.button.y); + lua_pushinteger(L, e.button.x * window_renderer.scale_x); + lua_pushinteger(L, e.button.y * window_renderer.scale_y); lua_pushinteger(L, e.button.clicks); return 5; @@ -292,8 +292,8 @@ top: if (e.button.button == 1) { SDL_CaptureMouse(0); } lua_pushstring(L, "mousereleased"); lua_pushstring(L, button_name(e.button.button)); - lua_pushinteger(L, e.button.x); - lua_pushinteger(L, e.button.y); + lua_pushinteger(L, e.button.x * window_renderer.scale_x); + lua_pushinteger(L, e.button.y * window_renderer.scale_y); return 4; case SDL_MOUSEMOTION: @@ -305,10 +305,10 @@ top: e.motion.yrel += event_plus.motion.yrel; } lua_pushstring(L, "mousemoved"); - lua_pushinteger(L, e.motion.x); - lua_pushinteger(L, e.motion.y); - lua_pushinteger(L, e.motion.xrel); - lua_pushinteger(L, e.motion.yrel); + lua_pushinteger(L, e.motion.x * window_renderer.scale_x); + lua_pushinteger(L, e.motion.y * window_renderer.scale_y); + lua_pushinteger(L, e.motion.xrel * window_renderer.scale_x); + lua_pushinteger(L, e.motion.yrel * window_renderer.scale_y); return 5; case SDL_MOUSEWHEEL: diff --git a/src/renderer.c b/src/renderer.c index 0e36aaa1..70cc6a2d 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -520,6 +520,7 @@ void ren_init(SDL_Window *win) { void ren_resize_window(RenWindow *window_renderer) { renwin_resize_surface(window_renderer); + renwin_update_scale(window_renderer); } diff --git a/src/renwindow.c b/src/renwindow.c index fe40d009..15c9e86c 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -29,7 +29,8 @@ static void setup_renderer(RenWindow *ren, int w, int h) { #endif -void renwin_init_surface(UNUSED RenWindow *ren) { +void renwin_init_surface(RenWindow *ren) { + ren->scale_x = ren->scale_y = 1; #ifdef LITE_USE_SDL_RENDERER if (ren->rensurface.surface) { SDL_FreeSurface(ren->rensurface.surface); @@ -95,6 +96,16 @@ void renwin_resize_surface(UNUSED RenWindow *ren) { #endif } +void renwin_update_scale(RenWindow *ren) { +#ifndef LITE_USE_SDL_RENDERER + SDL_Surface *surface = SDL_GetWindowSurface(ren->window); + int window_w = surface->w, window_h = surface->h; + SDL_GetWindowSize(ren->window, &window_w, &window_h); + ren->scale_x = (float)surface->w / window_w; + ren->scale_y = (float)surface->h / window_h; +#endif +} + void renwin_show_window(RenWindow *ren) { SDL_ShowWindow(ren->window); } diff --git a/src/renwindow.h b/src/renwindow.h index a80586a0..364950de 100644 --- a/src/renwindow.h +++ b/src/renwindow.h @@ -6,6 +6,8 @@ struct RenWindow { uint8_t *command_buf; size_t command_buf_idx; size_t command_buf_size; + float scale_x; + float scale_y; #ifdef LITE_USE_SDL_RENDERER SDL_Renderer *renderer; SDL_Texture *texture; @@ -19,6 +21,7 @@ void renwin_init_command_buf(RenWindow *ren); void renwin_clip_to_surface(RenWindow *ren); void renwin_set_clip_rect(RenWindow *ren, RenRect rect); void renwin_resize_surface(RenWindow *ren); +void renwin_update_scale(RenWindow *ren); void renwin_show_window(RenWindow *ren); void renwin_update_rects(RenWindow *ren, RenRect *rects, int count); void renwin_free(RenWindow *ren); From 2571e17d1bff358a207d7863218540d1dc03817c Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 16:33:34 +0100 Subject: [PATCH 156/176] Fix `core.redraw` when window is not focused (#1601) * Execute at least one step when window has no focus This way if `core.redraw` is set, it's respected. * Fully run threads at least once when window has no focus This allows threads that set `core.redraw` (like `projectsearch`) to continue running even after the window loses focus. "Fully" here means that `run_threads` has gone through *all* the "timed out" coroutines at least once. --- data/core/init.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index aee11529..58411e3f 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1423,11 +1423,11 @@ local run_threads = coroutine.wrap(function() -- stop running threads if we're about to hit the end of frame if system.get_time() - core.frame_start > max_time then - coroutine.yield(0) + coroutine.yield(0, false) end end - coroutine.yield(minimal_time_to_wake) + coroutine.yield(minimal_time_to_wake, true) end end) @@ -1435,10 +1435,15 @@ end) function core.run() local next_step local last_frame_time + local run_threads_full = 0 while true do core.frame_start = system.get_time() - local time_to_wake = run_threads() + local time_to_wake, threads_done = run_threads() + if threads_done then + run_threads_full = run_threads_full + 1 + end local did_redraw = false + local did_step = false local force_draw = core.redraw and last_frame_time and core.frame_start - last_frame_time > (1 / config.fps) if force_draw or not next_step or system.get_time() >= next_step then if core.step() then @@ -1446,11 +1451,12 @@ function core.run() last_frame_time = core.frame_start end next_step = nil + did_step = true end if core.restart_request or core.quit_request then break end if not did_redraw then - if system.window_has_focus() then + if system.window_has_focus() or not did_step or run_threads_full < 2 then local now = system.get_time() if not next_step then -- compute the time until the next blink local t = now - core.blink_start @@ -1467,6 +1473,7 @@ function core.run() next_step = nil -- perform a step when we're not in focus if get we an event end else -- if we redrew, then make sure we only draw at most FPS/sec + run_threads_full = 0 local now = system.get_time() local elapsed = now - core.frame_start local next_frame = math.max(0, 1 / config.fps - elapsed) From 9301220d269e38d133e47aa015194097b8e07345 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 16:40:47 +0100 Subject: [PATCH 157/176] Fix selecting newlines with `find-replace:select-add-{next,all}` (#1608) * Avoid adding existing selections in `select_add_next` * Use the first available selection as delimiter in `select_add_next` * Fix returning searches with newlines in `search.find` * Fix repeat search when the last result spanned multiple lines --- data/core/commands/findreplace.lua | 11 +++++++---- data/core/doc/search.lua | 13 ++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua index a3151cb7..b77bbcf2 100644 --- a/data/core/commands/findreplace.lua +++ b/data/core/commands/findreplace.lua @@ -164,13 +164,16 @@ local function is_in_any_selection(line, col) end local function select_add_next(all) - local il1, ic1 = doc():get_selection(true) - for idx, l1, c1, l2, c2 in doc():get_selections(true, true) do + local il1, ic1 + for _, l1, c1, l2, c2 in doc():get_selections(true, true) do + if not il1 then + il1, ic1 = l1, c1 + end local text = doc():get_text(l1, c1, l2, c2) repeat l1, c1, l2, c2 = search.find(doc(), l2, c2, text, { wrap = true }) if l1 == il1 and c1 == ic1 then break end - if l2 and (all or not is_in_any_selection(l2, c2)) then + if l2 and not is_in_any_selection(l2, c2) then doc():add_selection(l2, c2, l1, c1) if not all then core.active_view:scroll_to_make_visible(l2, c2) @@ -266,7 +269,7 @@ command.add(valid_for_finding, { core.error("No find to continue from") else local sl1, sc1, sl2, sc2 = dv.doc:get_selection(true) - local line1, col1, line2, col2 = last_fn(dv.doc, sl1, sc2, last_text, case_sensitive, find_regex, false) + local line1, col1, line2, col2 = last_fn(dv.doc, sl2, sc2, last_text, case_sensitive, find_regex, false) if line1 then dv.doc:set_selection(line2, col2, line1, col1) dv:scroll_to_line(line2, true) diff --git a/data/core/doc/search.lua b/data/core/doc/search.lua index 8395769a..3cfe6a2d 100644 --- a/data/core/doc/search.lua +++ b/data/core/doc/search.lua @@ -66,7 +66,18 @@ function search.find(doc, line, col, text, opt) s, e = search_func(line_text, pattern, col, plain) end if s then - return line, s, line, e + 1 + local line2 = line + -- If we've matched the newline too, + -- return until the initial character of the next line. + if e >= #doc.lines[line] then + line2 = line + 1 + e = 0 + end + -- Avoid returning matches that go beyond the last line. + -- This is needed to avoid selecting the "last" newline. + if line2 <= #doc.lines then + return line, s, line2, e + 1 + end end col = opt.reverse and -1 or 1 end From de043f2e13e5bf65e0d86fdbb888b16bf2611ec7 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 16:45:53 +0100 Subject: [PATCH 158/176] Fix editing after undo not clearing the change id (#1574) --- data/core/doc/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index deeb3816..c3eeba87 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -488,6 +488,10 @@ end function Doc:insert(line, col, text) self.redo_stack = { idx = 1 } + -- Reset the clean id when we're pushing something new before it + if self:get_change_id() < self.clean_change_id then + self.clean_change_id = -1 + end line, col = self:sanitize_position(line, col) self:raw_insert(line, col, text, self.undo_stack, system.get_time()) self:on_text_change("insert") From ee02d0e0b615a226f4e954fedcca889a7d29bc77 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 17:00:09 +0100 Subject: [PATCH 159/176] Fix `language_js` regex constant detection (#1581) * Fix `language_js` regex constant detection * Simplify regex constant detection in `language_js` * Add more possessive quantifiers in `language_js` regex constant detection This avoids more catastrophic backtracking cases. * Allow `.` after regex constant in `language_js` --- data/plugins/language_js.lua | 74 ++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/data/plugins/language_js.lua b/data/plugins/language_js.lua index f79fece6..307aeecf 100644 --- a/data/plugins/language_js.lua +++ b/data/plugins/language_js.lua @@ -1,24 +1,74 @@ -- mod-version:3 local syntax = require "core.syntax" +-- Regex pattern explanation: +-- This will match / and will look ahead for something that looks like a regex. +-- +-- (?!/) Don't match empty regexes. +-- +-- (?>...) this is using an atomic group to minimize backtracking, as that'd +-- cause "Catastrophic Backtracking" in some cases. +-- +-- [^\\[\/]++ will match anything that's isn't an escape, a start of character +-- class or an end of pattern, without backtracking (the second +). +-- +-- \\. will match anything that's escaped. +-- +-- \[(?:[^\\\]++]|\\.)*+\] will match character classes. +-- +-- /[gmiyuvsd]*\s*[\n,;\)\]\}\.]) will match the end of pattern delimiter, optionally +-- followed by pattern options, and anything that can +-- be after a pattern. +-- +-- Demo with some unit tests (click on the Unit Tests entry): https://regex101.com/r/R0w8Qw/1 +-- Note that it has a couple of changes to make it work on that platform. +local regex_pattern = { + [=[/(?=(?!/)(?:(?>[^\\[\/]++|\\.|\[(?:[^\\\]]++|\\.)*+\])*+)++/[gmiyuvsd]*\s*[\n,;\)\]\}\.])()]=], + "/()[gmiyuvsd]*", "\\" +} + +-- For the moment let's not actually differentiate the insides of the regex, +-- as this will need new token types... +local inner_regex_syntax = { + patterns = { + { pattern = "%(()%?[:!=><]", type = { "string", "string" } }, + { pattern = "[.?+*%(%)|]", type = "string" }, + { pattern = "{%d*,?%d*}", type = "string" }, + { regex = { [=[\[()\^?]=], [=[(?:\]|(?=\n))()]=], "\\" }, + type = { "string", "string" }, + syntax = { -- Inside character class + patterns = { + { pattern = "\\\\", type = "string" }, + { pattern = "\\%]", type = "string" }, + { pattern = "[^%]\n]", type = "string" } + }, + symbols = {} + } + }, + { regex = "\\/", type = "string" }, + { regex = "[^/\n]", type = "string" }, + }, + symbols = {} +} + syntax.add { name = "JavaScript", files = { "%.js$", "%.json$", "%.cson$", "%.mjs$", "%.cjs$" }, comment = "//", block_comment = { "/*", "*/" }, patterns = { - { pattern = "//.*", type = "comment" }, - { pattern = { "/%*", "%*/" }, type = "comment" }, - { pattern = { '/[^= ]', '/', '\\' },type = "string" }, - { pattern = { '"', '"', '\\' }, type = "string" }, - { pattern = { "'", "'", '\\' }, type = "string" }, - { pattern = { "`", "`", '\\' }, type = "string" }, - { pattern = "0x[%da-fA-F_]+n?", type = "number" }, - { pattern = "-?%d+[%d%.eE_n]*", type = "number" }, - { pattern = "-?%.?%d+", type = "number" }, - { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, - { pattern = "[%a_][%w_]*%f[(]", type = "function" }, - { pattern = "[%a_][%w_]*", type = "symbol" }, + { pattern = "//.*", type = "comment" }, + { pattern = { "/%*", "%*/" }, type = "comment" }, + { regex = regex_pattern, syntax = inner_regex_syntax, type = {"string", "string"} }, + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = { "`", "`", '\\' }, type = "string" }, + { pattern = "0x[%da-fA-F_]+n?()%s*()/?", type = {"number", "normal", "operator"} }, + { pattern = "-?%d+[%d%.eE_n]*()%s*()/?", type = {"number", "normal", "operator"} }, + { pattern = "-?%.?%d+()%s*()/?", type = {"number", "normal", "operator"} }, + { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, + { pattern = "[%a_][%w_]*%f[(]", type = "function" }, + { pattern = "[%a_][%w_]*()%s*()/?", type = {"symbol", "normal", "operator"} }, }, symbols = { ["async"] = "keyword", From 234dd40e49b7c49ddb899efdcf6f8e939de03762 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 17:11:46 +0100 Subject: [PATCH 160/176] Fix patterns starting with `^` in `tokenizer` (#1645) Previously the "dirty" version of the pattern was used, which could result in trying to match with multiple `^`, which failed valid matches. --- data/core/tokenizer.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index 5f70fa20..7e83249f 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -210,9 +210,11 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) -- Remove '^' from the beginning of the pattern if type(target) == "table" then target[p_idx] = code:usub(2) + code = target[p_idx] else p.pattern = p.pattern and code:usub(2) p.regex = p.regex and code:usub(2) + code = p.pattern or p.regex end end end From f43cfc4a9402f39b809ed2e346fe7c03791a831e Mon Sep 17 00:00:00 2001 From: ThaCuber <70547062+thacuber2a03@users.noreply.github.com> Date: Wed, 29 Nov 2023 15:12:43 -0400 Subject: [PATCH 161/176] Text overwriting (#1495) * added text overwriting * rewrote `DocView:draw_caret` to not use the order of draws * forgot to delete some old code in `DocView:draw_overlay` also added a temporary solution to overwriting and added the missing arguments in `DocView:draw_ime_decoration` and fixed `DocView:draw_caret` * accidentally broke the `draw_caret` call in `draw_overlay` in the process * multiline * fixed calling `Doc:get_char` as a function that, in turn, crashed the editor because "can't index a number" * move and rename some stuff * remove unneeded extra check I just had to change the `~=` to `<` in the second condition * overwrite disregards pasting text * disregard overwrite on selections; doc only removes selection * Fixed error where `doc` was used, instead of `self`. --------- Co-authored-by: ThaCuber <70547062+ThaCuber@users.noreply.github.com> Co-authored-by: Adam Harrison --- data/core/commands/doc.lua | 5 +++ data/core/doc/init.lua | 87 +++++++++++++++++--------------------- data/core/docview.lua | 14 ++++-- data/core/keymap.lua | 1 + data/core/statusview.lua | 13 ++++++ 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index c698d2cc..3d4426c3 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -545,6 +545,11 @@ local commands = { dv.doc.crlf = not dv.doc.crlf end, + ["doc:toggle-overwrite"] = function(dv) + dv.doc.overwrite = not dv.doc.overwrite + core.blink_reset() -- to show the cursor has changed edit modes + end, + ["doc:save-as"] = function(dv) local last_doc = core.last_active_view and core.last_active_view.doc local text diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index c3eeba87..3c0a30d7 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -1,5 +1,6 @@ local Object = require "core.object" local Highlighter = require "core.doc.highlighter" +local translate = require "core.doc.translate" local core = require "core" local syntax = require "core.syntax" local config = require "core.config" @@ -29,7 +30,6 @@ function Doc:new(filename, abs_filename, new_file) end end - function Doc:reset() self.lines = { "\n" } self.selections = { 1, 1, 1, 1 } @@ -38,10 +38,10 @@ function Doc:reset() self.redo_stack = { idx = 1 } self.clean_change_id = 1 self.highlighter = Highlighter(self) + self.overwrite = false self:reset_syntax() end - function Doc:reset_syntax() local header = self:get_text(1, 1, self:position_offset(1, 1, 128)) local path = self.abs_filename @@ -56,16 +56,14 @@ function Doc:reset_syntax() end end - function Doc:set_filename(filename, abs_filename) self.filename = filename self.abs_filename = abs_filename self:reset_syntax() end - function Doc:load(filename) - local fp = assert( io.open(filename, "rb") ) + local fp = assert(io.open(filename, "rb")) self:reset() self.lines = {} local i = 1 @@ -85,7 +83,6 @@ function Doc:load(filename) self:reset_syntax() end - function Doc:reload() if self.filename then local sel = { self:get_selection() } @@ -95,7 +92,6 @@ function Doc:reload() end end - function Doc:save(filename, abs_filename) if not filename then assert(self.filename, "no filename set to default to") @@ -104,7 +100,7 @@ function Doc:save(filename, abs_filename) else assert(self.filename or abs_filename, "calling save on unnamed doc without absolute path") end - local fp = assert( io.open(filename, "wb") ) + local fp = assert(io.open(filename, "wb")) for _, line in ipairs(self.lines) do if self.crlf then line = line:gsub("\n", "\r\n") end fp:write(line) @@ -115,12 +111,10 @@ function Doc:save(filename, abs_filename) self:clean() end - function Doc:get_name() return self.filename or "unsaved" end - function Doc:is_dirty() if self.new_file then if self.filename then return true end @@ -130,20 +124,17 @@ function Doc:is_dirty() end end - function Doc:clean() self.clean_change_id = self:get_change_id() end - function Doc:get_indent_info() if not self.indent_info then return config.tab_type, config.indent_size, false end return self.indent_info.type or config.tab_type, - self.indent_info.size or config.indent_size, - self.indent_info.confirmed + self.indent_info.size or config.indent_size, + self.indent_info.confirmed end - function Doc:get_change_id() return self.undo_stack.idx end @@ -167,13 +158,14 @@ function Doc:get_selection(sort) return line1, col1, line2, col2, swap end - ---Get the selection specified by `idx` ---@param idx integer @the index of the selection to retrieve ---@param sort? boolean @whether to sort the selection returned ---@return integer,integer,integer,integer,boolean? @line1, col1, line2, col2, was the selection sorted function Doc:get_selection_idx(idx, sort) - local line1, col1, line2, col2 = self.selections[idx*4-3], self.selections[idx*4-2], self.selections[idx*4-1], self.selections[idx*4] + local line1, col1, line2, col2 = self.selections[idx * 4 - 3], self.selections[idx * 4 - 2], + self.selections[idx * 4 - 1], + self.selections[idx * 4] if line1 and sort then return sort_positions(line1, col1, line2, col2) else @@ -217,7 +209,7 @@ function Doc:set_selections(idx, line1, col1, line2, col2, swap, rm) if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end line1, col1 = self:sanitize_position(line1, col1) line2, col2 = self:sanitize_position(line2 or line1, col2 or col1) - common.splice(self.selections, (idx - 1)*4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 }) + common.splice(self.selections, (idx - 1) * 4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 }) end function Doc:add_selection(line1, col1, line2, col2, swap) @@ -233,7 +225,6 @@ function Doc:add_selection(line1, col1, line2, col2, swap) self.last_selection = target end - function Doc:remove_selection(idx) if self.last_selection >= idx then self.last_selection = self.last_selection - 1 @@ -241,7 +232,6 @@ function Doc:remove_selection(idx) common.splice(self.selections, (idx - 1) * 4 + 1, 4) end - function Doc:set_selection(line1, col1, line2, col2, swap) self.selections = {} self:set_selections(1, line1, col1, line2, col2, swap) @@ -252,24 +242,24 @@ function Doc:merge_cursors(idx) for i = (idx or (#self.selections - 3)), (idx or 5), -4 do for j = 1, i - 4, 4 do if self.selections[i] == self.selections[j] and - self.selections[i+1] == self.selections[j+1] then - common.splice(self.selections, i, 4) - if self.last_selection >= (i+3)/4 then - self.last_selection = self.last_selection - 1 - end - break + self.selections[i + 1] == self.selections[j + 1] then + common.splice(self.selections, i, 4) + if self.last_selection >= (i + 3) / 4 then + self.last_selection = self.last_selection - 1 + end + break end end end end local function selection_iterator(invariant, idx) - local target = invariant[3] and (idx*4 - 7) or (idx*4 + 1) + local target = invariant[3] and (idx * 4 - 7) or (idx * 4 + 1) if target > #invariant[1] or target <= 0 or (type(invariant[3]) == "number" and invariant[3] ~= idx - 1) then return end if invariant[2] then - return idx+(invariant[3] and -1 or 1), sort_positions(table.unpack(invariant[1], target, target+4)) + return idx + (invariant[3] and -1 or 1), sort_positions(table.unpack(invariant[1], target, target + 4)) else - return idx+(invariant[3] and -1 or 1), table.unpack(invariant[1], target, target+4) + return idx + (invariant[3] and -1 or 1), table.unpack(invariant[1], target, target + 4) end end @@ -277,8 +267,9 @@ end -- If a number, runs for exactly that iteration. function Doc:get_selections(sort_intra, idx_reverse) return selection_iterator, { self.selections, sort_intra, idx_reverse }, - idx_reverse == true and ((#self.selections / 4) + 1) or ((idx_reverse or -1)+1) + idx_reverse == true and ((#self.selections / 4) + 1) or ((idx_reverse or -1) + 1) end + -- End of cursor seciton. function Doc:sanitize_position(line, col) @@ -291,7 +282,6 @@ function Doc:sanitize_position(line, col) return line, common.clamp(col, 1, #self.lines[line]) end - local function position_offset_func(self, line, col, fn, ...) line, col = self:sanitize_position(line, col) return fn(self, line, col, ...) @@ -330,7 +320,6 @@ function Doc:position_offset(line, col, ...) end end - function Doc:get_text(line1, col1, line2, col2) line1, col1 = self:sanitize_position(line1, col1) line2, col2 = self:sanitize_position(line2, col2) @@ -346,13 +335,11 @@ function Doc:get_text(line1, col1, line2, col2) return table.concat(lines) end - function Doc:get_char(line, col) line, col = self:sanitize_position(line, col) return self.lines[line]:sub(col, col) end - local function push_undo(undo_stack, time, type, ...) undo_stack[undo_stack.idx] = { type = type, time = time, ... } undo_stack[undo_stack.idx - config.max_undos] = nil @@ -413,7 +400,8 @@ function Doc:raw_insert(line, col, text, undo_stack, time) if cline1 < line then break end local line_addition = (line < cline1 or col < ccol1) and #lines - 1 or 0 local column_addition = line == cline1 and ccol1 > col and len or 0 - self:set_selections(idx, cline1 + line_addition, ccol1 + column_addition, cline2 + line_addition, ccol2 + column_addition) + self:set_selections(idx, cline1 + line_addition, ccol1 + column_addition, cline2 + line_addition, + ccol2 + column_addition) end -- push undo @@ -426,7 +414,6 @@ function Doc:raw_insert(line, col, text, undo_stack, time) self:sanitize_selection() end - function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) -- push undo local text = self:get_text(line1, col1, line2, col2) @@ -485,7 +472,6 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) self:sanitize_selection() end - function Doc:insert(line, col, text) self.redo_stack = { idx = 1 } -- Reset the clean id when we're pushing something new before it @@ -497,7 +483,6 @@ function Doc:insert(line, col, text) self:on_text_change("insert") end - function Doc:remove(line1, col1, line2, col2) self.redo_stack = { idx = 1 } line1, col1 = self:sanitize_position(line1, col1) @@ -507,28 +492,34 @@ function Doc:remove(line1, col1, line2, col2) self:on_text_change("remove") end - function Doc:undo() pop_undo(self, self.undo_stack, self.redo_stack, false) end - function Doc:redo() pop_undo(self, self.redo_stack, self.undo_stack, false) end - function Doc:text_input(text, idx) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx or true) do + local had_selection = false if line1 ~= line2 or col1 ~= col2 then self:delete_to_cursor(sidx) + had_selection = true end + + if self.overwrite + and not had_selection + and col1 < #self.lines[line1] + and text:ulen() == 1 then + self:remove(line1, col1, translate.next_char(self, line1, col1)) + end + self:insert(line1, col1, text) self:move_to_cursor(sidx, #text) end end - function Doc:ime_text_editing(text, start, length, idx) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx or true) do if line1 ~= line2 or col1 ~= col2 then @@ -539,7 +530,6 @@ function Doc:ime_text_editing(text, start, length, idx) end end - function Doc:replace_cursor(idx, line1, col1, line2, col2, fn) local old_text = self:get_text(line1, col1, line2, col2) local new_text, res = fn(old_text) @@ -555,7 +545,7 @@ function Doc:replace_cursor(idx, line1, col1, line2, col2, fn) end function Doc:replace(fn) - local has_selection, results = false, { } + local has_selection, results = false, {} for idx, line1, col1, line2, col2 in self:get_selections(true) do if line1 ~= line2 or col1 ~= col2 then results[idx] = self:replace_cursor(idx, line1, col1, line2, col2, fn) @@ -569,7 +559,6 @@ function Doc:replace(fn) return results end - function Doc:delete_to_cursor(idx, ...) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx) do if line1 ~= line2 or col1 ~= col2 then @@ -583,6 +572,7 @@ function Doc:delete_to_cursor(idx, ...) end self:merge_cursors(idx) end + function Doc:delete_to(...) return self:delete_to_cursor(nil, ...) end function Doc:move_to_cursor(idx, ...) @@ -591,8 +581,8 @@ function Doc:move_to_cursor(idx, ...) end self:merge_cursors(idx) end -function Doc:move_to(...) return self:move_to_cursor(nil, ...) end +function Doc:move_to(...) return self:move_to_cursor(nil, ...) end function Doc:select_to_cursor(idx, ...) for sidx, line, col, line2, col2 in self:get_selections(false, idx) do @@ -601,8 +591,8 @@ function Doc:select_to_cursor(idx, ...) end self:merge_cursors(idx) end -function Doc:select_to(...) return self:select_to_cursor(nil, ...) end +function Doc:select_to(...) return self:select_to_cursor(nil, ...) end function Doc:get_indent_string() local indent_type, indent_size = self:get_indent_info() @@ -625,7 +615,7 @@ function Doc:get_line_indent(line, rnd_up) local indent = e and line:sub(1, e):gsub("\t", soft_tab) or "" local number = #indent / #soft_tab return e, indent:sub(1, - (rnd_up and math.ceil(number) or math.floor(number))*#soft_tab) + (rnd_up and math.ceil(number) or math.floor(number)) * #soft_tab) end end @@ -674,5 +664,4 @@ function Doc:on_close() core.log_quiet("Closed doc \"%s\"", self:get_name()) end - return Doc diff --git a/data/core/docview.lua b/data/core/docview.lua index e2da6dfc..c2502040 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -460,9 +460,14 @@ function DocView:draw_line_text(line, x, y) return self:get_line_height() end -function DocView:draw_caret(x, y) - local lh = self:get_line_height() +function DocView:draw_caret(x, y, line, col) + local lh = self:get_line_height() + if self.doc.overwrite then + local w = self:get_font():get_width(self.doc:get_char(line, col)) + renderer.draw_rect(x, y + lh, w, style.caret_width * 2, style.caret) + else renderer.draw_rect(x, y, style.caret_width, lh, style.caret) + end end function DocView:draw_line_body(line, x, y) @@ -542,7 +547,7 @@ function DocView:draw_ime_decoration(line1, col1, line2, col2) line_size = style.caret_width renderer.draw_rect(x + math.min(x1, x2), y + lh - line_size, math.abs(x1 - x2), line_size, style.caret) end - self:draw_caret(x + x1, y) + self:draw_caret(x + x1, y, line1, col) end @@ -559,7 +564,8 @@ function DocView:draw_overlay() else if config.disable_blink or (core.blink_timer - core.blink_start) % T < T / 2 then - self:draw_caret(self:get_line_screen_position(line1, col1)) + local x, y = self:get_line_screen_position(line1, col1) + self:draw_caret(x, y, line1, col1) end end end diff --git a/data/core/keymap.lua b/data/core/keymap.lua index 74e270d2..9f19cfb7 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -341,6 +341,7 @@ keymap.add_direct { ["ctrl+x"] = "doc:cut", ["ctrl+c"] = "doc:copy", ["ctrl+v"] = "doc:paste", + ["insert"] = "doc:toggle-overwrite", ["ctrl+insert"] = "doc:copy", ["shift+insert"] = "doc:paste", ["escape"] = { "command:escape", "doc:select-none", "dialog:select-no" }, diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 3ef40d82..74124768 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -319,6 +319,19 @@ function StatusView:register_docview_items() end, command = "doc:toggle-line-ending" }) + + self:add_item { + predicate = predicate_docview, + name = "doc:overwrite-mode", + alignment = StatusView.Item.RIGHT, + get_item = function() + return { + style.text, core.active_view.doc.overwrite and "OVR" or "INS" + } + end, + command = "doc:toggle-overwrite", + separator = StatusView.separator2 + } end From e14af4604ae00da9cdf5aa1bcf9aa9cc18b87ab1 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 29 Nov 2023 15:29:37 -0500 Subject: [PATCH 162/176] Reverted cursor API to something more compatible with old API. (#1674) * Reverted cursor API to something more compatible with old API. * Implemented discord discussion. * Reduced thiccness of overwrite cursor. --- data/core/docview.lua | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/data/core/docview.lua b/data/core/docview.lua index c2502040..b679eb6f 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -460,14 +460,16 @@ function DocView:draw_line_text(line, x, y) return self:get_line_height() end -function DocView:draw_caret(x, y, line, col) + +function DocView:draw_overwrite_caret(x, y, width) local lh = self:get_line_height() - if self.doc.overwrite then - local w = self:get_font():get_width(self.doc:get_char(line, col)) - renderer.draw_rect(x, y + lh, w, style.caret_width * 2, style.caret) - else - renderer.draw_rect(x, y, style.caret_width, lh, style.caret) - end + renderer.draw_rect(x, y + lh - style.caret_width, width, style.caret_width, style.caret) +end + + +function DocView:draw_caret(x, y) + local lh = self:get_line_height() + renderer.draw_rect(x, y, style.caret_width, lh, style.caret) end function DocView:draw_line_body(line, x, y) @@ -547,7 +549,7 @@ function DocView:draw_ime_decoration(line1, col1, line2, col2) line_size = style.caret_width renderer.draw_rect(x + math.min(x1, x2), y + lh - line_size, math.abs(x1 - x2), line_size, style.caret) end - self:draw_caret(x + x1, y, line1, col) + self:draw_caret(x + x1, y) end @@ -565,7 +567,11 @@ function DocView:draw_overlay() if config.disable_blink or (core.blink_timer - core.blink_start) % T < T / 2 then local x, y = self:get_line_screen_position(line1, col1) - self:draw_caret(x, y, line1, col1) + if self.doc.overwrite then + self:draw_overwrite_caret(x, y, self:get_font():get_width(self.doc:get_char(line1, col1))) + else + self:draw_caret(x, y) + end end end end From 5719f4de6fcc762640bc40710a7a756720201703 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 21:44:48 +0100 Subject: [PATCH 163/176] Use x offset to define render command rect in `rencache_draw_text` (#1618) * Return x offset for the first character in `ren_font_group_get_width` * Use x offset to define render command rect in `rencache_draw_text` --- src/api/renderer.c | 2 +- src/rencache.c | 5 +++-- src/renderer.c | 10 +++++++++- src/renderer.h | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index 901824fe..6ef22023 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -198,7 +198,7 @@ static int f_font_get_width(lua_State *L) { size_t len; const char *text = luaL_checklstring(L, 2, &len); - lua_pushnumber(L, ren_font_group_get_width(&window_renderer, fonts, text, len)); + lua_pushnumber(L, ren_font_group_get_width(&window_renderer, fonts, text, len, NULL)); return 1; } diff --git a/src/rencache.c b/src/rencache.c index d28ed543..a77f82ca 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -191,8 +191,9 @@ void rencache_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color double rencache_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, double x, int y, RenColor color) { - double width = ren_font_group_get_width(window_renderer, fonts, text, len); - RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) }; + int x_offset; + double width = ren_font_group_get_width(window_renderer, fonts, text, len, &x_offset); + RenRect rect = { x + x_offset, y, (int)(width - x_offset), ren_font_group_get_height(fonts) }; if (rects_overlap(last_clip_rect, rect)) { int sz = len + 1; DrawTextCommand *cmd = push_command(window_renderer, DRAW_TEXT, sizeof(DrawTextCommand) + sz); diff --git a/src/renderer.c b/src/renderer.c index 70cc6a2d..cd5ec7ba 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -348,10 +348,11 @@ int ren_font_group_get_height(RenFont **fonts) { return fonts[0]->height; } -double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len) { +double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, int *x_offset) { double width = 0; const char* end = text + len; GlyphMetric* metric = NULL; GlyphSet* set = NULL; + bool set_x_offset = x_offset == NULL; while (text < end) { unsigned int codepoint; text = utf8_to_codepoint(text, &codepoint); @@ -359,8 +360,15 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con if (!metric) break; width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance; + if (!set_x_offset) { + set_x_offset = true; + *x_offset = metric->bitmap_left; // TODO: should this be scaled by the surface scale? + } } const int surface_scale = renwin_get_surface(window_renderer).scale; + if (!set_x_offset) { + *x_offset = 0; + } return width / surface_scale; } diff --git a/src/renderer.h b/src/renderer.h index 0e96d9a9..1c865c8f 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -34,7 +34,7 @@ int ren_font_group_get_height(RenFont **font); float ren_font_group_get_size(RenFont **font); void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); -double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); +double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, int *x_offset); double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color); From dac8d1ac8e7b77059c4c75a1a328459c8269ad81 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 29 Nov 2023 22:12:22 +0100 Subject: [PATCH 164/176] Improve font/color change detection in `language_md` (#1614) * Delay setting font for custom `language_md` token types * Improve font/color change detection in `language_md` --- data/plugins/language_md.lua | 76 +++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/data/plugins/language_md.lua b/data/plugins/language_md.lua index 4b6cf0c2..544bff15 100644 --- a/data/plugins/language_md.lua +++ b/data/plugins/language_md.lua @@ -3,25 +3,6 @@ local syntax = require "core.syntax" local style = require "core.style" local core = require "core" -local initial_color = style.syntax["keyword2"] - --- Add 3 type of font styles for use on markdown files -for _, attr in pairs({"bold", "italic", "bold_italic"}) do - local attributes = {} - if attr ~= "bold_italic" then - attributes[attr] = true - else - attributes["bold"] = true - attributes["italic"] = true - end - style.syntax_fonts["markdown_"..attr] = style.code_font:copy( - style.code_font:get_size(), - attributes - ) - -- also add a color for it - style.syntax["markdown_"..attr] = style.syntax["keyword2"] -end - local in_squares_match = "^%[%]" local in_parenthesis_match = "^%(%)" @@ -225,12 +206,63 @@ syntax.add { -- Adjust the color on theme changes core.add_thread(function() + local custom_fonts = { bold = {font = nil, color = nil}, italic = {}, bold_italic = {} } + local initial_color + local last_code_font + + local function set_font(attr) + local attributes = {} + if attr ~= "bold_italic" then + attributes[attr] = true + else + attributes["bold"] = true + attributes["italic"] = true + end + local font = style.code_font:copy( + style.code_font:get_size(), + attributes + ) + custom_fonts[attr].font = font + style.syntax_fonts["markdown_"..attr] = font + end + + local function set_color(attr) + custom_fonts[attr].color = style.syntax["keyword2"] + style.syntax["markdown_"..attr] = style.syntax["keyword2"] + end + + -- Add 3 type of font styles for use on markdown files + for attr, _ in pairs(custom_fonts) do + -- Only set it if the font wasn't manually customized + if not style.syntax_fonts["markdown_"..attr] then + set_font(attr) + end + + -- Only set it if the color wasn't manually customized + if not style.syntax["markdown_"..attr] then + set_color(attr) + end + end + while true do - if initial_color ~= style.syntax["keyword2"] then - for _, attr in pairs({"bold", "italic", "bold_italic"}) do - style.syntax["markdown_"..attr] = style.syntax["keyword2"] + if last_code_font ~= style.code_font then + last_code_font = style.code_font + for attr, _ in pairs(custom_fonts) do + -- Only set it if the font wasn't manually customized + if style.syntax_fonts["markdown_"..attr] == custom_fonts[attr].font then + set_font(attr) + end end + end + + if initial_color ~= style.syntax["keyword2"] then initial_color = style.syntax["keyword2"] + for attr, _ in pairs(custom_fonts) do + -- Only set it if the color wasn't manually customized + if style.syntax["markdown_"..attr] == custom_fonts[attr].color then + set_color(attr) + end + end end coroutine.yield(1) end From 2d36359e6ed696fb2c9c2abf1517ed27f88ae9ca Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:23:50 +0800 Subject: [PATCH 165/176] Revert "feat(subprojects): update wraps (#1577)" This reverts commit a97de87d869c227c2d41595d76ecafdc29e76bef. --- .github/workflows/build.yml | 2 +- meson.build | 17 ++--------------- resources/include/lite_xl_plugin_api.h | 12 +----------- subprojects/freetype2.wrap | 11 +++++------ subprojects/lua.wrap | 18 ++++++++---------- subprojects/pcre2.wrap | 11 +++++------ subprojects/sdl2.wrap | 19 ++++++++----------- 7 files changed, 30 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 21f3a8b4..96db355f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,7 +204,7 @@ jobs: run: | "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV "INSTALL_REF=$($env:GITHUB_REF -replace ".*/")" >> $env:GITHUB_ENV - "LUA_SUBPROJECT_PATH=subprojects/$(awk -F ' *= *' '/directory/ { printf $2 }' subprojects/lua.wrap)" >> $env:GITHUB_ENV + "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV - name: Download and patch subprojects shell: bash run: | diff --git a/meson.build b/meson.build index f0614cc8..3cfec808 100644 --- a/meson.build +++ b/meson.build @@ -101,7 +101,7 @@ if not get_option('source-only') endforeach else lua_dep = dependency('', fallback: ['lua', 'lua_dep'], required : true, - default_options: default_fallback_options + ['default_library=static', 'line_editing=disabled', 'interpreter=false'] + default_options: default_fallback_options + ['default_library=static', 'line_editing=false', 'interpreter=false'] ) endif @@ -123,7 +123,6 @@ if not get_option('source-only') sdl_options += 'use_atomic=enabled' sdl_options += 'use_threads=enabled' sdl_options += 'use_timers=enabled' - sdl_options += 'with_main=true' # investigate if this is truly needed # Do not remove before https://github.com/libsdl-org/SDL/issues/5413 is released sdl_options += 'use_events=enabled' @@ -156,24 +155,12 @@ if not get_option('source-only') sdl_options += 'use_video_vulkan=disabled' sdl_options += 'use_video_offscreen=disabled' sdl_options += 'use_power=disabled' - sdl_options += 'system_iconv=disabled' sdl_dep = dependency('sdl2', fallback: ['sdl2', 'sdl2_dep'], default_options: default_fallback_options + sdl_options ) - if host_machine.system() == 'windows' - if sdl_dep.type_name() == 'internal' - sdlmain_dep = dependency('sdl2main', fallback: ['sdl2main_dep']) - else - sdlmain_dep = cc.find_library('SDL2main') - endif - else - sdlmain_dep = dependency('', required: false) - assert(not sdlmain_dep.found(), 'checking if fake dependency has been found') - endif - - lite_deps = [lua_dep, sdl_dep, sdlmain_dep, freetype_dep, pcre2_dep, libm, libdl] + lite_deps = [lua_dep, sdl_dep, freetype_dep, pcre2_dep, libm, libdl] endif #=============================================================================== # Install Configuration diff --git a/resources/include/lite_xl_plugin_api.h b/resources/include/lite_xl_plugin_api.h index 0f500059..0c5e93e9 100644 --- a/resources/include/lite_xl_plugin_api.h +++ b/resources/include/lite_xl_plugin_api.h @@ -31,14 +31,9 @@ * An example command would be: gcc -shared -o xxxxx.so xxxxx.c * You must not link to ANY lua library to avoid symbol collision. * - * This file contains stock configuration for a typical installation of Lua 5.4.6. + * This file contains stock configuration for a typical installation of Lua 5.4. * DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK * COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS. - * - * For reference, here are a list of permalinks to previous version of this file that targets an older version of Lua. - * If you don't need functionalities offered by the new version, use the OLDEST FILE for backwards compatibility. - * - * - Lua 5.4.4: https://github.com/lite-xl/lite-xl/blob/397973067f14420b26e3b20a238a50016c0b75e2/resources/include/lite_xl_plugin_api.h **/ #ifndef LITE_XL_PLUGIN_API #define LITE_XL_PLUGIN_API @@ -1033,7 +1028,6 @@ extern const char lua_ident[]; SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) SYMBOL_DECLARE(void, lua_close, lua_State *L) SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) -SYMBOL_DECLARE(int, lua_closethread, lua_State *L, lua_State *from) SYMBOL_DECLARE(int, lua_resetthread, lua_State *L) SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) @@ -1745,9 +1739,6 @@ SYMBOL_WRAP_DECL(void, lua_close, lua_State *L) { SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_newthread, L); } -SYMBOL_WRAP_DECL(int, lua_closethread, lua_State *L, lua_State *from) { - return SYMBOL_WRAP_CALL(lua_closethread, L, from); -} SYMBOL_WRAP_DECL(int, lua_resetthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_resetthread, L); } @@ -2360,7 +2351,6 @@ void lite_xl_plugin_init(void *XL) { IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); IMPORT_SYMBOL(lua_close, void, lua_State *L); IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); - IMPORT_SYMBOL(lua_closethread, int, lua_State *L, lua_State *from); IMPORT_SYMBOL(lua_resetthread, int, lua_State *L); IMPORT_SYMBOL(lua_atpanic, lua_CFunction, lua_State *L, lua_CFunction panicf); IMPORT_SYMBOL(lua_version, lua_Number, lua_State *L); diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap index e3554c9a..1ff89ecd 100644 --- a/subprojects/freetype2.wrap +++ b/subprojects/freetype2.wrap @@ -1,10 +1,9 @@ [wrap-file] -directory = freetype-2.13.2 -source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.2.tar.xz -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.2-1/freetype-2.13.2.tar.xz -source_filename = freetype-2.13.2.tar.xz -source_hash = 12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d -wrapdb_version = 2.13.2-1 +directory = freetype-2.12.1 +source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.xz +source_filename = freetype-2.12.1.tar.xz +source_hash = 4766f20157cc4cf0cd292f80bf917f92d1c439b243ac3018debf6b9140c41a7f +wrapdb_version = 2.12.1-2 [provide] freetype2 = freetype_dep diff --git a/subprojects/lua.wrap b/subprojects/lua.wrap index 16502616..5a2d615b 100644 --- a/subprojects/lua.wrap +++ b/subprojects/lua.wrap @@ -1,14 +1,12 @@ [wrap-file] -directory = lua-5.4.6 -source_url = https://www.lua.org/ftp/lua-5.4.6.tar.gz -source_filename = lua-5.4.6.tar.gz -source_hash = 7d5ea1b9cb6aa0b59ca3dde1c6adcb57ef83a1ba8e5432c0ecd06bf439b3ad88 -patch_filename = lua_5.4.6-3_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.6-3/get_patch -patch_hash = 9b72a95422fd47f79f969d9abdb589ee95712d5512a5246f94e7e4f63d2cb7b7 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lua_5.4.6-3/lua-5.4.6.tar.gz -wrapdb_version = 5.4.6-3 +directory = lua-5.4.4 +source_url = https://www.lua.org/ftp/lua-5.4.4.tar.gz +source_filename = lua-5.4.4.tar.gz +source_hash = 164c7849653b80ae67bec4b7473b884bf5cc8d2dca05653475ec2ed27b9ebf61 +patch_filename = lua_5.4.4-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.4-1/get_patch +patch_hash = e61cd965c629d6543176f41a9f1cb9050edfd1566cf00ce768ff211086e40bdc [provide] lua-5.4 = lua_dep -lua = lua_dep + diff --git a/subprojects/pcre2.wrap b/subprojects/pcre2.wrap index 6bfef6f3..8fada34e 100644 --- a/subprojects/pcre2.wrap +++ b/subprojects/pcre2.wrap @@ -1,13 +1,12 @@ [wrap-file] directory = pcre2-10.42 -source_url = https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 +source_url = https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 source_filename = pcre2-10.42.tar.bz2 source_hash = 8d36cd8cb6ea2a4c2bb358ff6411b0c788633a2a45dabbf1aeb4b701d1b5e840 -patch_filename = pcre2_10.42-5_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-5/get_patch -patch_hash = 7ba1730a3786c46f41735658a9884b09bc592af3840716e0ccc552e7ddf5630c -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/pcre2_10.42-5/pcre2-10.42.tar.bz2 -wrapdb_version = 10.42-5 +patch_filename = pcre2_10.42-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-1/get_patch +patch_hash = 06969e916dfee663c189810df57d98574f15e0754a44cd93f3f0bc7234b05d89 +wrapdb_version = 10.42-1 [provide] libpcre2-8 = libpcre2_8 diff --git a/subprojects/sdl2.wrap b/subprojects/sdl2.wrap index 14c18533..53a71e2f 100644 --- a/subprojects/sdl2.wrap +++ b/subprojects/sdl2.wrap @@ -1,15 +1,12 @@ [wrap-file] -directory = SDL2-2.28.1 -source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.28.1/SDL2-2.28.1.tar.gz -source_filename = SDL2-2.28.1.tar.gz -source_hash = 4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d -patch_filename = sdl2_2.28.1-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.28.1-2/get_patch -patch_hash = 2dd332226ba2a4373c6d4eb29fa915e9d5414cf7bb9fa2e4a5ef3b16a06e2736 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.28.1-2/SDL2-2.28.1.tar.gz -wrapdb_version = 2.28.1-2 +directory = SDL2-2.26.0 +source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.26.0/SDL2-2.26.0.tar.gz +source_filename = SDL2-2.26.0.tar.gz +source_hash = 8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 +patch_filename = sdl2_2.26.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.26.0-1/get_patch +patch_hash = 6fcfd727d71cf7837332723518d5e47ffd64f1e7630681cf4b50e99f2bf7676f +wrapdb_version = 2.26.0-1 [provide] sdl2 = sdl2_dep -sdl2main = sdl2main_dep -sdl2_test = sdl2_test_dep From 7b064bae6b021cad03716b0672326b71fc7e89cc Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:46:56 +0800 Subject: [PATCH 166/176] fix(ci,build.sh): un-hardcode lua subproject detection --- .github/workflows/build.yml | 2 +- scripts/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96db355f..21f3a8b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,7 +204,7 @@ jobs: run: | "INSTALL_NAME=lite-xl-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV "INSTALL_REF=$($env:GITHUB_REF -replace ".*/")" >> $env:GITHUB_ENV - "LUA_SUBPROJECT_PATH=subprojects/lua-5.4.4" >> $env:GITHUB_ENV + "LUA_SUBPROJECT_PATH=subprojects/$(awk -F ' *= *' '/directory/ { printf $2 }' subprojects/lua.wrap)" >> $env:GITHUB_ENV - name: Download and patch subprojects shell: bash run: | diff --git a/scripts/build.sh b/scripts/build.sh index 778f596d..0908ab19 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -181,7 +181,7 @@ main() { # download the subprojects so we can start patching before configure. # this will prevent reconfiguring the project. meson subprojects download - lua_subproject_path=$(echo subprojects/lua-*/) + lua_subproject_path="subprojects/$(awk -F ' *= *' '/directory/ { printf $2 }' subprojects/lua.wrap)" if [[ -d $lua_subproject_path ]]; then patch -d $lua_subproject_path -p1 --forward < resources/windows/001-lua-unicode.diff fi From 41813604e19e0e9fb10e467d5c0048f05b5d3b62 Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:48:20 +0800 Subject: [PATCH 167/176] chore(deps): update freetype --- subprojects/freetype2.wrap | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/subprojects/freetype2.wrap b/subprojects/freetype2.wrap index 1ff89ecd..e3554c9a 100644 --- a/subprojects/freetype2.wrap +++ b/subprojects/freetype2.wrap @@ -1,9 +1,10 @@ [wrap-file] -directory = freetype-2.12.1 -source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.xz -source_filename = freetype-2.12.1.tar.xz -source_hash = 4766f20157cc4cf0cd292f80bf917f92d1c439b243ac3018debf6b9140c41a7f -wrapdb_version = 2.12.1-2 +directory = freetype-2.13.2 +source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.2.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.2-1/freetype-2.13.2.tar.xz +source_filename = freetype-2.13.2.tar.xz +source_hash = 12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d +wrapdb_version = 2.13.2-1 [provide] freetype2 = freetype_dep From 79bae532b9e111bb0c153988d5a6c38ff01d354c Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:49:34 +0800 Subject: [PATCH 168/176] chore(deps): update pcre2 --- subprojects/pcre2.wrap | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/subprojects/pcre2.wrap b/subprojects/pcre2.wrap index 8fada34e..6bfef6f3 100644 --- a/subprojects/pcre2.wrap +++ b/subprojects/pcre2.wrap @@ -1,12 +1,13 @@ [wrap-file] directory = pcre2-10.42 -source_url = https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 +source_url = https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.bz2 source_filename = pcre2-10.42.tar.bz2 source_hash = 8d36cd8cb6ea2a4c2bb358ff6411b0c788633a2a45dabbf1aeb4b701d1b5e840 -patch_filename = pcre2_10.42-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-1/get_patch -patch_hash = 06969e916dfee663c189810df57d98574f15e0754a44cd93f3f0bc7234b05d89 -wrapdb_version = 10.42-1 +patch_filename = pcre2_10.42-5_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/pcre2_10.42-5/get_patch +patch_hash = 7ba1730a3786c46f41735658a9884b09bc592af3840716e0ccc552e7ddf5630c +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/pcre2_10.42-5/pcre2-10.42.tar.bz2 +wrapdb_version = 10.42-5 [provide] libpcre2-8 = libpcre2_8 From ad1fad26322579cbf3e0470786087926a7bbed73 Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:53:25 +0800 Subject: [PATCH 169/176] chore(deps): update SDL2 --- meson.build | 15 ++++++++++++++- subprojects/sdl2.wrap | 19 +++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/meson.build b/meson.build index 3cfec808..ddddbb3f 100644 --- a/meson.build +++ b/meson.build @@ -123,6 +123,7 @@ if not get_option('source-only') sdl_options += 'use_atomic=enabled' sdl_options += 'use_threads=enabled' sdl_options += 'use_timers=enabled' + sdl_options += 'with_main=true' # investigate if this is truly needed # Do not remove before https://github.com/libsdl-org/SDL/issues/5413 is released sdl_options += 'use_events=enabled' @@ -155,12 +156,24 @@ if not get_option('source-only') sdl_options += 'use_video_vulkan=disabled' sdl_options += 'use_video_offscreen=disabled' sdl_options += 'use_power=disabled' + sdl_options += 'system_iconv=disabled' sdl_dep = dependency('sdl2', fallback: ['sdl2', 'sdl2_dep'], default_options: default_fallback_options + sdl_options ) - lite_deps = [lua_dep, sdl_dep, freetype_dep, pcre2_dep, libm, libdl] + if host_machine.system() == 'windows' + if sdl_dep.type_name() == 'internal' + sdlmain_dep = dependency('sdl2main', fallback: ['sdl2main_dep']) + else + sdlmain_dep = cc.find_library('SDL2main') + endif + else + sdlmain_dep = dependency('', required: false) + assert(not sdlmain_dep.found(), 'checking if fake dependency has been found') + endif + + lite_deps = [lua_dep, sdl_dep, sdlmain_dep, freetype_dep, pcre2_dep, libm, libdl] endif #=============================================================================== # Install Configuration diff --git a/subprojects/sdl2.wrap b/subprojects/sdl2.wrap index 53a71e2f..14c18533 100644 --- a/subprojects/sdl2.wrap +++ b/subprojects/sdl2.wrap @@ -1,12 +1,15 @@ [wrap-file] -directory = SDL2-2.26.0 -source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.26.0/SDL2-2.26.0.tar.gz -source_filename = SDL2-2.26.0.tar.gz -source_hash = 8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 -patch_filename = sdl2_2.26.0-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.26.0-1/get_patch -patch_hash = 6fcfd727d71cf7837332723518d5e47ffd64f1e7630681cf4b50e99f2bf7676f -wrapdb_version = 2.26.0-1 +directory = SDL2-2.28.1 +source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.28.1/SDL2-2.28.1.tar.gz +source_filename = SDL2-2.28.1.tar.gz +source_hash = 4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d +patch_filename = sdl2_2.28.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.28.1-2/get_patch +patch_hash = 2dd332226ba2a4373c6d4eb29fa915e9d5414cf7bb9fa2e4a5ef3b16a06e2736 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.28.1-2/SDL2-2.28.1.tar.gz +wrapdb_version = 2.28.1-2 [provide] sdl2 = sdl2_dep +sdl2main = sdl2main_dep +sdl2_test = sdl2_test_dep From a9ac33429ecb799c540b888ea070b008822a95d1 Mon Sep 17 00:00:00 2001 From: takase1121 <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:57:09 +0800 Subject: [PATCH 170/176] chore(deps): update Lua --- meson.build | 2 +- resources/include/lite_xl_plugin_api.h | 12 +++++++++++- subprojects/lua.wrap | 18 ++++++++++-------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/meson.build b/meson.build index ddddbb3f..f0614cc8 100644 --- a/meson.build +++ b/meson.build @@ -101,7 +101,7 @@ if not get_option('source-only') endforeach else lua_dep = dependency('', fallback: ['lua', 'lua_dep'], required : true, - default_options: default_fallback_options + ['default_library=static', 'line_editing=false', 'interpreter=false'] + default_options: default_fallback_options + ['default_library=static', 'line_editing=disabled', 'interpreter=false'] ) endif diff --git a/resources/include/lite_xl_plugin_api.h b/resources/include/lite_xl_plugin_api.h index 0c5e93e9..0f500059 100644 --- a/resources/include/lite_xl_plugin_api.h +++ b/resources/include/lite_xl_plugin_api.h @@ -31,9 +31,14 @@ * An example command would be: gcc -shared -o xxxxx.so xxxxx.c * You must not link to ANY lua library to avoid symbol collision. * - * This file contains stock configuration for a typical installation of Lua 5.4. + * This file contains stock configuration for a typical installation of Lua 5.4.6. * DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK * COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS. + * + * For reference, here are a list of permalinks to previous version of this file that targets an older version of Lua. + * If you don't need functionalities offered by the new version, use the OLDEST FILE for backwards compatibility. + * + * - Lua 5.4.4: https://github.com/lite-xl/lite-xl/blob/397973067f14420b26e3b20a238a50016c0b75e2/resources/include/lite_xl_plugin_api.h **/ #ifndef LITE_XL_PLUGIN_API #define LITE_XL_PLUGIN_API @@ -1028,6 +1033,7 @@ extern const char lua_ident[]; SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) SYMBOL_DECLARE(void, lua_close, lua_State *L) SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) +SYMBOL_DECLARE(int, lua_closethread, lua_State *L, lua_State *from) SYMBOL_DECLARE(int, lua_resetthread, lua_State *L) SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) @@ -1739,6 +1745,9 @@ SYMBOL_WRAP_DECL(void, lua_close, lua_State *L) { SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_newthread, L); } +SYMBOL_WRAP_DECL(int, lua_closethread, lua_State *L, lua_State *from) { + return SYMBOL_WRAP_CALL(lua_closethread, L, from); +} SYMBOL_WRAP_DECL(int, lua_resetthread, lua_State *L) { return SYMBOL_WRAP_CALL(lua_resetthread, L); } @@ -2351,6 +2360,7 @@ void lite_xl_plugin_init(void *XL) { IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); IMPORT_SYMBOL(lua_close, void, lua_State *L); IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); + IMPORT_SYMBOL(lua_closethread, int, lua_State *L, lua_State *from); IMPORT_SYMBOL(lua_resetthread, int, lua_State *L); IMPORT_SYMBOL(lua_atpanic, lua_CFunction, lua_State *L, lua_CFunction panicf); IMPORT_SYMBOL(lua_version, lua_Number, lua_State *L); diff --git a/subprojects/lua.wrap b/subprojects/lua.wrap index 5a2d615b..16502616 100644 --- a/subprojects/lua.wrap +++ b/subprojects/lua.wrap @@ -1,12 +1,14 @@ [wrap-file] -directory = lua-5.4.4 -source_url = https://www.lua.org/ftp/lua-5.4.4.tar.gz -source_filename = lua-5.4.4.tar.gz -source_hash = 164c7849653b80ae67bec4b7473b884bf5cc8d2dca05653475ec2ed27b9ebf61 -patch_filename = lua_5.4.4-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.4-1/get_patch -patch_hash = e61cd965c629d6543176f41a9f1cb9050edfd1566cf00ce768ff211086e40bdc +directory = lua-5.4.6 +source_url = https://www.lua.org/ftp/lua-5.4.6.tar.gz +source_filename = lua-5.4.6.tar.gz +source_hash = 7d5ea1b9cb6aa0b59ca3dde1c6adcb57ef83a1ba8e5432c0ecd06bf439b3ad88 +patch_filename = lua_5.4.6-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.6-3/get_patch +patch_hash = 9b72a95422fd47f79f969d9abdb589ee95712d5512a5246f94e7e4f63d2cb7b7 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lua_5.4.6-3/lua-5.4.6.tar.gz +wrapdb_version = 5.4.6-3 [provide] lua-5.4 = lua_dep - +lua = lua_dep From 7111b8a6c93d14a922458a6b3bd43deff18ed558 Mon Sep 17 00:00:00 2001 From: Takase <20792268+takase1121@users.noreply.github.com> Date: Thu, 30 Nov 2023 23:33:24 +0800 Subject: [PATCH 171/176] feat(process): allow commands and envs on proces_start (#1477) * feat(process): allow commands and envs on proces_start * refactor(process): copy process arguments once whenever possible Refactors the code to use an arglist type which is just lpCmdline on Windows and a list in Linux. The function automatically escapes the command when it is needed, avoiding a second copy. This also allows UTF-8 commands btw. * fix(process): fix invalid dereference * refactor(process): mark xstrdup as potentially unused * feat(process): add parent process environment when launching process * fix(process): fix operator precedence with array operators * fix(process): fix segfault when freeing random memory * fix(process): fix wrong check for setenv() * fix(process): fix accidentally initializing an array by assignment * fix(process): clear return value if success --- src/api/process.c | 422 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 328 insertions(+), 94 deletions(-) diff --git a/src/api/process.c b/src/api/process.c index d7bfeb72..66f27536 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -31,6 +31,8 @@ typedef DWORD process_error_t; typedef HANDLE process_stream_t; typedef HANDLE process_handle_t; +typedef wchar_t process_arglist_t[32767]; +typedef wchar_t *process_env_t; #define HANDLE_INVALID (INVALID_HANDLE_VALUE) #define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess) @@ -42,12 +44,20 @@ static volatile long PipeSerialNumber; typedef int process_error_t; typedef int process_stream_t; typedef pid_t process_handle_t; +typedef char **process_arglist_t; +typedef char **process_env_t; #define HANDLE_INVALID (0) #define PROCESS_GET_HANDLE(P) ((P)->pid) #endif +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif + typedef struct { bool running, detached; int returncode, deadline; @@ -339,51 +349,264 @@ static bool signal_process(process_t* proc, signal_e sig) { return true; } -static int process_start(lua_State* L) { - int retval = 1; - size_t env_len = 0, key_len, val_len; - const char *cmd[256] = { NULL }, *env_names[256] = { NULL }, *env_values[256] = { NULL }, *cwd = NULL; - bool detach = false, literal = false; - int deadline = 10, new_fds[3] = { STDIN_FD, STDOUT_FD, STDERR_FD }; - size_t arg_len = lua_gettop(L), cmd_len; - if (lua_type(L, 1) == LUA_TTABLE) { - #if LUA_VERSION_NUM > 501 - lua_len(L, 1); - #else - lua_pushinteger(L, (int)lua_objlen(L, 1)); - #endif - cmd_len = luaL_checknumber(L, -1); lua_pop(L, 1); - if (!cmd_len) - // we have not allocated anything here yet, so we can skip cleanup code - // don't do this anywhere else! - return luaL_argerror(L, 1,"table cannot be empty"); - for (size_t i = 1; i <= cmd_len; ++i) { - lua_pushinteger(L, i); - lua_rawget(L, 1); - cmd[i-1] = luaL_checkstring(L, -1); - } + +static UNUSED char *xstrdup(const char *str) { + char *result = str ? malloc(strlen(str) + 1) : NULL; + if (result) strcpy(result, str); + return result; +} + + +static int process_arglist_init(process_arglist_t *list, size_t *list_len, size_t nargs) { + *list_len = 0; +#ifdef _WIN32 + memset(*list, 0, sizeof(process_arglist_t)); +#else + *list = calloc(sizeof(char *), nargs + 1); + if (!*list) return ENOMEM; +#endif + return 0; +} + + +static int process_arglist_add(process_arglist_t *list, size_t *list_len, const char *arg, bool escape) { + size_t len = *list_len; +#ifdef _WIN32 + int arg_len; + wchar_t *cmdline = *list; + wchar_t arg_w[32767]; + // this length includes the null terminator! + if (!(arg_len = MultiByteToWideChar(CP_UTF8, 0, arg, -1, arg_w, 32767))) + return GetLastError(); + if (arg_len + len > 32767) + return ERROR_NOT_ENOUGH_MEMORY; + + if (!escape) { + // replace the current null terminator with a space + if (len > 0) cmdline[len-1] = ' '; + memcpy(cmdline + len, arg_w, arg_len * sizeof(wchar_t)); + len += arg_len; } else { - literal = true; - cmd[0] = luaL_checkstring(L, 1); - cmd_len = 1; + // if the string contains spaces, then we must quote it + bool quote = wcspbrk(arg_w, L" \t\v\r\n"); + int backslash = 0, escaped_len = quote ? 2 : 0; + for (int i = 0; i < arg_len; i++) { + if (arg_w[i] == L'\\') { + backslash++; + } else if (arg_w[i] == L'"') { + escaped_len += backslash + 1; + backslash = 0; + } else { + backslash = 0; + } + escaped_len++; + } + // escape_len contains NUL terminator + if (escaped_len + len > 32767) + return ERROR_NOT_ENOUGH_MEMORY; + // replace our previous NUL terminator with space + if (len > 0) cmdline[len-1] = L' '; + if (quote) cmdline[len++] = L'"'; + // we are not going to iterate over NUL terminator + for (int i = 0;arg_w[i]; i++) { + if (arg_w[i] == L'\\') { + backslash++; + } else if (arg_w[i] == L'"') { + // add backslash + 1 backslashes + for (int j = 0; j < backslash; j++) + cmdline[len++] = L'\\'; + cmdline[len++] = L'\\'; + backslash = 0; + } else { + backslash = 0; + } + cmdline[len++] = arg_w[i]; + } + if (quote) cmdline[len++] = L'"'; + cmdline[len++] = L'\0'; + } +#else + char **cmd = *list; + cmd[len] = xstrdup(arg); + if (!cmd[len]) return ENOMEM; + len++; +#endif + *list_len = len; + return 0; +} + + +static void process_arglist_free(process_arglist_t *list) { +#ifndef _WIN32 + char **cmd = *list; + for (int i = 0; cmd[i]; i++) + free(cmd[i]); + free(cmd); + *list = NULL; +#endif +} + + +static int process_env_init(process_env_t *env_list, size_t *env_len, size_t nenv) { + *env_len = 0; +#ifdef _WIN32 + *env_list = NULL; +#else + *env_list = calloc(sizeof(char *), nenv * 2); + if (!*env_list) return ENOMEM; +#endif + return 0; +} + + +#ifdef _WIN32 +static int cmp_name(wchar_t *a, wchar_t *b) { + wchar_t _A[32767], _B[32767], *A = _A, *B = _B, *a_eq, *b_eq; + int na, nb, r; + a_eq = wcschr(a, L'='); + b_eq = wcschr(b, L'='); + assert(a_eq); + assert(b_eq); + na = a_eq - a; + nb = b_eq - b; + r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na); + assert(r == na); + A[na] = L'\0'; + r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb); + assert(r == nb); + B[nb] = L'\0'; + + for (;;) { + wchar_t AA = *A++, BB = *B++; + if (AA > BB) + return 1; + else if (AA < BB) + return -1; + else if (!AA && !BB) + return 0; + } +} + + +static int process_env_add_variable(process_env_t *env_list, size_t *env_list_len, wchar_t *var, size_t var_len) { + wchar_t *list, *list_p; + size_t block_var_len, list_len; + list = list_p = *env_list; + list_len = *env_list_len; + if (list_len) { + // check if it is already in the block + while ((block_var_len = wcslen(list_p))) { + if (cmp_name(list_p, var) == 0) + return -1; // already installed + list_p += block_var_len + 1; + } + } + // allocate list + 1 characters for the block terminator + list = realloc(list, (list_len + var_len + 1) * sizeof(wchar_t)); + if (!list) return ERROR_NOT_ENOUGH_MEMORY; + // copy the env variable to the block + memcpy(list + list_len, var, var_len * sizeof(wchar_t)); + // terminate the block again + list[list_len + var_len] = L'\0'; + *env_list = list; + *env_list_len = (list_len + var_len); + return 0; +} + + +static int process_env_add_system(process_env_t *env_list, size_t *env_list_len) { + int retval = 0; + wchar_t *proc_env_block, *proc_env_block_p; + int proc_env_len; + + proc_env_block = proc_env_block_p = GetEnvironmentStringsW(); + while ((proc_env_len = wcslen(proc_env_block_p))) { + // try to add it to the list + if ((retval = process_env_add_variable(env_list, env_list_len, proc_env_block_p, proc_env_len + 1)) > 0) + goto cleanup; + proc_env_block_p += proc_env_len + 1; + } + retval = 0; + +cleanup: + if (proc_env_block) FreeEnvironmentStringsW(proc_env_block); + return retval; +} +#endif + + +static int process_env_add(process_env_t *env_list, size_t *env_len, const char *key, const char *value) { +#ifdef _WIN32 + wchar_t env_var[32767]; + int r, var_len = 0; + if (!(r = MultiByteToWideChar(CP_UTF8, 0, key, -1, env_var, 32767))) + return GetLastError(); + var_len += r; + env_var[var_len-1] = L'='; + if (!(r = MultiByteToWideChar(CP_UTF8, 0, value, -1, env_var + var_len, 32767 - var_len))) + return GetLastError(); + var_len += r; + return process_env_add_variable(env_list, env_len, env_var, var_len); +#else + (*env_list)[*env_len] = xstrdup(key); + if (!(*env_list)[*env_len]) + return ENOMEM; + (*env_list)[*env_len + 1] = xstrdup(value); + if (!(*env_list)[*env_len + 1]) + return ENOMEM; + *env_len += 2; +#endif + return 0; +} + + +static void process_env_free(process_env_t *list) { + if (!*list) return; +#ifdef _WIN32 + free(*list); +#else + for (size_t i = 0; (*list)[i]; i++) free((*list)[i]); + free(*list); +#endif + *list = NULL; +} + + +static int process_start(lua_State* L) { + int r, retval = 1; + size_t env_len = 0, cmd_len = 0, arglist_len = 0, env_vars_len = 0; + process_arglist_t arglist; + process_env_t env_vars = NULL; + const char *cwd = NULL; + bool detach = false, escape = true; + int deadline = 10, new_fds[3] = { STDIN_FD, STDOUT_FD, STDERR_FD }; + + if (lua_isstring(L, 1)) { + escape = false; + // create a table that contains the string as the value + lua_createtable(L, 1, 0); + lua_pushvalue(L, 1); + lua_rawseti(L, -2, 1); + lua_replace(L, 1); } - if (arg_len > 1) { - lua_getfield(L, 2, "env"); - if (!lua_isnil(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - const char* key = luaL_checklstring(L, -2, &key_len); - const char* val = luaL_checklstring(L, -1, &val_len); - env_names[env_len] = malloc(key_len+1); - strcpy((char*)env_names[env_len], key); - env_values[env_len] = malloc(val_len+1); - strcpy((char*)env_values[env_len], val); - lua_pop(L, 1); - ++env_len; - } - } else - lua_pop(L, 1); + luaL_checktype(L, 1, LUA_TTABLE); + #if LUA_VERSION_NUM > 501 + lua_len(L, 1); + #else + lua_pushinteger(L, (int)lua_objlen(L, 1)); + #endif + cmd_len = luaL_checknumber(L, -1); lua_pop(L, 1); + if (!cmd_len) + return luaL_argerror(L, 1, "table cannot be empty"); + // check if each arguments is a string + for (size_t i = 1; i <= cmd_len; ++i) { + lua_rawgeti(L, 1, i); + luaL_checkstring(L, -1); + lua_pop(L, 1); + } + + if (lua_istable(L, 2)) { lua_getfield(L, 2, "detach"); detach = lua_toboolean(L, -1); lua_getfield(L, 2, "timeout"); deadline = luaL_optnumber(L, -1, deadline); lua_getfield(L, 2, "cwd"); cwd = luaL_optstring(L, -1, NULL); @@ -391,20 +614,70 @@ static int process_start(lua_State* L) { lua_getfield(L, 2, "stdout"); new_fds[STDOUT_FD] = luaL_optnumber(L, -1, STDOUT_FD); lua_getfield(L, 2, "stderr"); new_fds[STDERR_FD] = luaL_optnumber(L, -1, STDERR_FD); for (int stream = STDIN_FD; stream <= STDERR_FD; ++stream) { - if (new_fds[stream] > STDERR_FD || new_fds[stream] < REDIRECT_PARENT) { - lua_pushfstring(L, "error: redirect to handles, FILE* and paths are not supported"); + if (new_fds[stream] > STDERR_FD || new_fds[stream] < REDIRECT_PARENT) + return luaL_error(L, "error: redirect to handles, FILE* and paths are not supported"); + } + lua_pop(L, 6); // pop all the values above + + luaL_getsubtable(L, 2, "env"); + // count environment variobles + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + luaL_checkstring(L, -2); + luaL_checkstring(L, -1); + lua_pop(L, 1); + env_len++; + } + + if (env_len) { + if ((r = process_env_init(&env_vars, &env_vars_len, env_len)) != 0) { retval = -1; + push_error(L, "cannot allocate environment list", r); goto cleanup; } + + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + if ((r = process_env_add(&env_vars, &env_vars_len, lua_tostring(L, -2), lua_tostring(L, -1))) != 0) { + retval = -1; + push_error(L, "cannot copy environment variable", r); + goto cleanup; + } + lua_pop(L, 1); + env_len++; + } } } + // allocate and copy commands + if ((r = process_arglist_init(&arglist, &arglist_len, cmd_len)) != 0) { + retval = -1; + push_error(L, "cannot create argument list", r); + goto cleanup; + } + for (size_t i = 1; i <= cmd_len; i++) { + lua_rawgeti(L, 1, i); + if ((r = process_arglist_add(&arglist, &arglist_len, lua_tostring(L, -1), escape)) != 0) { + retval = -1; + push_error(L, "cannot add argument", r); + goto cleanup; + } + lua_pop(L, 1); + } + process_t* self = lua_newuserdata(L, sizeof(process_t)); memset(self, 0, sizeof(process_t)); luaL_setmetatable(L, API_TYPE_PROCESS); self->deadline = deadline; self->detached = detach; #if _WIN32 + if (env_vars) { + if ((r = process_env_add_system(&env_vars, &env_vars_len)) != 0) { + retval = -1; + push_error(L, "cannot add environment variable", r); + goto cleanup; + } + } for (int i = 0; i < 3; ++i) { switch (new_fds[i]) { case REDIRECT_PARENT: @@ -455,7 +728,7 @@ static int process_start(lua_State* L) { self->child_pipes[i][1] = self->child_pipes[new_fds[i]][1]; } } - STARTUPINFO siStartInfo; + STARTUPINFOW siStartInfo; memset(&self->process_information, 0, sizeof(self->process_information)); memset(&siStartInfo, 0, sizeof(siStartInfo)); siStartInfo.cb = sizeof(siStartInfo); @@ -463,48 +736,10 @@ static int process_start(lua_State* L) { siStartInfo.hStdInput = self->child_pipes[STDIN_FD][0]; siStartInfo.hStdOutput = self->child_pipes[STDOUT_FD][1]; siStartInfo.hStdError = self->child_pipes[STDERR_FD][1]; - char commandLine[32767] = { 0 }, environmentBlock[32767], wideEnvironmentBlock[32767*2]; - int offset = 0; - if (!literal) { - for (size_t i = 0; i < cmd_len; ++i) { - size_t len = strlen(cmd[i]); - if (offset + len + 2 >= sizeof(commandLine)) break; - if (i > 0) - commandLine[offset++] = ' '; - commandLine[offset++] = '"'; - int backslashCount = 0; // Yes, this is necessary. - for (size_t j = 0; j < len && offset + 2 + backslashCount < sizeof(commandLine); ++j) { - if (cmd[i][j] == '\\') - ++backslashCount; - else if (cmd[i][j] == '"') { - for (size_t k = 0; k < backslashCount; ++k) - commandLine[offset++] = '\\'; - commandLine[offset++] = '\\'; - backslashCount = 0; - } else - backslashCount = 0; - commandLine[offset++] = cmd[i][j]; - } - if (offset + 1 + backslashCount >= sizeof(commandLine)) break; - for (size_t k = 0; k < backslashCount; ++k) - commandLine[offset++] = '\\'; - commandLine[offset++] = '"'; - } - commandLine[offset] = 0; - } else { - strncpy(commandLine, cmd[0], sizeof(commandLine)); - } - offset = 0; - for (size_t i = 0; i < env_len; ++i) { - if (offset + strlen(env_values[i]) + strlen(env_names[i]) + 1 >= sizeof(environmentBlock)) - break; - offset += snprintf(&environmentBlock[offset], sizeof(environmentBlock) - offset, "%s=%s", env_names[i], env_values[i]); - environmentBlock[offset++] = 0; - } - environmentBlock[offset++] = 0; - if (env_len > 0) - MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, environmentBlock, offset, (LPWSTR)wideEnvironmentBlock, sizeof(wideEnvironmentBlock)); - if (!CreateProcess(NULL, commandLine, NULL, NULL, true, (detach ? DETACHED_PROCESS : CREATE_NO_WINDOW) | CREATE_UNICODE_ENVIRONMENT, env_len > 0 ? wideEnvironmentBlock : NULL, cwd, &siStartInfo, &self->process_information)) { + wchar_t cwd_w[MAX_PATH]; + if (cwd) // TODO: error handling + MultiByteToWideChar(CP_UTF8, 0, cwd, -1, cwd_w, MAX_PATH); + if (!CreateProcessW(NULL, arglist, NULL, NULL, true, (detach ? DETACHED_PROCESS : CREATE_NO_WINDOW) | CREATE_UNICODE_ENVIRONMENT, env_vars, cwd ? cwd_w : NULL, &siStartInfo, &self->process_information)) { push_error(L, NULL, GetLastError()); retval = -1; goto cleanup; @@ -552,9 +787,9 @@ static int process_start(lua_State* L) { close(self->child_pipes[stream][stream == STDIN_FD ? 1 : 0]); } size_t set; - for (set = 0; set < env_len && setenv(env_names[set], env_values[set], 1) == 0; ++set); - if (set == env_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1)) - execvp(cmd[0], (char** const)cmd); + for (set = 0; set < env_vars_len && setenv(env_vars[set], env_vars[set+1], 1) == 0; set += 2); + if (set == env_vars_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1)) + execvp(arglist[0], (char** const)arglist); write(control_pipe[1], &errno, sizeof(errno)); _exit(-1); } @@ -588,16 +823,15 @@ static int process_start(lua_State* L) { if (control_pipe[0]) close(control_pipe[0]); if (control_pipe[1]) close(control_pipe[1]); #endif - for (size_t i = 0; i < env_len; ++i) { - free((char*)env_names[i]); - free((char*)env_values[i]); - } for (int stream = 0; stream < 3; ++stream) { process_stream_t* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; if (*pipe) { close_fd(pipe); } } + process_arglist_free(&arglist); + process_env_free(&env_vars); + if (retval == -1) return lua_error(L); From a29327e37568023a8764704de9a31c492359e83a Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 30 Nov 2023 16:51:10 +0100 Subject: [PATCH 172/176] Use `\r\n` for new files on Windows (#1596) * Use `\r\n` for new files on Windows * Add `config.line_endings` --- data/core/config.lua | 6 ++++++ data/core/doc/init.lua | 3 +++ 2 files changed, 9 insertions(+) diff --git a/data/core/config.lua b/data/core/config.lua index 2381639f..88f8d96d 100644 --- a/data/core/config.lua +++ b/data/core/config.lua @@ -153,6 +153,12 @@ config.tab_type = "soft" ---@type boolean config.keep_newline_whitespace = false +---Default line endings for new files. +--- +---Defaults to `crlf` (`\r\n`) on Windows and `lf` (`\n`) on everything else. +---@type "crlf" | "lf" +config.line_endings = PLATFORM == "Windows" and "crlf" or "lf" + ---Maximum number of characters per-line for the line guide. --- ---Defaults to 80. diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 3c0a30d7..e44610e5 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -28,6 +28,9 @@ function Doc:new(filename, abs_filename, new_file) self:load(filename) end end + if new_file then + self.crlf = config.line_endings == "crlf" + end end function Doc:reset() From 39993a6d93cc5283984277ad1835d2ba0ec37ab3 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Thu, 30 Nov 2023 16:53:01 +0100 Subject: [PATCH 173/176] Expose plaintext syntax (#1652) --- data/core/syntax.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/core/syntax.lua b/data/core/syntax.lua index 9862fbdf..6555a17c 100644 --- a/data/core/syntax.lua +++ b/data/core/syntax.lua @@ -3,7 +3,7 @@ local common = require "core.common" local syntax = {} syntax.items = {} -local plain_text_syntax = { name = "Plain Text", patterns = {}, symbols = {} } +syntax.plain_text_syntax = { name = "Plain Text", patterns = {}, symbols = {} } function syntax.add(t) @@ -46,7 +46,7 @@ end function syntax.get(filename, header) return (filename and find(filename, "files")) or (header and find(header, "headers")) - or plain_text_syntax + or syntax.plain_text_syntax end From c45463459c56899c6f4355e40b96ba4fbf2f867d Mon Sep 17 00:00:00 2001 From: ThaCuber <70547062+thacuber2a03@users.noreply.github.com> Date: Sat, 2 Dec 2023 18:44:07 -0400 Subject: [PATCH 174/176] fix nagbar failed save message (#1678) * fix nagbar failed save message - visually separated statements with a `.` - first statement slightly rewritten - use `'` rather than `"` * yeahhhh no back to `"` --- data/core/commands/doc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 3d4426c3..aca5fc65 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -43,7 +43,7 @@ local function save(filename) core.log("Saved \"%s\"", saved_filename) else core.error(err) - core.nag_view:show("Saving failed", string.format("Could not save \"%s\" do you want to save to another location?", doc().filename), { + core.nag_view:show("Saving failed", string.format("Couldn't save file \"%s\". Do you want to save to another location?", doc().filename), { { text = "No", default_no = true }, { text = "Yes", default_yes = true } }, function(item) From cca61ab8ecc6282561a06cbaa7b71e9f565f37e2 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Sun, 3 Dec 2023 11:09:56 -0500 Subject: [PATCH 175/176] Fixed a minor bug, should close issue #1680. --- data/plugins/drawwhitespace.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/plugins/drawwhitespace.lua b/data/plugins/drawwhitespace.lua index 753b3bb4..8b8567b3 100644 --- a/data/plugins/drawwhitespace.lua +++ b/data/plugins/drawwhitespace.lua @@ -347,7 +347,7 @@ end command.add(nil, { ["draw-whitespace:toggle"] = function() - config.plugins.drawwhitespace.enabled = not config.drawwhitespace.enabled + config.plugins.drawwhitespace.enabled = not config.plugins.drawwhitespace.enabled end, ["draw-whitespace:disable"] = function() From 7b67a5d81bc79977842c3ac347e389f889e0ac54 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 6 Dec 2023 12:51:45 +0100 Subject: [PATCH 176/176] turn window_renderer into managed pointer (#1683) * turn window_renderer into managed pointer this will make it easier to move it into userdata in the future * remove unused function, remove comment --- src/api/renderer.c | 20 +++++++------- src/api/system.c | 68 +++++++++++++++++++++++----------------------- src/main.c | 4 +-- src/renderer.c | 42 +++++++++++++++------------- src/renderer.h | 6 ++-- 5 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/api/renderer.c b/src/api/renderer.c index 6ef22023..7f66c860 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -90,7 +90,7 @@ static int f_font_load(lua_State *L) { return ret_code; RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); - *font = ren_font_load(&window_renderer, filename, size, antialiasing, hinting, style); + *font = ren_font_load(window_renderer, filename, size, antialiasing, hinting, style); if (!*font) return luaL_error(L, "failed to load font"); luaL_setmetatable(L, API_TYPE_FONT); @@ -130,7 +130,7 @@ static int f_font_copy(lua_State *L) { } for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { RenFont** font = lua_newuserdata(L, sizeof(RenFont*)); - *font = ren_font_copy(&window_renderer, fonts[i], size, antialiasing, hinting, style); + *font = ren_font_copy(window_renderer, fonts[i], size, antialiasing, hinting, style); if (!*font) return luaL_error(L, "failed to copy font"); luaL_setmetatable(L, API_TYPE_FONT); @@ -198,7 +198,7 @@ static int f_font_get_width(lua_State *L) { size_t len; const char *text = luaL_checklstring(L, 2, &len); - lua_pushnumber(L, ren_font_group_get_width(&window_renderer, fonts, text, len, NULL)); + lua_pushnumber(L, ren_font_group_get_width(window_renderer, fonts, text, len, NULL)); return 1; } @@ -217,7 +217,7 @@ static int f_font_get_size(lua_State *L) { static int f_font_set_size(lua_State *L) { RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1); float size = luaL_checknumber(L, 2); - ren_font_group_set_size(&window_renderer, fonts, size); + ren_font_group_set_size(window_renderer, fonts, size); return 0; } @@ -276,7 +276,7 @@ static int f_show_debug(lua_State *L) { static int f_get_size(lua_State *L) { int w, h; - ren_get_size(&window_renderer, &w, &h); + ren_get_size(window_renderer, &w, &h); lua_pushnumber(L, w); lua_pushnumber(L, h); return 2; @@ -284,13 +284,13 @@ static int f_get_size(lua_State *L) { static int f_begin_frame(UNUSED lua_State *L) { - rencache_begin_frame(&window_renderer); + rencache_begin_frame(window_renderer); return 0; } static int f_end_frame(UNUSED lua_State *L) { - rencache_end_frame(&window_renderer); + rencache_end_frame(window_renderer); // clear the font reference table lua_newtable(L); lua_rawseti(L, LUA_REGISTRYINDEX, RENDERER_FONT_REF); @@ -311,7 +311,7 @@ static int f_set_clip_rect(lua_State *L) { lua_Number w = luaL_checknumber(L, 3); lua_Number h = luaL_checknumber(L, 4); RenRect rect = rect_to_grid(x, y, w, h); - rencache_set_clip_rect(&window_renderer, rect); + rencache_set_clip_rect(window_renderer, rect); return 0; } @@ -323,7 +323,7 @@ static int f_draw_rect(lua_State *L) { lua_Number h = luaL_checknumber(L, 4); RenRect rect = rect_to_grid(x, y, w, h); RenColor color = checkcolor(L, 5, 255); - rencache_draw_rect(&window_renderer, rect, color); + rencache_draw_rect(window_renderer, rect, color); return 0; } @@ -348,7 +348,7 @@ static int f_draw_text(lua_State *L) { double x = luaL_checknumber(L, 3); int y = luaL_checknumber(L, 4); RenColor color = checkcolor(L, 5, 255); - x = rencache_draw_text(&window_renderer, fonts, text, len, x, y, color); + x = rencache_draw_text(window_renderer, fonts, text, len, x, y, color); lua_pushnumber(L, x); return 1; } diff --git a/src/api/system.c b/src/api/system.c index 2a09621f..da99f592 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -74,7 +74,7 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p const int controls_width = hit_info->controls_width; int w, h; - SDL_GetWindowSize(window_renderer.window, &w, &h); + SDL_GetWindowSize(window_renderer->window, &w, &h); if (pt->y < hit_info->title_height && #if RESIZE_FROM_TOP @@ -186,7 +186,7 @@ top: case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) { - ren_resize_window(&window_renderer); + ren_resize_window(window_renderer); lua_pushstring(L, "resized"); /* The size below will be in points. */ lua_pushinteger(L, e.window.data1); @@ -225,8 +225,8 @@ top: SDL_GetMouseState(&mx, &my); lua_pushstring(L, "filedropped"); lua_pushstring(L, e.drop.file); - lua_pushinteger(L, mx * window_renderer.scale_x); - lua_pushinteger(L, my * window_renderer.scale_y); + lua_pushinteger(L, mx * window_renderer->scale_x); + lua_pushinteger(L, my * window_renderer->scale_y); SDL_free(e.drop.file); return 4; @@ -283,8 +283,8 @@ top: if (e.button.button == 1) { SDL_CaptureMouse(1); } lua_pushstring(L, "mousepressed"); lua_pushstring(L, button_name(e.button.button)); - lua_pushinteger(L, e.button.x * window_renderer.scale_x); - lua_pushinteger(L, e.button.y * window_renderer.scale_y); + lua_pushinteger(L, e.button.x * window_renderer->scale_x); + lua_pushinteger(L, e.button.y * window_renderer->scale_y); lua_pushinteger(L, e.button.clicks); return 5; @@ -292,8 +292,8 @@ top: if (e.button.button == 1) { SDL_CaptureMouse(0); } lua_pushstring(L, "mousereleased"); lua_pushstring(L, button_name(e.button.button)); - lua_pushinteger(L, e.button.x * window_renderer.scale_x); - lua_pushinteger(L, e.button.y * window_renderer.scale_y); + lua_pushinteger(L, e.button.x * window_renderer->scale_x); + lua_pushinteger(L, e.button.y * window_renderer->scale_y); return 4; case SDL_MOUSEMOTION: @@ -305,10 +305,10 @@ top: e.motion.yrel += event_plus.motion.yrel; } lua_pushstring(L, "mousemoved"); - lua_pushinteger(L, e.motion.x * window_renderer.scale_x); - lua_pushinteger(L, e.motion.y * window_renderer.scale_y); - lua_pushinteger(L, e.motion.xrel * window_renderer.scale_x); - lua_pushinteger(L, e.motion.yrel * window_renderer.scale_y); + lua_pushinteger(L, e.motion.x * window_renderer->scale_x); + lua_pushinteger(L, e.motion.y * window_renderer->scale_y); + lua_pushinteger(L, e.motion.xrel * window_renderer->scale_x); + lua_pushinteger(L, e.motion.yrel * window_renderer->scale_y); return 5; case SDL_MOUSEWHEEL: @@ -324,7 +324,7 @@ top: return 3; case SDL_FINGERDOWN: - SDL_GetWindowSize(window_renderer.window, &w, &h); + SDL_GetWindowSize(window_renderer->window, &w, &h); lua_pushstring(L, "touchpressed"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -333,7 +333,7 @@ top: return 4; case SDL_FINGERUP: - SDL_GetWindowSize(window_renderer.window, &w, &h); + SDL_GetWindowSize(window_renderer->window, &w, &h); lua_pushstring(L, "touchreleased"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -349,7 +349,7 @@ top: e.tfinger.dx += event_plus.tfinger.dx; e.tfinger.dy += event_plus.tfinger.dy; } - SDL_GetWindowSize(window_renderer.window, &w, &h); + SDL_GetWindowSize(window_renderer->window, &w, &h); lua_pushstring(L, "touchmoved"); lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w)); @@ -363,7 +363,7 @@ top: #ifdef LITE_USE_SDL_RENDERER rencache_invalidate(); #else - SDL_UpdateWindowSurface(window_renderer.window); + SDL_UpdateWindowSurface(window_renderer->window); #endif lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground"); return 1; @@ -429,7 +429,7 @@ static int f_set_cursor(lua_State *L) { static int f_set_window_title(lua_State *L) { const char *title = luaL_checkstring(L, 1); - SDL_SetWindowTitle(window_renderer.window, title); + SDL_SetWindowTitle(window_renderer->window, title); return 0; } @@ -439,39 +439,39 @@ enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN }; static int f_set_window_mode(lua_State *L) { int n = luaL_checkoption(L, 1, "normal", window_opts); - SDL_SetWindowFullscreen(window_renderer.window, + SDL_SetWindowFullscreen(window_renderer->window, n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer.window); } - if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window_renderer.window); } - if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window_renderer.window); } + if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer->window); } + if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window_renderer->window); } + if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window_renderer->window); } return 0; } static int f_set_window_bordered(lua_State *L) { int bordered = lua_toboolean(L, 1); - SDL_SetWindowBordered(window_renderer.window, bordered); + SDL_SetWindowBordered(window_renderer->window, bordered); return 0; } static int f_set_window_hit_test(lua_State *L) { if (lua_gettop(L) == 0) { - SDL_SetWindowHitTest(window_renderer.window, NULL, NULL); + SDL_SetWindowHitTest(window_renderer->window, NULL, NULL); return 0; } window_hit_info->title_height = luaL_checknumber(L, 1); window_hit_info->controls_width = luaL_checknumber(L, 2); window_hit_info->resize_border = luaL_checknumber(L, 3); - SDL_SetWindowHitTest(window_renderer.window, hit_test, window_hit_info); + SDL_SetWindowHitTest(window_renderer->window, hit_test, window_hit_info); return 0; } static int f_get_window_size(lua_State *L) { int x, y, w, h; - SDL_GetWindowSize(window_renderer.window, &w, &h); - SDL_GetWindowPosition(window_renderer.window, &x, &y); + SDL_GetWindowSize(window_renderer->window, &w, &h); + SDL_GetWindowPosition(window_renderer->window, &x, &y); lua_pushinteger(L, w); lua_pushinteger(L, h); lua_pushinteger(L, x); @@ -485,22 +485,22 @@ static int f_set_window_size(lua_State *L) { double h = luaL_checknumber(L, 2); double x = luaL_checknumber(L, 3); double y = luaL_checknumber(L, 4); - SDL_SetWindowSize(window_renderer.window, w, h); - SDL_SetWindowPosition(window_renderer.window, x, y); - ren_resize_window(&window_renderer); + SDL_SetWindowSize(window_renderer->window, w, h); + SDL_SetWindowPosition(window_renderer->window, x, y); + ren_resize_window(window_renderer); return 0; } static int f_window_has_focus(lua_State *L) { - unsigned flags = SDL_GetWindowFlags(window_renderer.window); + unsigned flags = SDL_GetWindowFlags(window_renderer->window); lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS); return 1; } static int f_get_window_mode(lua_State *L) { - unsigned flags = SDL_GetWindowFlags(window_renderer.window); + unsigned flags = SDL_GetWindowFlags(window_renderer->window); if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { lua_pushstring(L, "fullscreen"); } else if (flags & SDL_WINDOW_MINIMIZED) { @@ -538,8 +538,8 @@ static int f_raise_window(lua_State *L) { to allow the window to be focused. Also on wayland the raise window event may not always be obeyed. */ - SDL_SetWindowInputFocus(window_renderer.window); - SDL_RaiseWindow(window_renderer.window); + SDL_SetWindowInputFocus(window_renderer->window); + SDL_RaiseWindow(window_renderer->window); return 0; } @@ -916,7 +916,7 @@ static int f_fuzzy_match(lua_State *L) { static int f_set_window_opacity(lua_State *L) { double n = luaL_checknumber(L, 1); - int r = SDL_SetWindowOpacity(window_renderer.window, n); + int r = SDL_SetWindowOpacity(window_renderer->window, n); lua_pushboolean(L, r > -1); return 1; } diff --git a/src/main.c b/src/main.c index 252b0f45..104e5fe2 100644 --- a/src/main.c +++ b/src/main.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError()); exit(1); } - ren_init(window); + window_renderer = ren_init(window); lua_State *L; init_lua: @@ -264,7 +264,7 @@ init_lua: // This allows the window to be destroyed before lite-xl is done with // reaping child processes - ren_free_window_resources(&window_renderer); + ren_free(window_renderer); lua_close(L); return EXIT_SUCCESS; diff --git a/src/renderer.c b/src/renderer.c index cd5ec7ba..f1c5bb54 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -22,7 +22,7 @@ #define MAX_LOADABLE_GLYPHSETS (MAX_UNICODE / GLYPHSET_SIZE) #define SUBPIXEL_BITMAPS_CACHED 3 -RenWindow window_renderer = {0}; +RenWindow* window_renderer = NULL; static FT_Library library; // draw_rect_surface is used as a 1x1 surface to simplify ren_draw_rect with blending @@ -501,31 +501,35 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) { } /*************** Window Management ****************/ -void ren_free_window_resources(RenWindow *window_renderer) { +RenWindow* ren_init(SDL_Window *win) { + assert(win); + int error = FT_Init_FreeType( &library ); + if ( error ) { + fprintf(stderr, "internal font error when starting the application\n"); + return NULL; + } + RenWindow* window_renderer = malloc(sizeof(RenWindow)); + + window_renderer->window = win; + renwin_init_surface(window_renderer); + renwin_init_command_buf(window_renderer); + renwin_clip_to_surface(window_renderer); + draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32, + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + + return window_renderer; +} + +void ren_free(RenWindow* window_renderer) { + assert(window_renderer); renwin_free(window_renderer); SDL_FreeSurface(draw_rect_surface); free(window_renderer->command_buf); window_renderer->command_buf = NULL; window_renderer->command_buf_size = 0; + free(window_renderer); } -// TODO remove global and return RenWindow* -void ren_init(SDL_Window *win) { - assert(win); - int error = FT_Init_FreeType( &library ); - if ( error ) { - fprintf(stderr, "internal font error when starting the application\n"); - return; - } - window_renderer.window = win; - renwin_init_surface(&window_renderer); - renwin_init_command_buf(&window_renderer); - renwin_clip_to_surface(&window_renderer); - draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32, - 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); -} - - void ren_resize_window(RenWindow *window_renderer) { renwin_resize_surface(window_renderer); renwin_update_scale(window_renderer); diff --git a/src/renderer.h b/src/renderer.h index 1c865c8f..78811341 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -23,7 +23,7 @@ typedef struct { SDL_Surface *surface; int scale; } RenSurface; struct RenWindow; typedef struct RenWindow RenWindow; -extern RenWindow window_renderer; +extern RenWindow* window_renderer; RenFont* ren_font_load(RenWindow *window_renderer, const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style); RenFont* ren_font_copy(RenWindow *window_renderer, RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style); @@ -39,12 +39,12 @@ double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t le void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color); -void ren_init(SDL_Window *win); +RenWindow* ren_init(SDL_Window *win); +void ren_free(RenWindow* window_renderer); void ren_resize_window(RenWindow *window_renderer); void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count); void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect); void ren_get_size(RenWindow *window_renderer, int *x, int *y); /* Reports the size in points. */ -void ren_free_window_resources(RenWindow *window_renderer); #endif