Manual merge of into .
This commit is contained in:
+5
-2
@@ -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
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user