Compare commits
30 Commits
amiga2.1
...
os4-1.16.1
Author | SHA1 | Date |
---|---|---|
George Sokianos | 79f0ac4f80 | |
George Sokianos | ce62b9c8da | |
George Sokianos | fb3d36da43 | |
George Sokianos | 94807d505c | |
George Sokianos | 44cd036b7a | |
George Sokianos | 3c7da82ad2 | |
George Sokianos | d30a9622a5 | |
George Sokianos | 2fdf19ec49 | |
George Sokianos | 9f656f8ab4 | |
George Sokianos | 32a3d4b933 | |
George Sokianos | c5309e04d6 | |
George Sokianos | 1c3f766e6b | |
George Sokianos | de6c0fd575 | |
George Sokianos | 7bd164b17e | |
George Sokianos | de3e4815ee | |
George Sokianos | b5d4f3f0f8 | |
George Sokianos | a788ac871b | |
George Sokianos | 1f27d6f923 | |
George Sokianos | 5af782b884 | |
George Sokianos | 95ece12d74 | |
George Sokianos | 03f2818657 | |
George Sokianos | 689901daca | |
George Sokianos | 4499f1f111 | |
George Sokianos | 14d813cea1 | |
George Sokianos | 2c711138d7 | |
George Sokianos | ff535843e8 | |
George Sokianos | fdd2f3af33 | |
George Sokianos | 7c85530e92 | |
George Sokianos | e13efe91b4 | |
George Sokianos | c155f797cf |
|
@ -7,3 +7,5 @@ build*
|
||||||
subprojects/lua
|
subprojects/lua
|
||||||
subprojects/libagg
|
subprojects/libagg
|
||||||
sybprojects/lua
|
sybprojects/lua
|
||||||
|
lite
|
||||||
|
.config/
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#
|
||||||
|
# Project: Lite XL
|
||||||
|
#
|
||||||
|
# Created on: 26-12-2021
|
||||||
|
#
|
||||||
|
.PHONY: build release
|
||||||
|
|
||||||
|
default: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
@sh os4build.sh
|
||||||
|
|
||||||
|
release:
|
||||||
|
mkdir -p release/LiteXL
|
||||||
|
cp release_files/* release/LiteXL/ -r
|
||||||
|
mv release/LiteXL/LiteXL.info release/
|
||||||
|
cp data release/LiteXL/ -r
|
||||||
|
cp doc release/LiteXL/ -r
|
||||||
|
cp lite release/LiteXL/
|
||||||
|
strip release/LiteXL/lite
|
||||||
|
cp README.md release/LiteXL/
|
||||||
|
cp README_OS4.md release/LiteXL/
|
||||||
|
cp LICENSE release/LiteXL/
|
||||||
|
lha -aeqr3 a LiteXL.lha release/
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Lite XL for AmigaOS 4.1 FE
|
||||||
|
|
||||||
|
Lite XL is coming to AmigaOS 4.1.
|
||||||
|
|
||||||
|
A few things are not quite working. Please have a look at the "Known issues"
|
||||||
|
section below.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
You can extract the Lite XL archive wherever you want and run the *lite*
|
||||||
|
editor.
|
||||||
|
|
||||||
|
## Configuration folder
|
||||||
|
This editor creates a `.config` folder where the configuration is saved, as
|
||||||
|
well as plugins, themes etc.. By default this AmigaOS 4.1 FE version uses the
|
||||||
|
executable folder, but if you want to ovveride it, create an ENV variable
|
||||||
|
named `HOME` and set there your path.
|
||||||
|
|
||||||
|
You can check if there is one already set by executing the following command
|
||||||
|
in a shell
|
||||||
|
```
|
||||||
|
GetEnv HOME
|
||||||
|
```
|
||||||
|
If there is one set, then you will see the path at the output.
|
||||||
|
|
||||||
|
Otherwise, you can set your home path be executing the following command.
|
||||||
|
Change the path to the one of your preference.
|
||||||
|
```
|
||||||
|
SetEnv SAVE HOME "Sys:home/"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Know issues
|
||||||
|
You can find the known issues at
|
||||||
|
https://git.walkero.gr/walkero/lite-xl/issues
|
||||||
|
|
||||||
|
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [1.16.12.7] - future
|
||||||
|
## Added
|
||||||
|
- Added config.scroll_past_end that when its true lets the user scroll
|
||||||
|
further than the end of the file. By default is set to true.
|
||||||
|
- Added "SDL_RENDERER_ACCELERATED" and "SDL_RENDERER_PRESENTVSYNC" on
|
||||||
|
SDL_CreateRenderer() since this reduces the CPU usage when the user
|
||||||
|
scrolls and seems to work pretty good on my systems (X5000, A1222 and
|
||||||
|
microAmigaOne). This is exeprimental. If this brings problems on your
|
||||||
|
system, you can disable them using SDL ENV variable, like below:
|
||||||
|
setenv SDL_RENDER_VSYNC 0
|
||||||
|
setenv SDL_RENDER_DRIVER "software"
|
||||||
|
|
||||||
|
## [1.16.12.6] - 2022-01-04
|
||||||
|
### Fixed
|
||||||
|
- Fixed a problem introduced in previous version when LiteXL was executed
|
||||||
|
from the root path of a partition or from ram disk (#13)
|
||||||
|
|
||||||
|
## [1.16.12.5] - 2022-01-03
|
||||||
|
### Changed
|
||||||
|
- Changed the Gfx memory leak solution to a fix that was applied by the
|
||||||
|
editor development team on Lua scripts at a later version. Less custom
|
||||||
|
code for AmigaOS 4 port.
|
||||||
|
- Now, when return from fullscreen, there is no extra header visible
|
||||||
|
at the top of the window content
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed the assertion error and crash when the window is resized (#2)
|
||||||
|
- Fixed the resolution on fullscreen toggle to be like the workbench (#4)
|
||||||
|
- Fixed loading the current folder from terminal using the dot, like
|
||||||
|
`lite .` or without it (#3)
|
||||||
|
|
||||||
|
## [1.16.12.4] - 2021-12-31
|
||||||
|
### Fixed
|
||||||
|
- Fixed the Gfx memory leak. Now LiteXL frees the reserved memory from the
|
||||||
|
gfx card.
|
||||||
|
|
||||||
|
## [1.16.12.3] - 2021-12-29
|
||||||
|
### Changed
|
||||||
|
- Compiled with an experimental version of the latest Anti-Grain Geometry
|
||||||
|
library. This is might have issues and crash LiteXL
|
||||||
|
|
||||||
|
## [1.16.12.2] - 2021-12-26
|
||||||
|
### Added
|
||||||
|
- Added Amiga version. This version of LiteXL is based on v1.16.12 source code
|
||||||
|
which will not change. I will use the fourth digit to distinguish different
|
||||||
|
AmigaOS 4 releases, until a new port of the latest available source (v2.x)
|
||||||
|
is made.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- The keyboard shortcuts are now working
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Now the `HOME` ENV variable is optional. If this is not set, the LiteXL
|
||||||
|
folder will be used to create user's `.config` folder
|
||||||
|
|
Binary file not shown.
|
@ -6,6 +6,7 @@ local LogView = require "core.logview"
|
||||||
|
|
||||||
|
|
||||||
local fullscreen = false
|
local fullscreen = false
|
||||||
|
local restore_title_view = false
|
||||||
|
|
||||||
local function suggest_directory(text)
|
local function suggest_directory(text)
|
||||||
text = common.home_expand(text)
|
text = common.home_expand(text)
|
||||||
|
@ -27,9 +28,12 @@ command.add(nil, {
|
||||||
|
|
||||||
["core:toggle-fullscreen"] = function()
|
["core:toggle-fullscreen"] = function()
|
||||||
fullscreen = not fullscreen
|
fullscreen = not fullscreen
|
||||||
|
if fullscreen then
|
||||||
|
restore_title_view = core.title_view.visible
|
||||||
|
end
|
||||||
system.set_window_mode(fullscreen and "fullscreen" or "normal")
|
system.set_window_mode(fullscreen and "fullscreen" or "normal")
|
||||||
core.show_title_bar(not fullscreen)
|
core.show_title_bar(not fullscreen and restore_title_view)
|
||||||
core.title_view:configure_hit_test(not fullscreen)
|
core.title_view:configure_hit_test(not fullscreen and restore_title_view)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["core:reload-module"] = function()
|
["core:reload-module"] = function()
|
||||||
|
|
|
@ -24,13 +24,16 @@ local function get_indent_string()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function doc_multiline_selection(sort)
|
local function doc_multiline_selections(sort)
|
||||||
local line1, col1, line2, col2, swap = doc():get_selection(sort)
|
local iter, state, idx, line1, col1, line2, col2 = doc():get_selections(sort)
|
||||||
if line2 > line1 and col2 == 1 then
|
return function()
|
||||||
line2 = line2 - 1
|
idx, line1, col1, line2, col2 = iter(state, idx)
|
||||||
col2 = #doc().lines[line2]
|
if idx and line2 > line1 and col2 == 1 then
|
||||||
|
line2 = line2 - 1
|
||||||
|
col2 = #doc().lines[line2]
|
||||||
|
end
|
||||||
|
return idx, line1, col1, line2, col2
|
||||||
end
|
end
|
||||||
return line1, col1, line2, col2, swap
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function append_line_if_last_line(line)
|
local function append_line_if_last_line(line)
|
||||||
|
@ -39,7 +42,6 @@ local function append_line_if_last_line(line)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function save(filename)
|
local function save(filename)
|
||||||
doc():save(filename and core.normalize_to_project_dir(filename))
|
doc():save(filename and core.normalize_to_project_dir(filename))
|
||||||
local saved_filename = doc().filename
|
local saved_filename = doc().filename
|
||||||
|
@ -47,55 +49,31 @@ local function save(filename)
|
||||||
core.log("Saved \"%s\"", saved_filename)
|
core.log("Saved \"%s\"", saved_filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- returns the size of the original indent, and the indent
|
local function cut_or_copy(delete)
|
||||||
-- in your config format, rounded either up or down
|
local full_text = ""
|
||||||
local function get_line_indent(line, rnd_up)
|
for idx, line1, col1, line2, col2 in doc():get_selections() do
|
||||||
local _, e = line:find("^[ \t]+")
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
local soft_tab = string.rep(" ", config.indent_size)
|
local text = doc():get_text(line1, col1, line2, col2)
|
||||||
if config.tab_type == "hard" then
|
if delete then
|
||||||
local indent = e and line:sub(1, e):gsub(soft_tab, "\t") or ""
|
doc():delete_to_cursor(idx, 0)
|
||||||
return e, indent:gsub(" +", rnd_up and "\t" or "")
|
end
|
||||||
else
|
full_text = full_text == "" and text or (full_text .. "\n" .. text)
|
||||||
local indent = e and line:sub(1, e):gsub("\t", soft_tab) or ""
|
doc().cursor_clipboard[idx] = text
|
||||||
local number = #indent / #soft_tab
|
else
|
||||||
return e, indent:sub(1,
|
doc().cursor_clipboard[idx] = ""
|
||||||
(rnd_up and math.ceil(number) or math.floor(number))*#soft_tab)
|
end
|
||||||
end
|
end
|
||||||
|
system.set_clipboard(full_text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- un/indents text; behaviour varies based on selection and un/indent.
|
local function split_cursor(direction)
|
||||||
-- * if there's a selection, it will stay static around the
|
local new_cursors = {}
|
||||||
-- text for both indenting and unindenting.
|
for _, line1, col1 in doc():get_selections() do
|
||||||
-- * if you are in the beginning whitespace of a line, and are indenting, the
|
if line1 + direction >= 1 and line1 + direction <= #doc().lines then
|
||||||
-- cursor will insert the exactly appropriate amount of spaces, and jump the
|
table.insert(new_cursors, { line1 + direction, col1 })
|
||||||
-- cursor to the beginning of first non whitespace characters
|
|
||||||
-- * if you are not in the beginning whitespace of a line, and you indent, it
|
|
||||||
-- inserts the appropriate whitespace, as if you typed them normally.
|
|
||||||
-- * if you are unindenting, the cursor will jump to the start of the line,
|
|
||||||
-- and remove the appropriate amount of spaces (or a tab).
|
|
||||||
local function indent_text(unindent)
|
|
||||||
local text = get_indent_string()
|
|
||||||
local line1, col1, line2, col2, swap = doc_multiline_selection(true)
|
|
||||||
local _, se = doc().lines[line1]:find("^[ \t]+")
|
|
||||||
local in_beginning_whitespace = col1 == 1 or (se and col1 <= se + 1)
|
|
||||||
if unindent or doc():has_selection() or in_beginning_whitespace then
|
|
||||||
local l1d, l2d = #doc().lines[line1], #doc().lines[line2]
|
|
||||||
for line = line1, line2 do
|
|
||||||
local e, rnded = get_line_indent(doc().lines[line], unindent)
|
|
||||||
doc():remove(line, 1, line, (e or 0) + 1)
|
|
||||||
doc():insert(line, 1,
|
|
||||||
unindent and rnded:sub(1, #rnded - #text) or rnded .. text)
|
|
||||||
end
|
end
|
||||||
l1d, l2d = #doc().lines[line1] - l1d, #doc().lines[line2] - l2d
|
|
||||||
if (unindent or in_beginning_whitespace) and not doc():has_selection() then
|
|
||||||
local start_cursor = (se and se + 1 or 1) + l1d or #(doc().lines[line1])
|
|
||||||
doc():set_selection(line1, start_cursor, line2, start_cursor, swap)
|
|
||||||
else
|
|
||||||
doc():set_selection(line1, col1 + l1d, line2, col2 + l2d, swap)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
doc():text_input(text)
|
|
||||||
end
|
end
|
||||||
|
for i,v in ipairs(new_cursors) do doc():add_selection(v[1], v[2]) end
|
||||||
end
|
end
|
||||||
|
|
||||||
local commands = {
|
local commands = {
|
||||||
|
@ -108,65 +86,66 @@ local commands = {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:cut"] = function()
|
["doc:cut"] = function()
|
||||||
if doc():has_selection() then
|
cut_or_copy(true)
|
||||||
local text = doc():get_text(doc():get_selection())
|
|
||||||
system.set_clipboard(text)
|
|
||||||
doc():delete_to(0)
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:copy"] = function()
|
["doc:copy"] = function()
|
||||||
if doc():has_selection() then
|
cut_or_copy(false)
|
||||||
local text = doc():get_text(doc():get_selection())
|
|
||||||
system.set_clipboard(text)
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:paste"] = function()
|
["doc:paste"] = function()
|
||||||
doc():text_input(system.get_clipboard():gsub("\r", ""))
|
for idx, line1, col1, line2, col2 in doc():get_selections() do
|
||||||
|
local value = doc().cursor_clipboard[idx] or system.get_clipboard()
|
||||||
|
doc():text_input(value:gsub("\r", ""), idx)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:newline"] = function()
|
["doc:newline"] = function()
|
||||||
local line, col = doc():get_selection()
|
for idx, line, col in doc():get_selections(false, true) do
|
||||||
local indent = doc().lines[line]:match("^[\t ]*")
|
local indent = doc().lines[line]:match("^[\t ]*")
|
||||||
if col <= #indent then
|
if col <= #indent then
|
||||||
indent = indent:sub(#indent + 2 - col)
|
indent = indent:sub(#indent + 2 - col)
|
||||||
|
end
|
||||||
|
doc():text_input("\n" .. indent, idx)
|
||||||
end
|
end
|
||||||
doc():text_input("\n" .. indent)
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:newline-below"] = function()
|
["doc:newline-below"] = function()
|
||||||
local line = doc():get_selection()
|
for idx, line in doc():get_selections(false, true) do
|
||||||
local indent = doc().lines[line]:match("^[\t ]*")
|
local indent = doc().lines[line]:match("^[\t ]*")
|
||||||
doc():insert(line, math.huge, "\n" .. indent)
|
doc():insert(line, math.huge, "\n" .. indent)
|
||||||
doc():set_selection(line + 1, math.huge)
|
doc():set_selections(idx, line + 1, math.huge)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:newline-above"] = function()
|
["doc:newline-above"] = function()
|
||||||
local line = doc():get_selection()
|
for idx, line in doc():get_selections(false, true) do
|
||||||
local indent = doc().lines[line]:match("^[\t ]*")
|
local indent = doc().lines[line]:match("^[\t ]*")
|
||||||
doc():insert(line, 1, indent .. "\n")
|
doc():insert(line, 1, indent .. "\n")
|
||||||
doc():set_selection(line, math.huge)
|
doc():set_selections(idx, line, math.huge)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:delete"] = function()
|
["doc:delete"] = function()
|
||||||
local line, col = doc():get_selection()
|
for idx, line1, col1, line2, col2 in doc():get_selections() do
|
||||||
if not doc():has_selection() and doc().lines[line]:find("^%s*$", col) then
|
if line1 == line2 and col1 == col2 and doc().lines[line1]:find("^%s*$", col1) then
|
||||||
doc():remove(line, col, line, math.huge)
|
doc():remove(line1, col1, line1, math.huge)
|
||||||
|
end
|
||||||
|
doc():delete_to_cursor(idx, translate.next_char)
|
||||||
end
|
end
|
||||||
doc():delete_to(translate.next_char)
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:backspace"] = function()
|
["doc:backspace"] = function()
|
||||||
local line, col = doc():get_selection()
|
for idx, line1, col1, line2, col2 in doc():get_selections() do
|
||||||
if not doc():has_selection() then
|
if line1 == line2 and col1 == col2 then
|
||||||
local text = doc():get_text(line, 1, line, col)
|
local text = doc():get_text(line1, 1, line1, col1)
|
||||||
if #text >= config.indent_size and text:find("^ *$") then
|
if #text >= config.indent_size and text:find("^ *$") then
|
||||||
doc():delete_to(0, -config.indent_size)
|
doc():delete_to_cursor(idx, 0, -config.indent_size)
|
||||||
return
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
doc():delete_to_cursor(idx, translate.previous_char)
|
||||||
end
|
end
|
||||||
doc():delete_to(translate.previous_char)
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:select-all"] = function()
|
["doc:select-all"] = function()
|
||||||
|
@ -177,77 +156,104 @@ local commands = {
|
||||||
local line, col = doc():get_selection()
|
local line, col = doc():get_selection()
|
||||||
doc():set_selection(line, col)
|
doc():set_selection(line, col)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
||||||
|
["doc:indent"] = function()
|
||||||
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
|
local l1, c1, l2, c2 = doc():indent_text(false, line1, col1, line2, col2)
|
||||||
|
if l1 then
|
||||||
|
doc():set_selections(idx, l1, c1, l2, c2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
["doc:select-lines"] = function()
|
["doc:select-lines"] = function()
|
||||||
local line1, _, line2, _, swap = doc():get_selection(true)
|
for idx, line1, _, line2 in doc():get_selections(true) do
|
||||||
append_line_if_last_line(line2)
|
append_line_if_last_line(line2)
|
||||||
doc():set_selection(line1, 1, line2 + 1, 1, swap)
|
doc():set_selections(idx, line1, 1, line2 + 1, 1, swap)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:select-word"] = function()
|
["doc:select-word"] = function()
|
||||||
local line1, col1 = doc():get_selection(true)
|
for idx, line1, col1 in doc():get_selections(true) do
|
||||||
local line1, col1 = translate.start_of_word(doc(), line1, col1)
|
local line1, col1 = translate.start_of_word(doc(), line1, col1)
|
||||||
local line2, col2 = translate.end_of_word(doc(), line1, col1)
|
local line2, col2 = translate.end_of_word(doc(), line1, col1)
|
||||||
doc():set_selection(line2, col2, line1, col1)
|
doc():set_selections(idx, line2, col2, line1, col1)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:join-lines"] = function()
|
["doc:join-lines"] = function()
|
||||||
local line1, _, line2 = doc():get_selection(true)
|
for idx, line1, col1, line2, col2 in doc():get_selections(true) do
|
||||||
if line1 == line2 then line2 = line2 + 1 end
|
if line1 == line2 then line2 = line2 + 1 end
|
||||||
local text = doc():get_text(line1, 1, line2, math.huge)
|
local text = doc():get_text(line1, 1, line2, math.huge)
|
||||||
text = text:gsub("(.-)\n[\t ]*", function(x)
|
text = text:gsub("(.-)\n[\t ]*", function(x)
|
||||||
return x:find("^%s*$") and x or x .. " "
|
return x:find("^%s*$") and x or x .. " "
|
||||||
end)
|
end)
|
||||||
doc():insert(line1, 1, text)
|
doc():insert(line1, 1, text)
|
||||||
doc():remove(line1, #text + 1, line2, math.huge)
|
doc():remove(line1, #text + 1, line2, math.huge)
|
||||||
if doc():has_selection() then
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
doc():set_selection(line1, math.huge)
|
doc():set_selections(idx, line1, math.huge)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:indent"] = function()
|
["doc:indent"] = function()
|
||||||
indent_text()
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
|
local l1, c1, l2, c2 = doc():indent_text(false, line1, col1, line2, col2)
|
||||||
|
if l1 then
|
||||||
|
doc():set_selections(idx, l1, c1, l2, c2)
|
||||||
|
end
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:unindent"] = function()
|
["doc:unindent"] = function()
|
||||||
indent_text(true)
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
|
local l1, c1, l2, c2 = doc():indent_text(true, line1, col1, line2, col2)
|
||||||
|
if l1 then
|
||||||
|
doc():set_selections(idx, l1, c1, l2, c2)
|
||||||
|
end
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:duplicate-lines"] = function()
|
["doc:duplicate-lines"] = function()
|
||||||
local line1, col1, line2, col2, swap = doc_multiline_selection(true)
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
append_line_if_last_line(line2)
|
append_line_if_last_line(line2)
|
||||||
local text = doc():get_text(line1, 1, line2 + 1, 1)
|
local text = doc():get_text(line1, 1, line2 + 1, 1)
|
||||||
doc():insert(line2 + 1, 1, text)
|
doc():insert(line2 + 1, 1, text)
|
||||||
local n = line2 - line1 + 1
|
local n = line2 - line1 + 1
|
||||||
doc():set_selection(line1 + n, col1, line2 + n, col2, swap)
|
doc():set_selections(idx, line1 + n, col1, line2 + n, col2, swap)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:delete-lines"] = function()
|
["doc:delete-lines"] = function()
|
||||||
local line1, col1, line2 = doc_multiline_selection(true)
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
append_line_if_last_line(line2)
|
append_line_if_last_line(line2)
|
||||||
doc():remove(line1, 1, line2 + 1, 1)
|
doc():remove(line1, 1, line2 + 1, 1)
|
||||||
doc():set_selection(line1, col1)
|
doc():set_selections(idx, line1, col1)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:move-lines-up"] = function()
|
["doc:move-lines-up"] = function()
|
||||||
local line1, col1, line2, col2, swap = doc_multiline_selection(true)
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
append_line_if_last_line(line2)
|
append_line_if_last_line(line2)
|
||||||
if line1 > 1 then
|
if line1 > 1 then
|
||||||
local text = doc().lines[line1 - 1]
|
local text = doc().lines[line1 - 1]
|
||||||
doc():insert(line2 + 1, 1, text)
|
doc():insert(line2 + 1, 1, text)
|
||||||
doc():remove(line1 - 1, 1, line1, 1)
|
doc():remove(line1 - 1, 1, line1, 1)
|
||||||
doc():set_selection(line1 - 1, col1, line2 - 1, col2, swap)
|
doc():set_selections(idx, line1 - 1, col1, line2 - 1, col2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:move-lines-down"] = function()
|
["doc:move-lines-down"] = function()
|
||||||
local line1, col1, line2, col2, swap = doc_multiline_selection(true)
|
for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do
|
||||||
append_line_if_last_line(line2 + 1)
|
append_line_if_last_line(line2 + 1)
|
||||||
if line2 < #doc().lines then
|
if line2 < #doc().lines then
|
||||||
local text = doc().lines[line2 + 1]
|
local text = doc().lines[line2 + 1]
|
||||||
doc():remove(line2 + 1, 1, line2 + 2, 1)
|
doc():remove(line2 + 1, 1, line2 + 2, 1)
|
||||||
doc():insert(line1, 1, text)
|
doc():insert(line1, 1, text)
|
||||||
doc():set_selection(line1 + 1, col1, line2 + 1, col2, swap)
|
doc():set_selections(idx, line1 + 1, col1, line2 + 1, col2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
@ -256,28 +262,29 @@ local commands = {
|
||||||
if not comment then return end
|
if not comment then return end
|
||||||
local indentation = get_indent_string()
|
local indentation = get_indent_string()
|
||||||
local comment_text = comment .. " "
|
local comment_text = comment .. " "
|
||||||
local line1, _, line2 = doc_multiline_selection(true)
|
for idx, line1, _, line2 in doc_multiline_selections(true) do
|
||||||
local uncomment = true
|
local uncomment = true
|
||||||
local start_offset = math.huge
|
local start_offset = math.huge
|
||||||
for line = line1, line2 do
|
for line = line1, line2 do
|
||||||
local text = doc().lines[line]
|
local text = doc().lines[line]
|
||||||
local s = text:find("%S")
|
local s = text:find("%S")
|
||||||
local cs, ce = text:find(comment_text, s, true)
|
|
||||||
if s and cs ~= s then
|
|
||||||
uncomment = false
|
|
||||||
start_offset = math.min(start_offset, s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for line = line1, line2 do
|
|
||||||
local text = doc().lines[line]
|
|
||||||
local s = text:find("%S")
|
|
||||||
if uncomment then
|
|
||||||
local cs, ce = text:find(comment_text, s, true)
|
local cs, ce = text:find(comment_text, s, true)
|
||||||
if ce then
|
if s and cs ~= s then
|
||||||
doc():remove(line, cs, line, ce + 1)
|
uncomment = false
|
||||||
|
start_offset = math.min(start_offset, s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for line = line1, line2 do
|
||||||
|
local text = doc().lines[line]
|
||||||
|
local s = text:find("%S")
|
||||||
|
if uncomment then
|
||||||
|
local cs, ce = text:find(comment_text, s, true)
|
||||||
|
if ce then
|
||||||
|
doc():remove(line, cs, line, ce + 1)
|
||||||
|
end
|
||||||
|
elseif s then
|
||||||
|
doc():insert(line, start_offset, comment_text)
|
||||||
end
|
end
|
||||||
elseif s then
|
|
||||||
doc():insert(line, start_offset, comment_text)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -363,6 +370,32 @@ local commands = {
|
||||||
end
|
end
|
||||||
end, common.path_suggest)
|
end, common.path_suggest)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
||||||
|
["file:delete"] = function()
|
||||||
|
local filename = doc().abs_filename
|
||||||
|
if not filename then
|
||||||
|
core.error("Cannot remove unsaved doc")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i,docview in ipairs(core.get_views_referencing_doc(doc())) do
|
||||||
|
local node = core.root_view.root_node:get_node_for_view(docview)
|
||||||
|
node:close_view(core.root_view, docview)
|
||||||
|
end
|
||||||
|
os.remove(filename)
|
||||||
|
core.log("Removed \"%s\"", filename)
|
||||||
|
end,
|
||||||
|
|
||||||
|
["doc:create-cursor-previous-line"] = function()
|
||||||
|
split_cursor(-1)
|
||||||
|
doc():merge_cursors()
|
||||||
|
end,
|
||||||
|
|
||||||
|
["doc:create-cursor-next-line"] = function()
|
||||||
|
split_cursor(1)
|
||||||
|
doc():merge_cursors()
|
||||||
|
end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,21 +425,21 @@ for name, fn in pairs(translations) do
|
||||||
end
|
end
|
||||||
|
|
||||||
commands["doc:move-to-previous-char"] = function()
|
commands["doc:move-to-previous-char"] = function()
|
||||||
if doc():has_selection() then
|
for idx, line1, col1, line2, col2 in doc():get_selections(true) do
|
||||||
local line, col = doc():get_selection(true)
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
doc():set_selection(line, col)
|
doc():set_selections(idx, line1, col1)
|
||||||
else
|
end
|
||||||
doc():move_to(translate.previous_char)
|
|
||||||
end
|
end
|
||||||
|
doc():move_to(translate.previous_char)
|
||||||
end
|
end
|
||||||
|
|
||||||
commands["doc:move-to-next-char"] = function()
|
commands["doc:move-to-next-char"] = function()
|
||||||
if doc():has_selection() then
|
for idx, line1, col1, line2, col2 in doc():get_selections(true) do
|
||||||
local _, _, line, col = doc():get_selection(true)
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
doc():set_selection(line, col)
|
doc():set_selections(idx, line2, col2)
|
||||||
else
|
end
|
||||||
doc():move_to(translate.next_char)
|
|
||||||
end
|
end
|
||||||
|
doc():move_to(translate.next_char)
|
||||||
end
|
end
|
||||||
|
|
||||||
command.add("core.docview", commands)
|
command.add("core.docview", commands)
|
||||||
|
|
|
@ -54,6 +54,26 @@ function common.color(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function common.splice(t, at, remove, insert)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function compare_score(a, b)
|
local function compare_score(a, b)
|
||||||
return a.score > b.score
|
return a.score > b.score
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ config.max_log_items = 80
|
||||||
config.message_timeout = 5
|
config.message_timeout = 5
|
||||||
config.mouse_wheel_scroll = 50 * SCALE
|
config.mouse_wheel_scroll = 50 * SCALE
|
||||||
config.file_size_limit = 10
|
config.file_size_limit = 10
|
||||||
|
config.scroll_past_end = true
|
||||||
config.ignore_files = "^%."
|
config.ignore_files = "^%."
|
||||||
config.symbol_pattern = "[%a_][%w_]*"
|
config.symbol_pattern = "[%a_][%w_]*"
|
||||||
config.non_word_chars = " \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
|
config.non_word_chars = " \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"
|
||||||
|
|
|
@ -16,26 +16,6 @@ local function split_lines(text)
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function splice(t, at, remove, insert)
|
|
||||||
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
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Doc:new(filename)
|
function Doc:new(filename)
|
||||||
self:reset()
|
self:reset()
|
||||||
if filename then
|
if filename then
|
||||||
|
@ -46,7 +26,8 @@ end
|
||||||
|
|
||||||
function Doc:reset()
|
function Doc:reset()
|
||||||
self.lines = { "\n" }
|
self.lines = { "\n" }
|
||||||
self.selection = { a = { line=1, col=1 }, b = { line=1, col=1 } }
|
self.selections = { 1, 1, 1, 1 }
|
||||||
|
self.cursor_clipboard = {}
|
||||||
self.undo_stack = { idx = 1 }
|
self.undo_stack = { idx = 1 }
|
||||||
self.redo_stack = { idx = 1 }
|
self.redo_stack = { idx = 1 }
|
||||||
self.clean_change_id = 1
|
self.clean_change_id = 1
|
||||||
|
@ -126,45 +107,87 @@ function Doc:get_change_id()
|
||||||
return self.undo_stack.idx
|
return self.undo_stack.idx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Cursor section. Cursor indices are *only* valid during a get_selections() call.
|
||||||
|
-- Cursors will always be iterated in order from top to bottom. Through normal operation
|
||||||
|
-- curors can never swap positions; only merge or split, or change their position in cursor
|
||||||
|
-- order.
|
||||||
|
function Doc:get_selection(sort)
|
||||||
|
local idx, line1, col1, line2, col2 = self:get_selections(sort)({ self.selections, sort }, 0)
|
||||||
|
return line1, col1, line2, col2, sort
|
||||||
|
end
|
||||||
|
|
||||||
function Doc:set_selection(line1, col1, line2, col2, swap)
|
function Doc:has_selection()
|
||||||
assert(not line2 == not col2, "expected 2 or 4 arguments")
|
local line1, col1, line2, col2 = self:get_selection(false)
|
||||||
|
return line1 ~= line2 or col1 ~= col2
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:sanitize_selection()
|
||||||
|
for idx, line1, col1, line2, col2 in self:get_selections() do
|
||||||
|
self:set_selections(idx, line1, col1, line2, col2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sort_positions(line1, col1, line2, col2)
|
||||||
|
if line1 > line2 or line1 == line2 and col1 > col2 then
|
||||||
|
return line2, col2, line1, col1
|
||||||
|
end
|
||||||
|
return line1, col1, line2, col2
|
||||||
|
end
|
||||||
|
|
||||||
|
function Doc:set_selections(idx, line1, col1, line2, col2, swap, rm)
|
||||||
|
assert(not line2 == not col2, "expected 3 or 5 arguments")
|
||||||
if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end
|
if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end
|
||||||
line1, col1 = self:sanitize_position(line1, col1)
|
line1, col1 = self:sanitize_position(line1, col1)
|
||||||
line2, col2 = self:sanitize_position(line2 or line1, col2 or col1)
|
line2, col2 = self:sanitize_position(line2 or line1, col2 or col1)
|
||||||
self.selection.a.line, self.selection.a.col = line1, col1
|
common.splice(self.selections, (idx - 1)*4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 })
|
||||||
self.selection.b.line, self.selection.b.col = line2, col2
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Doc:add_selection(line1, col1, line2, col2, swap)
|
||||||
local function sort_positions(line1, col1, line2, col2)
|
local l1, c1 = sort_positions(line1, col1, line2 or line1, col2 or col1)
|
||||||
if line1 > line2
|
local target = #self.selections / 4 + 1
|
||||||
or line1 == line2 and col1 > col2 then
|
for idx, tl1, tc1 in self:get_selections(true) do
|
||||||
return line2, col2, line1, col1, true
|
if l1 < tl1 or l1 == tl1 and c1 < tc1 then
|
||||||
|
target = idx
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return line1, col1, line2, col2, false
|
self:set_selections(target, line1, col1, line2, col2, swap, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Doc:set_selection(line1, col1, line2, col2, swap)
|
||||||
|
self.selections, self.cursor_clipboard = {}, {}
|
||||||
|
self:set_selections(1, line1, col1, line2, col2, swap)
|
||||||
|
end
|
||||||
|
|
||||||
function Doc:get_selection(sort)
|
function Doc:merge_cursors(idx)
|
||||||
local a, b = self.selection.a, self.selection.b
|
for i = (idx or (#self.selections - 3)), (idx or 5), -4 do
|
||||||
if sort then
|
for j = 1, i - 4, 4 do
|
||||||
return sort_positions(a.line, a.col, b.line, b.col)
|
if self.selections[i] == self.selections[j] and
|
||||||
|
self.selections[i+1] == self.selections[j+1] then
|
||||||
|
common.splice(self.selections, i, 4)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return a.line, a.col, b.line, b.col
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function selection_iterator(invariant, idx)
|
||||||
function Doc:has_selection()
|
local target = invariant[3] and (idx*4 - 7) or (idx*4 + 1)
|
||||||
local a, b = self.selection.a, self.selection.b
|
if target > #invariant[1] or target <= 0 or (type(invariant[3]) == "number" and invariant[3] ~= idx - 1) then return end
|
||||||
return not (a.line == b.line and a.col == b.col)
|
if invariant[2] then
|
||||||
|
return idx+(invariant[3] and -1 or 1), sort_positions(unpack(invariant[1], target, target+4))
|
||||||
|
else
|
||||||
|
return idx+(invariant[3] and -1 or 1), unpack(invariant[1], target, target+4)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- If idx_reverse is true, it'll reverse iterate. If nil, or false, regular iterate.
|
||||||
function Doc:sanitize_selection()
|
-- If a number, runs for exactly that iteration.
|
||||||
self:set_selection(self:get_selection())
|
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)
|
||||||
end
|
end
|
||||||
|
-- End of cursor seciton.
|
||||||
|
|
||||||
function Doc:sanitize_position(line, col)
|
function Doc:sanitize_position(line, col)
|
||||||
line = common.clamp(line, 1, #self.lines)
|
line = common.clamp(line, 1, #self.lines)
|
||||||
|
@ -251,14 +274,11 @@ local function pop_undo(self, undo_stack, redo_stack, modified)
|
||||||
if cmd.type == "insert" then
|
if cmd.type == "insert" then
|
||||||
local line, col, text = table.unpack(cmd)
|
local line, col, text = table.unpack(cmd)
|
||||||
self:raw_insert(line, col, text, redo_stack, cmd.time)
|
self:raw_insert(line, col, text, redo_stack, cmd.time)
|
||||||
|
|
||||||
elseif cmd.type == "remove" then
|
elseif cmd.type == "remove" then
|
||||||
local line1, col1, line2, col2 = table.unpack(cmd)
|
local line1, col1, line2, col2 = table.unpack(cmd)
|
||||||
self:raw_remove(line1, col1, line2, col2, redo_stack, cmd.time)
|
self:raw_remove(line1, col1, line2, col2, redo_stack, cmd.time)
|
||||||
|
|
||||||
elseif cmd.type == "selection" then
|
elseif cmd.type == "selection" then
|
||||||
self.selection.a.line, self.selection.a.col = cmd[1], cmd[2]
|
self.selections = { unpack(cmd) }
|
||||||
self.selection.b.line, self.selection.b.col = cmd[3], cmd[4]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
modified = modified or (cmd.type ~= "selection")
|
modified = modified or (cmd.type ~= "selection")
|
||||||
|
@ -288,11 +308,11 @@ function Doc:raw_insert(line, col, text, undo_stack, time)
|
||||||
lines[#lines] = lines[#lines] .. after
|
lines[#lines] = lines[#lines] .. after
|
||||||
|
|
||||||
-- splice lines into line array
|
-- splice lines into line array
|
||||||
splice(self.lines, line, 1, lines)
|
common.splice(self.lines, line, 1, lines)
|
||||||
|
|
||||||
-- push undo
|
-- push undo
|
||||||
local line2, col2 = self:position_offset(line, col, #text)
|
local line2, col2 = self:position_offset(line, col, #text)
|
||||||
push_undo(undo_stack, time, "selection", self:get_selection())
|
push_undo(undo_stack, time, "selection", unpack(self.selections))
|
||||||
push_undo(undo_stack, time, "remove", line, col, line2, col2)
|
push_undo(undo_stack, time, "remove", line, col, line2, col2)
|
||||||
|
|
||||||
-- update highlighter and assure selection is in bounds
|
-- update highlighter and assure selection is in bounds
|
||||||
|
@ -304,7 +324,7 @@ end
|
||||||
function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time)
|
function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time)
|
||||||
-- push undo
|
-- push undo
|
||||||
local text = self:get_text(line1, col1, line2, col2)
|
local text = self:get_text(line1, col1, line2, col2)
|
||||||
push_undo(undo_stack, time, "selection", self:get_selection())
|
push_undo(undo_stack, time, "selection", unpack(self.selections))
|
||||||
push_undo(undo_stack, time, "insert", line1, col1, text)
|
push_undo(undo_stack, time, "insert", line1, col1, text)
|
||||||
|
|
||||||
-- get line content before/after removed text
|
-- get line content before/after removed text
|
||||||
|
@ -312,7 +332,7 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time)
|
||||||
local after = self.lines[line2]:sub(col2)
|
local after = self.lines[line2]:sub(col2)
|
||||||
|
|
||||||
-- splice line into line array
|
-- splice line into line array
|
||||||
splice(self.lines, line1, line2 - line1 + 1, { before .. after })
|
common.splice(self.lines, line1, line2 - line1 + 1, { before .. after })
|
||||||
|
|
||||||
-- update highlighter and assure selection is in bounds
|
-- update highlighter and assure selection is in bounds
|
||||||
self.highlighter:invalidate(line1)
|
self.highlighter:invalidate(line1)
|
||||||
|
@ -348,22 +368,20 @@ function Doc:redo()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:text_input(text)
|
function Doc:text_input(text, idx)
|
||||||
if self:has_selection() then
|
for sidx, line1, col1, line2, col2 in self:get_selections(true, idx) do
|
||||||
self:delete_to()
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
|
self:delete_to_cursor(sidx)
|
||||||
|
end
|
||||||
|
self:insert(line1, col1, text)
|
||||||
|
self:move_to_cursor(sidx, #text)
|
||||||
end
|
end
|
||||||
local line, col = self:get_selection()
|
|
||||||
self:insert(line, col, text)
|
|
||||||
self:move_to(#text)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:replace(fn)
|
function Doc:replace(fn)
|
||||||
local line1, col1, line2, col2, swap
|
local line1, col1, line2, col2 = self:get_selection(true)
|
||||||
local had_selection = self:has_selection()
|
if line1 == line2 and col1 == col2 then
|
||||||
if had_selection then
|
|
||||||
line1, col1, line2, col2, swap = self:get_selection(true)
|
|
||||||
else
|
|
||||||
line1, col1, line2, col2 = 1, 1, #self.lines, #self.lines[#self.lines]
|
line1, col1, line2, col2 = 1, 1, #self.lines, #self.lines[#self.lines]
|
||||||
end
|
end
|
||||||
local old_text = self:get_text(line1, col1, line2, col2)
|
local old_text = self:get_text(line1, col1, line2, col2)
|
||||||
|
@ -371,38 +389,104 @@ function Doc:replace(fn)
|
||||||
if old_text ~= new_text then
|
if old_text ~= new_text then
|
||||||
self:insert(line2, col2, new_text)
|
self:insert(line2, col2, new_text)
|
||||||
self:remove(line1, col1, line2, col2)
|
self:remove(line1, col1, line2, col2)
|
||||||
if had_selection then
|
if line1 == line2 and col1 == col2 then
|
||||||
line2, col2 = self:position_offset(line1, col1, #new_text)
|
line2, col2 = self:position_offset(line1, col1, #new_text)
|
||||||
self:set_selection(line1, col1, line2, col2, swap)
|
self:set_selection(line1, col1, line2, col2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:delete_to(...)
|
function Doc:delete_to_cursor(idx, ...)
|
||||||
local line, col = self:get_selection(true)
|
for sidx, line1, col1, line2, col2 in self:get_selections(true, idx) do
|
||||||
if self:has_selection() then
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
self:remove(self:get_selection())
|
self:remove(line1, col1, line2, col2)
|
||||||
else
|
else
|
||||||
local line2, col2 = self:position_offset(line, col, ...)
|
local l2, c2 = self:position_offset(line1, col1, ...)
|
||||||
self:remove(line, col, line2, col2)
|
self:remove(line1, col1, l2, c2)
|
||||||
line, col = sort_positions(line, col, line2, col2)
|
line1, col1 = sort_positions(line1, col1, l2, c2)
|
||||||
|
end
|
||||||
|
self:set_selections(sidx, line1, col1)
|
||||||
end
|
end
|
||||||
self:set_selection(line, col)
|
self:merge_cursors(idx)
|
||||||
|
end
|
||||||
|
function Doc:delete_to(...) return self:delete_to_cursor(nil, ...) end
|
||||||
|
|
||||||
|
function Doc:move_to_cursor(idx, ...)
|
||||||
|
for sidx, line, col in self:get_selections(false, idx) do
|
||||||
|
self:set_selections(sidx, self:position_offset(line, col, ...))
|
||||||
|
end
|
||||||
|
self:merge_cursors(idx)
|
||||||
|
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
|
||||||
|
line, col = self:position_offset(line, col, ...)
|
||||||
|
self:set_selections(sidx, line, col, line2, col2)
|
||||||
|
end
|
||||||
|
self:merge_cursors(idx)
|
||||||
|
end
|
||||||
|
function Doc:select_to(...) return self:select_to_cursor(nil, ...) end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_indent_string()
|
||||||
|
if config.tab_type == "hard" then
|
||||||
|
return "\t"
|
||||||
|
end
|
||||||
|
return string.rep(" ", config.indent_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- returns the size of the original indent, and the indent
|
||||||
function Doc:move_to(...)
|
-- in your config format, rounded either up or down
|
||||||
local line, col = self:get_selection()
|
local function get_line_indent(line, rnd_up)
|
||||||
self:set_selection(self:position_offset(line, col, ...))
|
local _, e = line:find("^[ \t]+")
|
||||||
|
local soft_tab = string.rep(" ", config.indent_size)
|
||||||
|
if config.tab_type == "hard" then
|
||||||
|
local indent = e and line:sub(1, e):gsub(soft_tab, "\t") or ""
|
||||||
|
return e, indent:gsub(" +", rnd_up and "\t" or "")
|
||||||
|
else
|
||||||
|
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)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- un/indents text; behaviour varies based on selection and un/indent.
|
||||||
function Doc:select_to(...)
|
-- * if there's a selection, it will stay static around the
|
||||||
local line, col, line2, col2 = self:get_selection()
|
-- text for both indenting and unindenting.
|
||||||
line, col = self:position_offset(line, col, ...)
|
-- * if you are in the beginning whitespace of a line, and are indenting, the
|
||||||
self:set_selection(line, col, line2, col2)
|
-- cursor will insert the exactly appropriate amount of spaces, and jump the
|
||||||
|
-- cursor to the beginning of first non whitespace characters
|
||||||
|
-- * if you are not in the beginning whitespace of a line, and you indent, it
|
||||||
|
-- inserts the appropriate whitespace, as if you typed them normally.
|
||||||
|
-- * if you are unindenting, the cursor will jump to the start of the line,
|
||||||
|
-- and remove the appropriate amount of spaces (or a tab).
|
||||||
|
function Doc:indent_text(unindent, line1, col1, line2, col2)
|
||||||
|
local text = get_indent_string()
|
||||||
|
local _, se = self.lines[line1]:find("^[ \t]+")
|
||||||
|
local in_beginning_whitespace = col1 == 1 or (se and col1 <= se + 1)
|
||||||
|
local has_selection = line1 ~= line2 or col1 ~= col2
|
||||||
|
if unindent or has_selection or in_beginning_whitespace then
|
||||||
|
local l1d, l2d = #self.lines[line1], #self.lines[line2]
|
||||||
|
for line = line1, line2 do
|
||||||
|
local e, rnded = get_line_indent(self.lines[line], unindent)
|
||||||
|
self:remove(line, 1, line, (e or 0) + 1)
|
||||||
|
self:insert(line, 1,
|
||||||
|
unindent and rnded:sub(1, #rnded - #text) or rnded .. text)
|
||||||
|
end
|
||||||
|
l1d, l2d = #self.lines[line1] - l1d, #self.lines[line2] - l2d
|
||||||
|
if (unindent or in_beginning_whitespace) and not has_selection then
|
||||||
|
local start_cursor = (se and se + 1 or 1) + l1d or #(self.lines[line1])
|
||||||
|
return line1, start_cursor, line2, start_cursor
|
||||||
|
end
|
||||||
|
return line1, col1 + l1d, line2, col2 + l2d
|
||||||
|
end
|
||||||
|
self:insert(line1, col1, text)
|
||||||
|
return line1, col1 + #text, line1, col1 + #text
|
||||||
end
|
end
|
||||||
|
|
||||||
-- For plugins to add custom actions of document change
|
-- For plugins to add custom actions of document change
|
||||||
|
|
|
@ -96,7 +96,10 @@ function DocView:get_filename()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function DocView:get_scrollable_size()
|
function DocView:get_scrollable_size()
|
||||||
|
if not config.scroll_past_end then
|
||||||
|
return self:get_line_height() * (#self.doc.lines) + style.padding.y * 2
|
||||||
|
end
|
||||||
return self:get_line_height() * (#self.doc.lines - 1) + self.size.y
|
return self:get_line_height() * (#self.doc.lines - 1) + self.size.y
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -256,7 +259,11 @@ function DocView:on_mouse_pressed(button, x, y, clicks)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local line, col = self:resolve_screen_position(x, y)
|
local line, col = self:resolve_screen_position(x, y)
|
||||||
self.doc:set_selection(mouse_selection(self.doc, clicks, line, col, line, col))
|
if keymap.modkeys["ctrl"] then
|
||||||
|
self.doc:add_selection(mouse_selection(self.doc, clicks, line, col, line, col))
|
||||||
|
else
|
||||||
|
self.doc:set_selection(mouse_selection(self.doc, clicks, line, col, line, col))
|
||||||
|
end
|
||||||
self.mouse_selecting = { line, col, clicks = clicks }
|
self.mouse_selecting = { line, col, clicks = clicks }
|
||||||
end
|
end
|
||||||
core.blink_reset()
|
core.blink_reset()
|
||||||
|
@ -276,7 +283,15 @@ function DocView:on_mouse_moved(x, y, ...)
|
||||||
local l1, c1 = self:resolve_screen_position(x, y)
|
local l1, c1 = self:resolve_screen_position(x, y)
|
||||||
local l2, c2 = table.unpack(self.mouse_selecting)
|
local l2, c2 = table.unpack(self.mouse_selecting)
|
||||||
local clicks = self.mouse_selecting.clicks
|
local clicks = self.mouse_selecting.clicks
|
||||||
self.doc:set_selection(mouse_selection(self.doc, clicks, l1, c1, l2, c2))
|
if keymap.modkeys["ctrl"] then
|
||||||
|
if l1 > l2 then l1, l2 = l2, l1 end
|
||||||
|
self.doc.selections = { }
|
||||||
|
for i = l1, l2 do
|
||||||
|
self.doc:set_selections(i - l1 + 1, i, math.min(c1, #self.doc.lines[i]), i, math.min(c2, #self.doc.lines[i]))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.doc:set_selection(mouse_selection(self.doc, clicks, l1, c1, l2, c2))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -340,46 +355,50 @@ end
|
||||||
|
|
||||||
|
|
||||||
function DocView:draw_line_body(idx, x, y)
|
function DocView:draw_line_body(idx, x, y)
|
||||||
local line, col = self.doc:get_selection()
|
|
||||||
|
|
||||||
-- draw selection if it overlaps this line
|
-- draw selection if it overlaps this line
|
||||||
local line1, col1, line2, col2 = self.doc:get_selection(true)
|
for lidx, line1, col1, line2, col2 in self.doc:get_selections(true) do
|
||||||
if idx >= line1 and idx <= line2 then
|
if idx >= line1 and idx <= line2 then
|
||||||
local text = self.doc.lines[idx]
|
local text = self.doc.lines[idx]
|
||||||
if line1 ~= idx then col1 = 1 end
|
if line1 ~= idx then col1 = 1 end
|
||||||
if line2 ~= idx then col2 = #text + 1 end
|
if line2 ~= idx then col2 = #text + 1 end
|
||||||
local x1 = x + self:get_col_x_offset(idx, col1)
|
local x1 = x + self:get_col_x_offset(idx, col1)
|
||||||
local x2 = x + self:get_col_x_offset(idx, col2)
|
local x2 = x + self:get_col_x_offset(idx, col2)
|
||||||
local lh = self:get_line_height()
|
local lh = self:get_line_height()
|
||||||
renderer.draw_rect(x1, y, x2 - x1, lh, style.selection)
|
renderer.draw_rect(x1, y, x2 - x1, lh, style.selection)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
for lidx, line1, col1, line2, col2 in self.doc:get_selections(true) do
|
||||||
-- draw line highlight if caret is on this line
|
-- draw line highlight if caret is on this line
|
||||||
if config.highlight_current_line and not self.doc:has_selection()
|
if config.highlight_current_line and (line1 == line2 and col1 == col2)
|
||||||
and line == idx and core.active_view == self then
|
and line1 == idx and core.active_view == self then
|
||||||
self:draw_line_highlight(x + self.scroll.x, y)
|
self:draw_line_highlight(x + self.scroll.x, y)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw line's text
|
-- draw line's text
|
||||||
self:draw_line_text(idx, x, y)
|
self:draw_line_text(idx, x, y)
|
||||||
|
|
||||||
-- draw caret if it overlaps this line
|
-- draw caret if it overlaps this line
|
||||||
local T = config.blink_period
|
local T = config.blink_period
|
||||||
if line == idx and core.active_view == self
|
for _, line, col in self.doc:get_selections() do
|
||||||
and (core.blink_timer - core.blink_start) % T < T / 2
|
if line == idx and core.active_view == self
|
||||||
and system.window_has_focus() then
|
and (core.blink_timer - core.blink_start) % T < T / 2
|
||||||
local lh = self:get_line_height()
|
and system.window_has_focus() then
|
||||||
local x1 = x + self:get_col_x_offset(line, col)
|
local lh = self:get_line_height()
|
||||||
renderer.draw_rect(x1, y, style.caret_width, lh, style.caret)
|
local x1 = x + self:get_col_x_offset(line, col)
|
||||||
|
renderer.draw_rect(x1, y, style.caret_width, lh, style.caret)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function DocView:draw_line_gutter(idx, x, y)
|
function DocView:draw_line_gutter(idx, x, y)
|
||||||
local color = style.line_number
|
local color = style.line_number
|
||||||
local line1, _, line2, _ = self.doc:get_selection(true)
|
for _, line1, _, line2 in self.doc:get_selections(true) do
|
||||||
if idx >= line1 and idx <= line2 then
|
if idx >= line1 and idx <= line2 then
|
||||||
color = style.line_number2
|
color = style.line_number2
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local yoffset = self:get_line_text_y_offset()
|
local yoffset = self:get_line_text_y_offset()
|
||||||
x = x + style.padding.x
|
x = x + style.padding.x
|
||||||
|
|
|
@ -59,9 +59,9 @@ end
|
||||||
|
|
||||||
|
|
||||||
function core.reschedule_project_scan()
|
function core.reschedule_project_scan()
|
||||||
if core.project_scan_thread_id then
|
-- if core.project_scan_thread_id then
|
||||||
core.threads[core.project_scan_thread_id].wake = 0
|
-- core.threads[core.project_scan_thread_id].wake = 0
|
||||||
end
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -512,6 +512,7 @@ function core.init()
|
||||||
core.redraw = true
|
core.redraw = true
|
||||||
core.visited_files = {}
|
core.visited_files = {}
|
||||||
core.restart_request = false
|
core.restart_request = false
|
||||||
|
core.quite_request = false
|
||||||
core.replacements = whitespace_replacements()
|
core.replacements = whitespace_replacements()
|
||||||
|
|
||||||
core.root_view = RootView()
|
core.root_view = RootView()
|
||||||
|
@ -535,7 +536,7 @@ function core.init()
|
||||||
local plugins_success, plugins_refuse_list = core.load_plugins()
|
local plugins_success, plugins_refuse_list = core.load_plugins()
|
||||||
|
|
||||||
do
|
do
|
||||||
local pdir, pname = project_dir_abs:match("(.*)[/\\\\](.*)")
|
local pdir, pname = project_dir_abs:match("(.*)[:/\\\\](.*)")
|
||||||
core.log("Opening project %q from directory %s", pname, pdir)
|
core.log("Opening project %q from directory %s", pname, pdir)
|
||||||
end
|
end
|
||||||
local got_project_error = not core.load_project_module()
|
local got_project_error = not core.load_project_module()
|
||||||
|
@ -668,7 +669,8 @@ local function quit_with_function(quit_fn, force)
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.quit(force)
|
function core.quit(force)
|
||||||
quit_with_function(os.exit, force)
|
-- quit_with_function(os.exit, force)
|
||||||
|
quit_with_function(function() core.quit_request = true end, force)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1044,7 +1046,7 @@ function core.run()
|
||||||
core.frame_start = system.get_time()
|
core.frame_start = system.get_time()
|
||||||
local did_redraw = core.step()
|
local did_redraw = core.step()
|
||||||
local need_more_work = run_threads()
|
local need_more_work = run_threads()
|
||||||
if core.restart_request then break end
|
if core.restart_request or core.quit_request then break end
|
||||||
if not did_redraw and not need_more_work then
|
if not did_redraw and not need_more_work then
|
||||||
idle_iterations = idle_iterations + 1
|
idle_iterations = idle_iterations + 1
|
||||||
-- do not wait of events at idle_iterations = 1 to give a chance at core.step to run
|
-- do not wait of events at idle_iterations = 1 to give a chance at core.step to run
|
||||||
|
|
|
@ -101,6 +101,8 @@ local function keymap_macos(keymap)
|
||||||
["cmd+shift+end"] = "doc:select-to-end-of-doc",
|
["cmd+shift+end"] = "doc:select-to-end-of-doc",
|
||||||
["shift+pageup"] = "doc:select-to-previous-page",
|
["shift+pageup"] = "doc:select-to-previous-page",
|
||||||
["shift+pagedown"] = "doc:select-to-next-page",
|
["shift+pagedown"] = "doc:select-to-next-page",
|
||||||
|
["cmd+shift+up"] = "doc:create-cursor-previous-line",
|
||||||
|
["cmd+shift+down"] = "doc:create-cursor-next-line"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,12 @@ keymap.map = {}
|
||||||
keymap.reverse_map = {}
|
keymap.reverse_map = {}
|
||||||
|
|
||||||
local macos = rawget(_G, "MACOS_RESOURCES")
|
local macos = rawget(_G, "MACOS_RESOURCES")
|
||||||
|
local os4 = false
|
||||||
|
if PLATFORM == "AmigaOS 4" then
|
||||||
|
os4 = true
|
||||||
|
end
|
||||||
-- Thanks to mathewmariani, taken from his lite-macos github repository.
|
-- Thanks to mathewmariani, taken from his lite-macos github repository.
|
||||||
local modkeys_os = require("core.modkeys-" .. (macos and "macos" or "generic"))
|
local modkeys_os = require("core.modkeys-" .. (macos and "macos" or os4 and "os4" or "generic"))
|
||||||
local modkey_map = modkeys_os.map
|
local modkey_map = modkeys_os.map
|
||||||
local modkeys = modkeys_os.keys
|
local modkeys = modkeys_os.keys
|
||||||
|
|
||||||
|
@ -202,6 +205,8 @@ keymap.add_direct {
|
||||||
["ctrl+shift+end"] = "doc:select-to-end-of-doc",
|
["ctrl+shift+end"] = "doc:select-to-end-of-doc",
|
||||||
["shift+pageup"] = "doc:select-to-previous-page",
|
["shift+pageup"] = "doc:select-to-previous-page",
|
||||||
["shift+pagedown"] = "doc:select-to-next-page",
|
["shift+pagedown"] = "doc:select-to-next-page",
|
||||||
|
["ctrl+shift+up"] = "doc:create-cursor-previous-line",
|
||||||
|
["ctrl+shift+down"] = "doc:create-cursor-next-line"
|
||||||
}
|
}
|
||||||
|
|
||||||
return keymap
|
return keymap
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
local modkeys = {}
|
||||||
|
|
||||||
|
modkeys.map = {
|
||||||
|
["left amiga"] = "cmd",
|
||||||
|
["right amiga"] = "cmd",
|
||||||
|
["control"] = "ctrl",
|
||||||
|
["left shift"] = "shift",
|
||||||
|
["right shift"] = "shift",
|
||||||
|
["left alt"] = "alt",
|
||||||
|
["right alt"] = "altgr",
|
||||||
|
}
|
||||||
|
|
||||||
|
modkeys.keys = { "cmd", "ctrl", "alt", "altgr", "shift" }
|
||||||
|
|
||||||
|
return modkeys
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cxxcompiler="g++"
|
||||||
|
cxxflags="-Wall -O3 -g -std=c++03 -fno-exceptions -fno-rtti -Isrc -Ilib/font_renderer -DFONT_RENDERER_HEIGHT_HACK -lagg -lfreetype -I/sdk/local/common/include/agg"
|
||||||
|
|
||||||
|
echo "compiling font renderer library..."
|
||||||
|
|
||||||
|
g++ -c $cxxflags agg_font_freetype.cpp -o agg_font_freetype.o
|
||||||
|
g++ -c $cxxflags font_renderer.cpp -o font_renderer.o
|
||||||
|
|
||||||
|
ar -rcs libfontrenderer.a *.o
|
||||||
|
|
||||||
|
rm *.o
|
||||||
|
echo "font renderer library created"
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cflags="-D__USE_INLINE__ -DLITE_XL_DATA_USE_EXEDIR -DLITE_USE_SDL_RENDERER -Wall -O3 -std=gnu11 -fno-strict-aliasing -Isrc -Ilib/font_renderer -I/sdk/local/newlib/include/SDL2 -lSDL2 -llua -lauto"
|
||||||
|
#cflags+=" $(pkg-config --cflags lua5.2) $(sdl2-config --cflags)"
|
||||||
|
lflags="-mcrt=newlib -static-libgcc -static-libstdc++ -lSDL2 -lagg -lfreetype -llua -lm -lpthread -athread=native"
|
||||||
|
#for package in libagg freetype2 lua5.2; do
|
||||||
|
# lflags+=" $(pkg-config --libs $package)"
|
||||||
|
#done
|
||||||
|
#lflags+=" $(sdl2-config --libs) -lm"
|
||||||
|
|
||||||
|
#if [[ $* == *windows* ]]; then
|
||||||
|
# echo "cross compiling for windows is not yet supported"
|
||||||
|
# exit 1
|
||||||
|
#else
|
||||||
|
outfile="lite"
|
||||||
|
compiler="gcc"
|
||||||
|
cxxcompiler="g++"
|
||||||
|
#fi
|
||||||
|
|
||||||
|
#lib/font_renderer/build.sh || exit 1
|
||||||
|
#libs=libfontrenderer.a
|
||||||
|
libs="-lfontrenderer"
|
||||||
|
|
||||||
|
echo "compiling lite..."
|
||||||
|
|
||||||
|
gcc -c $cflags src/fontdesc.c -o fontdesc.o
|
||||||
|
gcc -c $cflags src/main.c -o main.o
|
||||||
|
gcc -c $cflags src/rencache.c -o rencache.o
|
||||||
|
gcc -c $cflags src/renderer.c -o renderer.o
|
||||||
|
gcc -c $cflags src/renwindow.c -o renwindow.o
|
||||||
|
|
||||||
|
gcc -c $cflags src/api/api.c -o api.o
|
||||||
|
gcc -c $cflags src/api/cp_replace.c -o cp_replace.o
|
||||||
|
gcc -c $cflags src/api/renderer.c -o apirenderer.o
|
||||||
|
gcc -c $cflags src/api/renderer_font.c -o renderer_font.o
|
||||||
|
gcc -c $cflags src/api/system.c -o system.o
|
||||||
|
|
||||||
|
gcc -c $cflags src/platform/amigaos4.c -o amigaos4.o
|
||||||
|
|
||||||
|
echo "linking..."
|
||||||
|
g++ -o $outfile *.o $libs $lflags
|
||||||
|
|
||||||
|
echo "cleaning up..."
|
||||||
|
rm *.o
|
||||||
|
echo "done"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -12,6 +12,10 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __amigaos4__
|
||||||
|
#include "platform/amigaos4.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern SDL_Window *window;
|
extern SDL_Window *window;
|
||||||
|
|
||||||
|
|
||||||
|
@ -287,7 +291,11 @@ static int f_set_window_mode(lua_State *L) {
|
||||||
int n = luaL_checkoption(L, 1, "normal", window_opts);
|
int n = luaL_checkoption(L, 1, "normal", window_opts);
|
||||||
SDL_SetWindowFullscreen(window,
|
SDL_SetWindowFullscreen(window,
|
||||||
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||||
if (n == WIN_NORMAL) { SDL_RestoreWindow(window); }
|
if (n == WIN_NORMAL)
|
||||||
|
{
|
||||||
|
ren_resize_window();
|
||||||
|
SDL_RestoreWindow(window);
|
||||||
|
}
|
||||||
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); }
|
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); }
|
||||||
if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window); }
|
if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window); }
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -423,6 +431,10 @@ static int f_list_dir(lua_State *L) {
|
||||||
#define realpath(x, y) _fullpath(y, x, MAX_PATH)
|
#define realpath(x, y) _fullpath(y, x, MAX_PATH)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __amigaos4__
|
||||||
|
#define realpath(x, y) _fullpath(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
static int f_absolute_path(lua_State *L) {
|
static int f_absolute_path(lua_State *L) {
|
||||||
const char *path = luaL_checkstring(L, 1);
|
const char *path = luaL_checkstring(L, 1);
|
||||||
char *res = realpath(path, NULL);
|
char *res = realpath(path, NULL);
|
||||||
|
|
15
src/main.c
15
src/main.c
|
@ -13,6 +13,8 @@
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/Xresource.h>
|
#include <X11/Xresource.h>
|
||||||
|
#elif __amigaos4__
|
||||||
|
#include "platform/amigaos4.h"
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,12 +72,13 @@ static void get_exe_filename(char *buf, int sz) {
|
||||||
char exepath[size];
|
char exepath[size];
|
||||||
_NSGetExecutablePath(exepath, &size);
|
_NSGetExecutablePath(exepath, &size);
|
||||||
realpath(exepath, buf);
|
realpath(exepath, buf);
|
||||||
|
#elif __amigaos4__
|
||||||
|
strcpy(buf, _fullpath("./lite"));
|
||||||
#else
|
#else
|
||||||
strcpy(buf, "./lite");
|
strcpy(buf, "./lite");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void init_window_icon(void) {
|
static void init_window_icon(void) {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include "../icon.inl"
|
#include "../icon.inl"
|
||||||
|
@ -132,6 +135,8 @@ int main(int argc, char **argv) {
|
||||||
window = SDL_CreateWindow(
|
window = SDL_CreateWindow(
|
||||||
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
|
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
|
||||||
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
|
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
|
||||||
|
SDL_SetWindowDisplayMode(window, &dm);
|
||||||
|
|
||||||
init_window_icon();
|
init_window_icon();
|
||||||
ren_init(window);
|
ren_init(window);
|
||||||
|
|
||||||
|
@ -154,7 +159,6 @@ init_lua:
|
||||||
|
|
||||||
lua_pushnumber(L, get_scale());
|
lua_pushnumber(L, get_scale());
|
||||||
lua_setglobal(L, "SCALE");
|
lua_setglobal(L, "SCALE");
|
||||||
|
|
||||||
char exename[2048];
|
char exename[2048];
|
||||||
get_exe_filename(exename, sizeof(exename));
|
get_exe_filename(exename, sizeof(exename));
|
||||||
lua_pushstring(L, exename);
|
lua_pushstring(L, exename);
|
||||||
|
@ -164,13 +168,15 @@ init_lua:
|
||||||
set_macos_bundle_resources(L);
|
set_macos_bundle_resources(L);
|
||||||
enable_momentum_scroll();
|
enable_momentum_scroll();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *init_lite_code = \
|
const char *init_lite_code = \
|
||||||
"local core\n"
|
"local core\n"
|
||||||
"xpcall(function()\n"
|
"xpcall(function()\n"
|
||||||
" HOME = os.getenv('" LITE_OS_HOME "')\n"
|
" HOME = os.getenv('" LITE_OS_HOME "')\n"
|
||||||
" local exedir = EXEFILE:match(\"^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$\")\n"
|
" local exedir = EXEFILE:match(\"^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$\")\n"
|
||||||
" local prefix = exedir:match(\"^(.*)" LITE_PATHSEP_PATTERN "bin$\")\n"
|
" local prefix = exedir:match(\"^(.*)" LITE_PATHSEP_PATTERN "bin$\")\n"
|
||||||
|
" if not HOME then\n"
|
||||||
|
" HOME = exedir\n"
|
||||||
|
" end\n"
|
||||||
" dofile((MACOS_RESOURCES or (prefix and prefix .. '/share/lite-xl' or exedir .. '/data')) .. '/core/start.lua')\n"
|
" dofile((MACOS_RESOURCES or (prefix and prefix .. '/share/lite-xl' or exedir .. '/data')) .. '/core/start.lua')\n"
|
||||||
" core = require('core')\n"
|
" core = require('core')\n"
|
||||||
" core.init()\n"
|
" core.init()\n"
|
||||||
|
@ -203,11 +209,12 @@ init_lua:
|
||||||
lua_pcall(L, 0, 1, 0);
|
lua_pcall(L, 0, 1, 0);
|
||||||
if (lua_toboolean(L, -1)) {
|
if (lua_toboolean(L, -1)) {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
|
rencache_invalidate();
|
||||||
goto init_lua;
|
goto init_lua;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
ren_free_window_resources();
|
ren_free_window_resources();
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "amigaos4.h"
|
||||||
|
|
||||||
|
static char *getFullPath(const char *path)
|
||||||
|
{
|
||||||
|
char *appPath = malloc(sizeof(char) * MAX_DOS_NAME);
|
||||||
|
BPTR pathLock = Lock(path, SHARED_LOCK);
|
||||||
|
if (pathLock)
|
||||||
|
{
|
||||||
|
NameFromLock(pathLock, appPath, sizeof(char) * MAX_DOS_NAME);
|
||||||
|
UnLock(pathLock);
|
||||||
|
|
||||||
|
return appPath;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *getCurrentPath(void)
|
||||||
|
{
|
||||||
|
char *appPath = malloc(sizeof(char) * MAX_DOS_NAME);
|
||||||
|
BPTR pathLock = GetCurrentDir();
|
||||||
|
if (pathLock)
|
||||||
|
{
|
||||||
|
NameFromLock(pathLock, appPath, sizeof(char) * MAX_DOS_NAME);
|
||||||
|
return appPath;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *_fullpath(const char *path)
|
||||||
|
{
|
||||||
|
static char prvPath[MAX_DOS_NAME];
|
||||||
|
static char result[MAX_DOS_NAME];
|
||||||
|
|
||||||
|
if (!strcmp(path, prvPath))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(prvPath, path);
|
||||||
|
|
||||||
|
if (!strcmp(path, "./lite"))
|
||||||
|
{
|
||||||
|
// TODO: Add code to get the name of the executable
|
||||||
|
strcpy(result, getFullPath("PROGDIR:lite"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(path, "."))
|
||||||
|
{
|
||||||
|
strcpy(result, getCurrentPath());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(result, getFullPath(path));
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef _AMIGAOS4_H
|
||||||
|
#define _AMIGAOS4_H
|
||||||
|
|
||||||
|
#include <proto/dos.h>
|
||||||
|
#include <proto/exec.h>
|
||||||
|
|
||||||
|
#define VSTRING "Lite XL 1.16.12.6 (04.01.2022)"
|
||||||
|
#define VERSTAG "\0$VER: " VSTRING
|
||||||
|
|
||||||
|
static CONST_STRPTR stack USED = "$STACK:102400";
|
||||||
|
static CONST_STRPTR version USED = VERSTAG;
|
||||||
|
|
||||||
|
char *_fullpath(const char *);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,6 +9,15 @@ static int query_surface_scale(RenWindow *ren) {
|
||||||
SDL_GetWindowSize(ren->window, &w_points, &h_points);
|
SDL_GetWindowSize(ren->window, &w_points, &h_points);
|
||||||
/* We consider that the ratio pixel/point will always be an integer and
|
/* We consider that the ratio pixel/point will always be an integer and
|
||||||
it is the same along the x and the y axis. */
|
it is the same along the x and the y axis. */
|
||||||
|
|
||||||
|
// This is a workaround when the w_pixels != w_points and h_pixels != h_points
|
||||||
|
// because of redraw delays, especially when the "Resize with contents" is enabled
|
||||||
|
if (w_pixels != w_points) {
|
||||||
|
w_pixels = w_points;
|
||||||
|
}
|
||||||
|
if (h_pixels != h_points) {
|
||||||
|
h_pixels = h_points;
|
||||||
|
}
|
||||||
assert(w_pixels % w_points == 0 && h_pixels % h_points == 0 && w_pixels / w_points == h_pixels / h_points);
|
assert(w_pixels % w_points == 0 && h_pixels % h_points == 0 && w_pixels / w_points == h_pixels / h_points);
|
||||||
return w_pixels / w_points;
|
return w_pixels / w_points;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +29,7 @@ static void setup_renderer(RenWindow *ren, int w, int h) {
|
||||||
SDL_DestroyTexture(ren->texture);
|
SDL_DestroyTexture(ren->texture);
|
||||||
SDL_DestroyRenderer(ren->renderer);
|
SDL_DestroyRenderer(ren->renderer);
|
||||||
}
|
}
|
||||||
ren->renderer = SDL_CreateRenderer(ren->window, -1, 0);
|
ren->renderer = SDL_CreateRenderer(ren->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||||
ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h);
|
ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h);
|
||||||
ren->surface_scale = query_surface_scale(ren);
|
ren->surface_scale = query_surface_scale(ren);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue