Manual merge of into .

This commit is contained in:
Adam Harrison
2021-11-23 15:57:22 -05:00
44 changed files with 2789 additions and 311 deletions
+5 -2
View File
@@ -68,8 +68,11 @@ static int f_pcre_match(lua_State *L) {
int rc = pcre2_match(re, (PCRE2_SPTR)str, len, offset - 1, opts, md, NULL);
if (rc < 0) {
pcre2_match_data_free(md);
if (rc != PCRE2_ERROR_NOMATCH)
luaL_error(L, "regex matching error %d", rc);
if (rc != PCRE2_ERROR_NOMATCH) {
PCRE2_UCHAR buffer[120];
pcre2_get_error_message(rc, buffer, sizeof(buffer));
luaL_error(L, "regex matching error %d: %s", rc, buffer);
}
return 0;
}
PCRE2_SIZE* ovector = pcre2_get_ovector_pointer(md);
+17 -10
View File
@@ -174,23 +174,30 @@ static int f_end_frame(lua_State *L) {
}
static RenRect rect_to_grid(lua_Number x, lua_Number y, lua_Number w, lua_Number h) {
int x1 = (int) (x + 0.5), y1 = (int) (y + 0.5);
int x2 = (int) (x + w + 0.5), y2 = (int) (y + h + 0.5);
return (RenRect) {x1, y1, x2 - x1, y2 - y1};
}
static int f_set_clip_rect(lua_State *L) {
RenRect rect;
rect.x = luaL_checknumber(L, 1);
rect.y = luaL_checknumber(L, 2);
rect.width = luaL_checknumber(L, 3);
rect.height = luaL_checknumber(L, 4);
lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2);
lua_Number w = luaL_checknumber(L, 3);
lua_Number h = luaL_checknumber(L, 4);
RenRect rect = rect_to_grid(x, y, w, h);
rencache_set_clip_rect(rect);
return 0;
}
static int f_draw_rect(lua_State *L) {
RenRect rect;
rect.x = luaL_checknumber(L, 1);
rect.y = luaL_checknumber(L, 2);
rect.width = luaL_checknumber(L, 3);
rect.height = luaL_checknumber(L, 4);
lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2);
lua_Number w = luaL_checknumber(L, 3);
lua_Number h = luaL_checknumber(L, 4);
RenRect rect = rect_to_grid(x, y, w, h);
RenColor color = checkcolor(L, 5, 255);
rencache_draw_rect(rect, color);
return 0;
+154
View File
@@ -6,11 +6,14 @@
#include <errno.h>
#include <sys/stat.h>
#include "api.h"
#include "dirmonitor.h"
#include "rencache.h"
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#include <fileapi.h>
#elif __linux__
#include <sys/vfs.h>
#endif
extern SDL_Window *window;
@@ -238,6 +241,26 @@ top:
lua_pushnumber(L, e.wheel.y);
return 2;
case SDL_USEREVENT:
lua_pushstring(L, "dirchange");
lua_pushnumber(L, e.user.code >> 16);
switch (e.user.code & 0xffff) {
case DMON_ACTION_DELETE:
lua_pushstring(L, "delete");
break;
case DMON_ACTION_CREATE:
lua_pushstring(L, "create");
break;
case DMON_ACTION_MODIFY:
lua_pushstring(L, "modify");
break;
default:
return luaL_error(L, "unknown dmon event action: %d", e.user.code & 0xffff);
}
lua_pushstring(L, e.user.data1);
free(e.user.data1);
return 4;
default:
goto top;
}
@@ -526,6 +549,45 @@ static int f_get_file_info(lua_State *L) {
return 1;
}
#if __linux__
// https://man7.org/linux/man-pages/man2/statfs.2.html
struct f_type_names {
uint32_t magic;
const char *name;
};
static struct f_type_names fs_names[] = {
{ 0xef53, "ext2/ext3" },
{ 0x6969, "nfs" },
{ 0x65735546, "fuse" },
{ 0x517b, "smb" },
{ 0xfe534d42, "smb2" },
{ 0x52654973, "reiserfs" },
{ 0x01021994, "tmpfs" },
{ 0x858458f6, "ramfs" },
{ 0x5346544e, "ntfs" },
{ 0x0, NULL },
};
static int f_get_fs_type(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
struct statfs buf;
int status = statfs(path, &buf);
if (status != 0) {
return luaL_error(L, "error calling statfs on %s", path);
}
for (int i = 0; fs_names[i].magic; i++) {
if (fs_names[i].magic == buf.f_type) {
lua_pushstring(L, fs_names[i].name);
return 1;
}
}
lua_pushstring(L, "unknown");
return 1;
}
#endif
static int f_mkdir(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
@@ -709,6 +771,91 @@ static int f_load_native_plugin(lua_State *L) {
return result;
}
static int f_watch_dir(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
const int recursive = lua_toboolean(L, 2);
uint32_t dmon_flags = (recursive ? DMON_WATCHFLAGS_RECURSIVE : 0);
dmon_watch_id watch_id = dmon_watch(path, dirmonitor_watch_callback, dmon_flags, NULL);
if (watch_id.id == 0) { luaL_error(L, "directory monitoring watch failed"); }
lua_pushnumber(L, watch_id.id);
return 1;
}
#if __linux__
static int f_watch_dir_add(lua_State *L) {
dmon_watch_id watch_id;
watch_id.id = luaL_checkinteger(L, 1);
const char *subdir = luaL_checkstring(L, 2);
lua_pushboolean(L, dmon_watch_add(watch_id, subdir));
return 1;
}
static int f_watch_dir_rm(lua_State *L) {
dmon_watch_id watch_id;
watch_id.id = luaL_checkinteger(L, 1);
const char *subdir = luaL_checkstring(L, 2);
lua_pushboolean(L, dmon_watch_rm(watch_id, subdir));
return 1;
}
#endif
#ifdef _WIN32
#define PATHSEP '\\'
#else
#define PATHSEP '/'
#endif
/* Special purpose filepath compare function. Corresponds to the
order used in the TreeView view of the project's files. Returns true iff
path1 < path2 in the TreeView order. */
static int f_path_compare(lua_State *L) {
const char *path1 = luaL_checkstring(L, 1);
const char *type1_s = luaL_checkstring(L, 2);
const char *path2 = luaL_checkstring(L, 3);
const char *type2_s = luaL_checkstring(L, 4);
const int len1 = strlen(path1), len2 = strlen(path2);
int type1 = strcmp(type1_s, "dir") != 0;
int type2 = strcmp(type2_s, "dir") != 0;
/* Find the index of the common part of the path. */
int offset = 0, i;
for (i = 0; i < len1 && i < len2; i++) {
if (path1[i] != path2[i]) break;
if (path1[i] == PATHSEP) {
offset = i + 1;
}
}
/* If a path separator is present in the name after the common part we consider
the entry like a directory. */
if (strchr(path1 + offset, PATHSEP)) {
type1 = 0;
}
if (strchr(path2 + offset, PATHSEP)) {
type2 = 0;
}
/* If types are different "dir" types comes before "file" types. */
if (type1 != type2) {
lua_pushboolean(L, type1 < type2);
return 1;
}
/* If types are the same compare the files' path alphabetically. */
int cfr = 0;
int len_min = (len1 < len2 ? len1 : len2);
for (int j = offset; j <= len_min; j++) {
if (path1[j] == path2[j]) continue;
if (path1[j] == 0 || path2[j] == 0) {
cfr = (path1[j] == 0);
} else if (path1[j] == PATHSEP || path2[j] == PATHSEP) {
/* For comparison we treat PATHSEP as if it was the string terminator. */
cfr = (path1[j] == PATHSEP);
} else {
cfr = (path1[j] < path2[j]);
}
break;
}
lua_pushboolean(L, cfr);
return 1;
}
static const luaL_Reg lib[] = {
{ "poll_event", f_poll_event },
@@ -737,6 +884,13 @@ static const luaL_Reg lib[] = {
{ "fuzzy_match", f_fuzzy_match },
{ "set_window_opacity", f_set_window_opacity },
{ "load_native_plugin", f_load_native_plugin },
{ "watch_dir", f_watch_dir },
{ "path_compare", f_path_compare },
#if __linux__
{ "watch_dir_add", f_watch_dir_add },
{ "watch_dir_rm", f_watch_dir_rm },
{ "get_fs_type", f_get_fs_type },
#endif
{ NULL, NULL }
};
+59
View File
@@ -0,0 +1,59 @@
#include <stdio.h>
#include <string.h>
#include <SDL.h>
#define DMON_IMPL
#include "dmon.h"
#include "dmon_extra.h"
#include "dirmonitor.h"
static void send_sdl_event(dmon_watch_id watch_id, dmon_action action, const char *filepath) {
SDL_Event ev;
const int size = strlen(filepath) + 1;
/* The string allocated below should be deallocated as soon as the event is
treated in the SDL main loop. */
char *new_filepath = malloc(size);
if (!new_filepath) return;
memcpy(new_filepath, filepath, size);
#ifdef _WIN32
for (int i = 0; i < size; i++) {
if (new_filepath[i] == '/') {
new_filepath[i] = '\\';
}
}
#endif
SDL_zero(ev);
ev.type = SDL_USEREVENT;
ev.user.code = ((watch_id.id & 0xffff) << 16) | (action & 0xffff);
ev.user.data1 = new_filepath;
SDL_PushEvent(&ev);
}
void dirmonitor_init() {
dmon_init();
/* In theory we should register our user event but since we
have just one type of user event this is not really needed. */
/* sdl_dmon_event_type = SDL_RegisterEvents(1); */
}
void dirmonitor_deinit() {
dmon_deinit();
}
void dirmonitor_watch_callback(dmon_watch_id watch_id, dmon_action action, const char *rootdir,
const char *filepath, const char *oldfilepath, void *user)
{
(void) rootdir;
(void) user;
switch (action) {
case DMON_ACTION_MOVE:
send_sdl_event(watch_id, DMON_ACTION_DELETE, oldfilepath);
send_sdl_event(watch_id, DMON_ACTION_CREATE, filepath);
break;
default:
send_sdl_event(watch_id, action, filepath);
}
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef DIRMONITOR_H
#define DIRMONITOR_H
#include <stdint.h>
#include "dmon.h"
#include "dmon_extra.h"
void dirmonitor_init();
void dirmonitor_deinit();
void dirmonitor_watch_callback(dmon_watch_id watch_id, dmon_action action, const char *rootdir,
const char *filepath, const char *oldfilepath, void *user);
#endif
+5
View File
@@ -14,6 +14,8 @@
#include <mach-o/dyld.h>
#endif
#include "dirmonitor.h"
SDL_Window *window;
@@ -106,6 +108,8 @@ int main(int argc, char **argv) {
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
dirmonitor_init();
window = SDL_CreateWindow(
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
@@ -188,6 +192,7 @@ init_lua:
lua_close(L);
ren_free_window_resources();
dirmonitor_deinit();
return EXIT_SUCCESS;
}
+3 -2
View File
@@ -4,6 +4,7 @@ lite_sources = [
'api/regex.c',
'api/system.c',
'api/process.c',
'dirmonitor.c',
'renderer.c',
'renwindow.c',
'rencache.c',
@@ -18,11 +19,11 @@ elif host_machine.system() == 'darwin'
lite_sources += 'bundle_open.m'
endif
lite_include = include_directories('.')
lite_includes += include_directories('.')
executable('lite-xl',
lite_sources + lite_rc,
include_directories: [lite_include],
include_directories: lite_includes,
dependencies: lite_deps,
c_args: lite_cargs,
objc_args: lite_cargs,
+3 -1
View File
@@ -123,7 +123,9 @@ void rencache_set_clip_rect(RenRect rect) {
void rencache_draw_rect(RenRect rect, RenColor color) {
if (!rects_overlap(screen_rect, rect)) { return; }
if (!rects_overlap(screen_rect, rect) || rect.width == 0 || rect.height == 0) {
return;
}
Command *cmd = push_command(DRAW_RECT, COMMAND_BARE_SIZE);
if (cmd) {
cmd->rect = rect;