2019-12-28 12:16:32 +01:00
|
|
|
#include <stdio.h>
|
2021-06-03 21:48:15 +02:00
|
|
|
#include <stdlib.h>
|
2020-06-29 15:24:08 +02:00
|
|
|
#include <SDL.h>
|
2019-12-28 12:16:32 +01:00
|
|
|
#include "api/api.h"
|
2021-05-05 09:32:24 +02:00
|
|
|
#include "rencache.h"
|
2019-12-28 12:16:32 +01:00
|
|
|
#include "renderer.h"
|
2019-12-31 11:49:07 +01:00
|
|
|
|
2022-12-20 23:11:05 +01:00
|
|
|
#include <signal.h>
|
|
|
|
|
2019-12-28 12:16:32 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
2022-12-20 23:11:05 +01:00
|
|
|
#elif defined(__linux__)
|
2019-12-31 11:49:07 +01:00
|
|
|
#include <unistd.h>
|
2022-12-20 23:11:05 +01:00
|
|
|
#elif defined(__APPLE__)
|
2020-06-11 16:05:39 +02:00
|
|
|
#include <mach-o/dyld.h>
|
2022-12-20 23:11:05 +01:00
|
|
|
#elif defined(__FreeBSD__)
|
2022-11-13 15:46:42 +01:00
|
|
|
#include <sys/sysctl.h>
|
2019-12-28 12:16:32 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2023-01-12 00:25:06 +01:00
|
|
|
static SDL_Window *window;
|
2019-12-28 12:16:32 +01:00
|
|
|
|
2020-05-17 10:36:46 +02:00
|
|
|
static void get_exe_filename(char *buf, int sz) {
|
2019-12-31 11:49:07 +01:00
|
|
|
#if _WIN32
|
2023-04-07 19:06:01 +02:00
|
|
|
int len;
|
|
|
|
wchar_t *buf_w = malloc(sizeof(wchar_t) * sz);
|
|
|
|
if (buf_w) {
|
|
|
|
len = GetModuleFileNameW(NULL, buf_w, sz - 1);
|
|
|
|
buf_w[len] = L'\0';
|
|
|
|
// if the conversion failed we'll empty the string
|
|
|
|
if (!WideCharToMultiByte(CP_UTF8, 0, buf_w, -1, buf, sz, NULL, NULL))
|
|
|
|
buf[0] = '\0';
|
|
|
|
free(buf_w);
|
|
|
|
} else {
|
|
|
|
buf[0] = '\0';
|
|
|
|
}
|
2019-12-31 11:49:07 +01:00
|
|
|
#elif __linux__
|
2021-10-12 09:06:37 +02:00
|
|
|
char path[] = "/proc/self/exe";
|
2023-01-05 21:59:45 +01:00
|
|
|
ssize_t len = readlink(path, buf, sz - 1);
|
|
|
|
if (len > 0)
|
|
|
|
buf[len] = '\0';
|
2019-12-31 11:49:07 +01:00
|
|
|
#elif __APPLE__
|
2021-06-03 21:48:15 +02:00
|
|
|
/* use realpath to resolve a symlink if the process was launched from one.
|
|
|
|
** This happens when Homebrew installs a cack and creates a symlink in
|
|
|
|
** /usr/loca/bin for launching the executable from the command line. */
|
2019-12-31 11:49:07 +01:00
|
|
|
unsigned size = sz;
|
2021-06-03 21:48:15 +02:00
|
|
|
char exepath[size];
|
|
|
|
_NSGetExecutablePath(exepath, &size);
|
|
|
|
realpath(exepath, buf);
|
2022-11-13 15:46:42 +01:00
|
|
|
#elif __FreeBSD__
|
|
|
|
size_t len = sz;
|
|
|
|
const int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
|
|
|
sysctl(mib, 4, buf, &len, NULL, 0);
|
2019-12-31 11:49:07 +01:00
|
|
|
#else
|
2022-12-20 23:11:05 +01:00
|
|
|
*buf = 0;
|
2019-12-31 11:49:07 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-06 20:49:34 +02:00
|
|
|
static void init_window_icon(void) {
|
2021-09-29 22:22:00 +02:00
|
|
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
2021-06-20 17:37:08 +02:00
|
|
|
#include "../resources/icons/icon.inl"
|
2020-05-06 20:49:34 +02:00
|
|
|
(void) icon_rgba_len; /* unused */
|
|
|
|
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
|
|
|
|
icon_rgba, 64, 64,
|
|
|
|
32, 64 * 4,
|
|
|
|
0x000000ff,
|
|
|
|
0x0000ff00,
|
|
|
|
0x00ff0000,
|
|
|
|
0xff000000);
|
|
|
|
SDL_SetWindowIcon(window, surf);
|
|
|
|
SDL_FreeSurface(surf);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-05 09:42:48 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define LITE_OS_HOME "USERPROFILE"
|
|
|
|
#define LITE_PATHSEP_PATTERN "\\\\"
|
2021-03-05 23:46:41 +01:00
|
|
|
#define LITE_NONPATHSEP_PATTERN "[^\\\\]+"
|
2021-03-05 09:42:48 +01:00
|
|
|
#else
|
|
|
|
#define LITE_OS_HOME "HOME"
|
|
|
|
#define LITE_PATHSEP_PATTERN "/"
|
2021-03-05 23:46:41 +01:00
|
|
|
#define LITE_NONPATHSEP_PATTERN "[^/]+"
|
2021-03-05 09:42:48 +01:00
|
|
|
#endif
|
2019-12-31 11:49:07 +01:00
|
|
|
|
2021-04-19 09:52:00 +02:00
|
|
|
#ifdef __APPLE__
|
2021-04-21 09:52:16 +02:00
|
|
|
void enable_momentum_scroll();
|
2021-08-18 14:26:51 +02:00
|
|
|
#ifdef MACOS_USE_BUNDLE
|
|
|
|
void set_macos_bundle_resources(lua_State *L);
|
|
|
|
#endif
|
2021-04-19 09:52:00 +02:00
|
|
|
#endif
|
|
|
|
|
2022-09-19 00:27:50 +02:00
|
|
|
#ifndef LITE_ARCH_TUPLE
|
2022-11-16 04:23:45 +01:00
|
|
|
// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-140
|
|
|
|
#if defined(__x86_64__) || defined(_M_AMD64) || defined(__MINGW64__)
|
2022-09-19 00:27:50 +02:00
|
|
|
#define ARCH_PROCESSOR "x86_64"
|
2022-11-16 04:23:45 +01:00
|
|
|
#elif defined(__i386__) || defined(_M_IX86) || defined(__MINGW32__)
|
2022-10-04 17:13:21 +02:00
|
|
|
#define ARCH_PROCESSOR "x86"
|
2022-11-16 04:23:45 +01:00
|
|
|
#elif defined(__aarch64__) || defined(_M_ARM64) || defined (_M_ARM64EC)
|
2022-09-19 00:27:50 +02:00
|
|
|
#define ARCH_PROCESSOR "aarch64"
|
2022-11-16 04:23:45 +01:00
|
|
|
#elif defined(__arm__) || defined(_M_ARM)
|
2022-09-19 00:27:50 +02:00
|
|
|
#define ARCH_PROCESSOR "arm"
|
|
|
|
#endif
|
2022-10-04 17:13:21 +02:00
|
|
|
|
2022-09-19 00:27:50 +02:00
|
|
|
#if _WIN32
|
|
|
|
#define ARCH_PLATFORM "windows"
|
|
|
|
#elif __linux__
|
|
|
|
#define ARCH_PLATFORM "linux"
|
2022-10-04 17:13:21 +02:00
|
|
|
#elif __FreeBSD__
|
|
|
|
#define ARCH_PLATFORM "freebsd"
|
2022-09-19 00:27:50 +02:00
|
|
|
#elif __APPLE__
|
|
|
|
#define ARCH_PLATFORM "darwin"
|
2022-10-04 17:13:21 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(ARCH_PROCESSOR) || !defined(ARCH_PLATFORM)
|
2022-09-19 00:27:50 +02:00
|
|
|
#error "Please define -DLITE_ARCH_TUPLE."
|
|
|
|
#endif
|
2022-10-04 17:13:21 +02:00
|
|
|
|
2022-09-19 00:27:50 +02:00
|
|
|
#define LITE_ARCH_TUPLE ARCH_PROCESSOR "-" ARCH_PLATFORM
|
|
|
|
#endif
|
|
|
|
|
2019-12-28 12:16:32 +01:00
|
|
|
int main(int argc, char **argv) {
|
2023-03-09 14:58:32 +01:00
|
|
|
#ifndef _WIN32
|
2021-06-02 17:27:40 +02:00
|
|
|
signal(SIGPIPE, SIG_IGN);
|
2019-12-28 12:16:32 +01:00
|
|
|
#endif
|
|
|
|
|
2022-05-31 20:57:26 +02:00
|
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
|
|
|
fprintf(stderr, "Error initializing sdl: %s", SDL_GetError());
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-12-28 12:16:32 +01:00
|
|
|
SDL_EnableScreenSaver();
|
|
|
|
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
|
|
|
atexit(SDL_Quit);
|
2020-06-03 15:05:55 +02:00
|
|
|
|
|
|
|
#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
|
2019-12-28 12:16:32 +01:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
|
|
|
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
|
|
|
#endif
|
2022-10-16 01:58:51 +02:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
|
|
|
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
|
|
|
#endif
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 22)
|
|
|
|
SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1");
|
|
|
|
#endif
|
2019-12-28 12:16:32 +01:00
|
|
|
|
2022-05-23 07:10:11 +02:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 8)
|
|
|
|
/* This hint tells SDL to respect borderless window as a normal window.
|
|
|
|
** For example, the window will sit right on top of the taskbar instead
|
|
|
|
** of obscuring it. */
|
|
|
|
SDL_SetHint("SDL_BORDERLESS_WINDOWED_STYLE", "1");
|
|
|
|
#endif
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
|
|
|
/* This hint tells SDL to allow the user to resize a borderless windoow.
|
|
|
|
** It also enables aero-snap on Windows apparently. */
|
|
|
|
SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1");
|
|
|
|
#endif
|
2022-08-21 19:08:32 +02:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
|
|
|
SDL_SetHint("SDL_MOUSE_DOUBLE_CLICK_RADIUS", "4");
|
|
|
|
#endif
|
2022-05-23 07:10:11 +02:00
|
|
|
|
2019-12-28 12:16:32 +01:00
|
|
|
SDL_DisplayMode dm;
|
|
|
|
SDL_GetCurrentDisplayMode(0, &dm);
|
|
|
|
|
|
|
|
window = SDL_CreateWindow(
|
2020-05-14 23:28:22 +02:00
|
|
|
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
|
|
|
|
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
|
2020-05-06 20:49:34 +02:00
|
|
|
init_window_icon();
|
2022-05-31 20:57:26 +02:00
|
|
|
if (!window) {
|
|
|
|
fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError());
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-12-28 12:16:32 +01:00
|
|
|
ren_init(window);
|
|
|
|
|
2020-12-10 12:44:01 +01:00
|
|
|
lua_State *L;
|
|
|
|
init_lua:
|
|
|
|
L = luaL_newstate();
|
2019-12-28 12:16:32 +01:00
|
|
|
luaL_openlibs(L);
|
|
|
|
api_load_libs(L);
|
|
|
|
|
|
|
|
|
|
|
|
lua_newtable(L);
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
lua_pushstring(L, argv[i]);
|
|
|
|
lua_rawseti(L, -2, i + 1);
|
|
|
|
}
|
2020-04-25 10:57:35 +02:00
|
|
|
lua_setglobal(L, "ARGS");
|
|
|
|
|
2020-04-23 21:03:14 +02:00
|
|
|
lua_pushstring(L, SDL_GetPlatform());
|
2020-04-25 10:57:35 +02:00
|
|
|
lua_setglobal(L, "PLATFORM");
|
2019-12-28 12:16:32 +01:00
|
|
|
|
2022-09-19 00:27:50 +02:00
|
|
|
lua_pushstring(L, LITE_ARCH_TUPLE);
|
|
|
|
lua_setglobal(L, "ARCH");
|
|
|
|
|
2020-05-17 10:36:46 +02:00
|
|
|
char exename[2048];
|
|
|
|
get_exe_filename(exename, sizeof(exename));
|
2022-11-13 15:54:08 +01:00
|
|
|
if (*exename) {
|
|
|
|
lua_pushstring(L, exename);
|
|
|
|
} else {
|
|
|
|
// get_exe_filename failed
|
|
|
|
lua_pushstring(L, argv[0]);
|
|
|
|
}
|
2020-05-17 10:36:46 +02:00
|
|
|
lua_setglobal(L, "EXEFILE");
|
2019-12-31 11:49:07 +01:00
|
|
|
|
2021-04-18 17:51:31 +02:00
|
|
|
#ifdef __APPLE__
|
2021-04-21 09:52:16 +02:00
|
|
|
enable_momentum_scroll();
|
2021-08-18 14:26:51 +02:00
|
|
|
#ifdef MACOS_USE_BUNDLE
|
|
|
|
set_macos_bundle_resources(L);
|
|
|
|
#endif
|
2021-04-18 17:51:31 +02:00
|
|
|
#endif
|
2023-04-07 18:42:46 +02:00
|
|
|
SDL_EventState(SDL_TEXTINPUT, SDL_ENABLE);
|
|
|
|
SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
|
2021-04-18 17:51:31 +02:00
|
|
|
|
2020-12-10 12:44:01 +01:00
|
|
|
const char *init_lite_code = \
|
2019-12-28 12:16:32 +01:00
|
|
|
"local core\n"
|
2023-05-19 19:28:39 +02:00
|
|
|
"local os_exit = os.exit\n"
|
|
|
|
"os.exit = function(code, close)\n"
|
|
|
|
" os_exit(code, close == nil and true or close)\n"
|
|
|
|
"end\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
"xpcall(function()\n"
|
2023-04-07 19:06:01 +02:00
|
|
|
" local match = require('utf8extra').match\n"
|
2021-03-05 09:42:48 +01:00
|
|
|
" HOME = os.getenv('" LITE_OS_HOME "')\n"
|
2023-04-07 19:06:01 +02:00
|
|
|
" local exedir = match(EXEFILE, '^(.*)" LITE_PATHSEP_PATTERN LITE_NONPATHSEP_PATTERN "$')\n"
|
|
|
|
" local prefix = os.getenv('LITE_PREFIX') or match(exedir, '^(.*)" LITE_PATHSEP_PATTERN "bin$')\n"
|
2021-04-18 17:51:31 +02:00
|
|
|
" dofile((MACOS_RESOURCES or (prefix and prefix .. '/share/lite-xl' or exedir .. '/data')) .. '/core/start.lua')\n"
|
2021-09-18 21:56:23 +02:00
|
|
|
" core = require(os.getenv('LITE_XL_RUNTIME') or 'core')\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
" core.init()\n"
|
|
|
|
" core.run()\n"
|
|
|
|
"end, function(err)\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" local error_path = 'error.txt'\n"
|
2021-03-07 09:48:44 +01:00
|
|
|
" io.stdout:write('Error: '..tostring(err)..'\\n')\n"
|
2023-04-07 19:18:16 +02:00
|
|
|
" io.stdout:write(debug.traceback(nil, 2)..'\\n')\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
" if core and core.on_error then\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" error_path = USERDIR .. PATHSEP .. error_path\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
" pcall(core.on_error, err)\n"
|
2021-03-05 23:46:41 +01:00
|
|
|
" else\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" local fp = io.open(error_path, 'wb')\n"
|
2021-03-05 23:46:41 +01:00
|
|
|
" fp:write('Error: ' .. tostring(err) .. '\\n')\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" fp:write(debug.traceback(nil, 2)..'\\n')\n"
|
2021-03-05 23:46:41 +01:00
|
|
|
" fp:close()\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" error_path = system.absolute_path(error_path)\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
" end\n"
|
2021-03-05 23:46:41 +01:00
|
|
|
" system.show_fatal_error('Lite XL internal error',\n"
|
|
|
|
" 'An internal error occurred in a critical part of the application.\\n\\n'..\n"
|
2023-04-14 21:22:22 +02:00
|
|
|
" 'Error: '..tostring(err)..'\\n\\n'..\n"
|
|
|
|
" 'Details can be found in \\\"'..error_path..'\\\"')\n"
|
2019-12-28 12:16:32 +01:00
|
|
|
" os.exit(1)\n"
|
2020-12-10 12:44:01 +01:00
|
|
|
"end)\n"
|
|
|
|
"return core and core.restart_request\n";
|
2019-12-28 12:16:32 +01:00
|
|
|
|
2020-12-10 12:44:01 +01:00
|
|
|
if (luaL_loadstring(L, init_lite_code)) {
|
|
|
|
fprintf(stderr, "internal error when starting the application\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
lua_pcall(L, 0, 1, 0);
|
|
|
|
if (lua_toboolean(L, -1)) {
|
|
|
|
lua_close(L);
|
2021-09-26 16:18:13 +02:00
|
|
|
rencache_invalidate();
|
2020-12-10 12:44:01 +01:00
|
|
|
goto init_lua;
|
|
|
|
}
|
2019-12-28 12:16:32 +01:00
|
|
|
|
2023-03-22 13:36:05 +01:00
|
|
|
// This allows the window to be destroyed before lite-xl is done with
|
|
|
|
// reaping child processes
|
2023-01-22 04:11:42 +01:00
|
|
|
ren_free_window_resources(&window_renderer);
|
2023-03-22 13:36:05 +01:00
|
|
|
lua_close(L);
|
2019-12-28 12:16:32 +01:00
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|