Compare commits

..

No commits in common. "amigaos4" and "v1.04" have entirely different histories.

40 changed files with 290 additions and 908 deletions

3
.github/FUNDING.yml vendored
View File

@ -1,3 +0,0 @@
# These are supported funding model platforms
github: rxi

5
.gitignore vendored
View File

@ -1,5 +0,0 @@
src/*.o
src/*/*.o
src/*/*/*.o
lite
*.txt

105
Makefile
View File

@ -1,105 +0,0 @@
#
# Makefile generated by:
# codebench 0.55
#
# Project: lite
#
# Created on: 15-12-2021 22:58:23
#
#
###################################################################
##
##//// Objects
##
###################################################################
lite_OBJ := \
src/lib/stb/stb_truetype.o src/api/renderer.o src/api/renderer_font.o \
src/api/system.o src/main.o src/api/api.o \
src/rencache.o src/renderer.o
###################################################################
##
##//// Variables and Environment
##
###################################################################
CC := gcc:bin/gcc
INCPATH := -I. -Isrc
CFLAGS := $(INCPATH) -D__USE_INLINE__ -Wall -Werror -Wwrite-strings
###################################################################
##
##//// General rules
##
###################################################################
.PHONY: all all-before all-after clean clean-custom realclean
all: all-before lite all-after
all-before:
# You can add rules here to execute before the project is built
all-after:
# You can add rules here to execute after the project is built
clean: clean-custom
@echo "Cleaning compiler objects..."
@rm -f $(lite_OBJ)
realclean:
@echo "Cleaning compiler objects and targets..."
@rm -f $(lite_OBJ) lite
###################################################################
##
##//// Targets
##
###################################################################
lite: $(lite_OBJ)
@echo "Linking lite"
@gcc:bin/gcc -o lite $(lite_OBJ) -llua -lSDL2 -lpthread -lauto
@echo "Removing stale debug target: lite"
@rm -f lite.debug
###################################################################
##
##//// Standard rules
##
###################################################################
# A default rule to make all the objects listed below
# because we are hiding compiler commands from the output
.c.o:
@echo "Compiling $<"
@$(CC) -c $< -o $*.o $(CFLAGS)
src/api/api.o: src/api/api.c
src/api/renderer.o: src/api/renderer.c src/api/api.h src/renderer.h \
src/api/renderer_font.o: src/api/renderer_font.c src/api/api.h src/renderer.h \
src/api/system.o: src/api/system.c src/api/api.h
src/main.o: src/main.c src/api/api.h src/renderer.h \
src/rencache.o: src/rencache.c
src/renderer.o: src/renderer.c src/lib/stb/stb_truetype.h
src/lib/stb/stb_truetype.o: src/lib/stb/stb_truetype.c

View File

@ -5,7 +5,6 @@ A lightweight text editor written in Lua
* **[Get lite](https://github.com/rxi/lite/releases/latest)** — Download * **[Get lite](https://github.com/rxi/lite/releases/latest)** — Download
for Windows and Linux for Windows and Linux
* **[Get started](doc/usage.md)** — A quick overview on how to get started
* **[Get plugins](https://github.com/rxi/lite-plugins)** — Add additional * **[Get plugins](https://github.com/rxi/lite-plugins)** — Add additional
functionality functionality
* **[Get color themes](https://github.com/rxi/lite-colors)** — Add additional colors * **[Get color themes](https://github.com/rxi/lite-colors)** — Add additional colors
@ -24,10 +23,9 @@ The editor can be customized by making changes to the
[user module](data/user/init.lua). [user module](data/user/init.lua).
## Building ## Building
You can build the project yourself on Linux using the `build.sh` script You can build the project yourself on Linux using the provided `build.sh`
or on Windows using the `build.bat` script *([MinGW](https://nuwen.net/mingw.html) is required)*. script. Note that the project does not need to be rebuilt if you are only making
Note that the project does not need to be rebuilt if you are only making changes changes to the Lua portion of the code.
to the Lua portion of the code.
## Contributing ## Contributing
Any additional functionality that can be added through a plugin should be done Any additional functionality that can be added through a plugin should be done

View File

@ -1,16 +0,0 @@
@echo off
rem download this:
rem https://nuwen.net/mingw.html
echo compiling (windows)...
windres res.rc -O coff -o res.res
gcc src/*.c src/api/*.c src/lib/lua52/*.c src/lib/stb/*.c^
-O3 -s -std=gnu11 -fno-strict-aliasing -Isrc -DLUA_USE_POPEN^
-Iwinlib/SDL2-2.0.10/x86_64-w64-mingw32/include^
-lmingw32 -lm -lSDL2main -lSDL2 -Lwinlib/SDL2-2.0.10/x86_64-w64-mingw32/lib^
-mwindows res.res^
-o lite.exe
echo done

View File

@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
cflags="-Wall -O3 -g -std=gnu11 -fno-strict-aliasing -Isrc" cflags="-Wall -O3 -g -std=gnu11 -Isrc -DLUA_USE_POPEN"
lflags="-lSDL2 -lm" lflags="-lSDL2 -lm"
if [[ $* == *windows* ]]; then if [[ $* == *windows* ]]; then
platform="windows" platform="windows"
outfile="lite.exe" outfile="lite.exe"
compiler="x86_64-w64-mingw32-gcc" compiler="x86_64-w64-mingw32-gcc"
cflags="$cflags -DLUA_USE_POPEN -Iwinlib/SDL2-2.0.10/x86_64-w64-mingw32/include" cflags="$cflags -Iwinlib/SDL2-2.0.10/x86_64-w64-mingw32/include"
lflags="$lflags -Lwinlib/SDL2-2.0.10/x86_64-w64-mingw32/lib" lflags="$lflags -Lwinlib/SDL2-2.0.10/x86_64-w64-mingw32/lib"
lflags="-lmingw32 -lSDL2main $lflags -mwindows -o $outfile res.res" lflags="-lmingw32 -lSDL2main $lflags -mwindows -o $outfile res.res"
x86_64-w64-mingw32-windres res.rc -O coff -o res.res x86_64-w64-mingw32-windres res.rc -O coff -o res.res
@ -15,7 +15,6 @@ else
platform="unix" platform="unix"
outfile="lite" outfile="lite"
compiler="gcc" compiler="gcc"
cflags="$cflags -DLUA_USE_POSIX"
lflags="$lflags -o $outfile" lflags="$lflags -o $outfile"
fi fi

View File

@ -35,7 +35,7 @@ command.add(nil, {
end) end)
end, end,
["core:find-command"] = function() ["core:command-finder"] = function()
local commands = command.get_all_valid() local commands = command.get_all_valid()
core.command_view:enter("Do Command", function(text, item) core.command_view:enter("Do Command", function(text, item)
if item then if item then
@ -54,15 +54,15 @@ command.add(nil, {
end) end)
end, end,
["core:find-file"] = function() ["core:file-finder"] = function()
core.command_view:enter("Open File From Project", function(text, item) core.command_view:enter("Open File From Project", function(text, item)
text = item and item.text or text text = core.project_dir .. PATHSEP .. (item and item.text or text)
core.root_view:open_doc(core.open_doc(text)) core.root_view:open_doc(core.open_doc(text))
end, function(text) end, function(text)
local files = {} local files = {}
for _, item in pairs(core.project_files) do for _, item in pairs(core.project_files) do
if item.type == "file" then if item.type == "file" then
table.insert(files, item.filename) table.insert(files, item.filename:sub(#core.project_dir + 2))
end end
end end
return common.fuzzy_match(files, text) return common.fuzzy_match(files, text)
@ -89,7 +89,7 @@ command.add(nil, {
end, end,
["core:open-project-module"] = function() ["core:open-project-module"] = function()
local filename = ".lite_project.lua" local filename = core.project_dir .. "/.lite_project.lua"
if system.get_file_info(filename) then if system.get_file_info(filename) then
core.root_view:open_doc(core.open_doc(filename)) core.root_view:open_doc(core.open_doc(filename))
else else

View File

@ -160,9 +160,7 @@ local commands = {
local line1, _, line2 = doc():get_selection(true) local line1, _, line2 = doc():get_selection(true)
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 ]*", " ")
return x:find("^%s*$") and x or x .. " "
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 doc():has_selection() then
@ -322,10 +320,10 @@ local commands = {
local translations = { local translations = {
["previous-char"] = translate.previous_char, ["previous-char"] = translate.previous_char,
["next-char"] = translate.next_char, ["next-char"] = translate.next_char,
["previous-word-start"] = translate.previous_word_start, ["previous-word-boundary"] = translate.previous_word_boundary,
["next-word-end"] = translate.next_word_end, ["next-word-boundary"] = translate.next_word_boundary,
["previous-block-start"] = translate.previous_block_start, ["previous-start-of-block"] = translate.previous_start_of_block,
["next-block-end"] = translate.next_block_end, ["next-start-of-block"] = translate.next_start_of_block,
["start-of-doc"] = translate.start_of_doc, ["start-of-doc"] = translate.start_of_doc,
["end-of-doc"] = translate.end_of_doc, ["end-of-doc"] = translate.end_of_doc,
["start-of-line"] = translate.start_of_line, ["start-of-line"] = translate.start_of_line,

View File

@ -45,24 +45,23 @@ local function find(label, search_fn)
else else
core.error("Couldn't find %q", text) core.error("Couldn't find %q", text)
dv.doc:set_selection(table.unpack(sel)) dv.doc:set_selection(table.unpack(sel))
dv:scroll_to_make_visible(sel[1], sel[2])
end end
end, function(text) end, function(text)
local ok, line1, col1, line2, col2 = pcall(search_fn, dv.doc, sel[1], sel[2], text) local ok, line1, col1, line2, col2 = pcall(search_fn, dv.doc, sel[1], sel[2], text)
if ok and line1 and text ~= "" then if text == "" then
dv.doc:set_selection(table.unpack(sel))
elseif ok and line1 then
dv.doc:set_selection(line2, col2, line1, col1) dv.doc:set_selection(line2, col2, line1, col1)
dv:scroll_to_line(line2, true) dv:scroll_to_line(line2, true)
found = true found = true
else else
dv.doc:set_selection(table.unpack(sel))
found = false found = false
end end
end, function(explicit) end, function(explicit)
if explicit then if explicit then
dv.doc:set_selection(table.unpack(sel)) dv.doc:set_selection(table.unpack(sel))
dv:scroll_to_make_visible(sel[1], sel[2])
end end
end) end)
end end

View File

@ -94,7 +94,7 @@ for _, dir in ipairs { "left", "right", "up", "down" } do
end end
local node = core.root_view.root_node:get_child_overlapping_point(x, y) local node = core.root_view.root_node:get_child_overlapping_point(x, y)
if not node:get_locked_size() then if not node:get_locked_size() then
core.set_active_view(node.active_view) core.active_view = node.active_view
end end
end end
end end

View File

@ -111,8 +111,9 @@ function CommandView:enter(text, submit, suggest, cancel)
submit = submit or noop, submit = submit or noop,
suggest = suggest or noop, suggest = suggest or noop,
cancel = cancel or noop, cancel = cancel or noop,
view = core.active_view
} }
core.set_active_view(self) core.active_view = self
self:update_suggestions() self:update_suggestions()
self.gutter_text_brightness = 100 self.gutter_text_brightness = 100
self.label = text .. ": " self.label = text .. ": "
@ -121,7 +122,7 @@ end
function CommandView:exit(submitted, inexplicit) function CommandView:exit(submitted, inexplicit)
if core.active_view == self then if core.active_view == self then
core.set_active_view(core.last_active_view) core.active_view = self.state.view
end end
local cancel = self.state.cancel local cancel = self.state.cancel
self.state = default_state self.state = default_state

View File

@ -46,7 +46,7 @@ end
function Highlighter:invalidate(idx) function Highlighter:invalidate(idx)
self.first_invalid_line = math.min(self.first_invalid_line, idx) self.first_invalid_line = idx
self.max_wanted_line = math.min(self.max_wanted_line, #self.doc.lines) self.max_wanted_line = math.min(self.max_wanted_line, #self.doc.lines)
end end

View File

@ -56,8 +56,7 @@ end
function Doc:reset_syntax() function Doc:reset_syntax()
local header = self:get_text(1, 1, self:position_offset(1, 1, 128)) local syn = syntax.get(self.filename or "")
local syn = syntax.get(self.filename or "", header)
if self.syntax ~= syn then if self.syntax ~= syn then
self.syntax = syn self.syntax = syn
self.highlighter:reset() self.highlighter:reset()

View File

@ -28,32 +28,33 @@ function translate.next_char(doc, line, col)
end end
function translate.previous_word_start(doc, line, col) function translate.previous_word_boundary(doc, line, col)
local prev local char = doc:get_char(doc:position_offset(line, col, -1))
while line > 1 or col > 1 do local inword = not is_non_word(char)
local l, c = doc:position_offset(line, col, -1) repeat
local char = doc:get_char(l, c) local line2, col2 = line, col
if prev and prev ~= char or not is_non_word(char) then line, col = doc:position_offset(line, col, -1)
if line == line2 and col == col2 then
break break
end end
prev, line, col = char, l, c local c = doc:get_char(doc:position_offset(line, col, -1))
end until inword and is_non_word(c) or not inword and c ~= char
return translate.start_of_word(doc, line, col) return line, col
end end
function translate.next_word_end(doc, line, col) function translate.next_word_boundary(doc, line, col)
local prev
local end_line, end_col = translate.end_of_doc(doc, line, col)
while line < end_line or col < end_col do
local char = doc:get_char(line, col) local char = doc:get_char(line, col)
if prev and prev ~= char or not is_non_word(char) then local inword = not is_non_word(char)
repeat
local line2, col2 = line, col
line, col = doc:position_offset(line, col, 1)
if line == line2 and col == col2 then
break break
end end
line, col = doc:position_offset(line, col, 1) local c = doc:get_char(line, col)
prev = char until inword and is_non_word(c) or not inword and c ~= char
end return line, col
return translate.end_of_word(doc, line, col)
end end
@ -85,30 +86,30 @@ function translate.end_of_word(doc, line, col)
end end
function translate.previous_block_start(doc, line, col) function translate.previous_start_of_block(doc, line, col)
while true do while true do
line = line - 1 line = line - 1
if line <= 1 then if line <= 1 then
return 1, 1 return 1, 1
end end
if doc.lines[line-1]:find("^%s*$") if doc.lines[line-1]:match("^%s*$")
and not doc.lines[line]:find("^%s*$") then and not doc.lines[line]:match("^%s*$") then
return line, (doc.lines[line]:find("%S")) return line, (doc.lines[line]:find("%S"))
end end
end end
end end
function translate.next_block_end(doc, line, col) function translate.next_start_of_block(doc, line, col)
while true do while true do
line = line + 1
if line >= #doc.lines then if line >= #doc.lines then
return #doc.lines, 1 return #doc.lines, 1
end end
if doc.lines[line+1]:find("^%s*$") if doc.lines[line-1]:match("^%s*$")
and not doc.lines[line]:find("^%s*$") then and not doc.lines[line]:match("^%s*$") then
return line+1, #doc.lines[line+1] return line, (doc.lines[line]:find("%S"))
end end
line = line + 1
end end
end end

View File

@ -192,42 +192,28 @@ function DocView:scroll_to_make_visible(line, col)
end end
local function mouse_selection(doc, clicks, line1, col1, line2, col2)
local swap = line2 < line1 or line2 == line1 and col2 <= col1
if swap then
line1, col1, line2, col2 = line2, col2, line1, col1
end
if clicks == 2 then
line1, col1 = translate.start_of_word(doc, line1, col1)
line2, col2 = translate.end_of_word(doc, line2, col2)
elseif clicks == 3 then
if line2 == #doc.lines and doc.lines[#doc.lines] ~= "\n" then
doc:insert(math.huge, math.huge, "\n")
end
line1, col1, line2, col2 = line1, 1, line2 + 1, 1
end
if swap then
return line2, col2, line1, col1
end
return line1, col1, line2, col2
end
function DocView:on_mouse_pressed(button, x, y, clicks) function DocView:on_mouse_pressed(button, x, y, clicks)
local caught = DocView.super.on_mouse_pressed(self, button, x, y, clicks) local caught = DocView.super.on_mouse_pressed(self, button, x, y, clicks)
if caught then if caught then
return return
end end
if keymap.modkeys["shift"] then
if clicks == 1 then
local line1, col1 = select(3, self.doc:get_selection())
local line2, col2 = self:resolve_screen_position(x, y)
self.doc:set_selection(line2, col2, line1, col1)
end
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 clicks == 2 then
self.mouse_selecting = { line, col, clicks = clicks } local line1, col1 = translate.start_of_word(self.doc, line, col)
local line2, col2 = translate.end_of_word(self.doc, line, col)
self.doc:set_selection(line2, col2, line1, col1)
elseif clicks == 3 then
if line == #self.doc.lines then
self.doc:insert(math.huge, math.huge, "\n")
end
self.doc:set_selection(line + 1, 1, line, 1)
else
local line2, col2
if keymap.modkeys["shift"] then
line2, col2 = select(3, self.doc:get_selection())
end
self.doc:set_selection(line, col, line2, col2)
self.mouse_selecting = true
end end
self.blink_timer = 0 self.blink_timer = 0
end end
@ -243,17 +229,16 @@ function DocView:on_mouse_moved(x, y, ...)
end end
if self.mouse_selecting then if self.mouse_selecting then
local l1, c1 = self:resolve_screen_position(x, y) local _, _, line2, col2 = self.doc:get_selection()
local l2, c2 = table.unpack(self.mouse_selecting) local line1, col1 = self:resolve_screen_position(x, y)
local clicks = self.mouse_selecting.clicks self.doc:set_selection(line1, col1, line2, col2)
self.doc:set_selection(mouse_selection(self.doc, clicks, l1, c1, l2, c2))
end end
end end
function DocView:on_mouse_released(button) function DocView:on_mouse_released(button)
DocView.super.on_mouse_released(self, button) DocView.super.on_mouse_released(self, button)
self.mouse_selecting = nil self.mouse_selecting = false
end end

View File

@ -36,7 +36,7 @@ local function project_scan_thread()
for _, file in ipairs(all) do for _, file in ipairs(all) do
if not common.match_pattern(file, config.ignore_files) then if not common.match_pattern(file, config.ignore_files) then
local file = (path ~= "." and path .. PATHSEP or "") .. file local file = path .. PATHSEP .. file
local info = system.get_file_info(file) local info = system.get_file_info(file)
if info and info.size < size_limit then if info and info.size < size_limit then
info.filename = file info.filename = file
@ -62,7 +62,7 @@ local function project_scan_thread()
while true do while true do
-- get project files and replace previous table if the new table is -- get project files and replace previous table if the new table is
-- different -- different
local t = get_files(".") local t = get_files(core.project_dir)
if diff_files(core.project_files, t) then if diff_files(core.project_files, t) then
core.project_files = t core.project_files = t
core.redraw = true core.redraw = true
@ -82,26 +82,18 @@ function core.init()
CommandView = require "core.commandview" CommandView = require "core.commandview"
Doc = require "core.doc" Doc = require "core.doc"
local project_dir = EXEDIR
local files = {}
for i = 2, #ARGS do
local info = system.get_file_info(ARGS[i]) or {}
if info.type == "file" then
table.insert(files, system.absolute_path(ARGS[i]))
elseif info.type == "dir" then
project_dir = ARGS[i]
end
end
system.chdir(project_dir)
core.frame_start = 0 core.frame_start = 0
core.clip_rect_stack = {{ 0,0,0,0 }} core.clip_rect_stack = {{ 0,0,0,0 }}
core.log_items = {} core.log_items = {}
core.docs = {} core.docs = {}
core.threads = setmetatable({}, { __mode = "k" }) core.threads = setmetatable({}, { __mode = "k" })
core.project_files = {} core.project_files = {}
core.redraw = true core.project_dir = "."
local info = ARGS[2] and system.get_file_info(ARGS[2])
if info and info.type == "dir" then
core.project_dir = ARGS[2]:gsub("[\\/]$", "")
end
core.root_view = RootView() core.root_view = RootView()
core.command_view = CommandView() core.command_view = CommandView()
@ -109,6 +101,7 @@ function core.init()
core.root_view.root_node:split("down", core.command_view, true) core.root_view.root_node:split("down", core.command_view, true)
core.root_view.root_node.b:split("down", core.status_view, true) core.root_view.root_node.b:split("down", core.status_view, true)
core.active_view = core.root_view.root_node.a.active_view
core.add_thread(project_scan_thread) core.add_thread(project_scan_thread)
command.add_defaults() command.add_defaults()
@ -116,9 +109,13 @@ function core.init()
local got_user_error = not core.try(require, "user") local got_user_error = not core.try(require, "user")
local got_project_error = not core.load_project_module() local got_project_error = not core.load_project_module()
for _, filename in ipairs(files) do for i = 2, #ARGS do
local filename = ARGS[i]
local info = system.get_file_info(filename)
if info and info.type == "file" then
core.root_view:open_doc(core.open_doc(filename)) core.root_view:open_doc(core.open_doc(filename))
end end
end
if got_plugin_error or got_user_error or got_project_error then if got_plugin_error or got_user_error or got_project_error then
command.perform("core:open-log") command.perform("core:open-log")
@ -126,28 +123,8 @@ function core.init()
end end
local temp_uid = (system.get_time() * 1000) % 0xffffffff
local temp_file_prefix = string.format(".lite_temp_%08x", temp_uid)
local temp_file_counter = 0
local function delete_temp_files()
for _, filename in ipairs(system.list_dir(EXEDIR)) do
if filename:find(temp_file_prefix, 1, true) == 1 then
os.remove(EXEDIR .. PATHSEP .. filename)
end
end
end
function core.temp_filename(ext)
temp_file_counter = temp_file_counter + 1
return EXEDIR .. PATHSEP .. temp_file_prefix
.. string.format("%06x", temp_file_counter) .. (ext or "")
end
function core.quit(force) function core.quit(force)
if force then if force then
delete_temp_files()
os.exit() os.exit()
end end
local dirty_count = 0 local dirty_count = 0
@ -189,7 +166,7 @@ end
function core.load_project_module() function core.load_project_module()
local filename = ".lite_project.lua" local filename = core.project_dir .. "/.lite_project.lua"
if system.get_file_info(filename) then if system.get_file_info(filename) then
return core.try(function() return core.try(function()
local fn, err = loadfile(filename) local fn, err = loadfile(filename)
@ -213,15 +190,6 @@ function core.reload_module(name)
end end
function core.set_active_view(view)
assert(view, "Tried to set active view to nil")
if view ~= core.active_view then
core.last_active_view = core.active_view
core.active_view = view
end
end
function core.add_thread(f, weak_ref) function core.add_thread(f, weak_ref)
local key = weak_ref or #core.threads + 1 local key = weak_ref or #core.threads + 1
local fn = function() return core.try(f) end local fn = function() return core.try(f) end
@ -339,18 +307,12 @@ function core.on_event(type, ...)
elseif type == "mousewheel" then elseif type == "mousewheel" then
core.root_view:on_mouse_wheel(...) core.root_view:on_mouse_wheel(...)
elseif type == "filedropped" then elseif type == "filedropped" then
local filename, mx, my = ... local mx, my = core.root_view.mouse.x, core.root_view.mouse.y
local info = system.get_file_info(filename) local ok, doc = core.try(core.open_doc, select(1, ...))
if info and info.type == "dir" then
system.exec(string.format("%q %q", EXEFILE, filename))
else
local ok, doc = core.try(core.open_doc, filename)
if ok then if ok then
local node = core.root_view.root_node:get_child_overlapping_point(mx, my) core.root_view:on_mouse_pressed("left", mx, my, 1)
node:set_active_view(node.active_view)
core.root_view:open_doc(doc) core.root_view:open_doc(doc)
end end
end
elseif type == "quit" then elseif type == "quit" then
core.quit() core.quit()
end end
@ -386,7 +348,10 @@ function core.step()
-- update -- update
core.root_view.size.x, core.root_view.size.y = width, height core.root_view.size.x, core.root_view.size.y = width, height
core.root_view:update() core.root_view:update()
if not core.redraw then return false end if not core.redraw then
if not system.window_has_focus() then system.wait_event(0.5) end
return
end
core.redraw = false core.redraw = false
-- close unreferenced docs -- close unreferenced docs
@ -400,10 +365,10 @@ function core.step()
-- update window title -- update window title
local name = core.active_view:get_name() local name = core.active_view:get_name()
local title = (name ~= "---") and (name .. " - lite") or "lite" if name ~= "---" then
if title ~= core.window_title then system.set_window_title(name .. " - lite")
system.set_window_title(title) else
core.window_title = title system.set_window_title("lite")
end end
-- draw -- draw
@ -412,7 +377,6 @@ function core.step()
renderer.set_clip_rect(table.unpack(core.clip_rect_stack[1])) renderer.set_clip_rect(table.unpack(core.clip_rect_stack[1]))
core.root_view:draw() core.root_view:draw()
renderer.end_frame() renderer.end_frame()
return true
end end
@ -451,11 +415,8 @@ end)
function core.run() function core.run()
while true do while true do
core.frame_start = system.get_time() core.frame_start = system.get_time()
local did_redraw = core.step() core.step()
run_threads() run_threads()
if not did_redraw and not system.window_has_focus() then
system.wait_event(0.25)
end
local elapsed = system.get_time() - core.frame_start local elapsed = system.get_time() - core.frame_start
system.sleep(math.max(0, 1 / config.fps - elapsed)) system.sleep(math.max(0, 1 / config.fps - elapsed))
end end

View File

@ -84,8 +84,8 @@ end
keymap.add { keymap.add {
["ctrl+shift+p"] = "core:find-command", ["ctrl+shift+p"] = "core:command-finder",
["ctrl+p"] = "core:find-file", ["ctrl+p"] = "core:file-finder",
["ctrl+o"] = "core:open-file", ["ctrl+o"] = "core:open-file",
["ctrl+n"] = "core:new-doc", ["ctrl+n"] = "core:new-doc",
["alt+return"] = "core:toggle-fullscreen", ["alt+return"] = "core:toggle-fullscreen",
@ -132,14 +132,13 @@ keymap.add {
["shift+tab"] = "doc:unindent", ["shift+tab"] = "doc:unindent",
["backspace"] = "doc:backspace", ["backspace"] = "doc:backspace",
["shift+backspace"] = "doc:backspace", ["shift+backspace"] = "doc:backspace",
["ctrl+backspace"] = "doc:delete-to-previous-word-start", ["ctrl+backspace"] = "doc:delete-to-previous-word-boundary",
["ctrl+shift+backspace"] = "doc:delete-to-previous-word-start", ["ctrl+shift+backspace"] = "doc:delete-to-previous-word-boundary",
["delete"] = "doc:delete", ["delete"] = "doc:delete",
["shift+delete"] = "doc:delete", ["shift+delete"] = "doc:delete",
["ctrl+delete"] = "doc:delete-to-next-word-end", ["ctrl+delete"] = "doc:delete-to-next-word-boundary",
["ctrl+shift+delete"] = "doc:delete-to-next-word-end", ["ctrl+shift+delete"] = "doc:delete-to-next-word-boundary",
["return"] = { "command:submit", "doc:newline" }, ["return"] = { "command:submit", "doc:newline" },
["keypad enter"] = { "command:submit", "doc:newline" },
["ctrl+return"] = "doc:newline-below", ["ctrl+return"] = "doc:newline-below",
["ctrl+shift+return"] = "doc:newline-above", ["ctrl+shift+return"] = "doc:newline-above",
["ctrl+j"] = "doc:join-lines", ["ctrl+j"] = "doc:join-lines",
@ -156,10 +155,10 @@ keymap.add {
["right"] = "doc:move-to-next-char", ["right"] = "doc:move-to-next-char",
["up"] = { "command:select-previous", "doc:move-to-previous-line" }, ["up"] = { "command:select-previous", "doc:move-to-previous-line" },
["down"] = { "command:select-next", "doc:move-to-next-line" }, ["down"] = { "command:select-next", "doc:move-to-next-line" },
["ctrl+left"] = "doc:move-to-previous-word-start", ["ctrl+left"] = "doc:move-to-previous-word-boundary",
["ctrl+right"] = "doc:move-to-next-word-end", ["ctrl+right"] = "doc:move-to-next-word-boundary",
["ctrl+["] = "doc:move-to-previous-block-start", ["ctrl+["] = "doc:move-to-previous-start-of-block",
["ctrl+]"] = "doc:move-to-next-block-end", ["ctrl+]"] = "doc:move-to-next-start-of-block",
["home"] = "doc:move-to-start-of-line", ["home"] = "doc:move-to-start-of-line",
["end"] = "doc:move-to-end-of-line", ["end"] = "doc:move-to-end-of-line",
["ctrl+home"] = "doc:move-to-start-of-doc", ["ctrl+home"] = "doc:move-to-start-of-doc",
@ -171,10 +170,10 @@ keymap.add {
["shift+right"] = "doc:select-to-next-char", ["shift+right"] = "doc:select-to-next-char",
["shift+up"] = "doc:select-to-previous-line", ["shift+up"] = "doc:select-to-previous-line",
["shift+down"] = "doc:select-to-next-line", ["shift+down"] = "doc:select-to-next-line",
["ctrl+shift+left"] = "doc:select-to-previous-word-start", ["ctrl+shift+left"] = "doc:select-to-previous-word-boundary",
["ctrl+shift+right"] = "doc:select-to-next-word-end", ["ctrl+shift+right"] = "doc:select-to-next-word-boundary",
["ctrl+shift+["] = "doc:select-to-previous-block-start", ["ctrl+shift+["] = "doc:select-to-previous-start-of-block",
["ctrl+shift+]"] = "doc:select-to-next-block-end", ["ctrl+shift+]"] = "doc:select-to-next-start-of-block",
["shift+home"] = "doc:select-to-start-of-line", ["shift+home"] = "doc:select-to-start-of-line",
["shift+end"] = "doc:select-to-end-of-line", ["shift+end"] = "doc:select-to-end-of-line",
["ctrl+shift+home"] = "doc:select-to-start-of-doc", ["ctrl+shift+home"] = "doc:select-to-start-of-doc",

View File

@ -9,33 +9,22 @@ local DocView = require "core.docview"
local EmptyView = View:extend() local EmptyView = View:extend()
local function draw_text(x, y, color)
local th = style.big_font:get_height()
local dh = th + style.padding.y * 2
x = renderer.draw_text(style.big_font, "lite", x, y + (dh - th) / 2, color)
x = x + style.padding.x
renderer.draw_rect(x, y, math.ceil(1 * SCALE), dh, color)
local lines = {
{ fmt = "%s to run a command", cmd = "core:find-command" },
{ fmt = "%s to open a file from the project", cmd = "core:find-file" },
}
th = style.font:get_height()
y = y + (dh - th * 2 - style.padding.y) / 2
local w = 0
for _, line in ipairs(lines) do
local text = string.format(line.fmt, keymap.get_binding(line.cmd))
w = math.max(w, renderer.draw_text(style.font, text, x + style.padding.x, y, color))
y = y + th + style.padding.y
end
return w, dh
end
function EmptyView:draw() function EmptyView:draw()
self:draw_background(style.background) self:draw_background(style.background)
local w, h = draw_text(0, 0, { 0, 0, 0, 0 }) local pos = self.position
local x = self.position.x + math.max(style.padding.x, (self.size.x - w) / 2) local x, y, w, h = pos.x, pos.y, self.size.x, self.size.y
local y = self.position.y + (self.size.y - h) / 2 local _, y = common.draw_text(style.big_font, style.dim, "empty", "center", x, y, w, h)
draw_text(x, y, style.dim) local lines = {
{ fmt = "%s to run a command", cmd = "core:command-finder" },
{ fmt = "%s to open a file from the project", cmd = "core:file-finder" },
}
local th = style.font:get_height()
for _, line in ipairs(lines) do
local text = string.format(line.fmt, keymap.get_binding(line.cmd))
y = y + style.padding.y
common.draw_text(style.font, style.dim, text, "center", x, y, w, th)
y = y + th
end
end end
@ -88,18 +77,17 @@ end
local type_map = { up="vsplit", down="vsplit", left="hsplit", right="hsplit" } local type_map = { up="vsplit", down="vsplit", left="hsplit", right="hsplit" }
function Node:split(dir, view, locked) function Node:split(dir, view, locked)
assert(self.type == "leaf", "Tried to split non-leaf node") assert(self.type == "leaf", "tried to split non-leaf node")
local type = assert(type_map[dir], "Invalid direction") local type = assert(type_map[dir], "invalid direction")
local last_active = core.active_view
local child = Node() local child = Node()
child:consume(self) child:consume(self)
self:consume(Node(type)) self:consume(Node(type))
self.a = child self.a = child
self.b = Node() self.b = Node()
if view then self.b:add_view(view) end
if locked then
self.b.locked = locked self.b.locked = locked
core.set_active_view(last_active) if view then self.b:add_view(view) end
if not self.b.active_view.focusable then
self.a:set_active_view(self.a.active_view)
end end
if dir == "up" or dir == "left" then if dir == "up" or dir == "left" then
self.a, self.b = self.b, self.a self.a, self.b = self.b, self.a
@ -130,15 +118,13 @@ function Node:close_active_view(root)
p:set_active_view(p.active_view) p:set_active_view(p.active_view)
end end
end end
core.last_active_view = nil
end end
self.active_view:try_close(do_close) self.active_view:try_close(do_close)
end end
function Node:add_view(view) function Node:add_view(view)
assert(self.type == "leaf", "Tried to add view to non-leaf node") assert(self.type == "leaf", "tried to add view to non-leaf node")
assert(not self.locked, "Tried to add view to locked node")
if self.views[1] and self.views[1]:is(EmptyView) then if self.views[1] and self.views[1]:is(EmptyView) then
table.remove(self.views) table.remove(self.views)
end end
@ -148,9 +134,9 @@ end
function Node:set_active_view(view) function Node:set_active_view(view)
assert(self.type == "leaf", "Tried to set active view on non-leaf node") assert(self.type == "leaf", "tried to set active view on non-leaf node")
self.active_view = view self.active_view = view
core.set_active_view(view) core.active_view = view
end end
@ -349,9 +335,7 @@ function Node:draw_tabs()
color = style.text color = style.text
end end
core.push_clip_rect(x, y, w, h) core.push_clip_rect(x, y, w, h)
x, w = x + style.padding.x, w - style.padding.x * 2 common.draw_text(style.font, color, text, "center", x, y, w, h)
local align = style.font:get_width(text) > w and "left" or "center"
common.draw_text(style.font, color, text, align, x, y, w, h)
core.pop_clip_rect() core.pop_clip_rect()
end end
@ -393,16 +377,13 @@ end
function RootView:get_active_node() function RootView:get_active_node()
return self.root_node:get_node_for_view(core.active_view) local node = self.root_node:get_node_for_view(core.active_view)
return node or self.root_node.a
end end
function RootView:open_doc(doc) function RootView:open_doc(doc)
local node = self:get_active_node() local node = self:get_active_node()
if node.locked and core.last_active_view then
core.set_active_view(core.last_active_view)
node = self:get_active_node()
end
assert(not node.locked, "Cannot open doc on locked node") assert(not node.locked, "Cannot open doc on locked node")
for i, view in ipairs(node.views) do for i, view in ipairs(node.views) do
if view.doc == doc then if view.doc == doc then
@ -432,7 +413,9 @@ function RootView:on_mouse_pressed(button, x, y, clicks)
node:close_active_view(self.root_node) node:close_active_view(self.root_node)
end end
else else
core.set_active_view(node.active_view) if node.active_view.focusable then
core.active_view = node.active_view
end
node.active_view:on_mouse_pressed(button, x, y, clicks) node.active_view:on_mouse_pressed(button, x, y, clicks)
end end
end end
@ -448,13 +431,13 @@ end
function RootView:on_mouse_moved(x, y, dx, dy) function RootView:on_mouse_moved(x, y, dx, dy)
if self.dragged_divider then if self.dragged_divider then
local node = self.dragged_divider local div = self.dragged_divider
if node.type == "hsplit" then if div.type == "hsplit" then
node.divider = node.divider + dx / node.size.x div.divider = div.divider + dx / div.size.x
else else
node.divider = node.divider + dy / node.size.y div.divider = div.divider + dy / div.size.y
end end
node.divider = common.clamp(node.divider, 0.01, 0.99) div.divider = common.clamp(div.divider, 0.01, 0.99)
return return
end end

View File

@ -16,13 +16,13 @@ StatusView.separator2 = " | "
function StatusView:new() function StatusView:new()
StatusView.super.new(self) StatusView.super.new(self)
self.focusable = false
self.message_timeout = 0 self.message_timeout = 0
self.message = {} self.message = {}
end end
function StatusView:on_mouse_pressed() function StatusView:on_mouse_pressed()
core.set_active_view(core.last_active_view)
if system.get_time() < self.message_timeout if system.get_time() < self.message_timeout
and not core.active_view:is(LogView) then and not core.active_view:is(LogView) then
command.perform "core:open-log" command.perform "core:open-log"

View File

@ -11,19 +11,14 @@ function syntax.add(t)
end end
local function find(string, field) function syntax.get(filename)
for i = #syntax.items, 1, -1 do for i = #syntax.items, 1, -1 do
local t = syntax.items[i] local t = syntax.items[i]
if common.match_pattern(string, t[field] or {}) then if common.match_pattern(filename, t.files) then
return t return t
end end
end end
end return plain_text_syntax
function syntax.get(filename, header)
return find(filename, "files")
or find(header, "headers")
or plain_text_syntax
end end

View File

@ -14,6 +14,7 @@ function View:new()
self.scroll = { x = 0, y = 0, to = { x = 0, y = 0 } } self.scroll = { x = 0, y = 0, to = { x = 0, y = 0 } }
self.cursor = "arrow" self.cursor = "arrow"
self.scrollable = false self.scrollable = false
self.focusable = true
end end

View File

@ -18,7 +18,7 @@ local function reload_doc(doc)
local sel = { doc:get_selection() } local sel = { doc:get_selection() }
doc:remove(1, 1, math.huge, math.huge) doc:remove(1, 1, math.huge, math.huge)
doc:insert(1, 1, text:gsub("\r", ""):gsub("\n$", "")) doc:insert(1, 1, text:gsub("\n$", ""))
doc:set_selection(table.unpack(sel)) doc:set_selection(table.unpack(sel))
update_time(doc) update_time(doc)

View File

@ -8,7 +8,6 @@ syntax.add {
{ pattern = { "/%*", "%*/" }, type = "comment" }, { pattern = { "/%*", "%*/" }, type = "comment" },
{ pattern = { '"', '"', '\\' }, type = "string" }, { pattern = { '"', '"', '\\' }, type = "string" },
{ pattern = { "'", "'", '\\' }, type = "string" }, { pattern = { "'", "'", '\\' }, type = "string" },
{ pattern = { "`", "`", '\\' }, type = "string" },
{ pattern = "0x[%da-fA-F]+", type = "number" }, { pattern = "0x[%da-fA-F]+", type = "number" },
{ pattern = "-?%d+[%d%.eE]*", type = "number" }, { pattern = "-?%d+[%d%.eE]*", type = "number" },
{ pattern = "-?%.?%d+", type = "number" }, { pattern = "-?%.?%d+", type = "number" },
@ -17,6 +16,7 @@ syntax.add {
{ pattern = "[%a_][%w_]*", type = "symbol" }, { pattern = "[%a_][%w_]*", type = "symbol" },
}, },
symbols = { symbols = {
["arguments"] = "keyword2",
["async"] = "keyword", ["async"] = "keyword",
["await"] = "keyword", ["await"] = "keyword",
["break"] = "keyword", ["break"] = "keyword",
@ -32,6 +32,7 @@ syntax.add {
["else"] = "keyword", ["else"] = "keyword",
["export"] = "keyword", ["export"] = "keyword",
["extends"] = "keyword", ["extends"] = "keyword",
["false"] = "literal",
["finally"] = "keyword", ["finally"] = "keyword",
["for"] = "keyword", ["for"] = "keyword",
["function"] = "keyword", ["function"] = "keyword",
@ -39,29 +40,26 @@ syntax.add {
["if"] = "keyword", ["if"] = "keyword",
["import"] = "keyword", ["import"] = "keyword",
["in"] = "keyword", ["in"] = "keyword",
["Infinity"] = "keyword2",
["instanceof"] = "keyword", ["instanceof"] = "keyword",
["let"] = "keyword", ["let"] = "keyword",
["NaN"] = "keyword2",
["new"] = "keyword", ["new"] = "keyword",
["null"] = "literal",
["return"] = "keyword", ["return"] = "keyword",
["set"] = "keyword", ["set"] = "keyword",
["static"] = "keyword",
["super"] = "keyword", ["super"] = "keyword",
["switch"] = "keyword", ["switch"] = "keyword",
["this"] = "keyword2",
["throw"] = "keyword", ["throw"] = "keyword",
["true"] = "literal",
["try"] = "keyword", ["try"] = "keyword",
["typeof"] = "keyword", ["typeof"] = "keyword",
["undefined"] = "literal",
["var"] = "keyword", ["var"] = "keyword",
["void"] = "keyword", ["void"] = "keyword",
["while"] = "keyword", ["while"] = "keyword",
["with"] = "keyword", ["with"] = "keyword",
["yield"] = "keyword", ["yield"] = "keyword",
["true"] = "literal",
["false"] = "literal",
["null"] = "literal",
["undefined"] = "literal",
["arguments"] = "keyword2",
["Infinity"] = "keyword2",
["NaN"] = "keyword2",
["this"] = "keyword2",
}, },
} }

View File

@ -2,7 +2,6 @@ local syntax = require "core.syntax"
syntax.add { syntax.add {
files = "%.lua$", files = "%.lua$",
headers = "^#!.*[ /]lua",
comment = "--", comment = "--",
patterns = { patterns = {
{ pattern = { '"', '"', '\\' }, type = "string" }, { pattern = { '"', '"', '\\' }, type = "string" },
@ -13,7 +12,6 @@ syntax.add {
{ pattern = "-?0x%x+", type = "number" }, { pattern = "-?0x%x+", type = "number" },
{ pattern = "-?%d+[%d%.eE]*", type = "number" }, { pattern = "-?%d+[%d%.eE]*", type = "number" },
{ pattern = "-?%.?%d+", type = "number" }, { pattern = "-?%.?%d+", type = "number" },
{ pattern = "<%a+>", type = "keyword2" },
{ pattern = "%.%.%.?", type = "operator" }, { pattern = "%.%.%.?", type = "operator" },
{ pattern = "[<>~=]=", type = "operator" }, { pattern = "[<>~=]=", type = "operator" },
{ pattern = "[%+%-=/%*%^%%#<>]", type = "operator" }, { pattern = "[%+%-=/%*%^%%#<>]", type = "operator" },

View File

@ -1,8 +1,7 @@
local syntax = require "core.syntax" local syntax = require "core.syntax"
syntax.add { syntax.add {
files = { "%.py$", "%.pyw$" }, files = "%.py$",
headers = "^#!.*[ /]python",
comment = "#", comment = "#",
patterns = { patterns = {
{ pattern = { "#", "\n" }, type = "comment" }, { pattern = { "#", "\n" }, type = "comment" },

View File

@ -2,7 +2,6 @@ local syntax = require "core.syntax"
syntax.add { syntax.add {
files = { "%.xml$", "%.html?$" }, files = { "%.xml$", "%.html?$" },
headers = "<%?xml",
patterns = { patterns = {
{ pattern = { "<!%-%-", "%-%->" }, type = "comment" }, { pattern = { "<!%-%-", "%-%->" }, type = "comment" },
{ pattern = { '%f[^>][^<]', '%f[<]' }, type = "normal" }, { pattern = { '%f[^>][^<]', '%f[<]' }, type = "normal" },

View File

@ -22,6 +22,7 @@ local TreeView = View:extend()
function TreeView:new() function TreeView:new()
TreeView.super.new(self) TreeView.super.new(self)
self.scrollable = true self.scrollable = true
self.focusable = false
self.visible = true self.visible = true
self.init_size = true self.init_size = true
self.cache = {} self.cache = {}
@ -34,7 +35,7 @@ function TreeView:get_cached(item)
t = {} t = {}
t.filename = item.filename t.filename = item.filename
t.abs_filename = system.absolute_path(item.filename) t.abs_filename = system.absolute_path(item.filename)
t.name = t.filename:match("[^\\/]+$") t.path, t.name = t.filename:match("^(.*)[\\/](.+)$")
t.depth = get_depth(t.filename) t.depth = get_depth(t.filename)
t.type = item.type t.type = item.type
self.cache[t.filename] = t self.cache[t.filename] = t
@ -142,6 +143,7 @@ function TreeView:draw()
local icon_width = style.icon_font:get_width("D") local icon_width = style.icon_font:get_width("D")
local spacing = style.font:get_width(" ") * 2 local spacing = style.font:get_width(" ") * 2
local root_depth = get_depth(core.project_dir) + 1
local doc = core.active_view.doc local doc = core.active_view.doc
local active_filename = doc and system.absolute_path(doc.filename or "") local active_filename = doc and system.absolute_path(doc.filename or "")
@ -161,7 +163,7 @@ function TreeView:draw()
end end
-- icons -- icons
x = x + item.depth * style.padding.x + style.padding.x x = x + (item.depth - root_depth) * style.padding.x + style.padding.x
if item.type == "dir" then if item.type == "dir" then
local icon1 = item.expanded and "-" or "+" local icon1 = item.expanded and "-" or "+"
local icon2 = item.expanded and "D" or "d" local icon2 = item.expanded and "D" or "d"

View File

@ -4,16 +4,9 @@ local Doc = require "core.doc"
local function trim_trailing_whitespace(doc) local function trim_trailing_whitespace(doc)
local cline, ccol = doc:get_selection()
for i = 1, #doc.lines do for i = 1, #doc.lines do
local old_text = doc:get_text(i, 1, i, math.huge) local old_text = doc:get_text(i, 1, i, math.huge)
local new_text = old_text:gsub("%s*$", "") local new_text = old_text:gsub("%s*$", "")
-- don't remove whitespace which would cause the caret to reposition
if cline == i and ccol > #new_text then
new_text = old_text:sub(1, ccol - 1)
end
if old_text ~= new_text then if old_text ~= new_text then
doc:insert(i, 1, new_text) doc:insert(i, 1, new_text)
doc:remove(i, #new_text + 1, i, math.huge) doc:remove(i, #new_text + 1, i, math.huge)

View File

@ -5,7 +5,7 @@ style.background = { common.color "#fbfbfb" }
style.background2 = { common.color "#f2f2f2" } style.background2 = { common.color "#f2f2f2" }
style.background3 = { common.color "#f2f2f2" } style.background3 = { common.color "#f2f2f2" }
style.text = { common.color "#404040" } style.text = { common.color "#404040" }
style.caret = { common.color "#fc1785" } style.caret = { common.color "#181818" }
style.accent = { common.color "#fc1785" } style.accent = { common.color "#fc1785" }
style.dim = { common.color "#b0b0b0" } style.dim = { common.color "#b0b0b0" }
style.divider = { common.color "#e8e8e8" } style.divider = { common.color "#e8e8e8" }

View File

@ -1,146 +0,0 @@
# lite
![screenshot](https://user-images.githubusercontent.com/3920290/81471642-6c165880-91ea-11ea-8cd1-fae7ae8f0bc4.png)
## Overview
lite is a lightweight text editor written mostly in Lua — it aims to provide
something practical, pretty, *small* and fast, implemented as simply as
possible; easy to modify and extend, or to use without doing either.
## Getting Started
When lite is started it's typically opened with a *project directory* — this
is the directory where your project's code and other data resides. The project
directory is set once when lite is started and, for the duration of the
session, cannot be changed.
To open lite with a specific project directory the directory name can be passed
as a command-line argument *(`.` can be passed to use the current directory)* or
the directory can be dragged onto either the lite executable or a running
instance of lite.
The main way of opening files in lite is through the `core:find-file` command
— this provides a fuzzy finder over all of the project's files and can be
opened using the **`ctrl+p`** shortcut by default.
Commands can be run using keyboard shortcuts, or by using the `core:find-command`
command bound to **`ctrl+shift+p`** by default. For example, pressing
`ctrl+shift+p` and typing `newdoc` then pressing `return` would open a new
document. The current keyboard shortcut for a command can be seen to the right
of the command name on the command finder, thus to find the shortcut for a command
`ctrl+shift+p` can be pressed and the command name typed.
## User Module
lite can be configured through use of the user module. The user module can be
used for changing options in the config module, adding additional key bindings,
loading custom color themes, modifying the style or changing any other part of
lite to your personal preference.
The user module is loaded by lite when the application starts, after the plugins
have been loaded.
The user module can be modified by running the `core:open-user-module` command
or otherwise directly opening the `data/user/init.lua` file.
## Project Module
The project module is an optional module which is loaded from the current
project's directory when lite is started. Project modules can be useful for
things like adding custom commands for project-specific build systems, or
loading project-specific plugins.
The project module is loaded by lite when the application starts, after both the
plugins and user module have been loaded.
The project module can be edited by running the `core:open-project-module`
command — if the module does not exist for the current project when the
command is run it will be created.
## Commands
Commands in lite are used both through the command finder (`ctrl+shift+p`) and
by lite's keyboard shortcut system. Commands consist of 3 components:
* **Name** — The command name in the form of `namespace:action-name`, for
example: `doc:select-all`
* **Predicate** — A function that returns true if the command can be ran, for
example, for any document commands the predicate checks whether the active
view is a document
* **Function** — The function which performs the command itself
Commands can be added using the `command.add` function provided by the
`core.command` module:
```lua
local core = require "core"
local command = require "core.command"
command.add("core.docview", {
["doc:save"] = function()
core.active_view.doc:save()
core.log("Saved '%s', core.active_view.doc.filename)
end
})
```
Commands can be performed programatically (eg. from another command or by your
user module) by calling the `command.perform` function after requiring the
`command` module:
```lua
local command = require "core.command"
command.perform "core:quit"
```
## Keymap
All keyboard shortcuts in lite are handled by the `core.keymap` module. A key
binding in lite maps a "stroke" (eg. `ctrl+q`) to one or more commands (eg.
`core:quit`). When the shortcut is pressed lite will iterate each command
assigned to that key and run the *predicate function* for that command — if the
predicate passes it stops iterating and runs the command.
An example of where this used is the default binding of the `tab` key:
``` lua
["tab"] = { "command:complete", "doc:indent" },
```
When tab is pressed the `command:complete` command is attempted which will only
succeed if the command-input at the bottom of the window is active. Otherwise
the `doc:indent` command is attempted which will only succeed if we have a
document as our active view.
A new mapping can be added by your user module as follows:
```lua
local keymap = require "core.keymap"
keymap.add { ["ctrl+q"] = "core:quit" }
```
## Plugins
Plugins in lite are normal lua modules and are treated as such — no
complicated plugin manager is provided, and, once a plugin is loaded, it is never
expected be to have to unload itself.
To install a plugin simply drop it in the `data/plugins` directory — installed
plugins will be automatically loaded when lite starts. To uninstall a plugin the
plugin file can be deleted — any plugin (including those included with lite's
default installation) can be deleted to remove its functionality.
If you want to load a plugin only under a certain circumstance (for example,
only on a given project) the plugin can be placed somewhere other than the
`data/plugins` directory so that it is not automatically loaded. The plugin can
then be loaded manually as needed by using the `require` function.
Plugins can be downloaded from the [plugins repository](https://github.com/rxi/lite-plugins).
## Color Themes
Colors themes in lite are lua modules which overwrite the color fields of lite's
`core.style` module. Color themes should be placed in the `data/user/colors`
directory.
A color theme can be set by requiring it in your user module:
```lua
require "user.colors.winter"
```
Color themes can be downloaded from the [color themes repository](https://github.com/rxi/lite-colors).

View File

@ -1,49 +0,0 @@
<?xml version="1.0" ?>
<CodeBench_Project name="lite" path="SDH3:Programming&#047;workspace&#047;MyProjects&#047;lite&#047;lite.cbp" created="1387049720" lastmodified="1387152257">
<plugin name="PROGDIR:Plugins&#047;AmigaOS4SDK.CCPlugin" flags="0"/>
<target/>
<homedir name="SDH3:Programming&#047;workspace&#047;MyProjects&#047;lite"/>
<includedir name="Applications:Programming&#047;workspace&#047;OtherProjects&#047;lite&#047;src"/>
<compiler name="gcc:bin&#047;gcc" switches="-D__USE_INLINE__ -Wall -Werror -Wwrite-strings" stack="131072"/>
<linker switches="-lauto"/>
<debugger name="SDK:c&#047;gdb"/>
<builder name="SDK:c&#047;make -f"/>
<environment/>
<headers>
<file name="Applications:Programming&#047;workspace&#047;OtherProjects&#047;lite&#047;src&#047;api&#047;api.h" open="0"/>
<file name="Applications:Programming&#047;workspace&#047;OtherProjects&#047;lite&#047;src&#047;rencache.h" open="0"/>
<file name="Applications:Programming&#047;workspace&#047;OtherProjects&#047;lite&#047;src&#047;lib&#047;stb&#047;stb_truetype.h" open="0"/>
<file name="Applications:Programming&#047;workspace&#047;OtherProjects&#047;lite&#047;src&#047;renderer.h" open="0"/>
</headers>
<sources>
<file name="src&#047;api&#047;api.c" open="0"/>
<file name="src&#047;api&#047;renderer.c" open="0"/>
<file name="src&#047;api&#047;renderer_font.c" open="0"/>
<file name="src&#047;api&#047;system.c" open="0"/>
<file name="src&#047;main.c" open="1" current="1" top="75" left="0" line="97" row="16"/>
<file name="src&#047;rencache.c" open="0"/>
<file name="src&#047;renderer.c" open="0"/>
<file name="src&#047;lib&#047;stb&#047;stb_truetype.c" open="0"/>
</sources>
<flags value="0x0000000000078005"/>
<buildscript name="Makefile" depth="3" open="0"/>
<projectnotes open="0"/>
<buildwindow open="0"/>
<targets>
<target name="lite" linker="gcc:bin&#047;gcc" switches="-llua -lSDL2 -lpthread -lauto" flags="0x00000002">
<file name="src&#047;lib&#047;stb&#047;stb_truetype.c"/>
<file name="src&#047;api&#047;renderer.c"/>
<file name="src&#047;api&#047;renderer_font.c"/>
<file name="src&#047;api&#047;system.c"/>
<file name="src&#047;main.c"/>
<file name="src&#047;api&#047;api.c"/>
<file name="src&#047;rencache.c"/>
<file name="src&#047;renderer.c"/>
</target>
</targets>
<includepath>
<include path="src"/>
</includepath>
<logfile name="RAM Disk:Build.log"/>
<search lastsearch="stbtt_Scale" sensecase="1" replace_state="0"/>
</CodeBench_Project>

Binary file not shown.

BIN
lite.info

Binary file not shown.

View File

@ -2,11 +2,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h> #include <dirent.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "api.h" #include "api.h"
#include "rencache.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
@ -37,7 +35,6 @@ static char* key_name(char *dst, int sym) {
static int f_poll_event(lua_State *L) { static int f_poll_event(lua_State *L) {
char buf[16]; char buf[16];
int mx, my, wx, wy;
SDL_Event e; SDL_Event e;
top: top:
@ -57,9 +54,7 @@ top:
lua_pushnumber(L, e.window.data2); lua_pushnumber(L, e.window.data2);
return 3; return 3;
} else if (e.window.event == SDL_WINDOWEVENT_EXPOSED) { } else if (e.window.event == SDL_WINDOWEVENT_EXPOSED) {
rencache_invalidate(); SDL_UpdateWindowSurface(window);
lua_pushstring(L, "exposed");
return 1;
} }
/* on some systems, when alt-tabbing to the window SDL will queue up /* on some systems, when alt-tabbing to the window SDL will queue up
** several KEYDOWN events for the `tab` key; we flush all keydown ** several KEYDOWN events for the `tab` key; we flush all keydown
@ -70,14 +65,10 @@ top:
goto top; goto top;
case SDL_DROPFILE: case SDL_DROPFILE:
SDL_GetGlobalMouseState(&mx, &my);
SDL_GetWindowPosition(window, &wx, &wy);
lua_pushstring(L, "filedropped"); lua_pushstring(L, "filedropped");
lua_pushstring(L, e.drop.file); lua_pushstring(L, e.drop.file);
lua_pushnumber(L, mx - wx);
lua_pushnumber(L, my - wy);
SDL_free(e.drop.file); SDL_free(e.drop.file);
return 4; return 2;
case SDL_KEYDOWN: case SDL_KEYDOWN:
lua_pushstring(L, "keypressed"); lua_pushstring(L, "keypressed");
@ -225,14 +216,6 @@ static int f_show_confirm_dialog(lua_State *L) {
} }
static int f_chdir(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
int err = chdir(path);
if (err) { luaL_error(L, "chdir() failed"); }
return 0;
}
static int f_list_dir(lua_State *L) { static int f_list_dir(lua_State *L) {
const char *path = luaL_checkstring(L, 1); const char *path = luaL_checkstring(L, 1);
@ -338,10 +321,10 @@ static int f_sleep(lua_State *L) {
static int f_exec(lua_State *L) { static int f_exec(lua_State *L) {
size_t len; size_t len;
const char *cmd = luaL_checklstring(L, 1, &len); const char *cmd = luaL_checklstring(L, 1, &len);
char *buf = malloc(len + 32); char *buf = malloc(len + 16);
if (!buf) { luaL_error(L, "buffer allocation failed"); } if (!buf) { luaL_error(L, "buffer allocation failed"); }
#if _WIN32 #if _WIN32
sprintf(buf, "cmd /c \"%s\"", cmd); sprintf(buf, "cmd /c %s", cmd);
WinExec(buf, SW_HIDE); WinExec(buf, SW_HIDE);
#else #else
sprintf(buf, "%s &", cmd); sprintf(buf, "%s &", cmd);
@ -363,11 +346,11 @@ static int f_fuzzy_match(lua_State *L) {
while (*str == ' ') { str++; } while (*str == ' ') { str++; }
while (*ptn == ' ') { ptn++; } while (*ptn == ' ') { ptn++; }
if (tolower(*str) == tolower(*ptn)) { if (tolower(*str) == tolower(*ptn)) {
score += run * 10 - (*str != *ptn); score += run;
run++; run++;
ptn++; ptn++;
} else { } else {
score -= 10; score--;
run = 0; run = 0;
} }
str++; str++;
@ -387,7 +370,6 @@ static const luaL_Reg lib[] = {
{ "set_window_mode", f_set_window_mode }, { "set_window_mode", f_set_window_mode },
{ "window_has_focus", f_window_has_focus }, { "window_has_focus", f_window_has_focus },
{ "show_confirm_dialog", f_show_confirm_dialog }, { "show_confirm_dialog", f_show_confirm_dialog },
{ "chdir", f_chdir },
{ "list_dir", f_list_dir }, { "list_dir", f_list_dir },
{ "absolute_path", f_absolute_path }, { "absolute_path", f_absolute_path },
{ "get_file_info", f_get_file_info }, { "get_file_info", f_get_file_info },

View File

@ -1,14 +1,5 @@
// stb_truetype.h - v1.24 - public domain // stb_truetype.h - v1.19 - public domain
// authored from 2009-2020 by Sean Barrett / RAD Game Tools // authored from 2009-2016 by Sean Barrett / RAD Game Tools
//
// =======================================================================
//
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
//
// This library does no range checking of the offsets found in the file,
// meaning an attacker can use it to read arbitrary memory.
//
// =======================================================================
// //
// This library processes TrueType files: // This library processes TrueType files:
// parse files // parse files
@ -41,11 +32,11 @@
// Daniel Ribeiro Maciel // Daniel Ribeiro Maciel
// //
// Bug/warning reports/fixes: // Bug/warning reports/fixes:
// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe // "Zer" on mollyrocket Fabian "ryg" Giesen
// Cass Everitt Martins Mozeiko github:aloucks // Cass Everitt Martins Mozeiko
// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam // stoiko (Haemimont Games) Cap Petschulat
// Brian Hook Omar Cornut github:vassvik // Brian Hook Omar Cornut
// Walter van Niftrik Ryan Griege // Walter van Niftrik github:aloucks
// David Gow Peter LaValle // David Gow Peter LaValle
// David Given Sergey Popov // David Given Sergey Popov
// Ivan-Assen Ivanov Giumo X. Clanjor // Ivan-Assen Ivanov Giumo X. Clanjor
@ -53,16 +44,11 @@
// Johan Duparc Thomas Fields // Johan Duparc Thomas Fields
// Hou Qiming Derek Vinyard // Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton // Rob Loach Cort Stratton
// Kenney Phillis Jr. Brian Costabile // Kenney Phillis Jr. github:oyvindjam
// Ken Voskuil (kaesve) // Brian Costabile github:vassvik
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
// 1.21 (2019-02-25) fix warning
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
// 1.18 (2018-01-29) add missing function // 1.18 (2018-01-29) add missing function
// 1.17 (2017-07-23) make more arguments const; doc fix // 1.17 (2017-07-23) make more arguments const; doc fix
@ -89,7 +75,7 @@
// //
// USAGE // USAGE
// //
// Include this file in whatever places need to refer to it. In ONE C/C++ // Include this file in whatever places neeed to refer to it. In ONE C/C++
// file, write: // file, write:
// #define STB_TRUETYPE_IMPLEMENTATION // #define STB_TRUETYPE_IMPLEMENTATION
// before the #include of this file. This expands out the actual // before the #include of this file. This expands out the actual
@ -256,6 +242,19 @@
// recommend it. // recommend it.
// //
// //
// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
//
// Documentation & header file 520 LOC \___ 660 LOC documentation
// Sample code 140 LOC /
// Truetype parsing 620 LOC ---- 620 LOC TrueType
// Software rasterization 240 LOC \ .
// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
// Bitmap management 100 LOC /
// Baked bitmap interface 70 LOC /
// Font name matching & access 150 LOC ---- 150
// C runtime library abstraction 60 LOC ---- 60
//
//
// PERFORMANCE MEASUREMENTS FOR 1.06: // PERFORMANCE MEASUREMENTS FOR 1.06:
// //
// 32-bit 64-bit // 32-bit 64-bit
@ -557,8 +556,6 @@ STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int p
// //
// It's inefficient; you might want to c&p it and optimize it. // It's inefficient; you might want to c&p it and optimize it.
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
// Query the font vertical metrics without having to create a font first.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -644,12 +641,6 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
// To use with PackFontRangesGather etc., you must set it before calls // To use with PackFontRangesGather etc., you must set it before calls
// call to PackFontRangesGatherRects. // call to PackFontRangesGatherRects.
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
// If skip != 0, this tells stb_truetype to skip any codepoints for which
// there is no corresponding glyph. If skip=0, which is the default, then
// codepoints without a glyph recived the font's "missing character" glyph,
// typically an empty box by convention.
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
int char_index, // character to display int char_index, // character to display
float *xpos, float *ypos, // pointers to current position in screen pixel space float *xpos, float *ypos, // pointers to current position in screen pixel space
@ -678,7 +669,6 @@ struct stbtt_pack_context {
int height; int height;
int stride_in_bytes; int stride_in_bytes;
int padding; int padding;
int skip_missing;
unsigned int h_oversample, v_oversample; unsigned int h_oversample, v_oversample;
unsigned char *pixels; unsigned char *pixels;
void *nodes; void *nodes;
@ -704,7 +694,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// file will only define one font and it always be at offset 0, so it will // file will only define one font and it always be at offset 0, so it will
// return '0' for index 0, and -1 for all other indices. // return '0' for index 0, and -1 for all other indices.
// The following structure is defined publicly so you can declare one on // The following structure is defined publically so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque. // the stack or as a global or etc, but you should treat it as opaque.
struct stbtt_fontinfo struct stbtt_fontinfo
{ {
@ -714,7 +704,7 @@ struct stbtt_fontinfo
int numGlyphs; // number of glyphs, needed for range checking int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph int indexToLocFormat; // format needed to map from glyph index to glyph
@ -743,7 +733,6 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep
// and you want a speed-up, call this function with the character you're // and you want a speed-up, call this function with the character you're
// going to process, then use glyph-based functions instead of the // going to process, then use glyph-based functions instead of the
// codepoint-based functions. // codepoint-based functions.
// Returns 0 if the character codepoint is not defined in the font.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -797,18 +786,6 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
// as above, but takes one or more glyph indices for greater efficiency // as above, but takes one or more glyph indices for greater efficiency
typedef struct stbtt_kerningentry
{
int glyph1; // use stbtt_FindGlyphIndex
int glyph2;
int advance;
} stbtt_kerningentry;
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
// Retrieves a complete list of all of the kerning pairs provided by the font
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -843,7 +820,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
// returns # of vertices and fills *vertices with the pointer to them // returns # of vertices and fills *vertices with the pointer to them
// these are expressed in "unscaled" coordinates // these are expressed in "unscaled" coordinates
// //
// The shape is a series of contours. Each one starts with // The shape is a series of countours. Each one starts with
// a STBTT_moveto, then consists of a series of mixed // a STBTT_moveto, then consists of a series of mixed
// STBTT_lineto and STBTT_curveto segments. A lineto // STBTT_lineto and STBTT_curveto segments. A lineto
// draws a line from previous endpoint to its x,y; a curveto // draws a line from previous endpoint to its x,y; a curveto
@ -853,11 +830,6 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
// frees the data allocated above // frees the data allocated above
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
// fills svg with the character's SVG data.
// returns data size or 0 if SVG not found.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// BITMAP RENDERING // BITMAP RENDERING
@ -944,7 +916,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
// These functions compute a discretized SDF field for a single character, suitable for storing // These functions compute a discretized SDF field for a single character, suitable for storing
// in a single-channel texture, sampling with bilinear filtering, and testing against // in a single-channel texture, sampling with bilinear filtering, and testing against
// larger than some threshold to produce scalable fonts. // larger than some threshhold to produce scalable fonts.
// info -- the font // info -- the font
// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
// glyph/codepoint -- the character to generate the SDF for // glyph/codepoint -- the character to generate the SDF for
@ -1359,22 +1331,6 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
return stbtt__cff_get_index(&cff); return stbtt__cff_get_index(&cff);
} }
// since most people won't use this, find this table the first time it's needed
static int stbtt__get_svg(stbtt_fontinfo *info)
{
stbtt_uint32 t;
if (info->svg < 0) {
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
if (t) {
stbtt_uint32 offset = ttULONG(info->data + t + 2);
info->svg = t + offset;
} else {
info->svg = 0;
}
}
return info->svg;
}
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
{ {
stbtt_uint32 cmap, t; stbtt_uint32 cmap, t;
@ -1454,8 +1410,6 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
else else
info->numGlyphs = 0xffff; info->numGlyphs = 0xffff;
info->svg = -1;
// find a cmap encoding table we understand *now* to avoid searching // find a cmap encoding table we understand *now* to avoid searching
// later. (todo: could make this installable) // later. (todo: could make this installable)
// the same regardless of glyph. // the same regardless of glyph.
@ -1804,7 +1758,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
} }
} }
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
} else if (numberOfContours < 0) { } else if (numberOfContours == -1) {
// Compound shapes. // Compound shapes.
int more = 1; int more = 1;
stbtt_uint8 *comp = data + g + 10; stbtt_uint8 *comp = data + g + 10;
@ -1881,6 +1835,9 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
// More components ? // More components ?
more = flags & (1<<5); more = flags & (1<<5);
} }
} else if (numberOfContours < 0) {
// @TODO other compound variations?
STBTT_assert(0);
} else { } else {
// numberOfCounters == 0, do nothing // numberOfCounters == 0, do nothing
} }
@ -2309,48 +2266,6 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
} }
} }
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
{
stbtt_uint8 *data = info->data + info->kern;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
return ttUSHORT(data+10);
}
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
{
stbtt_uint8 *data = info->data + info->kern;
int k, length;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
length = ttUSHORT(data+10);
if (table_length < length)
length = table_length;
for (k = 0; k < length; k++)
{
table[k].glyph1 = ttUSHORT(data+18+(k*6));
table[k].glyph2 = ttUSHORT(data+20+(k*6));
table[k].advance = ttSHORT(data+22+(k*6));
}
return length;
}
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint8 *data = info->data + info->kern; stbtt_uint8 *data = info->data + info->kern;
@ -2548,7 +2463,6 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
if (valueFormat2 != 0) return 0; if (valueFormat2 != 0) return 0;
STBTT_assert(coverageIndex < pairSetCount); STBTT_assert(coverageIndex < pairSetCount);
STBTT__NOTUSED(pairSetCount);
needle=glyph2; needle=glyph2;
r=pairValueCount-1; r=pairValueCount-1;
@ -2626,7 +2540,8 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int
if (info->gpos) if (info->gpos)
xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
else if (info->kern)
if (info->kern)
xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
return xAdvance; return xAdvance;
@ -2687,45 +2602,6 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
STBTT_free(v, info->userdata); STBTT_free(v, info->userdata);
} }
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
{
int i;
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
int numEntries = ttUSHORT(svg_doc_list);
stbtt_uint8 *svg_docs = svg_doc_list + 2;
for(i=0; i<numEntries; i++) {
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
return svg_doc;
}
return 0;
}
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
{
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc;
if (info->svg == 0)
return 0;
svg_doc = stbtt_FindSVGDoc(info, gl);
if (svg_doc != NULL) {
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
return ttULONG(svg_doc + 8);
} else {
return 0;
}
}
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
{
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// antialiasing software rasterizer // antialiasing software rasterizer
@ -3284,13 +3160,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
if (e->y0 != e->y1) { if (e->y0 != e->y1) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
if (z != NULL) { if (z != NULL) {
if (j == 0 && off_y != 0) { STBTT_assert(z->ey >= scan_y_top);
if (z->ey < scan_y_top) {
// this can happen due to subpixel positioning and some kind of fp rounding error i think
z->ey = scan_y_top;
}
}
STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
// insert at front // insert at front
z->next = active; z->next = active;
active = z; active = z;
@ -3359,7 +3229,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
{ {
/* threshold for transitioning to insertion sort */ /* threshhold for transitioning to insertion sort */
while (n > 12) { while (n > 12) {
stbtt__edge t; stbtt__edge t;
int c01,c12,c,m,i,j; int c01,c12,c,m,i,j;
@ -3494,7 +3364,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
points[n].y = y; points[n].y = y;
} }
// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching // tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
{ {
// midpoint // midpoint
@ -3919,7 +3789,6 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
spc->h_oversample = 1; spc->h_oversample = 1;
spc->v_oversample = 1; spc->v_oversample = 1;
spc->skip_missing = 0;
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
@ -3945,11 +3814,6 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
spc->v_oversample = v_oversample; spc->v_oversample = v_oversample;
} }
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
{
spc->skip_missing = skip;
}
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
@ -4092,7 +3956,6 @@ static float stbtt__oversample_shift(int oversample)
STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{ {
int i,j,k; int i,j,k;
int missing_glyph_added = 0;
k=0; k=0;
for (i=0; i < num_ranges; ++i) { for (i=0; i < num_ranges; ++i) {
@ -4104,9 +3967,6 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
int x0,y0,x1,y1; int x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint); int glyph = stbtt_FindGlyphIndex(info, codepoint);
if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
rects[k].w = rects[k].h = 0;
} else {
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
scale * spc->h_oversample, scale * spc->h_oversample,
scale * spc->v_oversample, scale * spc->v_oversample,
@ -4114,9 +3974,6 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb
&x0,&y0,&x1,&y1); &x0,&y0,&x1,&y1);
rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
if (glyph == 0)
missing_glyph_added = 1;
}
++k; ++k;
} }
} }
@ -4150,7 +4007,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info
// rects array must be big enough to accommodate all characters in the given ranges // rects array must be big enough to accommodate all characters in the given ranges
STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
{ {
int i,j,k, missing_glyph = -1, return_value = 1; int i,j,k, return_value = 1;
// save current values // save current values
int old_h_over = spc->h_oversample; int old_h_over = spc->h_oversample;
@ -4169,7 +4026,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
sub_y = stbtt__oversample_shift(spc->v_oversample); sub_y = stbtt__oversample_shift(spc->v_oversample);
for (j=0; j < ranges[i].num_chars; ++j) { for (j=0; j < ranges[i].num_chars; ++j) {
stbrp_rect *r = &rects[k]; stbrp_rect *r = &rects[k];
if (r->was_packed && r->w != 0 && r->h != 0) { if (r->was_packed) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, lsb, x0,y0,x1,y1; int advance, lsb, x0,y0,x1,y1;
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
@ -4215,13 +4072,6 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const
bc->yoff = (float) y0 * recip_v + sub_y; bc->yoff = (float) y0 * recip_v + sub_y;
bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
bc->yoff2 = (y0 + r->h) * recip_v + sub_y; bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
if (glyph == 0)
missing_glyph = j;
} else if (spc->skip_missing) {
return_value = 0;
} else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
} else { } else {
return_value = 0; // if any fail, report failure return_value = 0; // if any fail, report failure
} }
@ -4290,19 +4140,6 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
} }
STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
{
int i_ascent, i_descent, i_lineGap;
float scale;
stbtt_fontinfo info;
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
*ascent = (float) i_ascent * scale;
*descent = (float) i_descent * scale;
*lineGap = (float) i_lineGap * scale;
}
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
{ {
float ipw = 1.0f / pw, iph = 1.0f / ph; float ipw = 1.0f / pw, iph = 1.0f / ph;
@ -4523,7 +4360,12 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
int w,h; int w,h;
unsigned char *data; unsigned char *data;
if (scale == 0) return NULL; // if one scale is 0, use same scale for both
if (scale_x == 0) scale_x = scale_y;
if (scale_y == 0) {
if (scale_x == 0) return NULL; // if both scales are 0, return NULL
scale_y = scale_x;
}
stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);

View File

@ -20,6 +20,8 @@ static double get_scale(void) {
SDL_GetDisplayDPI(0, NULL, &dpi, NULL); SDL_GetDisplayDPI(0, NULL, &dpi, NULL);
#if _WIN32 #if _WIN32
return dpi / 96.0; return dpi / 96.0;
#elif __APPLE__
return 1.0; /* dpi / 72.0; */
#else #else
return 1.0; return 1.0;
#endif #endif
@ -38,9 +40,6 @@ static void get_exe_filename(char *buf, int sz) {
#elif __APPLE__ #elif __APPLE__
unsigned size = sz; unsigned size = sz;
_NSGetExecutablePath(buf, &size); _NSGetExecutablePath(buf, &size);
#elif __amigaos4__
// TODO: Temporary. Needs to be done properly
strcpy(buf, "Applications:Programming/workspace/MyProjects/lite/lite");
#else #else
strcpy(buf, "./lite"); strcpy(buf, "./lite");
#endif #endif
@ -75,10 +74,6 @@ int main(int argc, char **argv) {
SDL_EnableScreenSaver(); SDL_EnableScreenSaver();
SDL_EventState(SDL_DROPFILE, SDL_ENABLE); SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
atexit(SDL_Quit); atexit(SDL_Quit);
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* Available since 2.0.8 */
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 5) #if SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif #endif
@ -105,7 +100,7 @@ int main(int argc, char **argv) {
} }
lua_setglobal(L, "ARGS"); lua_setglobal(L, "ARGS");
lua_pushstring(L, "1.11"); lua_pushstring(L, "1.04");
lua_setglobal(L, "VERSION"); lua_setglobal(L, "VERSION");
lua_pushstring(L, SDL_GetPlatform()); lua_pushstring(L, SDL_GetPlatform());
@ -125,7 +120,7 @@ int main(int argc, char **argv) {
"xpcall(function()\n" "xpcall(function()\n"
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n" " SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
" PATHSEP = package.config:sub(1, 1)\n" " PATHSEP = package.config:sub(1, 1)\n"
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n" " EXEDIR = EXEFILE:match(\"^(.-)[^/\\\\]*$\")"
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n" " package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n" " package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
" core = require('core')\n" " core = require('core')\n"

View File

@ -18,7 +18,6 @@ typedef struct {
RenRect rect; RenRect rect;
RenColor color; RenColor color;
RenFont *font; RenFont *font;
int tab_width;
char text[0]; char text[0];
} Command; } Command;
@ -144,7 +143,6 @@ int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor c
cmd->color = color; cmd->color = color;
cmd->font = font; cmd->font = font;
cmd->rect = rect; cmd->rect = rect;
cmd->tab_width = ren_get_font_tab_width(font);
} }
} }
@ -152,11 +150,6 @@ int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor c
} }
void rencache_invalidate(void) {
memset(cells_prev, 0xff, sizeof(cells_buf1));
}
void rencache_begin_frame(void) { void rencache_begin_frame(void) {
/* reset all cells if the screen width/height has changed */ /* reset all cells if the screen width/height has changed */
int w, h; int w, h;
@ -164,7 +157,7 @@ void rencache_begin_frame(void) {
if (screen_rect.width != w || h != screen_rect.height) { if (screen_rect.width != w || h != screen_rect.height) {
screen_rect.width = w; screen_rect.width = w;
screen_rect.height = h; screen_rect.height = h;
rencache_invalidate(); memset(cells_prev, 0xff, sizeof(cells_buf1));
} }
} }
@ -256,7 +249,6 @@ void rencache_end_frame(void) {
ren_draw_rect(cmd->rect, cmd->color); ren_draw_rect(cmd->rect, cmd->color);
break; break;
case DRAW_TEXT: case DRAW_TEXT:
ren_set_font_tab_width(cmd->font, cmd->tab_width);
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color); ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color);
break; break;
} }

View File

@ -9,7 +9,6 @@ void rencache_free_font(RenFont *font);
void rencache_set_clip_rect(RenRect rect); void rencache_set_clip_rect(RenRect rect);
void rencache_draw_rect(RenRect rect, RenColor color); void rencache_draw_rect(RenRect rect, RenColor color);
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color);
void rencache_invalidate(void);
void rencache_begin_frame(void); void rencache_begin_frame(void);
void rencache_end_frame(void); void rencache_end_frame(void);

View File

@ -222,12 +222,6 @@ void ren_set_font_tab_width(RenFont *font, int n) {
} }
int ren_get_font_tab_width(RenFont *font) {
GlyphSet *set = get_glyphset(font, '\t');
return set->glyphs['\t'].xadvance;
}
int ren_get_font_width(RenFont *font, const char *text) { int ren_get_font_width(RenFont *font, const char *text) {
int x = 0; int x = 0;
const char *p = text; const char *p = text;
@ -284,22 +278,17 @@ void ren_draw_rect(RenRect rect, RenColor color) {
int y2 = rect.y + rect.height; int y2 = rect.y + rect.height;
x2 = x2 > clip.right ? clip.right : x2; x2 = x2 > clip.right ? clip.right : x2;
y2 = y2 > clip.bottom ? clip.bottom : y2; y2 = y2 > clip.bottom ? clip.bottom : y2;
printf("DBG: rect\tx1: %d\ty1: %d\tx2:%d\ty2:%d\n", x1, y1, x2, y2);
SDL_Surface *surf = SDL_GetWindowSurface(window); SDL_Surface *surf = SDL_GetWindowSurface(window);
RenColor *d = (RenColor*) surf->pixels; RenColor *d = (RenColor*) surf->pixels;
printf("DBG: surf\tr: %d\tg: %d\tb:%d\ta:%d\tw: %d\n", d->r, d->g, d->b, d->a, surf->w); d += x1 + y1 * surf->w;
d += x1 + y1 * (surf->pitch / 4); int dr = surf->w - (x2 - x1);
//printf("DBG: surf\tr: %d\tg: %d\tb:%d\ta:%d\n", d->r, d->g, d->b, d->a);
int dr = (surf->pitch / 4) - (x2 - x1);
printf("DBG: r: %d\tg: %d\tb:%d\ta:%d\n", color.r, color.g, color.b, color.a);
if (color.a == 0xff) { if (color.a == 0xff) {
//rect_draw_loop(color); rect_draw_loop(color);
SDL_Rect rect = { x1, y1, x2 - x1, y2 - y1 };
SDL_FillRect(surf, &rect, SDL_MapRGBA(surf->format, color.r, color.g, color.b, color.a));
} else { } else {
rect_draw_loop(blend_pixel(*d, color)); rect_draw_loop(blend_pixel(*d, color));
} }
printf("======================\n");
} }

View File

@ -22,7 +22,6 @@ void ren_free_image(RenImage *image);
RenFont* ren_load_font(const char *filename, float size); RenFont* ren_load_font(const char *filename, float size);
void ren_free_font(RenFont *font); void ren_free_font(RenFont *font);
void ren_set_font_tab_width(RenFont *font, int n); void ren_set_font_tab_width(RenFont *font, int n);
int ren_get_font_tab_width(RenFont *font);
int ren_get_font_width(RenFont *font, const char *text); int ren_get_font_width(RenFont *font, const char *text);
int ren_get_font_height(RenFont *font); int ren_get_font_height(RenFont *font);