diff --git a/.gitignore b/.gitignore index 94ee9e64..834ccbfd 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,8 @@ subprojects/*/ *App* compile_commands.json error.txt -lite-xl +lite-xl* +LiteXL* .config/ *.lha *.o diff --git a/Makefile.mos b/Makefile.mos index 4b029cfc..d590be47 100644 --- a/Makefile.mos +++ b/Makefile.mos @@ -25,12 +25,12 @@ ifeq ($(UNAME), morphos) LFLAGS ?= -noixemul -lpcre2-8 -lSDL2 -llua54 -lagg -lfreetype -lm -lc \ -L/usr/local/lib DEL := delete ALL QUIET FORCE - LHA := lha -aeqr3 a + LHA := lha -aeqr3 a LiteXL2_MOS.lha release/ else INCPATH := -Isrc -I/gg/include/lua54 -I/gg/include/SDL2 LFLAGS ?= -noixemul -lpcre2-8 -lSDL2 -lGL -llua54 -lfreetype -lm DEL := rm -rf - LHA := lha aq + LHA := cd ./release && lha aq ../LiteXL2_MOS.lha ./* && cd .. endif ifeq ($(DEBUG),1) @@ -96,6 +96,6 @@ release: clean LiteXL @cp LICENSE release/LiteXL2/ @cp -r licenses release/LiteXL2/ @echo "Creating release archive..." - @$(LHA) LiteXL2_MOS.lha release/ + @$(LHA) @echo "Clean release files..." @$(DEL) release diff --git a/Makefile.os4 b/Makefile.os4 index 2f23e4b0..d3bdecce 100644 --- a/Makefile.os4 +++ b/Makefile.os4 @@ -19,11 +19,11 @@ STRIP := ppc-amigaos-strip ifeq ($(UNAME), AmigaOS) SDKPATH := /sdk DEL := delete ALL QUIET FORCE - LHA := lha -aeqr3 a + LHA := lha -aeqr3 a LiteXL2_OS4.lha release/ else SDKPATH := $(SDK_PATH) DEL := rm -rf - LHA := lha aq + LHA := cd ./release && lha aq ../LiteXL2_OS4.lha ./* && cd .. endif INCPATH := -Isrc -I$(SDKPATH)/local/newlib/include/SDL2 \ @@ -108,6 +108,6 @@ release: clean LiteXL @cp LICENSE release/LiteXL2/ @cp -r licenses release/LiteXL2/ @echo "Creating release archive..." - @$(LHA) LiteXL2_OS4.lha release/ + @$(LHA) @echo "Clean release files..." @$(DEL) release diff --git a/README_Amiga.md b/README_Amiga.md index 3bf04380..3f6e7806 100644 --- a/README_Amiga.md +++ b/README_Amiga.md @@ -229,6 +229,10 @@ You can find the known issues at https://git.walkero.gr/walkero/lite-xl/issues # Changelog +## [2.1.7r1] - 2024-12-26 +### Updated +- Updated the code to the upstream 2.1.7 release + ## [2.1.6r1] - 2024-12-3 ### Changed - Compiled with latest SDL v2.30.9 for the AmigaOS 4 diff --git a/changelog.md b/changelog.md index b1a93839..1d314d78 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,42 @@ # Changes Log +## [2.1.7] - 2024-12-05 + +This release fixes a bug related to scaling on macOS, +the comment line / block functionality and an issue with overscrolling +when the editor is too small. +The TreeView now allows creating directories when a trailing slash is added, +and the open file prompt now allows using both '/' and '\' as path separators. + +### Features + +* Allow `/` for path suggestions in Windows + ([#1875](https://github.com/lite-xl/lite-xl/pull/1875), + [#1976](https://github.com/lite-xl/lite-xl/pull/1976)) + +* Check item type before creating input text in treeview + ([#1904](https://github.com/lite-xl/lite-xl/pull/1904)) + +### Fixes + +* Return state when tokenizing plaintext syntaxes + +* Scale font pixel size in `RENDERER` mode + ([#1969](https://github.com/lite-xl/lite-xl/pull/1969)) + +* Prevent overscroll when DocView size is less than lh * 2 + ([#1971](https://github.com/lite-xl/lite-xl/pull/1971)) + +* Fix process:read_stdout() and process:read_stderr() not checking for process completion + ([#1973](https://github.com/lite-xl/lite-xl/pull/1973)) + +* Call poll_process when calling process:returncode() + ([#1981](https://github.com/lite-xl/lite-xl/pull/1981)) + +### Other Changes + +* Add winget releaser workflow + ## [2.1.6] - 2024-11-29 This release introduces a new icon for macOS, improves the performance of the renderer, @@ -1651,6 +1688,7 @@ A new global variable `USERDIR` is exposed to point to the user's directory. - subpixel font rendering with gamma correction +[2.1.7]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.7 [2.1.6]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.6 [2.1.5]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.5 [2.1.4]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.4 diff --git a/data/core/common.lua b/data/core/common.lua index 7763ddcb..d5df7e40 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -226,11 +226,17 @@ function common.path_suggest(text, root) if root and root:sub(-1) ~= PATHSEP then root = root .. PATHSEP end - local path, name + + local pathsep = PATHSEP + if PLATFORM == "Windows" then + pathsep = "\\/" + end + + local path if (PLATFORM == "AmigaOS 4" or PLATFORM == "MorphOS") then - path, name = text:match("^(.-)([^:"..PATHSEP.."]*)$") + path = text:match("^(.-)[^:"..PATHSEP.."]*$") else - path, name = text:match("^(.-)([^"..PATHSEP.."]*)$") + path = text:match("^(.-)[^"..pathsep.."]*$") end local clean_dotslash = false diff --git a/data/core/docview.lua b/data/core/docview.lua index 643af6be..6eb9ca06 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -259,7 +259,8 @@ function DocView:scroll_to_make_visible(line, col) local _, ly = self:get_line_screen_position(line, col) local lh = self:get_line_height() 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 overscroll = math.min(lh * 2, self.size.y) -- always show the previous / next line when possible + self.scroll.to.y = common.clamp(self.scroll.to.y, ly - oy - self.size.y + scroll_h + overscroll, 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(' ') diff --git a/data/core/start.lua b/data/core/start.lua index 32598f09..fd5d0b38 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -1,5 +1,5 @@ -- this file is used by lite-xl to setup the Lua environment when starting -VERSION = "2.1.6r1" +VERSION = "2.1.7r1" MOD_VERSION = "3" SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or 1 diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index a455184b..d78b2c57 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -135,12 +135,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 diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 5b047987..ff8983bb 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -676,7 +676,7 @@ command.add( local relfilename = item.filename if item.dir_name ~= core.project_dir then -- add secondary project dirs names to the file path to show - relfilename = common.basepath(common.basename(item.dir_name)) .. PATHSEP .. relfilename + relfilename = common.basepath(common.basename(item.dir_name)) .. relfilename end local file_info = system.get_file_info(filename) local file_type = file_info.type == "dir" and "Directory" or "File" @@ -746,7 +746,12 @@ command.add( ["treeview:new-file"] = function(item) local text if not is_project_folder(item.abs_filename) then - text = item.filename .. PATHSEP + if item.type == "dir" then + text = item.filename .. PATHSEP + elseif item.type == "file" then + local parent_dir = common.dirname(item.filename) + text = parent_dir and parent_dir .. PATHSEP + end end core.command_view:enter("Filename", { text = text, @@ -768,7 +773,12 @@ command.add( ["treeview:new-folder"] = function(item) local text if not is_project_folder(item.abs_filename) then - text = item.filename .. PATHSEP + if item.type == "dir" then + text = item.filename .. PATHSEP + elseif item.type == "file" then + local parent_dir = common.dirname(item.filename) + text = parent_dir and parent_dir .. PATHSEP + end end core.command_view:enter("Folder Name", { text = text, diff --git a/meson.build b/meson.build index 6af2af9d..71630f09 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('lite-xl', ['c'], - version : '2.1.6', + version : '2.1.7', license : 'MIT', meson_version : '>= 0.56', default_options : [ diff --git a/src/api/process.c b/src/api/process.c index 50fe6e22..c5cb80c9 100644 --- a/src/api/process.c +++ b/src/api/process.c @@ -615,7 +615,8 @@ static int g_read(lua_State* L, int stream, unsigned long read_size) { length = bytesTransferred; memset(&self->overlapped[writable_stream_idx], 0, sizeof(self->overlapped[writable_stream_idx])); } - } else { + } else if (GetLastError() != ERROR_HANDLE_EOF || !poll_process(self, WAIT_NONE)) { + // emulate POSIX behavior in the code below by returning empty string until process exits signal_process(self, SIGNAL_TERM); return 0; } @@ -696,7 +697,7 @@ static int f_pid(lua_State* L) { static int f_returncode(lua_State *L) { process_t* self = (process_t*) luaL_checkudata(L, 1, API_TYPE_PROCESS); - if (self->running) + if (poll_process(self, WAIT_NONE)) return 0; lua_pushinteger(L, self->returncode); return 1; diff --git a/src/arena_allocator.c b/src/arena_allocator.c new file mode 100644 index 00000000..a25d74ed --- /dev/null +++ b/src/arena_allocator.c @@ -0,0 +1,52 @@ +#include "arena_allocator.h" + +#include +#include + +struct lxl_arena { + lua_State *L; + int ref; +}; + +lxl_arena *lxl_arena_init(lua_State *L) { + lua_newtable(L); + lxl_arena *arena = lua_newuserdata(L, sizeof(lxl_arena)); + arena->L = L; arena->ref = lua_gettop(L)-1; + lua_rawseti(L, -2, 1); + return arena; +} + +void *lxl_arena_malloc(lxl_arena *arena, size_t size) { + if (!arena || !arena->L) return NULL; + if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference"); + void *data = lua_newuserdata(arena->L, size); + lua_pushlightuserdata(arena->L, data); + lua_pushvalue(arena->L, -2); + lua_settable(arena->L, arena->ref); + lua_pop(arena->L, 1); + return data; +} + +void *lxl_arena_zero(lxl_arena *arena, size_t size) { + void *v = lxl_arena_malloc(arena, size); + return v ? memset(v, 0, size) : NULL; +} + +char *lxl_arena_strdup(lxl_arena *arena, const char *str) { + if (!str) return NULL; + return lxl_arena_copy(arena, (void *) str, (strlen(str) + 1) * sizeof(char)); +} + +char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len) { + if (!ptr) return NULL; + char *output = lxl_arena_malloc(arena, sizeof(char) * len); + return output ? memcpy(output, ptr, len) : NULL; +} + +void lxl_arena_free(lxl_arena *arena, void *ptr) { + if (!arena || !arena->L || !ptr) return; + if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference"); + lua_pushlightuserdata(arena->L, ptr); + lua_pushnil(arena->L); + lua_settable(arena->L, arena->ref); +} \ No newline at end of file diff --git a/src/arena_allocator.h b/src/arena_allocator.h new file mode 100644 index 00000000..70665f70 --- /dev/null +++ b/src/arena_allocator.h @@ -0,0 +1,22 @@ +/** + * An arena allocator using the Lua state; similar to luaL_Buffer. + * Initialize the arena with lxl_arena_init(), and you can use lxl_arena_malloc(), + * lxl_arena_zero() to allocate (and optionally zero) the memory. + * lxl_arena_free() can be optionally used to free memory, but this is generally not needed. + */ + +#ifndef LUA_ALLOCATOR_H +#define LUA_ALLOCATOR_H + +#include + +typedef struct lxl_arena lxl_arena; + +lxl_arena *lxl_arena_init(lua_State *L); +void *lxl_arena_malloc(lxl_arena *arena, size_t size); +void *lxl_arena_zero(lxl_arena *arena, size_t size); +char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len); +char *lxl_arena_strdup(lxl_arena *arena, const char *str); +void lxl_arena_free(lxl_arena *arena, void *ptr); + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 28f34e28..b0dab84c 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,7 @@ #include #if defined(__amigaos4__) || defined(__morphos__) -#define VSTRING "Lite XL 2.1.6r1 (03.12.2024)" +#define VSTRING "Lite XL 2.1.7r1 (26.12.2024)" #define VERSTAG "\0$VER: " VSTRING #endif diff --git a/src/renderer.c b/src/renderer.c index c7e63749..4acf2c13 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -394,7 +394,11 @@ static void font_file_close(FT_Stream stream) { static int font_set_face_metrics(RenFont *font, FT_Face face) { FT_Error err; - if ((err = FT_Set_Pixel_Sizes(face, 0, (int) font->size)) != 0) + float pixel_size = font->size; + #ifdef LITE_USE_SDL_RENDERER + pixel_size *= font->scale; + #endif + if ((err = FT_Set_Pixel_Sizes(face, 0, (int) pixel_size)) != 0) return err; font->face = face;