├── .editorconfig ├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── init.lua ├── lite_xl_plugin_api.h ├── lua_tmt.c ├── minivt.c ├── minivt.h ├── pty.c ├── pty.win.c ├── tmt.c ├── tmt.h ├── winpty-agent.exe ├── winpty.dll └── winpty ├── winpty.h └── winpty_constants.h /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | 5 | [*.{c,h,lua}] 6 | indent_style = space 7 | indent_size = 4 8 | 9 | [Makefile] 10 | indent_style = tab 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: { push: { branches: [main] } } 3 | jobs: 4 | 5 | 6 | build_linux: 7 | runs-on: ubuntu-latest 8 | defaults: { run: {shell: bash } } 9 | env: 10 | GH_TOKEN: ${{ github.token }} 11 | steps: 12 | - uses: actions/checkout@v3 13 | with: { fetch-depth: 0 } 14 | - run: make 15 | - run: mkdir tmt && cp init.lua pty tmt.so tmt/ && tar -czf lite-xl-tmt-$(git rev-parse --short HEAD)-linux64.tar.gz tmt && rm -r tmt 16 | - run: make clean 17 | - run: sudo apt-get install mingw-w64 18 | - run: CC=x86_64-w64-mingw32-gcc make mingw 19 | - run: mkdir tmt && cp init.lua pty.exe tmt.dll winpty.dll winpty-agent.exe tmt/ && zip -r lite-xl-tmt-$(git rev-parse --short HEAD)-win64.zip tmt && rm -r tmt 20 | - run: make clean 21 | - run: gh release delete --cleanup-tag -y nightly || true; git tag -d nightly || true; gh release create -p -t "Nightly" nightly *.tar.gz *.zip 22 | - run: | 23 | if [[ `git tag --points-at HEAD | head -c 1` == "v" ]]; then 24 | export VERSION=`git tag --points-at HEAD` 25 | mv lite-xl-tmt-$(git rev-parse --short HEAD)-win64.zip lite-xl-tmt-$VERSION-win64.zip 26 | mv lite-xl-tmt-$(git rev-parse --short HEAD)-linux64.tar.gz lite-xl-tmt-$VERSION-linux64.tar.gz 27 | echo "Creating release $VERSION" 28 | gh release create --latest --generate-notes -t $VERSION $VERSION *.tar.gz *.zip 29 | else 30 | echo "Not creating a release; known tags:" 31 | git tag 32 | fi 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.dll 3 | /pty 4 | /pty.exe 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Quinten Kock 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -std=gnu99 -O2 -fPIC 2 | 3 | PTY_LIBS = -lutil 4 | 5 | SOEXT = so 6 | SONAME = tmt.$(SOEXT) 7 | 8 | PTY_SRC = pty.c 9 | 10 | all: $(SONAME) pty 11 | 12 | $(SONAME): lua_tmt.c tmt.c 13 | $(CC) -shared -o $@ $(CFLAGS) $^ 14 | 15 | pty: $(PTY_SRC) minivt.c 16 | $(CC) -o $@ $(CFLAGS) $(PTY_LIBS) $^ -I. -L. 17 | 18 | mingw: 19 | $(MAKE) PTY_LIBS=-lwinpty SOEXT=dll PTY_SRC=pty.win.c 20 | 21 | clean: 22 | rm -f tmt.so tmt.dll pty pty.exe 23 | 24 | .PHONY: clean mingw all 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | Consider using [lite-xl-terminal](https://github.com/adamharrison/lite-xl-terminal) instead. This project kept only for archival purposes. 3 | 4 | # lite-xl-tmt 5 | Terminal emulator for [Lite XL](https://github.com/lite-xl/lite-xl) based on [libtmt](https://github.com/deadpixi/libtmt) (more specifically [lua-tmt](https://github.com/max1220/lua-tmt)). 6 | 7 | ## Installation instructions 8 | - Head over to the [latest release](https://github.com/ColonelPhantom/lite-xl-tmt/releases/latest) page. 9 | - Download the appropriate zip/tar file for your platform (only Windows and Linux, and 64 bit only). 10 | - Then place the `tmt` folder that is in the archive into your plugins folder. 11 | - You should now have a Lua file at `$LITE_XL_USERDIR/plugins/tmt/init.lua` 12 | - Simply restart Lite XL and hit Ctrl+\` to get a terminal! 13 | 14 | Note that this plugin only works on Lite XL 2.1.1 and higher. 15 | 16 | ## Building from source 17 | Place this repo in `~/.config/lite-xl/plugins`, and rename it to `tmt`. (The full path should look like `~/.config/lite-xl/plugins/tmt/init.lua`, for example.) Then run `make`, or `make mingw` if you are on Windows. 18 | 19 | Example: 20 | ```sh 21 | git clone https://github.com/ColonelPhantom/lite-xl-tmt tmt 22 | make # or "make mingw" if you use Windows 23 | ``` 24 | 25 | Note: the repo contains some binaries for WinPTY stuff, you may need to replace or rebuild those depending on your needs (e.g. 32 bit support). 26 | 27 | ## Caveats 28 | This plugin is not widely tested, use at your own risk. 29 | 30 | The main author uses GNU/Linux, so Windows support is provided on a best-effort basis. (Should work, though.) 31 | 32 | TMT is a fairly limited terminal emulator, so some advanced terminal programs will not work correctly. 33 | 34 | There is no support for scrolling due to TMT limitations. 35 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | -- mod-version:3 -- lite-xl 2.1 2 | local core = require "core" 3 | local keymap = require "core.keymap" 4 | local command = require "core.command" 5 | local common = require "core.common" 6 | local config = require "core.config" 7 | local style = require "core.style" 8 | local View = require "core.view" 9 | 10 | local libtmt = require "plugins.tmt.tmt" 11 | 12 | 13 | config.plugins.tmt = { 14 | shell = os.getenv(PLATFORM == "Windows" and "COMSPEC" or "SHELL") or "/bin/sh", 15 | shell_args = {}, 16 | split_direction = "down", 17 | resize_interval = 0.3 -- in seconds 18 | } 19 | 20 | local ESC = "\x1b" 21 | 22 | local COLORS = { 23 | { common.color "#000000" }, 24 | { common.color "#cc0000" }, 25 | { common.color "#4e9a06" }, 26 | { common.color "#c4a000" }, 27 | { common.color "#3465a4" }, 28 | { common.color "#75507b" }, 29 | { common.color "#06989a" }, 30 | { common.color "#d3d7cf" }, 31 | } 32 | 33 | local function get_passthrough_exe() 34 | for _, dir in ipairs { USERDIR, DATADIR } do 35 | local path = dir .. "/plugins/tmt/pty" .. (PLATFORM == "Windows" and ".exe" or "") 36 | if system.get_file_info(path) then 37 | return path 38 | end 39 | end 40 | end 41 | 42 | local PASSTHROUGH_PATH = get_passthrough_exe() 43 | local TERMINATION_MSG = "\r\n\n[Process ended with status %d]" 44 | 45 | local shared_view = nil 46 | 47 | local TmtView = View:extend() 48 | 49 | function TmtView:new() 50 | TmtView.super.new(self) 51 | self.scrollable = false 52 | 53 | local args = { PASSTHROUGH_PATH, config.plugins.tmt.shell } 54 | for _, arg in ipairs(config.plugins.tmt.shell_args) do 55 | table.insert(args, arg) 56 | end 57 | self.proc = assert(process.start(args, { 58 | stdin = process.REDIRECT_PIPE, 59 | stdout = process.REDIRECT_PIPE 60 | })) 61 | 62 | self.tmt = libtmt.new(80,24) 63 | self.screen = {} 64 | 65 | self.title = "Tmt" 66 | self.visible = true 67 | self.scroll_region_start = 1 68 | self.scroll_region_end = self.rows 69 | 70 | self.term_target_size = { w = 80, h = 24 } 71 | 72 | self.alive = true 73 | 74 | core.add_thread(function() 75 | while self.alive do 76 | local output = self.proc:read_stdout() 77 | if not output then break end 78 | 79 | local events = self.tmt:write(output) 80 | core.redraw = events.screen 81 | self.bell = events.bell 82 | if events.answer then 83 | self:input_string(events.answer) 84 | end 85 | coroutine.yield(1 / config.fps) 86 | end 87 | 88 | self.alive = false 89 | self.tmt:write(string.format(TERMINATION_MSG, self.proc:returncode() or 0)) 90 | end, self) 91 | end 92 | 93 | function TmtView:try_close(...) 94 | if self == shared_view then shared_view = nil end 95 | self.proc:kill() 96 | TmtView.super.try_close(self, ...) 97 | end 98 | 99 | function TmtView:get_name() 100 | return self.title 101 | end 102 | 103 | function TmtView:update(...) 104 | TmtView.super.update(self, ...) 105 | 106 | local sw, sh = self:get_screen_char_size() 107 | local tw, th = self.tmt:get_size() 108 | if sw ~= tw or sh ~= th then 109 | self.term_target_size.w, self.term_target_size.h = sw, sh 110 | if not self.resize_start then 111 | self.resize_start = system.get_time() 112 | end 113 | end 114 | 115 | if self.resize_start 116 | and (system.get_time() - self.resize_start > config.plugins.tmt.resize_interval) then 117 | self.resize_start = nil 118 | self.tmt:set_size(sw, sh) 119 | pcall(function() 120 | self.proc:write(string.format("\x1bXP%d;%dR\x1b\\", sh, sw)) 121 | end) 122 | end 123 | 124 | -- update blink timer 125 | if self == core.active_view then 126 | local T, t0 = config.blink_period, core.blink_start 127 | local ta, tb = core.blink_timer, system.get_time() 128 | if ((tb - t0) % T < T / 2) ~= ((ta - t0) % T < T / 2) then 129 | core.redraw = true 130 | end 131 | core.blink_timer = tb 132 | end 133 | end 134 | 135 | function TmtView:on_text_input(text) 136 | self:input_string(text) 137 | end 138 | 139 | function TmtView:input_string(str) 140 | if not self.alive then 141 | local node = core.root_view:get_active_node() 142 | node:close_active_view(core.root_view.root_node) 143 | return 144 | end 145 | self.proc:write(str) 146 | end 147 | 148 | function TmtView:get_screen_char_size() 149 | local font = style.code_font 150 | local x = self.size.x - style.padding.x 151 | local y = self.size.y - style.padding.y 152 | return math.max(1, math.floor(x / font:get_width("A"))), 153 | math.max(1, math.floor(y / font:get_height())) 154 | end 155 | 156 | local invisible = { ["\r"] = true, ["\n"] = true, ["\v"] = true, ["\t"] = true, ["\f"] = true, [" "] = true } 157 | function TmtView:draw() 158 | self:draw_background(style.background) 159 | local font = style.code_font 160 | 161 | -- render screen 162 | local screen = self.tmt:get_screen(self.screen) 163 | local ox,oy = self:get_content_offset() 164 | local fw, fh = font:get_width("A"), font:get_height() 165 | 166 | ox, oy = ox + style.padding.x, oy + style.padding.y 167 | for i = 1, screen.width * screen.height do 168 | local cy = math.floor((i - 1) / screen.width) 169 | local cx = (i - 1) % screen.width 170 | 171 | local x, y = ox + cx * fw, oy + cy * fh 172 | local cell = screen[i] 173 | local char = cell.char 174 | if cell.bg > 0 then 175 | renderer.draw_rect(x, y, fw, fh, COLORS[cell.bg]) 176 | end 177 | 178 | local fg = COLORS[cell.fg] or style.syntax.normal 179 | if not invisible[char] then 180 | renderer.draw_text(font, char, x, y, fg) 181 | end 182 | end 183 | 184 | -- render caret 185 | core.blink_timer = system.get_time() 186 | local T = config.blink_period 187 | if system.window_has_focus() then 188 | if config.disable_blink or core.active_view ~= self 189 | or (core.blink_timer - core.blink_start) % T < T / 2 then 190 | local cx, cy = self.tmt:get_cursor() 191 | local x, y = ox + (cx - 1) * fw, oy + (cy - 1) * fh 192 | renderer.draw_rect(x, y, style.caret_width, fh, style.caret) 193 | end 194 | end 195 | end 196 | 197 | -- override input handling 198 | 199 | local macos = PLATFORM == "Mac OS X" 200 | local modkeys_os = require("core.modkeys-" .. (macos and "macos" or "generic")) 201 | local modkey_map = modkeys_os.map 202 | local modkeys = modkeys_os.keys 203 | 204 | local keymap_on_key_pressed = keymap.on_key_pressed 205 | function keymap.on_key_pressed(k, ...) 206 | if not core.active_view:is(TmtView) then 207 | return keymap_on_key_pressed(k, ...) 208 | end 209 | 210 | local mk = modkey_map[k] 211 | if mk then 212 | -- keymap_on_key_pressed(k) 213 | keymap.modkeys[mk] = true 214 | -- work-around for windows where `altgr` is treated as `ctrl+alt` 215 | if mk == "altgr" then 216 | keymap.modkeys["ctrl"] = false 217 | end 218 | else 219 | local actions = { 220 | ["return"] = "\r", 221 | ["up"] = ESC .. "OA", 222 | ["down"] = ESC .. "OB", 223 | ["right"] = ESC .. "OC", 224 | ["left"] = ESC .. "OD", 225 | ["backspace"] = "\x7f", 226 | ["escape"] = "\x1b", 227 | ["tab"] = "\t", 228 | ["space"] = " ", 229 | } 230 | local exceptions = { 231 | ["`"] = true, 232 | } 233 | if actions[k] then 234 | core.active_view:input_string(actions[k]) 235 | return true 236 | elseif keymap.modkeys["ctrl"] and exceptions[k] then 237 | keymap_on_key_pressed(k, ...) 238 | elseif keymap.modkeys["ctrl"] then 239 | local char = string.byte(k) - string.byte('a') + 1 240 | core.active_view:input_string(string.char(char)) 241 | return true 242 | else 243 | return false 244 | end 245 | end 246 | end 247 | 248 | local keymap_on_key_released = keymap.on_key_released 249 | function keymap.on_key_released(k) 250 | local mk = modkey_map[k] 251 | if mk then 252 | keymap_on_key_released(k) 253 | keymap.modkeys[mk] = false 254 | end 255 | end 256 | 257 | local function tmt_split(node, view) 258 | local dir = config.plugins.tmt.split_direction 259 | node:split(dir, view, {}, true) 260 | end 261 | 262 | command.add(nil, { 263 | ["tmt:new"] = function() 264 | local node = core.root_view:get_active_node() 265 | node:add_view(TmtView()) 266 | end, 267 | ["tmt:toggle"] = function() 268 | print("toggle") 269 | if not shared_view then 270 | -- create a terminal 271 | local node = core.root_view:get_active_node() 272 | shared_view = TmtView() 273 | tmt_split(node, shared_view) 274 | core.set_active_view(shared_view) 275 | elseif core.active_view == shared_view then 276 | -- hide the terminal 277 | shared_view.visible = not shared_view.visible 278 | local node = core.root_view:get_active_node() 279 | node:remove_view(core.root_view.root_node, shared_view) 280 | else 281 | -- show and focus the terminal 282 | local node = core.root_view:get_active_node() 283 | if not shared_view.visible then 284 | shared_view.visible = true 285 | tmt_split(node, shared_view) 286 | end 287 | core.set_active_view(shared_view) 288 | end 289 | end, 290 | }) 291 | 292 | keymap.add({ 293 | ["ctrl+t"] = "tmt:new", 294 | ["ctrl+`"] = "tmt:toggle" 295 | }) 296 | -------------------------------------------------------------------------------- /lite_xl_plugin_api.h: -------------------------------------------------------------------------------- 1 | #ifndef LITE_XL_PLUGIN_API 2 | #define LITE_XL_PLUGIN_API 3 | /** 4 | The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long 5 | as it has an entrypoint that looks like the following, where xxxxx is the plugin name: 6 | 7 | #define LITE_XL_PLUGIN_ENTRYPOINT 8 | #include "lite_xl_plugin_api.h" 9 | int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) { 10 | lite_xl_plugin_init(XL); 11 | ... 12 | return 1; 13 | } 14 | 15 | NOTE: `#define LITE_XL_PLUGIN_ENTRYPOINT` needs to be defined only on the 16 | source file where the lite_xl_plugin_init() initialization function is called. 17 | 18 | In linux, to compile this file, you'd do: 'gcc -o xxxxx.so -shared xxxxx.c'. Simple! 19 | Due to the way the API is structured, you *should not* link or include lua libraries. 20 | This file was automatically generated. DO NOT MODIFY DIRECTLY. 21 | 22 | UNLESS you're us, and you had to modify this file manually to get it ready for 2.1. 23 | 24 | Go figure. 25 | 26 | **/ 27 | 28 | 29 | #include 30 | #include // for BUFSIZ? this is kinda weird 31 | #include 32 | 33 | #define SYMBOL_WRAP_DECL(ret, name, ...) \ 34 | ret name(__VA_ARGS__) 35 | 36 | #define SYMBOL_WRAP_CALL(name, ...) \ 37 | return __##name(__VA_ARGS__) 38 | 39 | #define SYMBOL_WRAP_CALL_FB(name, ...) \ 40 | return __lite_xl_fallback_##name(__VA_ARGS__) 41 | 42 | #ifdef LITE_XL_PLUGIN_ENTRYPOINT 43 | #define SYMBOL_DECLARE(ret, name, ...) \ 44 | static ret (*__##name) (__VA_ARGS__); \ 45 | SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); \ 46 | static ret __lite_xl_fallback_##name(__VA_ARGS__) { \ 47 | fputs("warning: " #name " is a stub", stderr); \ 48 | exit(1); \ 49 | } 50 | #else 51 | #define SYMBOL_DECLARE(ret, name, ...) \ 52 | SYMBOL_WRAP_DECL(ret, name, __VA_ARGS__); 53 | #endif 54 | 55 | /** luaconf.h **/ 56 | 57 | #ifndef lconfig_h 58 | #define lconfig_h 59 | #include 60 | #include 61 | #if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) 62 | #define LUA_ANSI 63 | #endif 64 | #if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) 65 | #define LUA_WIN 66 | #endif 67 | #if defined(LUA_WIN) 68 | #define LUA_DL_DLL 69 | #define LUA_USE_AFORMAT 70 | #endif 71 | #if defined(LUA_USE_LINUX) 72 | #define LUA_USE_POSIX 73 | #define LUA_USE_DLOPEN 74 | #define LUA_USE_READLINE 75 | #define LUA_USE_STRTODHEX 76 | #define LUA_USE_AFORMAT 77 | #define LUA_USE_LONGLONG 78 | #endif 79 | #if defined(LUA_USE_MACOSX) 80 | #define LUA_USE_POSIX 81 | #define LUA_USE_DLOPEN 82 | #define LUA_USE_READLINE 83 | #define LUA_USE_STRTODHEX 84 | #define LUA_USE_AFORMAT 85 | #define LUA_USE_LONGLONG 86 | #endif 87 | #if defined(LUA_USE_POSIX) 88 | #define LUA_USE_MKSTEMP 89 | #define LUA_USE_ISATTY 90 | #define LUA_USE_POPEN 91 | #define LUA_USE_ULONGJMP 92 | #define LUA_USE_GMTIME_R 93 | #endif 94 | #if defined(_WIN32) 95 | #define LUA_LDIR "!\\lua\\" 96 | #define LUA_CDIR "!\\" 97 | #define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" 98 | #define LUA_CPATH_DEFAULT LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" 99 | #else 100 | #define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" 101 | #define LUA_ROOT "/usr/local/" 102 | #define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR 103 | #define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR 104 | #define LUA_PATH_DEFAULT LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" 105 | #define LUA_CPATH_DEFAULT LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" 106 | #endif 107 | #if defined(_WIN32) 108 | #define LUA_DIRSEP "\\" 109 | #else 110 | #define LUA_DIRSEP "/" 111 | #endif 112 | #define LUA_ENV "_ENV" 113 | #if defined(LUA_BUILD_AS_DLL) 114 | #if defined(LUA_CORE) || defined(LUA_LIB) 115 | #define LUA_API __declspec(dllexport) 116 | #else 117 | #define LUA_API __declspec(dllimport) 118 | #endif 119 | #else 120 | #define LUA_API extern 121 | #endif 122 | #define LUALIB_API LUA_API 123 | #define LUAMOD_API LUALIB_API 124 | #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && defined(__ELF__) 125 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern 126 | #define LUAI_DDEC LUAI_FUNC 127 | #define LUAI_DDEF 128 | #else 129 | #define LUAI_FUNC extern 130 | #define LUAI_DDEC extern 131 | #define LUAI_DDEF 132 | #endif 133 | #define LUA_QL(x) "'" x "'" 134 | #define LUA_QS LUA_QL("%s") 135 | #define LUA_IDSIZE 60 136 | #if defined(LUA_LIB) || defined(lua_c) 137 | #include 138 | #define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) 139 | #define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) 140 | #endif 141 | #define luai_writestringerror(s,p) (fprintf(stderr, (s), (p)), fflush(stderr)) 142 | #define LUAI_MAXSHORTLEN 40 143 | #if defined(LUA_COMPAT_ALL) 144 | #define LUA_COMPAT_UNPACK 145 | #define LUA_COMPAT_LOADERS 146 | #define lua_cpcall(L,f,u) (lua_pushcfunction(L, (f)), lua_pushlightuserdata(L,(u)), lua_pcall(L,1,0,0)) 147 | #define LUA_COMPAT_LOG10 148 | #define LUA_COMPAT_LOADSTRING 149 | #define LUA_COMPAT_MAXN 150 | #define lua_strlen(L,i) lua_rawlen(L, (i)) 151 | #define lua_objlen(L,i) lua_rawlen(L, (i)) 152 | #define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) 153 | #define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) 154 | #define LUA_COMPAT_MODULE 155 | #endif 156 | #if INT_MAX-20 < 32760 157 | #define LUAI_BITSINT 16 158 | #elif INT_MAX > 2147483640L 159 | #define LUAI_BITSINT 32 160 | #else 161 | #error "you must define LUA_BITSINT with number of bits in an integer" 162 | #endif 163 | #if LUAI_BITSINT >= 32 164 | #define LUA_INT32 int 165 | #define LUAI_UMEM size_t 166 | #define LUAI_MEM ptrdiff_t 167 | #else 168 | #define LUA_INT32 long 169 | #define LUAI_UMEM unsigned long 170 | #define LUAI_MEM long 171 | #endif 172 | #if LUAI_BITSINT >= 32 173 | #define LUAI_MAXSTACK 1000000 174 | #else 175 | #define LUAI_MAXSTACK 15000 176 | #endif 177 | #define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) 178 | #define LUAL_BUFFERSIZE BUFSIZ 179 | #define LUA_NUMBER_DOUBLE 180 | #define LUA_NUMBER double 181 | #define LUAI_UACNUMBER double 182 | #define LUA_NUMBER_SCAN "%lf" 183 | #define LUA_NUMBER_FMT "%.14g" 184 | #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) 185 | #define LUAI_MAXNUMBER2STR 32 186 | #define l_mathop(x) (x) 187 | #define lua_str2number(s,p) strtod((s), (p)) 188 | #if defined(LUA_USE_STRTODHEX) 189 | #define lua_strx2number(s,p) strtod((s), (p)) 190 | #endif 191 | #if defined(lobject_c) || defined(lvm_c) 192 | #include 193 | #define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) 194 | #define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) 195 | #endif 196 | #if defined(LUA_CORE) 197 | #define luai_numadd(L,a,b) ((a)+(b)) 198 | #define luai_numsub(L,a,b) ((a)-(b)) 199 | #define luai_nummul(L,a,b) ((a)*(b)) 200 | #define luai_numdiv(L,a,b) ((a)/(b)) 201 | #define luai_numunm(L,a) (-(a)) 202 | #define luai_numeq(a,b) ((a)==(b)) 203 | #define luai_numlt(L,a,b) ((a)<(b)) 204 | #define luai_numle(L,a,b) ((a)<=(b)) 205 | #define luai_numisnan(L,a) (!luai_numeq((a), (a))) 206 | #endif 207 | #define LUA_INTEGER ptrdiff_t 208 | #define LUA_UNSIGNED unsigned LUA_INT32 209 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) 210 | #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) 211 | #define LUA_MSASMTRICK 212 | #define LUA_IEEEENDIAN 0 213 | #define LUA_NANTRICK 214 | #elif defined(__i386__) || defined(__i386) || defined(__X86__) 215 | #define LUA_IEEE754TRICK 216 | #define LUA_IEEELL 217 | #define LUA_IEEEENDIAN 0 218 | #define LUA_NANTRICK 219 | #elif defined(__x86_64) 220 | #define LUA_IEEE754TRICK 221 | #define LUA_IEEEENDIAN 0 222 | #elif defined(__POWERPC__) || defined(__ppc__) 223 | #define LUA_IEEE754TRICK 224 | #define LUA_IEEEENDIAN 1 225 | #else 226 | #define LUA_IEEE754TRICK 227 | #endif 228 | #endif 229 | #endif 230 | 231 | /** lua.h **/ 232 | 233 | typedef struct lua_State lua_State; 234 | typedef int (*lua_CFunction) (lua_State *L); 235 | typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); 236 | typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); 237 | typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); 238 | typedef LUA_NUMBER lua_Number; 239 | typedef LUA_INTEGER lua_Integer; 240 | typedef LUA_UNSIGNED lua_Unsigned; 241 | typedef struct lua_Debug lua_Debug; 242 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); 243 | struct lua_Debug { 244 | int event; 245 | const char *name; 246 | const char *namewhat; 247 | const char *what; 248 | const char *source; 249 | int currentline; 250 | int linedefined; 251 | int lastlinedefined; 252 | unsigned char nups; 253 | unsigned char nparams; 254 | char isvararg; 255 | char istailcall; 256 | char short_src[LUA_IDSIZE]; 257 | struct CallInfo *i_ci; 258 | }; 259 | 260 | SYMBOL_DECLARE(lua_State *, lua_newstate, lua_Alloc f, void *ud) 261 | SYMBOL_DECLARE(void, lua_close, lua_State *L) 262 | SYMBOL_DECLARE(lua_State *, lua_newthread, lua_State *L) 263 | SYMBOL_DECLARE(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf) 264 | SYMBOL_DECLARE(const lua_Number *, lua_version, lua_State *L) 265 | SYMBOL_DECLARE(int, lua_absindex, lua_State *L, int idx) 266 | SYMBOL_DECLARE(int, lua_gettop, lua_State *L) 267 | SYMBOL_DECLARE(void, lua_settop, lua_State *L, int idx) 268 | SYMBOL_DECLARE(void, lua_pushvalue, lua_State *L, int idx) 269 | SYMBOL_DECLARE(void, lua_copy, lua_State *L, int fromidx, int toidx) 270 | SYMBOL_DECLARE(int, lua_checkstack, lua_State *L, int sz) 271 | SYMBOL_DECLARE(void, lua_xmove, lua_State *from, lua_State *to, int n) 272 | SYMBOL_DECLARE(int, lua_isnumber, lua_State *L, int idx) 273 | SYMBOL_DECLARE(int, lua_isstring, lua_State *L, int idx) 274 | SYMBOL_DECLARE(int, lua_iscfunction, lua_State *L, int idx) 275 | SYMBOL_DECLARE(int, lua_isuserdata, lua_State *L, int idx) 276 | SYMBOL_DECLARE(int, lua_type, lua_State *L, int idx) 277 | SYMBOL_DECLARE(const char *, lua_typename, lua_State *L, int tp) 278 | SYMBOL_DECLARE(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum) 279 | SYMBOL_DECLARE(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum) 280 | SYMBOL_DECLARE(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum) 281 | SYMBOL_DECLARE(int, lua_toboolean, lua_State *L, int idx) 282 | SYMBOL_DECLARE(const char *, lua_tolstring, lua_State *L, int idx, size_t *len) 283 | SYMBOL_DECLARE(size_t, lua_rawlen, lua_State *L, int idx) 284 | SYMBOL_DECLARE(lua_CFunction, lua_tocfunction, lua_State *L, int idx) 285 | SYMBOL_DECLARE(void *, lua_touserdata, lua_State *L, int idx) 286 | SYMBOL_DECLARE(lua_State *, lua_tothread, lua_State *L, int idx) 287 | SYMBOL_DECLARE(const void *, lua_topointer, lua_State *L, int idx) 288 | SYMBOL_DECLARE(void, lua_arith, lua_State *L, int op) 289 | SYMBOL_DECLARE(int, lua_rawequal, lua_State *L, int idx1, int idx2) 290 | SYMBOL_DECLARE(int, lua_compare, lua_State *L, int idx1, int idx2, int op) 291 | SYMBOL_DECLARE(void, lua_pushnil, lua_State *L) 292 | SYMBOL_DECLARE(void, lua_pushnumber, lua_State *L, lua_Number n) 293 | SYMBOL_DECLARE(void, lua_pushinteger, lua_State *L, lua_Integer n) 294 | SYMBOL_DECLARE(void, lua_pushunsigned, lua_State *L, lua_Unsigned n) 295 | SYMBOL_DECLARE(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l) 296 | SYMBOL_DECLARE(const char *, lua_pushstring, lua_State *L, const char *s) 297 | SYMBOL_DECLARE(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp) 298 | SYMBOL_DECLARE(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...) 299 | SYMBOL_DECLARE(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n) 300 | SYMBOL_DECLARE(void, lua_pushboolean, lua_State *L, int b) 301 | SYMBOL_DECLARE(void, lua_pushlightuserdata, lua_State *L, void *p) 302 | SYMBOL_DECLARE(int, lua_pushthread, lua_State *L) 303 | SYMBOL_DECLARE(void, lua_getglobal, lua_State *L, const char *var) 304 | SYMBOL_DECLARE(void, lua_gettable, lua_State *L, int idx) 305 | SYMBOL_DECLARE(void, lua_getfield, lua_State *L, int idx, const char *k) 306 | SYMBOL_DECLARE(void, lua_rawget, lua_State *L, int idx) 307 | SYMBOL_DECLARE(void, lua_rawgeti, lua_State *L, int idx, int n) 308 | SYMBOL_DECLARE(void, lua_rawgetp, lua_State *L, int idx, const void *p) 309 | SYMBOL_DECLARE(void, lua_createtable, lua_State *L, int narr, int nrec) 310 | SYMBOL_DECLARE(void *, lua_newuserdata, lua_State *L, size_t sz) 311 | SYMBOL_DECLARE(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue) 312 | SYMBOL_DECLARE(size_t, lua_objlen, lua_State *L, int idx) 313 | SYMBOL_DECLARE(int, lua_getmetatable, lua_State *L, int objindex) 314 | SYMBOL_DECLARE(void, lua_getuservalue, lua_State *L, int idx) 315 | SYMBOL_DECLARE(void, lua_getiuservalue, lua_State *L, int idx, int n) 316 | SYMBOL_DECLARE(void, lua_setglobal, lua_State *L, const char *var) 317 | SYMBOL_DECLARE(void, lua_settable, lua_State *L, int idx) 318 | SYMBOL_DECLARE(void, lua_setfield, lua_State *L, int idx, const char *k) 319 | SYMBOL_DECLARE(void, lua_rawset, lua_State *L, int idx) 320 | SYMBOL_DECLARE(void, lua_rawseti, lua_State *L, int idx, int n) 321 | SYMBOL_DECLARE(void, lua_rawsetp, lua_State *L, int idx, const void *p) 322 | SYMBOL_DECLARE(int, lua_setmetatable, lua_State *L, int objindex) 323 | SYMBOL_DECLARE(void, lua_setuservalue, lua_State *L, int idx) 324 | SYMBOL_DECLARE(void, lua_setiuservalue, lua_State *L, int idx, int n) 325 | SYMBOL_DECLARE(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k) 326 | SYMBOL_DECLARE(int, lua_getctx, lua_State *L, int *ctx) 327 | SYMBOL_DECLARE(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k) 328 | SYMBOL_DECLARE(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) 329 | SYMBOL_DECLARE(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip) 330 | SYMBOL_DECLARE(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k) 331 | SYMBOL_DECLARE(int, lua_resume, lua_State *L, lua_State *from, int narg) 332 | SYMBOL_DECLARE(int, lua_status, lua_State *L) 333 | SYMBOL_DECLARE(int, lua_gc, lua_State *L, int what, int data) 334 | SYMBOL_DECLARE(int, lua_error, lua_State *L) 335 | SYMBOL_DECLARE(int, lua_next, lua_State *L, int idx) 336 | SYMBOL_DECLARE(void, lua_concat, lua_State *L, int n) 337 | SYMBOL_DECLARE(void, lua_len, lua_State *L, int idx) 338 | SYMBOL_DECLARE(lua_Alloc, lua_getallocf, lua_State *L, void **ud) 339 | SYMBOL_DECLARE(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud) 340 | SYMBOL_DECLARE(int, lua_getstack, lua_State *L, int level, lua_Debug *ar) 341 | SYMBOL_DECLARE(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar) 342 | SYMBOL_DECLARE(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n) 343 | SYMBOL_DECLARE(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n) 344 | SYMBOL_DECLARE(const char *, lua_getupvalue, lua_State *L, int funcindex, int n) 345 | SYMBOL_DECLARE(const char *, lua_setupvalue, lua_State *L, int funcindex, int n) 346 | SYMBOL_DECLARE(void *, lua_upvalueid, lua_State *L, int fidx, int n) 347 | SYMBOL_DECLARE(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2) 348 | SYMBOL_DECLARE(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count) 349 | SYMBOL_DECLARE(lua_Hook, lua_gethook, lua_State *L) 350 | SYMBOL_DECLARE(int, lua_gethookmask, lua_State *L) 351 | SYMBOL_DECLARE(int, lua_gethookcount, lua_State *L) 352 | 353 | #define lua_h 354 | #define LUA_VERSION_MAJOR "5" 355 | #define LUA_VERSION_MINOR "4" 356 | #define LUA_VERSION_NUM 504 357 | #define LUA_VERSION_RELEASE "4" 358 | #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR 359 | #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE 360 | #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio" 361 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" 362 | #define LUA_SIGNATURE "\033Lua" 363 | #define LUA_MULTRET (-1) 364 | #define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX 365 | #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) 366 | #define LUA_OK 0 367 | #define LUA_YIELD 1 368 | #define LUA_ERRRUN 2 369 | #define LUA_ERRSYNTAX 3 370 | #define LUA_ERRMEM 4 371 | #define LUA_ERRGCMM 5 372 | #define LUA_ERRERR 6 373 | #define LUA_TNONE (-1) 374 | #define LUA_TNIL 0 375 | #define LUA_TBOOLEAN 1 376 | #define LUA_TLIGHTUSERDATA 2 377 | #define LUA_TNUMBER 3 378 | #define LUA_TSTRING 4 379 | #define LUA_TTABLE 5 380 | #define LUA_TFUNCTION 6 381 | #define LUA_TUSERDATA 7 382 | #define LUA_TTHREAD 8 383 | #define LUA_NUMTAGS 9 384 | #define LUA_MINSTACK 20 385 | #define LUA_RIDX_MAINTHREAD 1 386 | #define LUA_RIDX_GLOBALS 2 387 | #define LUA_RIDX_LAST LUA_RIDX_GLOBALS 388 | #define LUA_OPADD 0 389 | #define LUA_OPSUB 1 390 | #define LUA_OPMUL 2 391 | #define LUA_OPDIV 3 392 | #define LUA_OPMOD 4 393 | #define LUA_OPPOW 5 394 | #define LUA_OPUNM 6 395 | #define LUA_OPEQ 0 396 | #define LUA_OPLT 1 397 | #define LUA_OPLE 2 398 | #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) 399 | #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) 400 | #define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) 401 | #define LUA_GCSTOP 0 402 | #define LUA_GCRESTART 1 403 | #define LUA_GCCOLLECT 2 404 | #define LUA_GCCOUNT 3 405 | #define LUA_GCCOUNTB 4 406 | #define LUA_GCSTEP 5 407 | #define LUA_GCSETPAUSE 6 408 | #define LUA_GCSETSTEPMUL 7 409 | #define LUA_GCSETMAJORINC 8 410 | #define LUA_GCISRUNNING 9 411 | #define LUA_GCGEN 10 412 | #define LUA_GCINC 11 413 | #define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) 414 | #define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) 415 | #define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) 416 | #define lua_pop(L,n) lua_settop(L, -(n)-1) 417 | #define lua_newtable(L) lua_createtable(L, 0, 0) 418 | #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) 419 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) 420 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) 421 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) 422 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) 423 | #define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) 424 | #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) 425 | #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) 426 | #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) 427 | #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) 428 | #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) 429 | #define lua_pushglobaltable(L) lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) 430 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) 431 | #define lua_insert(L,idx) lua_rotate(L, (idx), 1) 432 | #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) 433 | #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) 434 | #define LUA_HOOKCALL 0 435 | #define LUA_HOOKRET 1 436 | #define LUA_HOOKLINE 2 437 | #define LUA_HOOKCOUNT 3 438 | #define LUA_HOOKTAILCALL 4 439 | #define LUA_MASKCALL (1 << LUA_HOOKCALL) 440 | #define LUA_MASKRET (1 << LUA_HOOKRET) 441 | #define LUA_MASKLINE (1 << LUA_HOOKLINE) 442 | #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) 443 | 444 | /** lauxlib.h **/ 445 | 446 | typedef struct luaL_Reg { 447 | const char *name; 448 | lua_CFunction func; 449 | } luaL_Reg; 450 | typedef struct luaL_Buffer { 451 | char *b; 452 | size_t size; 453 | size_t n; 454 | lua_State *L; 455 | char initb[LUAL_BUFFERSIZE]; 456 | } luaL_Buffer; 457 | typedef struct luaL_Stream { 458 | FILE *f; 459 | lua_CFunction closef; 460 | } luaL_Stream; 461 | 462 | SYMBOL_DECLARE(void, luaL_checkversion_, lua_State *L, lua_Number ver) 463 | SYMBOL_DECLARE(int, luaL_getmetafield, lua_State *L, int obj, const char *e) 464 | SYMBOL_DECLARE(int, luaL_callmeta, lua_State *L, int obj, const char *e) 465 | SYMBOL_DECLARE(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len) 466 | SYMBOL_DECLARE(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg) 467 | SYMBOL_DECLARE(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l) 468 | SYMBOL_DECLARE(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l) 469 | SYMBOL_DECLARE(lua_Number, luaL_checknumber, lua_State *L, int numArg) 470 | SYMBOL_DECLARE(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def) 471 | SYMBOL_DECLARE(lua_Integer, luaL_checkinteger, lua_State *L, int numArg) 472 | SYMBOL_DECLARE(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def) 473 | SYMBOL_DECLARE(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg) 474 | SYMBOL_DECLARE(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def) 475 | SYMBOL_DECLARE(void, luaL_checkstack, lua_State *L, int sz, const char *msg) 476 | SYMBOL_DECLARE(void, luaL_checktype, lua_State *L, int narg, int t) 477 | SYMBOL_DECLARE(void, luaL_checkany, lua_State *L, int narg) 478 | SYMBOL_DECLARE(int, luaL_newmetatable, lua_State *L, const char *tname) 479 | SYMBOL_DECLARE(void, luaL_setmetatable, lua_State *L, const char *tname) 480 | SYMBOL_DECLARE(void *, luaL_testudata, lua_State *L, int ud, const char *tname) 481 | SYMBOL_DECLARE(void *, luaL_checkudata, lua_State *L, int ud, const char *tname) 482 | SYMBOL_DECLARE(void, luaL_where, lua_State *L, int lvl) 483 | SYMBOL_DECLARE(int, luaL_error, lua_State *L, const char *fmt, ...) 484 | SYMBOL_DECLARE(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]) 485 | SYMBOL_DECLARE(int, luaL_fileresult, lua_State *L, int stat, const char *fname) 486 | SYMBOL_DECLARE(int, luaL_execresult, lua_State *L, int stat) 487 | SYMBOL_DECLARE(int, luaL_ref, lua_State *L, int t) 488 | SYMBOL_DECLARE(void, luaL_unref, lua_State *L, int t, int ref) 489 | SYMBOL_DECLARE(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode) 490 | SYMBOL_DECLARE(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) 491 | SYMBOL_DECLARE(int, luaL_loadstring, lua_State *L, const char *s) 492 | SYMBOL_DECLARE(lua_State *, luaL_newstate, void) 493 | SYMBOL_DECLARE(int, luaL_len, lua_State *L, int idx) 494 | SYMBOL_DECLARE(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r) 495 | SYMBOL_DECLARE(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup) 496 | SYMBOL_DECLARE(int, luaL_getsubtable, lua_State *L, int idx, const char *fname) 497 | SYMBOL_DECLARE(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level) 498 | SYMBOL_DECLARE(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb) 499 | SYMBOL_DECLARE(void, luaL_buffinit, lua_State *L, luaL_Buffer *B) 500 | SYMBOL_DECLARE(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz) 501 | SYMBOL_DECLARE(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l) 502 | SYMBOL_DECLARE(void, luaL_addstring, luaL_Buffer *B, const char *s) 503 | SYMBOL_DECLARE(void, luaL_addvalue, luaL_Buffer *B) 504 | SYMBOL_DECLARE(void, luaL_pushresult, luaL_Buffer *B) 505 | SYMBOL_DECLARE(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz) 506 | SYMBOL_DECLARE(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz) 507 | SYMBOL_DECLARE(void, luaL_openlibs, lua_State *L) 508 | 509 | #define lauxlib_h 510 | #define LUA_ERRFILE (LUA_ERRERR+1) 511 | #define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) 512 | #define LUA_NOREF (-2) 513 | #define LUA_REFNIL (-1) 514 | #define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) 515 | #define luaL_newlibtable(L,l) lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) 516 | #define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) 517 | #define luaL_argcheck(L, cond,numarg,extramsg) ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) 518 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) 519 | #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) 520 | #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) 521 | #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) 522 | #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) 523 | #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) 524 | #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) 525 | #define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) 526 | #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) 527 | #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) 528 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) 529 | #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) 530 | #define luaL_addchar(B,c) ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), ((B)->b[(B)->n++] = (c))) 531 | #define luaL_addsize(B,s) ((B)->n += (s)) 532 | #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) 533 | #define LUA_FILEHANDLE "FILE*" 534 | 535 | #ifdef LITE_XL_PLUGIN_ENTRYPOINT 536 | 537 | SYMBOL_WRAP_DECL(lua_State *, lua_newstate, lua_Alloc f, void *ud){ 538 | SYMBOL_WRAP_CALL(lua_newstate, f, ud); 539 | } 540 | SYMBOL_WRAP_DECL(void, lua_close, lua_State *L){ 541 | SYMBOL_WRAP_CALL(lua_close, L); 542 | } 543 | SYMBOL_WRAP_DECL(lua_State *, lua_newthread, lua_State *L){ 544 | SYMBOL_WRAP_CALL(lua_newthread, L); 545 | } 546 | SYMBOL_WRAP_DECL(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf){ 547 | SYMBOL_WRAP_CALL(lua_atpanic, L, panicf); 548 | } 549 | SYMBOL_WRAP_DECL(const lua_Number *, lua_version, lua_State *L){ 550 | SYMBOL_WRAP_CALL(lua_version, L); 551 | } 552 | SYMBOL_WRAP_DECL(int, lua_absindex, lua_State *L, int idx){ 553 | SYMBOL_WRAP_CALL(lua_absindex, L, idx); 554 | } 555 | SYMBOL_WRAP_DECL(int, lua_gettop, lua_State *L){ 556 | SYMBOL_WRAP_CALL(lua_gettop, L); 557 | } 558 | SYMBOL_WRAP_DECL(void, lua_settop, lua_State *L, int idx){ 559 | SYMBOL_WRAP_CALL(lua_settop, L, idx); 560 | } 561 | SYMBOL_WRAP_DECL(void, lua_pushvalue, lua_State *L, int idx){ 562 | SYMBOL_WRAP_CALL(lua_pushvalue, L, idx); 563 | } 564 | SYMBOL_WRAP_DECL(void, lua_copy, lua_State *L, int fromidx, int toidx){ 565 | SYMBOL_WRAP_CALL(lua_copy, L, fromidx, toidx); 566 | } 567 | SYMBOL_WRAP_DECL(int, lua_checkstack, lua_State *L, int sz){ 568 | SYMBOL_WRAP_CALL(lua_checkstack, L, sz); 569 | } 570 | SYMBOL_WRAP_DECL(void, lua_xmove, lua_State *from, lua_State *to, int n){ 571 | SYMBOL_WRAP_CALL(lua_xmove, from, to, n); 572 | } 573 | SYMBOL_WRAP_DECL(int, lua_isnumber, lua_State *L, int idx){ 574 | SYMBOL_WRAP_CALL(lua_isnumber, L, idx); 575 | } 576 | SYMBOL_WRAP_DECL(int, lua_isstring, lua_State *L, int idx){ 577 | SYMBOL_WRAP_CALL(lua_isstring, L, idx); 578 | } 579 | SYMBOL_WRAP_DECL(int, lua_iscfunction, lua_State *L, int idx){ 580 | SYMBOL_WRAP_CALL(lua_iscfunction, L, idx); 581 | } 582 | SYMBOL_WRAP_DECL(int, lua_isuserdata, lua_State *L, int idx){ 583 | SYMBOL_WRAP_CALL(lua_isuserdata, L, idx); 584 | } 585 | SYMBOL_WRAP_DECL(int, lua_type, lua_State *L, int idx){ 586 | SYMBOL_WRAP_CALL(lua_type, L, idx); 587 | } 588 | SYMBOL_WRAP_DECL(const char *, lua_typename, lua_State *L, int tp){ 589 | SYMBOL_WRAP_CALL(lua_typename, L, tp); 590 | } 591 | SYMBOL_WRAP_DECL(lua_Number, lua_tonumberx, lua_State *L, int idx, int *isnum){ 592 | SYMBOL_WRAP_CALL(lua_tonumberx, L, idx, isnum); 593 | } 594 | SYMBOL_WRAP_DECL(lua_Integer, lua_tointegerx, lua_State *L, int idx, int *isnum){ 595 | SYMBOL_WRAP_CALL(lua_tointegerx, L, idx, isnum); 596 | } 597 | SYMBOL_WRAP_DECL(lua_Unsigned, lua_tounsignedx, lua_State *L, int idx, int *isnum){ 598 | SYMBOL_WRAP_CALL(lua_tounsignedx, L, idx, isnum); 599 | } 600 | SYMBOL_WRAP_DECL(int, lua_toboolean, lua_State *L, int idx){ 601 | SYMBOL_WRAP_CALL(lua_toboolean, L, idx); 602 | } 603 | SYMBOL_WRAP_DECL(const char *, lua_tolstring, lua_State *L, int idx, size_t *len){ 604 | SYMBOL_WRAP_CALL(lua_tolstring, L, idx, len); 605 | } 606 | SYMBOL_WRAP_DECL(size_t, lua_rawlen, lua_State *L, int idx){ 607 | SYMBOL_WRAP_CALL(lua_rawlen, L, idx); 608 | } 609 | SYMBOL_WRAP_DECL(lua_CFunction, lua_tocfunction, lua_State *L, int idx){ 610 | SYMBOL_WRAP_CALL(lua_tocfunction, L, idx); 611 | } 612 | SYMBOL_WRAP_DECL(void *, lua_touserdata, lua_State *L, int idx){ 613 | SYMBOL_WRAP_CALL(lua_touserdata, L, idx); 614 | } 615 | SYMBOL_WRAP_DECL(lua_State *, lua_tothread, lua_State *L, int idx){ 616 | SYMBOL_WRAP_CALL(lua_tothread, L, idx); 617 | } 618 | SYMBOL_WRAP_DECL(const void *, lua_topointer, lua_State *L, int idx){ 619 | SYMBOL_WRAP_CALL(lua_topointer, L, idx); 620 | } 621 | SYMBOL_WRAP_DECL(void, lua_arith, lua_State *L, int op){ 622 | SYMBOL_WRAP_CALL(lua_arith, L, op); 623 | } 624 | SYMBOL_WRAP_DECL(int, lua_rawequal, lua_State *L, int idx1, int idx2){ 625 | SYMBOL_WRAP_CALL(lua_rawequal, L, idx1, idx2); 626 | } 627 | SYMBOL_WRAP_DECL(int, lua_compare, lua_State *L, int idx1, int idx2, int op){ 628 | SYMBOL_WRAP_CALL(lua_compare, L, idx1, idx2, op); 629 | } 630 | SYMBOL_WRAP_DECL(void, lua_pushnil, lua_State *L){ 631 | SYMBOL_WRAP_CALL(lua_pushnil, L); 632 | } 633 | SYMBOL_WRAP_DECL(void, lua_pushnumber, lua_State *L, lua_Number n){ 634 | SYMBOL_WRAP_CALL(lua_pushnumber, L, n); 635 | } 636 | SYMBOL_WRAP_DECL(void, lua_pushinteger, lua_State *L, lua_Integer n){ 637 | SYMBOL_WRAP_CALL(lua_pushinteger, L, n); 638 | } 639 | SYMBOL_WRAP_DECL(void, lua_pushunsigned, lua_State *L, lua_Unsigned n){ 640 | SYMBOL_WRAP_CALL(lua_pushunsigned, L, n); 641 | } 642 | SYMBOL_WRAP_DECL(const char *, lua_pushlstring, lua_State *L, const char *s, size_t l){ 643 | SYMBOL_WRAP_CALL(lua_pushlstring, L, s, l); 644 | } 645 | SYMBOL_WRAP_DECL(const char *, lua_pushstring, lua_State *L, const char *s){ 646 | SYMBOL_WRAP_CALL(lua_pushstring, L, s); 647 | } 648 | SYMBOL_WRAP_DECL(const char *, lua_pushvfstring, lua_State *L, const char *fmt, va_list argp){ 649 | SYMBOL_WRAP_CALL(lua_pushvfstring, L, fmt, argp); 650 | } 651 | SYMBOL_WRAP_DECL(const char *, lua_pushfstring, lua_State *L, const char *fmt, ...){ 652 | SYMBOL_WRAP_CALL(lua_pushfstring, L, fmt); 653 | } 654 | SYMBOL_WRAP_DECL(void, lua_pushcclosure, lua_State *L, lua_CFunction fn, int n){ 655 | SYMBOL_WRAP_CALL(lua_pushcclosure, L, fn, n); 656 | } 657 | SYMBOL_WRAP_DECL(void, lua_pushboolean, lua_State *L, int b){ 658 | SYMBOL_WRAP_CALL(lua_pushboolean, L, b); 659 | } 660 | SYMBOL_WRAP_DECL(void, lua_pushlightuserdata, lua_State *L, void *p){ 661 | SYMBOL_WRAP_CALL(lua_pushlightuserdata, L, p); 662 | } 663 | SYMBOL_WRAP_DECL(int, lua_pushthread, lua_State *L){ 664 | SYMBOL_WRAP_CALL(lua_pushthread, L); 665 | } 666 | SYMBOL_WRAP_DECL(void, lua_getglobal, lua_State *L, const char *var){ 667 | SYMBOL_WRAP_CALL(lua_getglobal, L, var); 668 | } 669 | SYMBOL_WRAP_DECL(void, lua_gettable, lua_State *L, int idx){ 670 | SYMBOL_WRAP_CALL(lua_gettable, L, idx); 671 | } 672 | SYMBOL_WRAP_DECL(void, lua_getfield, lua_State *L, int idx, const char *k){ 673 | SYMBOL_WRAP_CALL(lua_getfield, L, idx, k); 674 | } 675 | SYMBOL_WRAP_DECL(void, lua_rawget, lua_State *L, int idx){ 676 | SYMBOL_WRAP_CALL(lua_rawget, L, idx); 677 | } 678 | SYMBOL_WRAP_DECL(void, lua_rawgeti, lua_State *L, int idx, int n){ 679 | SYMBOL_WRAP_CALL(lua_rawgeti, L, idx, n); 680 | } 681 | SYMBOL_WRAP_DECL(void, lua_rawgetp, lua_State *L, int idx, const void *p){ 682 | SYMBOL_WRAP_CALL(lua_rawgetp, L, idx, p); 683 | } 684 | SYMBOL_WRAP_DECL(void, lua_createtable, lua_State *L, int narr, int nrec){ 685 | SYMBOL_WRAP_CALL(lua_createtable, L, narr, nrec); 686 | } 687 | SYMBOL_WRAP_DECL(void *, lua_newuserdata, lua_State *L, size_t sz){ 688 | printf("called newuserdata non-uv\n"); 689 | if (__lua_newuserdatauv != __lite_xl_fallback_lua_newuserdatauv) { 690 | return lua_newuserdatauv(L, sz, 1); 691 | } else if (__lua_newuserdata != NULL) { 692 | SYMBOL_WRAP_CALL(lua_newuserdata, L, sz); 693 | } 694 | SYMBOL_WRAP_CALL_FB(lua_newuserdata, L, sz); 695 | } 696 | SYMBOL_WRAP_DECL(size_t, lua_objlen, lua_State *L, int idx){ 697 | if (__lua_rawlen != __lite_xl_fallback_lua_rawlen) { 698 | return lua_rawlen(L, idx); 699 | } else { 700 | SYMBOL_WRAP_CALL(lua_objlen, L, idx); 701 | } 702 | SYMBOL_WRAP_CALL_FB(lua_objlen, L, idx); 703 | } 704 | SYMBOL_WRAP_DECL(void *, lua_newuserdatauv, lua_State *L, size_t sz, int nuvalue){ 705 | SYMBOL_WRAP_CALL(lua_newuserdatauv, L, sz, nuvalue); 706 | } 707 | SYMBOL_WRAP_DECL(int, lua_getmetatable, lua_State *L, int objindex){ 708 | SYMBOL_WRAP_CALL(lua_getmetatable, L, objindex); 709 | } 710 | SYMBOL_WRAP_DECL(void, lua_getuservalue, lua_State *L, int idx){ 711 | if (__lua_getiuservalue != NULL) { 712 | return lua_getiuservalue(L, idx, 1); 713 | } else if (__lua_getuservalue != NULL) { 714 | SYMBOL_WRAP_CALL(lua_getuservalue, L, idx); 715 | } 716 | SYMBOL_WRAP_CALL_FB(lua_getuservalue, L, idx); 717 | } 718 | SYMBOL_WRAP_DECL(void, lua_getiuservalue, lua_State *L, int idx, int n){ 719 | SYMBOL_WRAP_CALL(lua_getiuservalue, L, idx, n); 720 | } 721 | SYMBOL_WRAP_DECL(void, lua_setglobal, lua_State *L, const char *var){ 722 | SYMBOL_WRAP_CALL(lua_setglobal, L, var); 723 | } 724 | SYMBOL_WRAP_DECL(void, lua_settable, lua_State *L, int idx){ 725 | SYMBOL_WRAP_CALL(lua_settable, L, idx); 726 | } 727 | SYMBOL_WRAP_DECL(void, lua_setfield, lua_State *L, int idx, const char *k){ 728 | SYMBOL_WRAP_CALL(lua_setfield, L, idx, k); 729 | } 730 | SYMBOL_WRAP_DECL(void, lua_rawset, lua_State *L, int idx){ 731 | SYMBOL_WRAP_CALL(lua_rawset, L, idx); 732 | } 733 | SYMBOL_WRAP_DECL(void, lua_rawseti, lua_State *L, int idx, int n){ 734 | SYMBOL_WRAP_CALL(lua_rawseti, L, idx, n); 735 | } 736 | SYMBOL_WRAP_DECL(void, lua_rawsetp, lua_State *L, int idx, const void *p){ 737 | SYMBOL_WRAP_CALL(lua_rawsetp, L, idx, p); 738 | } 739 | SYMBOL_WRAP_DECL(int, lua_setmetatable, lua_State *L, int objindex){ 740 | SYMBOL_WRAP_CALL(lua_setmetatable, L, objindex); 741 | } 742 | SYMBOL_WRAP_DECL(void, lua_setuservalue, lua_State *L, int idx){ 743 | if (__lua_setiuservalue != NULL) { 744 | return lua_setiuservalue(L, idx, 1); 745 | } else if (__lua_setuservalue != NULL) { 746 | SYMBOL_WRAP_CALL(lua_setuservalue, L, idx); 747 | } 748 | SYMBOL_WRAP_CALL_FB(lua_setuservalue, L, idx); 749 | } 750 | SYMBOL_WRAP_DECL(void, lua_setiuservalue, lua_State *L, int idx, int n){ 751 | SYMBOL_WRAP_CALL(lua_setiuservalue, L, idx, n); 752 | } 753 | SYMBOL_WRAP_DECL(void, lua_callk, lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k){ 754 | SYMBOL_WRAP_CALL(lua_callk, L, nargs, nresults, ctx, k); 755 | } 756 | SYMBOL_WRAP_DECL(int, lua_getctx, lua_State *L, int *ctx){ 757 | SYMBOL_WRAP_CALL(lua_getctx, L, ctx); 758 | } 759 | SYMBOL_WRAP_DECL(int, lua_pcallk, lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k){ 760 | SYMBOL_WRAP_CALL(lua_pcallk, L, nargs, nresults, errfunc, ctx, k); 761 | } 762 | SYMBOL_WRAP_DECL(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode){ 763 | SYMBOL_WRAP_CALL(lua_load, L, reader, dt, chunkname, mode); 764 | } 765 | SYMBOL_WRAP_DECL(int, lua_dump, lua_State *L, lua_Writer writer, void *data, int strip){ 766 | SYMBOL_WRAP_CALL(lua_dump, L, writer, data, strip); 767 | } 768 | SYMBOL_WRAP_DECL(int, lua_yieldk, lua_State *L, int nresults, int ctx, lua_CFunction k){ 769 | SYMBOL_WRAP_CALL(lua_yieldk, L, nresults, ctx, k); 770 | } 771 | SYMBOL_WRAP_DECL(int, lua_resume, lua_State *L, lua_State *from, int narg){ 772 | SYMBOL_WRAP_CALL(lua_resume, L, from, narg); 773 | } 774 | SYMBOL_WRAP_DECL(int, lua_status, lua_State *L){ 775 | SYMBOL_WRAP_CALL(lua_status, L); 776 | } 777 | SYMBOL_WRAP_DECL(int, lua_gc, lua_State *L, int what, int data){ 778 | SYMBOL_WRAP_CALL(lua_gc, L, what, data); 779 | } 780 | SYMBOL_WRAP_DECL(int, lua_error, lua_State *L){ 781 | SYMBOL_WRAP_CALL(lua_error, L); 782 | } 783 | SYMBOL_WRAP_DECL(int, lua_next, lua_State *L, int idx){ 784 | SYMBOL_WRAP_CALL(lua_next, L, idx); 785 | } 786 | SYMBOL_WRAP_DECL(void, lua_concat, lua_State *L, int n){ 787 | SYMBOL_WRAP_CALL(lua_concat, L, n); 788 | } 789 | SYMBOL_WRAP_DECL(void, lua_len, lua_State *L, int idx){ 790 | SYMBOL_WRAP_CALL(lua_len, L, idx); 791 | } 792 | SYMBOL_WRAP_DECL(lua_Alloc, lua_getallocf, lua_State *L, void **ud){ 793 | SYMBOL_WRAP_CALL(lua_getallocf, L, ud); 794 | } 795 | SYMBOL_WRAP_DECL(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud){ 796 | SYMBOL_WRAP_CALL(lua_setallocf, L, f, ud); 797 | } 798 | SYMBOL_WRAP_DECL(int, lua_getstack, lua_State *L, int level, lua_Debug *ar){ 799 | SYMBOL_WRAP_CALL(lua_getstack, L, level, ar); 800 | } 801 | SYMBOL_WRAP_DECL(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar){ 802 | SYMBOL_WRAP_CALL(lua_getinfo, L, what, ar); 803 | } 804 | SYMBOL_WRAP_DECL(const char *, lua_getlocal, lua_State *L, const lua_Debug *ar, int n){ 805 | SYMBOL_WRAP_CALL(lua_getlocal, L, ar, n); 806 | } 807 | SYMBOL_WRAP_DECL(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n){ 808 | SYMBOL_WRAP_CALL(lua_setlocal, L, ar, n); 809 | } 810 | SYMBOL_WRAP_DECL(const char *, lua_getupvalue, lua_State *L, int funcindex, int n){ 811 | SYMBOL_WRAP_CALL(lua_getupvalue, L, funcindex, n); 812 | } 813 | SYMBOL_WRAP_DECL(const char *, lua_setupvalue, lua_State *L, int funcindex, int n){ 814 | SYMBOL_WRAP_CALL(lua_setupvalue, L, funcindex, n); 815 | } 816 | SYMBOL_WRAP_DECL(void *, lua_upvalueid, lua_State *L, int fidx, int n){ 817 | SYMBOL_WRAP_CALL(lua_upvalueid, L, fidx, n); 818 | } 819 | SYMBOL_WRAP_DECL(void, lua_upvaluejoin, lua_State *L, int fidx1, int n1, int fidx2, int n2){ 820 | SYMBOL_WRAP_CALL(lua_upvaluejoin, L, fidx1, n1, fidx2, n2); 821 | } 822 | SYMBOL_WRAP_DECL(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count){ 823 | SYMBOL_WRAP_CALL(lua_sethook, L, func, mask, count); 824 | } 825 | SYMBOL_WRAP_DECL(lua_Hook, lua_gethook, lua_State *L){ 826 | SYMBOL_WRAP_CALL(lua_gethook, L); 827 | } 828 | SYMBOL_WRAP_DECL(int, lua_gethookmask, lua_State *L){ 829 | SYMBOL_WRAP_CALL(lua_gethookmask, L); 830 | } 831 | SYMBOL_WRAP_DECL(int, lua_gethookcount, lua_State *L){ 832 | SYMBOL_WRAP_CALL(lua_gethookcount, L); 833 | } 834 | SYMBOL_WRAP_DECL(void, luaL_checkversion_, lua_State *L, lua_Number ver){ 835 | SYMBOL_WRAP_CALL(luaL_checkversion_, L, ver); 836 | } 837 | SYMBOL_WRAP_DECL(int, luaL_getmetafield, lua_State *L, int obj, const char *e){ 838 | SYMBOL_WRAP_CALL(luaL_getmetafield, L, obj, e); 839 | } 840 | SYMBOL_WRAP_DECL(int, luaL_callmeta, lua_State *L, int obj, const char *e){ 841 | SYMBOL_WRAP_CALL(luaL_callmeta, L, obj, e); 842 | } 843 | SYMBOL_WRAP_DECL(const char *, luaL_tolstring, lua_State *L, int idx, size_t *len){ 844 | SYMBOL_WRAP_CALL(luaL_tolstring, L, idx, len); 845 | } 846 | SYMBOL_WRAP_DECL(int, luaL_argerror, lua_State *L, int numarg, const char *extramsg){ 847 | SYMBOL_WRAP_CALL(luaL_argerror, L, numarg, extramsg); 848 | } 849 | SYMBOL_WRAP_DECL(const char *, luaL_checklstring, lua_State *L, int numArg, size_t *l){ 850 | SYMBOL_WRAP_CALL(luaL_checklstring, L, numArg, l); 851 | } 852 | SYMBOL_WRAP_DECL(const char *, luaL_optlstring, lua_State *L, int numArg, const char *def, size_t *l){ 853 | SYMBOL_WRAP_CALL(luaL_optlstring, L, numArg, def, l); 854 | } 855 | SYMBOL_WRAP_DECL(lua_Number, luaL_checknumber, lua_State *L, int numArg){ 856 | SYMBOL_WRAP_CALL(luaL_checknumber, L, numArg); 857 | } 858 | SYMBOL_WRAP_DECL(lua_Number, luaL_optnumber, lua_State *L, int nArg, lua_Number def){ 859 | SYMBOL_WRAP_CALL(luaL_optnumber, L, nArg, def); 860 | } 861 | SYMBOL_WRAP_DECL(lua_Integer, luaL_checkinteger, lua_State *L, int numArg){ 862 | SYMBOL_WRAP_CALL(luaL_checkinteger, L, numArg); 863 | } 864 | SYMBOL_WRAP_DECL(lua_Integer, luaL_optinteger, lua_State *L, int nArg, lua_Integer def){ 865 | SYMBOL_WRAP_CALL(luaL_optinteger, L, nArg, def); 866 | } 867 | SYMBOL_WRAP_DECL(lua_Unsigned, luaL_checkunsigned, lua_State *L, int numArg){ 868 | SYMBOL_WRAP_CALL(luaL_checkunsigned, L, numArg); 869 | } 870 | SYMBOL_WRAP_DECL(lua_Unsigned, luaL_optunsigned, lua_State *L, int numArg, lua_Unsigned def){ 871 | SYMBOL_WRAP_CALL(luaL_optunsigned, L, numArg, def); 872 | } 873 | SYMBOL_WRAP_DECL(void, luaL_checkstack, lua_State *L, int sz, const char *msg){ 874 | SYMBOL_WRAP_CALL(luaL_checkstack, L, sz, msg); 875 | } 876 | SYMBOL_WRAP_DECL(void, luaL_checktype, lua_State *L, int narg, int t){ 877 | SYMBOL_WRAP_CALL(luaL_checktype, L, narg, t); 878 | } 879 | SYMBOL_WRAP_DECL(void, luaL_checkany, lua_State *L, int narg){ 880 | SYMBOL_WRAP_CALL(luaL_checkany, L, narg); 881 | } 882 | SYMBOL_WRAP_DECL(int, luaL_newmetatable, lua_State *L, const char *tname){ 883 | SYMBOL_WRAP_CALL(luaL_newmetatable, L, tname); 884 | } 885 | SYMBOL_WRAP_DECL(void, luaL_setmetatable, lua_State *L, const char *tname){ 886 | SYMBOL_WRAP_CALL(luaL_setmetatable, L, tname); 887 | } 888 | SYMBOL_WRAP_DECL(void *, luaL_testudata, lua_State *L, int ud, const char *tname){ 889 | SYMBOL_WRAP_CALL(luaL_testudata, L, ud, tname); 890 | } 891 | SYMBOL_WRAP_DECL(void *, luaL_checkudata, lua_State *L, int ud, const char *tname){ 892 | SYMBOL_WRAP_CALL(luaL_checkudata, L, ud, tname); 893 | } 894 | SYMBOL_WRAP_DECL(void, luaL_where, lua_State *L, int lvl){ 895 | SYMBOL_WRAP_CALL(luaL_where, L, lvl); 896 | } 897 | SYMBOL_WRAP_DECL(int, luaL_error, lua_State *L, const char *fmt, ...){ 898 | va_list argp; 899 | va_start(argp, fmt); 900 | luaL_where(L, 1); 901 | lua_pushvfstring(L, fmt, argp); 902 | va_end(argp); 903 | lua_concat(L, 2); 904 | return lua_error(L); 905 | } 906 | SYMBOL_WRAP_DECL(int, luaL_checkoption, lua_State *L, int narg, const char *def, const char *const lst[]){ 907 | SYMBOL_WRAP_CALL(luaL_checkoption, L, narg, def, lst); 908 | } 909 | SYMBOL_WRAP_DECL(int, luaL_fileresult, lua_State *L, int stat, const char *fname){ 910 | SYMBOL_WRAP_CALL(luaL_fileresult, L, stat, fname); 911 | } 912 | SYMBOL_WRAP_DECL(int, luaL_execresult, lua_State *L, int stat){ 913 | SYMBOL_WRAP_CALL(luaL_execresult, L, stat); 914 | } 915 | SYMBOL_WRAP_DECL(int, luaL_ref, lua_State *L, int t){ 916 | SYMBOL_WRAP_CALL(luaL_ref, L, t); 917 | } 918 | SYMBOL_WRAP_DECL(void, luaL_unref, lua_State *L, int t, int ref){ 919 | SYMBOL_WRAP_CALL(luaL_unref, L, t, ref); 920 | } 921 | SYMBOL_WRAP_DECL(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode){ 922 | SYMBOL_WRAP_CALL(luaL_loadfilex, L, filename, mode); 923 | } 924 | SYMBOL_WRAP_DECL(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode){ 925 | SYMBOL_WRAP_CALL(luaL_loadbufferx, L, buff, sz, name, mode); 926 | } 927 | SYMBOL_WRAP_DECL(int, luaL_loadstring, lua_State *L, const char *s){ 928 | SYMBOL_WRAP_CALL(luaL_loadstring, L, s); 929 | } 930 | SYMBOL_WRAP_DECL(lua_State *, luaL_newstate, void){ 931 | return __luaL_newstate(); 932 | } 933 | SYMBOL_WRAP_DECL(int, luaL_len, lua_State *L, int idx){ 934 | SYMBOL_WRAP_CALL(luaL_len, L, idx); 935 | } 936 | SYMBOL_WRAP_DECL(const char *, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r){ 937 | SYMBOL_WRAP_CALL(luaL_gsub, L, s, p, r); 938 | } 939 | SYMBOL_WRAP_DECL(void, luaL_setfuncs, lua_State *L, const luaL_Reg *l, int nup){ 940 | SYMBOL_WRAP_CALL(luaL_setfuncs, L, l, nup); 941 | } 942 | SYMBOL_WRAP_DECL(int, luaL_getsubtable, lua_State *L, int idx, const char *fname){ 943 | SYMBOL_WRAP_CALL(luaL_getsubtable, L, idx, fname); 944 | } 945 | SYMBOL_WRAP_DECL(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level){ 946 | SYMBOL_WRAP_CALL(luaL_traceback, L, L1, msg, level); 947 | } 948 | SYMBOL_WRAP_DECL(void, luaL_requiref, lua_State *L, const char *modname, lua_CFunction openf, int glb){ 949 | SYMBOL_WRAP_CALL(luaL_requiref, L, modname, openf, glb); 950 | } 951 | SYMBOL_WRAP_DECL(void, luaL_buffinit, lua_State *L, luaL_Buffer *B){ 952 | SYMBOL_WRAP_CALL(luaL_buffinit, L, B); 953 | } 954 | SYMBOL_WRAP_DECL(char *, luaL_prepbuffsize, luaL_Buffer *B, size_t sz){ 955 | SYMBOL_WRAP_CALL(luaL_prepbuffsize, B, sz); 956 | } 957 | SYMBOL_WRAP_DECL(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l){ 958 | SYMBOL_WRAP_CALL(luaL_addlstring, B, s, l); 959 | } 960 | SYMBOL_WRAP_DECL(void, luaL_addstring, luaL_Buffer *B, const char *s){ 961 | SYMBOL_WRAP_CALL(luaL_addstring, B, s); 962 | } 963 | SYMBOL_WRAP_DECL(void, luaL_addvalue, luaL_Buffer *B){ 964 | SYMBOL_WRAP_CALL(luaL_addvalue, B); 965 | } 966 | SYMBOL_WRAP_DECL(void, luaL_pushresult, luaL_Buffer *B){ 967 | SYMBOL_WRAP_CALL(luaL_pushresult, B); 968 | } 969 | SYMBOL_WRAP_DECL(void, luaL_pushresultsize, luaL_Buffer *B, size_t sz){ 970 | SYMBOL_WRAP_CALL(luaL_pushresultsize, B, sz); 971 | } 972 | SYMBOL_WRAP_DECL(char *, luaL_buffinitsize, lua_State *L, luaL_Buffer *B, size_t sz){ 973 | SYMBOL_WRAP_CALL(luaL_buffinitsize, L, B, sz); 974 | } 975 | SYMBOL_WRAP_DECL(void, luaL_openlibs, lua_State *L){ 976 | SYMBOL_WRAP_CALL(luaL_openlibs, L); 977 | } 978 | 979 | #define IMPORT_SYMBOL(name, ret, ...) \ 980 | __##name = (\ 981 | __##name = (ret (*) (__VA_ARGS__)) symbol(#name), \ 982 | __##name == NULL ? &__lite_xl_fallback_##name : __##name\ 983 | ) 984 | 985 | #define IMPORT_SYMBOL_OPT(name, ret, ...) \ 986 | __##name = symbol(#name) 987 | 988 | static void lite_xl_plugin_init(void *XL) { 989 | void* (*symbol)(const char *) = (void* (*) (const char *)) XL; 990 | IMPORT_SYMBOL(lua_newstate, lua_State *, lua_Alloc f, void *ud); 991 | IMPORT_SYMBOL(lua_close, void , lua_State *L); 992 | IMPORT_SYMBOL(lua_newthread, lua_State *, lua_State *L); 993 | IMPORT_SYMBOL(lua_atpanic, lua_CFunction , lua_State *L, lua_CFunction panicf); 994 | IMPORT_SYMBOL(lua_version, const lua_Number *, lua_State *L); 995 | IMPORT_SYMBOL(lua_absindex, int , lua_State *L, int idx); 996 | IMPORT_SYMBOL(lua_gettop, int , lua_State *L); 997 | IMPORT_SYMBOL(lua_settop, void , lua_State *L, int idx); 998 | IMPORT_SYMBOL(lua_pushvalue, void , lua_State *L, int idx); 999 | IMPORT_SYMBOL(lua_copy, void , lua_State *L, int fromidx, int toidx); 1000 | IMPORT_SYMBOL(lua_checkstack, int , lua_State *L, int sz); 1001 | IMPORT_SYMBOL(lua_xmove, void , lua_State *from, lua_State *to, int n); 1002 | IMPORT_SYMBOL(lua_isnumber, int , lua_State *L, int idx); 1003 | IMPORT_SYMBOL(lua_isstring, int , lua_State *L, int idx); 1004 | IMPORT_SYMBOL(lua_iscfunction, int , lua_State *L, int idx); 1005 | IMPORT_SYMBOL(lua_isuserdata, int , lua_State *L, int idx); 1006 | IMPORT_SYMBOL(lua_type, int , lua_State *L, int idx); 1007 | IMPORT_SYMBOL(lua_typename, const char *, lua_State *L, int tp); 1008 | IMPORT_SYMBOL(lua_tonumberx, lua_Number , lua_State *L, int idx, int *isnum); 1009 | IMPORT_SYMBOL(lua_tointegerx, lua_Integer , lua_State *L, int idx, int *isnum); 1010 | IMPORT_SYMBOL(lua_tounsignedx, lua_Unsigned , lua_State *L, int idx, int *isnum); 1011 | IMPORT_SYMBOL(lua_toboolean, int , lua_State *L, int idx); 1012 | IMPORT_SYMBOL(lua_tolstring, const char *, lua_State *L, int idx, size_t *len); 1013 | IMPORT_SYMBOL(lua_rawlen, size_t , lua_State *L, int idx); 1014 | IMPORT_SYMBOL(lua_tocfunction, lua_CFunction , lua_State *L, int idx); 1015 | IMPORT_SYMBOL(lua_touserdata, void *, lua_State *L, int idx); 1016 | IMPORT_SYMBOL(lua_tothread, lua_State *, lua_State *L, int idx); 1017 | IMPORT_SYMBOL(lua_topointer, const void *, lua_State *L, int idx); 1018 | IMPORT_SYMBOL(lua_arith, void , lua_State *L, int op); 1019 | IMPORT_SYMBOL(lua_rawequal, int , lua_State *L, int idx1, int idx2); 1020 | IMPORT_SYMBOL(lua_compare, int , lua_State *L, int idx1, int idx2, int op); 1021 | IMPORT_SYMBOL(lua_pushnil, void , lua_State *L); 1022 | IMPORT_SYMBOL(lua_pushnumber, void , lua_State *L, lua_Number n); 1023 | IMPORT_SYMBOL(lua_pushinteger, void , lua_State *L, lua_Integer n); 1024 | IMPORT_SYMBOL(lua_pushunsigned, void , lua_State *L, lua_Unsigned n); 1025 | IMPORT_SYMBOL(lua_pushlstring, const char *, lua_State *L, const char *s, size_t l); 1026 | IMPORT_SYMBOL(lua_pushstring, const char *, lua_State *L, const char *s); 1027 | IMPORT_SYMBOL(lua_pushvfstring, const char *, lua_State *L, const char *fmt, va_list argp); 1028 | IMPORT_SYMBOL(lua_pushfstring, const char *, lua_State *L, const char *fmt, ...); 1029 | IMPORT_SYMBOL(lua_pushcclosure, void , lua_State *L, lua_CFunction fn, int n); 1030 | IMPORT_SYMBOL(lua_pushboolean, void , lua_State *L, int b); 1031 | IMPORT_SYMBOL(lua_pushlightuserdata, void , lua_State *L, void *p); 1032 | IMPORT_SYMBOL(lua_pushthread, int , lua_State *L); 1033 | IMPORT_SYMBOL(lua_getglobal, void , lua_State *L, const char *var); 1034 | IMPORT_SYMBOL(lua_gettable, void , lua_State *L, int idx); 1035 | IMPORT_SYMBOL(lua_getfield, void , lua_State *L, int idx, const char *k); 1036 | IMPORT_SYMBOL(lua_rawget, void , lua_State *L, int idx); 1037 | IMPORT_SYMBOL(lua_rawgeti, void , lua_State *L, int idx, int n); 1038 | IMPORT_SYMBOL(lua_rawgetp, void , lua_State *L, int idx, const void *p); 1039 | IMPORT_SYMBOL(lua_createtable, void , lua_State *L, int narr, int nrec); 1040 | IMPORT_SYMBOL_OPT(lua_newuserdata, void *, lua_State *L, size_t sz); 1041 | IMPORT_SYMBOL(lua_newuserdatauv, void *, lua_State *L, size_t sz, int nuvalue); 1042 | IMPORT_SYMBOL(lua_objlen, size_t, lua_State *L, int idx); 1043 | IMPORT_SYMBOL(lua_getmetatable, int , lua_State *L, int objindex); 1044 | IMPORT_SYMBOL_OPT(lua_getuservalue, void , lua_State *L, int idx); 1045 | IMPORT_SYMBOL(lua_getiuservalue, void , lua_State *L, int idx, int n); 1046 | IMPORT_SYMBOL(lua_setglobal, void , lua_State *L, const char *var); 1047 | IMPORT_SYMBOL(lua_settable, void , lua_State *L, int idx); 1048 | IMPORT_SYMBOL(lua_setfield, void , lua_State *L, int idx, const char *k); 1049 | IMPORT_SYMBOL(lua_rawset, void , lua_State *L, int idx); 1050 | IMPORT_SYMBOL(lua_rawseti, void , lua_State *L, int idx, int n); 1051 | IMPORT_SYMBOL(lua_rawsetp, void , lua_State *L, int idx, const void *p); 1052 | IMPORT_SYMBOL(lua_setmetatable, int , lua_State *L, int objindex); 1053 | IMPORT_SYMBOL_OPT(lua_setuservalue, void , lua_State *L, int idx); 1054 | IMPORT_SYMBOL(lua_setiuservalue, void , lua_State *L, int idx, int n); 1055 | IMPORT_SYMBOL(lua_callk, void , lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); 1056 | IMPORT_SYMBOL(lua_getctx, int , lua_State *L, int *ctx); 1057 | IMPORT_SYMBOL(lua_pcallk, int , lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); 1058 | IMPORT_SYMBOL(lua_load, int , lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); 1059 | IMPORT_SYMBOL(lua_dump, int , lua_State *L, lua_Writer writer, void *data, int strip); 1060 | IMPORT_SYMBOL(lua_yieldk, int , lua_State *L, int nresults, int ctx, lua_CFunction k); 1061 | IMPORT_SYMBOL(lua_resume, int , lua_State *L, lua_State *from, int narg); 1062 | IMPORT_SYMBOL(lua_status, int , lua_State *L); 1063 | IMPORT_SYMBOL(lua_gc, int , lua_State *L, int what, int data); 1064 | IMPORT_SYMBOL(lua_error, int , lua_State *L); 1065 | IMPORT_SYMBOL(lua_next, int , lua_State *L, int idx); 1066 | IMPORT_SYMBOL(lua_concat, void , lua_State *L, int n); 1067 | IMPORT_SYMBOL(lua_len, void , lua_State *L, int idx); 1068 | IMPORT_SYMBOL(lua_getallocf, lua_Alloc , lua_State *L, void **ud); 1069 | IMPORT_SYMBOL(lua_setallocf, void , lua_State *L, lua_Alloc f, void *ud); 1070 | IMPORT_SYMBOL(lua_getstack, int , lua_State *L, int level, lua_Debug *ar); 1071 | IMPORT_SYMBOL(lua_getinfo, int , lua_State *L, const char *what, lua_Debug *ar); 1072 | IMPORT_SYMBOL(lua_getlocal, const char *, lua_State *L, const lua_Debug *ar, int n); 1073 | IMPORT_SYMBOL(lua_setlocal, const char *, lua_State *L, const lua_Debug *ar, int n); 1074 | IMPORT_SYMBOL(lua_getupvalue, const char *, lua_State *L, int funcindex, int n); 1075 | IMPORT_SYMBOL(lua_setupvalue, const char *, lua_State *L, int funcindex, int n); 1076 | IMPORT_SYMBOL(lua_upvalueid, void *, lua_State *L, int fidx, int n); 1077 | IMPORT_SYMBOL(lua_upvaluejoin, void , lua_State *L, int fidx1, int n1, int fidx2, int n2); 1078 | IMPORT_SYMBOL(lua_sethook, int , lua_State *L, lua_Hook func, int mask, int count); 1079 | IMPORT_SYMBOL(lua_gethook, lua_Hook , lua_State *L); 1080 | IMPORT_SYMBOL(lua_gethookmask, int , lua_State *L); 1081 | IMPORT_SYMBOL(lua_gethookcount, int , lua_State *L); 1082 | IMPORT_SYMBOL(luaL_checkversion_, void , lua_State *L, lua_Number ver); 1083 | IMPORT_SYMBOL(luaL_getmetafield, int , lua_State *L, int obj, const char *e); 1084 | IMPORT_SYMBOL(luaL_callmeta, int , lua_State *L, int obj, const char *e); 1085 | IMPORT_SYMBOL(luaL_tolstring, const char *, lua_State *L, int idx, size_t *len); 1086 | IMPORT_SYMBOL(luaL_argerror, int , lua_State *L, int numarg, const char *extramsg); 1087 | IMPORT_SYMBOL(luaL_checklstring, const char *, lua_State *L, int numArg, size_t *l); 1088 | IMPORT_SYMBOL(luaL_optlstring, const char *, lua_State *L, int numArg, const char *def, size_t *l); 1089 | IMPORT_SYMBOL(luaL_checknumber, lua_Number , lua_State *L, int numArg); 1090 | IMPORT_SYMBOL(luaL_optnumber, lua_Number , lua_State *L, int nArg, lua_Number def); 1091 | IMPORT_SYMBOL(luaL_checkinteger, lua_Integer , lua_State *L, int numArg); 1092 | IMPORT_SYMBOL(luaL_optinteger, lua_Integer , lua_State *L, int nArg, lua_Integer def); 1093 | IMPORT_SYMBOL(luaL_checkunsigned, lua_Unsigned , lua_State *L, int numArg); 1094 | IMPORT_SYMBOL(luaL_optunsigned, lua_Unsigned , lua_State *L, int numArg, lua_Unsigned def); 1095 | IMPORT_SYMBOL(luaL_checkstack, void , lua_State *L, int sz, const char *msg); 1096 | IMPORT_SYMBOL(luaL_checktype, void , lua_State *L, int narg, int t); 1097 | IMPORT_SYMBOL(luaL_checkany, void , lua_State *L, int narg); 1098 | IMPORT_SYMBOL(luaL_newmetatable, int , lua_State *L, const char *tname); 1099 | IMPORT_SYMBOL(luaL_setmetatable, void , lua_State *L, const char *tname); 1100 | IMPORT_SYMBOL(luaL_testudata, void *, lua_State *L, int ud, const char *tname); 1101 | IMPORT_SYMBOL(luaL_checkudata, void *, lua_State *L, int ud, const char *tname); 1102 | IMPORT_SYMBOL(luaL_where, void , lua_State *L, int lvl); 1103 | IMPORT_SYMBOL(luaL_error, int , lua_State *L, const char *fmt, ...); 1104 | IMPORT_SYMBOL(luaL_checkoption, int , lua_State *L, int narg, const char *def, const char *const lst[]); 1105 | IMPORT_SYMBOL(luaL_fileresult, int , lua_State *L, int stat, const char *fname); 1106 | IMPORT_SYMBOL(luaL_execresult, int , lua_State *L, int stat); 1107 | IMPORT_SYMBOL(luaL_ref, int , lua_State *L, int t); 1108 | IMPORT_SYMBOL(luaL_unref, void , lua_State *L, int t, int ref); 1109 | IMPORT_SYMBOL(luaL_loadfilex, int , lua_State *L, const char *filename, const char *mode); 1110 | IMPORT_SYMBOL(luaL_loadbufferx, int , lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); 1111 | IMPORT_SYMBOL(luaL_loadstring, int , lua_State *L, const char *s); 1112 | IMPORT_SYMBOL(luaL_newstate, lua_State *, void); 1113 | IMPORT_SYMBOL(luaL_len, int , lua_State *L, int idx); 1114 | IMPORT_SYMBOL(luaL_gsub, const char *, lua_State *L, const char *s, const char *p, const char *r); 1115 | IMPORT_SYMBOL(luaL_setfuncs, void , lua_State *L, const luaL_Reg *l, int nup); 1116 | IMPORT_SYMBOL(luaL_getsubtable, int , lua_State *L, int idx, const char *fname); 1117 | IMPORT_SYMBOL(luaL_traceback, void , lua_State *L, lua_State *L1, const char *msg, int level); 1118 | IMPORT_SYMBOL(luaL_requiref, void , lua_State *L, const char *modname, lua_CFunction openf, int glb); 1119 | IMPORT_SYMBOL(luaL_buffinit, void , lua_State *L, luaL_Buffer *B); 1120 | IMPORT_SYMBOL(luaL_prepbuffsize, char *, luaL_Buffer *B, size_t sz); 1121 | IMPORT_SYMBOL(luaL_addlstring, void , luaL_Buffer *B, const char *s, size_t l); 1122 | IMPORT_SYMBOL(luaL_addstring, void , luaL_Buffer *B, const char *s); 1123 | IMPORT_SYMBOL(luaL_addvalue, void , luaL_Buffer *B); 1124 | IMPORT_SYMBOL(luaL_pushresult, void , luaL_Buffer *B); 1125 | IMPORT_SYMBOL(luaL_pushresultsize, void , luaL_Buffer *B, size_t sz); 1126 | IMPORT_SYMBOL(luaL_buffinitsize, char *, lua_State *L, luaL_Buffer *B, size_t sz); 1127 | IMPORT_SYMBOL(luaL_openlibs, void, lua_State* L); 1128 | } 1129 | 1130 | #endif /* LITE_XL_PLUGIN_ENTRYPOINT */ 1131 | 1132 | #endif /* LITE_XL_PLUGIN_API */ 1133 | -------------------------------------------------------------------------------- /lua_tmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define LITE_XL_PLUGIN_ENTRYPOINT 6 | #include "lite_xl_plugin_api.h" 7 | 8 | #ifdef __WIN32 9 | #include 10 | #endif 11 | 12 | #include "tmt.h" 13 | 14 | 15 | #define LUA_T_PUSH_S_I(S, N) (lua_pushinteger(L, N), lua_setfield(L, -2, S)) 16 | #define LUA_T_PUSH_S_B(S, N) (lua_pushboolean(L, N), lua_setfield(L, -2, S)) 17 | #define LUA_T_PUSH_S_S(K, V) (lua_pushstring(L, V), lua_setfield(L, -2, K)) 18 | 19 | #define UTF8_SIZE 4 20 | #define ANS_SIZE 256 21 | #define API_TYPE_TMT "tmt" 22 | 23 | 24 | typedef struct { 25 | TMT *vt; 26 | int update_lines; 27 | int update_bell; 28 | int update_answer; 29 | int update_cursor; 30 | char *answer; 31 | size_t answer_len, answer_size; 32 | } tmt_t; 33 | 34 | 35 | 36 | // nobody likes wchar_t 37 | static int wchar_convert(wchar_t c, char *s) { 38 | #ifndef __WIN32 39 | return wctomb(s, c); 40 | #else 41 | int ret = WideCharToMultiByte(CP_UTF8, 0, &c, 1, s, 4, NULL, NULL); 42 | return ret == 0 ? -1 : ret; 43 | #endif 44 | } 45 | 46 | static int l_write(lua_State *L) { 47 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 48 | const char* str = lua_tolstring(L, 2, NULL); 49 | 50 | const TMTPOINT *c = tmt_cursor(tmt->vt); 51 | 52 | tmt_write(tmt->vt, str, 0); 53 | 54 | lua_newtable(L); 55 | LUA_T_PUSH_S_B("screen", tmt->update_lines); 56 | LUA_T_PUSH_S_B("bell", tmt->update_bell); 57 | if (tmt->update_answer) { 58 | lua_pushlstring(L, tmt->answer, tmt->answer_len); 59 | lua_setfield(L, -2, "answer"); 60 | tmt->answer_len = 0; 61 | } 62 | 63 | if (tmt->update_cursor) { 64 | lua_newtable(L); 65 | LUA_T_PUSH_S_I("x", c->c + 1); 66 | LUA_T_PUSH_S_I("y", c->r + 1); 67 | lua_setfield(L, -2, "cursor"); 68 | } 69 | 70 | tmt->update_lines = 0; 71 | tmt->update_bell = 0; 72 | tmt->update_answer = 0; 73 | tmt->update_cursor = 0; 74 | 75 | return 1; 76 | } 77 | 78 | 79 | 80 | void insert_char_table(lua_State *L, int x, TMTCHAR c) { 81 | lua_rawgeti(L, -1, x+1); 82 | 83 | #ifdef __WIN32 84 | char cp[UTF8_SIZE]; 85 | #else 86 | char cp[MB_CUR_MAX]; 87 | #endif 88 | int sz = wchar_convert(c.c, cp); 89 | if (sz == -1) 90 | lua_pushliteral(L, " "); 91 | else 92 | lua_pushlstring(L, cp, sz); 93 | lua_setfield(L, -2, "char"); 94 | 95 | LUA_T_PUSH_S_I("fg", (int)c.a.fg); 96 | LUA_T_PUSH_S_I("bg", (int)c.a.bg); 97 | 98 | LUA_T_PUSH_S_B("bold", c.a.bold); 99 | LUA_T_PUSH_S_B("dim", c.a.dim); 100 | LUA_T_PUSH_S_B("underline", c.a.underline); 101 | LUA_T_PUSH_S_B("blink", c.a.blink); 102 | LUA_T_PUSH_S_B("reverse", c.a.reverse); 103 | LUA_T_PUSH_S_B("invisible", c.a.invisible); 104 | 105 | lua_pop(L, 1); 106 | } 107 | 108 | 109 | 110 | static int l_get_screen(lua_State *L) { 111 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 112 | const TMTSCREEN *s = tmt_screen(tmt->vt); 113 | 114 | if (!lua_istable(L, 2)) 115 | lua_createtable(L, s->nline * s->ncol, 2); 116 | 117 | lua_settop(L, 2); 118 | 119 | LUA_T_PUSH_S_I("width", s->ncol); 120 | LUA_T_PUSH_S_I("height", s->nline); 121 | 122 | // ensure enough objects for later 123 | unsigned int l = s->nline * s->ncol; 124 | if (lua_objlen(L, -1) < l) { 125 | for (unsigned int i = lua_objlen(L, -1) + 1; i <= l; i++) { 126 | lua_newtable(L); 127 | lua_rawseti(L, -2, i); 128 | } 129 | } 130 | 131 | for (size_t y = 0; y < s->nline; y++) { 132 | if (!s->lines[y]->dirty) continue; 133 | for (size_t x = 0; x < s->ncol; x++) { 134 | insert_char_table(L, (y * s->ncol) + x, s->lines[y]->chars[x]); 135 | } 136 | } 137 | 138 | tmt_clean(tmt->vt); // reset dirty flags 139 | return 1; 140 | } 141 | 142 | 143 | 144 | static int l_get_cursor(lua_State *L) { 145 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 146 | const TMTPOINT *c = tmt_cursor(tmt->vt); 147 | 148 | lua_pushinteger(L, c->c+1); 149 | lua_pushinteger(L, c->r+1); 150 | return 2; 151 | } 152 | 153 | 154 | 155 | static int l_set_size(lua_State *L) { 156 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 157 | int w = lua_tointeger(L, 2); 158 | int h = lua_tointeger(L, 3); 159 | 160 | tmt_resize(tmt->vt, (size_t)h, (size_t)w); 161 | return 0; 162 | } 163 | 164 | 165 | 166 | static int l_get_size(lua_State *L) { 167 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 168 | const TMTSCREEN *s = tmt_screen(tmt->vt); 169 | 170 | lua_pushinteger(L, s->ncol); 171 | lua_pushinteger(L, s->nline); 172 | return 2; 173 | } 174 | 175 | 176 | 177 | void append_answer(tmt_t *tmt, const char *a) { 178 | size_t len = strlen(a) + 1; // counting \0 at the end 179 | if (tmt->answer_len + len > tmt->answer_size) { 180 | char *new = realloc(tmt->answer, (tmt->answer_size *= 2) * sizeof(char)); 181 | if (new == NULL) { 182 | fprintf(stderr, __FILE__ ": cannot allocate memory for answer\n"); 183 | return; 184 | } 185 | tmt->answer = new; 186 | } 187 | memcpy(tmt->answer + tmt->answer_len, a, len); 188 | tmt->answer_len += (len - 1); 189 | } 190 | 191 | 192 | 193 | void input_callback(tmt_msg_t m, TMT *vt, const void *a, void *p) { 194 | tmt_t *tmt = (tmt_t*)p; 195 | if (tmt->vt == NULL || tmt->answer == NULL) return; 196 | 197 | switch (m){ 198 | case TMT_MSG_BELL: 199 | tmt->update_bell = 1; 200 | break; 201 | case TMT_MSG_UPDATE: 202 | /* the screen image changed; a is a pointer to the TMTSCREEN */ 203 | tmt->update_lines = 1; 204 | break; 205 | case TMT_MSG_ANSWER: 206 | /* the terminal has a response to give to the program; a is a 207 | * pointer to a string */ 208 | tmt->update_answer = 1; 209 | append_answer(tmt, (const char *)a); 210 | break; 211 | case TMT_MSG_MOVED: 212 | /* the cursor moved; a is a pointer to the cursor's TMTPOINT */ 213 | tmt->update_cursor = 1; 214 | break; 215 | case TMT_MSG_CURSOR: 216 | break; 217 | } 218 | } 219 | 220 | 221 | 222 | static int l_new(lua_State *L) { 223 | int w = lua_tointeger(L, 1); 224 | int h = lua_tointeger(L, 2); 225 | 226 | tmt_t *tmt = (tmt_t *)lua_newuserdata(L, sizeof(tmt_t)); 227 | luaL_setmetatable(L, API_TYPE_TMT); 228 | 229 | TMT *vt = tmt_open((size_t)h, (size_t)w, input_callback, tmt, NULL); 230 | if (vt == NULL) 231 | return luaL_error(L, "cannot create virtual terminal"); 232 | 233 | tmt->vt = vt; 234 | tmt->update_lines = 0; 235 | tmt->update_bell = 0; 236 | tmt->update_answer = 0; 237 | tmt->update_cursor = 0; 238 | tmt->answer_len = 0; 239 | tmt->answer_size = ANS_SIZE; 240 | tmt->answer = malloc(tmt->answer_size * sizeof(char)); 241 | if (tmt->answer == NULL) { 242 | tmt_close(vt); 243 | return luaL_error(L, "cannot create virtual terminal"); 244 | } 245 | return 1; 246 | } 247 | 248 | 249 | 250 | static int l_gc(lua_State *L) { 251 | tmt_t *tmt = luaL_checkudata(L, 1, API_TYPE_TMT); 252 | if (tmt->vt != NULL) { 253 | tmt_close(tmt->vt); 254 | tmt->vt = NULL; 255 | } 256 | if (tmt->answer != NULL) { 257 | free(tmt->answer); 258 | tmt->answer = NULL; 259 | } 260 | return 0; 261 | } 262 | 263 | 264 | 265 | static const luaL_Reg lib[] = { 266 | { "new", l_new }, 267 | { "write", l_write }, 268 | { "get_screen", l_get_screen }, 269 | { "get_cursor", l_get_cursor }, 270 | { "get_size", l_get_size }, 271 | { "set_size", l_set_size }, 272 | { "__gc", l_gc }, 273 | { NULL, NULL } 274 | }; 275 | 276 | int luaopen_lite_xl_tmt(lua_State *L, void *XL) { 277 | lite_xl_plugin_init(XL); 278 | 279 | setlocale(LC_CTYPE, "en_US.UTF-8"); 280 | luaL_newmetatable(L, API_TYPE_TMT); 281 | lua_pushvalue(L, -1); 282 | lua_setfield(L, -2, "__index"); 283 | luaL_setfuncs(L, lib, 0); 284 | 285 | return 1; 286 | } 287 | -------------------------------------------------------------------------------- /minivt.c: -------------------------------------------------------------------------------- 1 | /** minivt - ANSI escape "parser" inspired by tmt 2 | * 3 | * MIT No Attribution 4 | * 5 | * Copyright 2022 takase1121 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | * software and associated documentation files (the "Software"), to deal in the Software 9 | * without restriction, including without limitation the rights to use, copy, modify, 10 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | #include 21 | #include 22 | 23 | #include "minivt.h" 24 | 25 | #define PARSE_ARG_MAX 16 26 | #define ANSI_ESC "\x1b" 27 | #define ANSI_SOS "X" 28 | #define ANSI_ST "\\" 29 | #define MIN(a, b) ((a) > (b) ? (b) : (a)) 30 | #define HANDLER(fn) static void fn(vt_parser_t *vt) 31 | 32 | enum { 33 | S_NUL, 34 | S_ESC, 35 | S_ARG, 36 | S_STR, 37 | S_SES 38 | }; 39 | 40 | struct vt_parser_s { 41 | callback_t cb; 42 | void *p; 43 | int state, narg; 44 | size_t args[PARSE_ARG_MAX], arg; 45 | }; 46 | 47 | 48 | HANDLER(consumearg) { 49 | if (vt->narg < PARSE_ARG_MAX) 50 | vt->args[vt->narg++] = vt->arg; 51 | vt->arg = 0; 52 | } 53 | 54 | HANDLER(resetarg) { 55 | memset(vt->args, 0, sizeof(vt->args)); 56 | vt->arg = vt->narg = 0; 57 | } 58 | 59 | vt_parser_t * 60 | vtnew(callback_t cb, void *p) { 61 | vt_parser_t *vt = malloc(sizeof(vt_parser_t)); 62 | if (vt == NULL) return NULL; 63 | memset(vt, 0, sizeof(vt_parser_t)); 64 | vt->cb = cb; 65 | vt->p = p; 66 | return vt; 67 | } 68 | 69 | void 70 | vtparse(vt_parser_t *vt, const char *data, size_t len) { 71 | #define ON(S, C, A) if (vt->state == (S) && strchr(C, c)) { A; continue; } 72 | #define ON_ANY(S, A) if (vt->state == (S)) { A; continue; } 73 | #define DO(S, C, A) ON(S, C, consumearg(vt); A; resetarg(vt)); 74 | #define CB(T) vt->cb(T, &ans, vt->p) 75 | #define BUF(T) int l = i - si - MIN(i, 1); if (l > 0) { ans.buffer.len = l; ans.buffer.b = data + si; CB(T); si = i + 1; } 76 | 77 | vt_answer_t ans; 78 | size_t si = 0; 79 | for (size_t i = 0; i < len; i++) { 80 | char c = data[i]; 81 | char cs[] = { c, '\0' }; 82 | ON(S_NUL, ANSI_ESC, vt->state = S_ESC) 83 | ON(S_ESC, ANSI_SOS, vt->state = S_STR; BUF(VT_MSG_PASS)) 84 | 85 | /* ANYTHING BETWEEN THESE ARE NONSTANDARD EVENTS */ 86 | ON(S_STR, "P", vt->state = S_ARG; resetarg(vt)) 87 | ON(S_ARG, ";", consumearg(vt)) 88 | ON(S_ARG, "0123456789", vt->arg = vt->arg * 10 + atoi(cs)) 89 | DO(S_ARG, "R", vt->state = S_STR; ans.point.r = vt->args[0]; ans.point.c = vt->args[1]; CB(VT_MSG_RESIZE)) 90 | /* END OF NONSTANDARD EVENTS */ 91 | 92 | ON(S_STR, ANSI_ESC, vt->state = S_SES) 93 | ON(S_SES, ANSI_ST, vt->state = S_NUL; BUF(VT_MSG_CONTENT); CB(VT_MSG_END)) 94 | ON_ANY(S_SES, vt->state = S_STR) 95 | } 96 | 97 | if (len - si > 0) { 98 | ans.buffer.len = len - si; 99 | ans.buffer.b = data + si; 100 | CB(vt->state >= S_STR ? VT_MSG_CONTENT : VT_MSG_PASS); 101 | } 102 | } 103 | 104 | void 105 | vtfree(vt_parser_t *vt) { 106 | if (vt != NULL) free(vt); 107 | } 108 | -------------------------------------------------------------------------------- /minivt.h: -------------------------------------------------------------------------------- 1 | /** minivt - ANSI escape "parser" inspired by tmt 2 | * 3 | * MIT No Attribution 4 | * 5 | * Copyright 2022 takase1121 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | * software and associated documentation files (the "Software"), to deal in the Software 9 | * without restriction, including without limitation the rights to use, copy, modify, 10 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | #ifndef MINIVT_H 21 | #define MINIVT_H 22 | 23 | #include 24 | enum { 25 | VT_MSG_PASS, 26 | VT_MSG_CONTENT, 27 | VT_MSG_END, 28 | VT_MSG_RESIZE 29 | }; 30 | 31 | typedef struct vt_parser_s vt_parser_t; 32 | typedef union { 33 | struct { size_t len; const char *b; } buffer; 34 | struct { size_t r, c; } point; 35 | } vt_answer_t; 36 | 37 | typedef void (*callback_t)(int type, vt_answer_t *, void *); 38 | 39 | vt_parser_t *vtnew(callback_t cb, void *p); 40 | void vtparse(vt_parser_t *vt, const char *data, size_t len); 41 | void vtfree(vt_parser_t *vt); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /pty.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "minivt.h" 12 | 13 | #define MIN(a, b) ((a) > (b) ? (b) : (a)) 14 | #define MAX_PTY_SIZE 999 15 | #define BUFFER_SIZE 2048 16 | 17 | void callback(int type, vt_answer_t *ans, void *p) { 18 | int master = *(int*)p; 19 | struct winsize wp = { 0 }; 20 | 21 | switch (type) { 22 | // FIXME: ignoring MSG_CONTENT here 23 | case VT_MSG_PASS: 24 | write(master, ans->buffer.b, ans->buffer.len); 25 | break; 26 | case VT_MSG_RESIZE: 27 | wp.ws_col = MIN(MAX_PTY_SIZE, ans->point.c); 28 | wp.ws_row = MIN(MAX_PTY_SIZE, ans->point.r); 29 | ioctl(master, TIOCSWINSZ, &wp); 30 | break; 31 | } 32 | } 33 | 34 | int main(int argc, char **argv) { 35 | #define LOG_ERR(S) (err = errno, perror(S), err) 36 | 37 | int master, err; 38 | pid_t pid; 39 | 40 | if (argc < 2) { 41 | fputs("insufficient arguments", stderr); 42 | return EXIT_FAILURE; 43 | } 44 | 45 | pid = forkpty(&master, NULL, NULL, NULL); 46 | if(pid == -1) 47 | return LOG_ERR("forkpty(): "); 48 | 49 | if (pid != 0) { 50 | // parent 51 | struct pollfd fds[2] = { 52 | { .fd = master, .events = POLLIN }, 53 | { .fd = STDIN_FILENO, .events = POLLIN }, 54 | }; 55 | 56 | vt_parser_t *vt = vtnew(callback, &master); 57 | char buffer[BUFFER_SIZE]; 58 | size_t length; 59 | int status; 60 | 61 | while (1) { 62 | poll(fds, 2, -1); 63 | if (fds[1].revents & POLLIN) { 64 | length = read(STDIN_FILENO, buffer, BUFFER_SIZE); 65 | vtparse(vt, buffer, length); 66 | } 67 | if (fds[0].revents & POLLIN) { 68 | length = read(master, &buffer[0], BUFFER_SIZE); 69 | write(STDOUT_FILENO, &buffer[0], length); 70 | } 71 | 72 | if (fds[0].revents & POLLHUP || fds[1].revents & POLLHUP) { 73 | waitpid(pid, &status, 0); 74 | vtfree(vt); 75 | return WEXITSTATUS(status); 76 | } 77 | if (fds[0].revents & POLLERR || fds[1].revents & POLLERR) { 78 | vtfree(vt); 79 | return EXIT_FAILURE; 80 | } 81 | } 82 | } else { 83 | // child 84 | setenv("TERM", "ansi", 1); 85 | execvp(argv[1], argv + 1); 86 | return LOG_ERR("execvp(): "); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /pty.win.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include "minivt.h" 8 | 9 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 10 | #define BUF_SIZE 2048 11 | 12 | // because the proper function isn't defined by microsoft duh 13 | uintptr_t _beginthreadex( // NATIVE CODE 14 | void *security, 15 | unsigned stack_size, 16 | unsigned ( __stdcall *start_address )( void * ), 17 | void *arglist, 18 | unsigned initflag, 19 | unsigned *thrdaddr 20 | ); 21 | 22 | typedef struct { 23 | winpty_t *pty; 24 | HANDLE read_side, write_side; 25 | } thread_t; 26 | 27 | static void write_callback(int type, vt_answer_t *ans, void *p) { 28 | uintptr_t *args = (uintptr_t *) p; 29 | thread_t *th = (thread_t *) args[0]; 30 | BOOL *w = (BOOL *) args[1]; 31 | DWORD *write = (DWORD *) args[2]; 32 | switch (type) { 33 | // TODO: don't ignore VT_MSG_CONTENT 34 | case VT_MSG_PASS: 35 | *w = WriteFile(th->write_side, ans->buffer.b, ans->buffer.len, write, NULL); 36 | break; 37 | case VT_MSG_RESIZE: 38 | winpty_set_size(th->pty, ans->point.c, ans->point.r, NULL); 39 | break; 40 | } 41 | } 42 | 43 | static BOOL try_read(HANDLE h, LPVOID data, DWORD max_size, DWORD *r) { 44 | DWORD read = 0; 45 | PeekNamedPipe(h, NULL, 0, NULL, &read, NULL); 46 | // if there's more data to read, we'll read that much to prevent block 47 | // if there's 1 or no data, we read 1 so it blocks until data is available 48 | read = read > 1 ? MIN(max_size, read) : 1; 49 | return ReadFile(h, data, read, r, NULL); 50 | } 51 | 52 | __stdcall unsigned int stdin_thread(void *ptr) { 53 | thread_t *th = (thread_t *) ptr; 54 | BYTE buf[BUF_SIZE]; 55 | DWORD read = 0, write = 0; 56 | BOOL r, w; 57 | 58 | intptr_t args[3] = { (intptr_t) ptr, (intptr_t) &w, (intptr_t) &write }; 59 | vt_parser_t *vt = vtnew(write_callback, args); 60 | do { 61 | r = try_read(th->read_side, buf, BUF_SIZE, &read); 62 | if (r && read > 0) 63 | vtparse(vt, (const char *)buf, read); 64 | } while (r && w); 65 | vtfree(vt); 66 | return 0; 67 | } 68 | 69 | __stdcall unsigned int stdout_thread(void *ptr) { 70 | thread_t *th = (thread_t *) ptr; 71 | BYTE buf[BUF_SIZE]; 72 | DWORD read = 0, write = 0; 73 | BOOL r, w; 74 | do { 75 | r = try_read(th->read_side, buf, BUF_SIZE, &read); 76 | w = WriteFile(th->write_side, buf, read, &write, NULL); 77 | } while (r && w); 78 | return 0; 79 | } 80 | 81 | static void winpty_error(winpty_error_ptr_t err) { 82 | LPCWSTR msg = winpty_error_msg(err); 83 | fwprintf(stderr, L"winpty: %ls\n", msg); 84 | winpty_error_free(err); 85 | } 86 | 87 | static void win32_error(DWORD err) { 88 | LPWSTR msg = NULL; 89 | FormatMessageW( 90 | FORMAT_MESSAGE_ALLOCATE_BUFFER 91 | | FORMAT_MESSAGE_FROM_SYSTEM 92 | | FORMAT_MESSAGE_IGNORE_INSERTS, 93 | NULL, 94 | err, 95 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 96 | (LPWSTR) &msg, 97 | 0, 98 | NULL 99 | ); 100 | 101 | if (msg != NULL) { 102 | fwprintf(stderr, L"error: %ls\n", msg); 103 | LocalFree(msg); 104 | } 105 | } 106 | 107 | int main() { 108 | int argc = 0; 109 | LPWSTR cmdline = GetCommandLineW(); 110 | LPWSTR *argv = CommandLineToArgvW(cmdline, &argc); 111 | 112 | if (argc < 2) { 113 | fprintf(stderr, "error: insufficient arguments\n"); 114 | return 1; 115 | } 116 | 117 | winpty_error_ptr_t err = NULL; 118 | winpty_config_t *config = NULL; 119 | winpty_t *pty = NULL; 120 | winpty_spawn_config_t *spawn_config = NULL; 121 | 122 | HANDLE stdin_handle, stdout_handle, pty_in, pty_out; 123 | HANDLE threads[2]; 124 | 125 | stdin_handle = stdout_handle = pty_in = pty_out = INVALID_HANDLE_VALUE; 126 | threads[0] = threads[1] = INVALID_HANDLE_VALUE; 127 | 128 | config = winpty_config_new(0, &err); 129 | if (config == NULL) { 130 | winpty_error(err); 131 | goto cleanup; 132 | } 133 | winpty_error_free(err); 134 | 135 | winpty_config_set_initial_size(config, 80, 24); 136 | 137 | pty = winpty_open(config, &err); 138 | if (pty == NULL) { 139 | winpty_error(err); 140 | goto cleanup; 141 | } 142 | winpty_error_free(err); 143 | 144 | LPCWSTR pty_in_name = winpty_conin_name(pty); 145 | LPCWSTR pty_out_name = winpty_conout_name(pty); 146 | 147 | stdin_handle = GetStdHandle(STD_INPUT_HANDLE); 148 | stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); 149 | 150 | DWORD cm = 0; 151 | GetConsoleMode(stdin_handle, &cm); 152 | SetConsoleMode(stdin_handle, cm & ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)); 153 | 154 | pty_in = CreateFileW(pty_in_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 155 | pty_out = CreateFileW(pty_out_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 156 | 157 | if (pty_in == INVALID_HANDLE_VALUE || pty_out == INVALID_HANDLE_VALUE) { 158 | win32_error(GetLastError()); 159 | goto cleanup; 160 | } 161 | 162 | thread_t in_thread = { pty, stdin_handle, pty_in }; 163 | 164 | thread_t out_thread = { pty, pty_out, stdout_handle }; 165 | 166 | unsigned int thread_id; 167 | threads[0] = (HANDLE) _beginthreadex(NULL, 0, stdin_thread, &in_thread, 0, &thread_id); 168 | threads[1] = (HANDLE) _beginthreadex(NULL, 0, stdout_thread, &out_thread, 0, &thread_id); 169 | 170 | spawn_config = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_MASK, argv[1], NULL, NULL, NULL, &err); 171 | if (spawn_config == NULL) { 172 | winpty_error(err); 173 | goto cleanup; 174 | } 175 | winpty_error_free(err); 176 | 177 | HANDLE proc = INVALID_HANDLE_VALUE; 178 | if (!winpty_spawn(pty, spawn_config, &proc, NULL, NULL, &err)) { 179 | winpty_error(err); 180 | goto cleanup; 181 | } 182 | winpty_error_free(err); 183 | 184 | WaitForSingleObject(proc, INFINITE); 185 | 186 | // this will cause pending ReadFile on stdin to stop so the thread will detect 187 | // that pty_out has closed 188 | CancelIoEx(stdin_handle, NULL); 189 | 190 | WaitForMultipleObjects(2, threads, TRUE, INFINITE); 191 | 192 | cleanup: 193 | winpty_config_free(config); 194 | winpty_free(pty); 195 | winpty_spawn_config_free(spawn_config); 196 | CloseHandle(threads[0]); 197 | CloseHandle(threads[1]); 198 | CloseHandle(pty_in); 199 | CloseHandle(pty_out); 200 | 201 | return 0; 202 | } 203 | -------------------------------------------------------------------------------- /tmt.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Rob King 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the copyright holder nor the 12 | * names of contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS, 19 | * COPYRIGHT HOLDERS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "tmt.h" 33 | 34 | #define BUF_MAX 100 35 | #define PAR_MAX 8 36 | #define TAB 8 37 | #define MAX(x, y) (((size_t)(x) > (size_t)(y)) ? (size_t)(x) : (size_t)(y)) 38 | #define MIN(x, y) (((size_t)(x) < (size_t)(y)) ? (size_t)(x) : (size_t)(y)) 39 | #define CLINE(vt) (vt)->screen.lines[MIN((vt)->curs.r, (vt)->screen.nline - 1)] 40 | 41 | #define P0(x) (vt->pars[x]) 42 | #define P1(x) (vt->pars[x]? vt->pars[x] : 1) 43 | #define CB(vt, m, a) ((vt)->cb? (vt)->cb(m, vt, a, (vt)->p) : (void)0) 44 | #define INESC ((vt)->state) 45 | 46 | #define COMMON_VARS \ 47 | TMTSCREEN *s = &vt->screen; \ 48 | TMTPOINT *c = &vt->curs; \ 49 | TMTLINE *l = CLINE(vt); \ 50 | TMTCHAR *t = vt->tabs->chars 51 | 52 | #define HANDLER(name) static void name (TMT *vt) { COMMON_VARS; 53 | 54 | struct TMT{ 55 | TMTPOINT curs, oldcurs; 56 | TMTATTRS attrs, oldattrs; 57 | 58 | bool dirty, acs, ignored, cignored; 59 | TMTSCREEN screen; 60 | TMTLINE *tabs; 61 | 62 | TMTCALLBACK cb; 63 | void *p; 64 | const wchar_t *acschars; 65 | 66 | mbstate_t ms; 67 | size_t nmb; 68 | char mb[BUF_MAX + 1]; 69 | 70 | size_t pars[PAR_MAX]; 71 | size_t npar; 72 | size_t arg; 73 | enum {S_NUL, S_ESC, S_ARG} state; 74 | }; 75 | 76 | static TMTATTRS defattrs = {.fg = TMT_COLOR_DEFAULT, .bg = TMT_COLOR_DEFAULT}; 77 | static void writecharatcurs(TMT *vt, wchar_t w); 78 | 79 | static wchar_t 80 | tacs(const TMT *vt, unsigned char c) 81 | { 82 | /* The terminfo alternate character set for ANSI. */ 83 | static unsigned char map[] = {0020U, 0021U, 0030U, 0031U, 0333U, 0004U, 84 | 0261U, 0370U, 0361U, 0260U, 0331U, 0277U, 85 | 0332U, 0300U, 0305U, 0176U, 0304U, 0304U, 86 | 0304U, 0137U, 0303U, 0264U, 0301U, 0302U, 87 | 0263U, 0363U, 0362U, 0343U, 0330U, 0234U, 88 | 0376U}; 89 | for (size_t i = 0; i < sizeof(map); i++) if (map[i] == c) 90 | return vt->acschars[i]; 91 | return (wchar_t)c; 92 | } 93 | 94 | static void 95 | dirtylines(TMT *vt, size_t s, size_t e) 96 | { 97 | vt->dirty = true; 98 | for (size_t i = s; i < e; i++) 99 | vt->screen.lines[i]->dirty = true; 100 | } 101 | 102 | static void 103 | clearline(TMT *vt, TMTLINE *l, size_t s, size_t e) 104 | { 105 | vt->dirty = l->dirty = true; 106 | for (size_t i = s; i < e && i < vt->screen.ncol; i++){ 107 | l->chars[i].a = defattrs; 108 | l->chars[i].c = L' '; 109 | } 110 | } 111 | 112 | static void 113 | clearlines(TMT *vt, size_t r, size_t n) 114 | { 115 | for (size_t i = r; i < r + n && i < vt->screen.nline; i++) 116 | clearline(vt, vt->screen.lines[i], 0, vt->screen.ncol); 117 | } 118 | 119 | static void 120 | scrup(TMT *vt, size_t r, size_t n) 121 | { 122 | n = MIN(n, vt->screen.nline - 1 - r); 123 | 124 | if (n){ 125 | TMTLINE *buf[n]; 126 | 127 | memcpy(buf, vt->screen.lines + r, n * sizeof(TMTLINE *)); 128 | memmove(vt->screen.lines + r, vt->screen.lines + r + n, 129 | (vt->screen.nline - n - r) * sizeof(TMTLINE *)); 130 | memcpy(vt->screen.lines + (vt->screen.nline - n), 131 | buf, n * sizeof(TMTLINE *)); 132 | 133 | clearlines(vt, vt->screen.nline - n, n); 134 | dirtylines(vt, r, vt->screen.nline); 135 | } 136 | } 137 | 138 | static void 139 | scrdn(TMT *vt, size_t r, size_t n) 140 | { 141 | n = MIN(n, vt->screen.nline - 1 - r); 142 | 143 | if (n){ 144 | TMTLINE *buf[n]; 145 | 146 | memcpy(buf, vt->screen.lines + (vt->screen.nline - n), 147 | n * sizeof(TMTLINE *)); 148 | memmove(vt->screen.lines + r + n, vt->screen.lines + r, 149 | (vt->screen.nline - n - r) * sizeof(TMTLINE *)); 150 | memcpy(vt->screen.lines + r, buf, n * sizeof(TMTLINE *)); 151 | 152 | clearlines(vt, r, n); 153 | dirtylines(vt, r, vt->screen.nline); 154 | } 155 | } 156 | 157 | HANDLER(ed) 158 | size_t b = 0; 159 | size_t e = s->nline; 160 | 161 | switch (P0(0)){ 162 | case 0: b = c->r + 1; clearline(vt, l, c->c, vt->screen.ncol); break; 163 | case 1: e = c->r - 1; clearline(vt, l, 0, c->c); break; 164 | case 2: /* use defaults */ break; 165 | default: /* do nothing */ return; 166 | } 167 | 168 | clearlines(vt, b, e - b); 169 | } 170 | 171 | HANDLER(ich) 172 | size_t n = P1(0); /* XXX use MAX */ 173 | if (n > s->ncol - c->c - 1) n = s->ncol - c->c - 1; 174 | 175 | memmove(l->chars + c->c + n, l->chars + c->c, 176 | MIN(s->ncol - 1 - c->c, 177 | (s->ncol - c->c - n - 1)) * sizeof(TMTCHAR)); 178 | clearline(vt, l, c->c, n); 179 | } 180 | 181 | HANDLER(dch) 182 | size_t n = P1(0); /* XXX use MAX */ 183 | if (n > s->ncol - c->c) n = s->ncol - c->c; 184 | 185 | memmove(l->chars + c->c, l->chars + c->c + n, 186 | (s->ncol - c->c - n) * sizeof(TMTCHAR)); 187 | 188 | clearline(vt, l, s->ncol - c->c - n, s->ncol); 189 | } 190 | 191 | HANDLER(el) 192 | switch (P0(0)){ 193 | case 0: clearline(vt, l, c->c, vt->screen.ncol); break; 194 | case 1: clearline(vt, l, 0, MIN(c->c + 1, s->ncol - 1)); break; 195 | case 2: clearline(vt, l, 0, vt->screen.ncol); break; 196 | } 197 | } 198 | 199 | HANDLER(sgr) 200 | #define FGBG(c) *(P0(i) < 40? &vt->attrs.fg : &vt->attrs.bg) = c 201 | for (size_t i = 0; i < vt->npar; i++) switch (P0(i)){ 202 | case 0: vt->attrs = defattrs; break; 203 | case 1: case 22: vt->attrs.bold = P0(0) < 20; break; 204 | case 2: case 23: vt->attrs.dim = P0(0) < 20; break; 205 | case 4: case 24: vt->attrs.underline = P0(0) < 20; break; 206 | case 5: case 25: vt->attrs.blink = P0(0) < 20; break; 207 | case 7: case 27: vt->attrs.reverse = P0(0) < 20; break; 208 | case 8: case 28: vt->attrs.invisible = P0(0) < 20; break; 209 | case 10: case 11: vt->acs = P0(0) > 10; break; 210 | case 30: case 40: FGBG(TMT_COLOR_BLACK); break; 211 | case 31: case 41: FGBG(TMT_COLOR_RED); break; 212 | case 32: case 42: FGBG(TMT_COLOR_GREEN); break; 213 | case 33: case 43: FGBG(TMT_COLOR_YELLOW); break; 214 | case 34: case 44: FGBG(TMT_COLOR_BLUE); break; 215 | case 35: case 45: FGBG(TMT_COLOR_MAGENTA); break; 216 | case 36: case 46: FGBG(TMT_COLOR_CYAN); break; 217 | case 37: case 47: FGBG(TMT_COLOR_WHITE); break; 218 | case 39: case 49: FGBG(TMT_COLOR_DEFAULT); break; 219 | } 220 | } 221 | 222 | HANDLER(rep) 223 | if (!c->c) return; 224 | wchar_t r = l->chars[c->c - 1].c; 225 | for (size_t i = 0; i < P1(0); i++) 226 | writecharatcurs(vt, r); 227 | } 228 | 229 | HANDLER(dsr) 230 | char r[BUF_MAX + 1] = {0}; 231 | snprintf(r, BUF_MAX, "\033[%zd;%zdR", c->r, c->c); 232 | CB(vt, TMT_MSG_ANSWER, (const char *)r); 233 | } 234 | 235 | HANDLER(resetparser) 236 | memset(vt->pars, 0, sizeof(vt->pars)); 237 | vt->state = vt->npar = vt->arg = vt->ignored = (bool)0; 238 | } 239 | 240 | HANDLER(consumearg) 241 | if (vt->npar < PAR_MAX) 242 | vt->pars[vt->npar++] = vt->arg; 243 | vt->arg = 0; 244 | } 245 | 246 | HANDLER(fixcursor) 247 | c->r = MIN(c->r, s->nline - 1); 248 | c->c = MIN(c->c, s->ncol - 1); 249 | } 250 | 251 | static bool 252 | handlechar(TMT *vt, char i) 253 | { 254 | COMMON_VARS; 255 | 256 | char cs[] = {i, 0}; 257 | #define ON(S, C, A) if (vt->state == (S) && strchr(C, i)){ A; return true;} 258 | #define DO(S, C, A) ON(S, C, consumearg(vt); if (!vt->ignored) {A;} \ 259 | fixcursor(vt); resetparser(vt);); 260 | 261 | DO(S_NUL, "\x07", vt->cignored = false; CB(vt, TMT_MSG_BELL, NULL)) 262 | DO(S_NUL, "\x08", if (c->c) c->c--) 263 | DO(S_NUL, "\x09", while (++c->c < s->ncol - 1 && t[c->c].c != L'*')) 264 | DO(S_NUL, "\x0a", c->r < s->nline - 1? (void)c->r++ : scrup(vt, 0, 1)) 265 | DO(S_NUL, "\x0d", c->c = 0) 266 | ON(S_NUL, "\x1b", vt->state = S_ESC) 267 | ON(S_ESC, "\x1b", vt->state = S_ESC) 268 | DO(S_ESC, "\\", vt->cignored = false) 269 | DO(S_ESC, "H", t[c->c].c = L'*') 270 | DO(S_ESC, "7", vt->oldcurs = vt->curs; vt->oldattrs = vt->attrs) 271 | DO(S_ESC, "8", vt->curs = vt->oldcurs; vt->attrs = vt->oldattrs) 272 | ON(S_ESC, "]X^_", vt->cignored = true) 273 | ON(S_ESC, "+*()", vt->ignored = true; vt->state = S_ARG) 274 | DO(S_ESC, "c", tmt_reset(vt)) 275 | ON(S_ESC, "[", vt->state = S_ARG) 276 | ON(S_ARG, "\x1b", vt->state = S_ESC) 277 | ON(S_ARG, ";", consumearg(vt)) 278 | ON(S_ARG, "?", (void)0) 279 | ON(S_ARG, "0123456789", vt->arg = vt->arg * 10 + atoi(cs)) 280 | DO(S_ARG, "A", c->r = MAX(c->r - P1(0), 0)) 281 | DO(S_ARG, "B", c->r = MIN(c->r + P1(0), s->nline - 1)) 282 | DO(S_ARG, "C", c->c = MIN(c->c + P1(0), s->ncol - 1)) 283 | DO(S_ARG, "D", c->c = MIN(c->c - P1(0), c->c)) 284 | DO(S_ARG, "E", c->c = 0; c->r = MIN(c->r + P1(0), s->nline - 1)) 285 | DO(S_ARG, "F", c->c = 0; c->r = MAX(c->r - P1(0), 0)) 286 | DO(S_ARG, "G", c->c = MIN(P1(0) - 1, s->ncol - 1)) 287 | DO(S_ARG, "d", c->r = MIN(P1(0) - 1, s->nline - 1)) 288 | DO(S_ARG, "Hf", c->r = P1(0) - 1; c->c = P1(1) - 1) 289 | DO(S_ARG, "I", while (++c->c < s->ncol - 1 && t[c->c].c != L'*')) 290 | DO(S_ARG, "J", ed(vt)) 291 | DO(S_ARG, "K", el(vt)) 292 | DO(S_ARG, "L", scrdn(vt, c->r, P1(0))) 293 | DO(S_ARG, "M", scrup(vt, c->r, P1(0))) 294 | DO(S_ARG, "P", dch(vt)) 295 | DO(S_ARG, "S", scrup(vt, 0, P1(0))) 296 | DO(S_ARG, "T", scrdn(vt, 0, P1(0))) 297 | DO(S_ARG, "X", clearline(vt, l, c->c, P1(0))) 298 | DO(S_ARG, "Z", while (c->c && t[--c->c].c != L'*')) 299 | DO(S_ARG, "b", rep(vt)); 300 | DO(S_ARG, "c", CB(vt, TMT_MSG_ANSWER, "\033[?6c")) 301 | DO(S_ARG, "g", if (P0(0) == 3) clearline(vt, vt->tabs, 0, s->ncol)) 302 | DO(S_ARG, "m", sgr(vt)) 303 | DO(S_ARG, "n", if (P0(0) == 6) dsr(vt)) 304 | DO(S_ARG, "h", if (P0(0) == 25) CB(vt, TMT_MSG_CURSOR, "t")) 305 | DO(S_ARG, "i", (void)0) 306 | DO(S_ARG, "l", if (P0(0) == 25) CB(vt, TMT_MSG_CURSOR, "f")) 307 | DO(S_ARG, "s", vt->oldcurs = vt->curs; vt->oldattrs = vt->attrs) 308 | DO(S_ARG, "u", vt->curs = vt->oldcurs; vt->attrs = vt->oldattrs) 309 | DO(S_ARG, "@", ich(vt)) 310 | 311 | return resetparser(vt), vt->cignored; 312 | } 313 | 314 | static void 315 | notify(TMT *vt, bool update, bool moved) 316 | { 317 | if (update) CB(vt, TMT_MSG_UPDATE, &vt->screen); 318 | if (moved) CB(vt, TMT_MSG_MOVED, &vt->curs); 319 | } 320 | 321 | static TMTLINE * 322 | allocline(TMT *vt, TMTLINE *o, size_t n, size_t pc) 323 | { 324 | TMTLINE *l = realloc(o, sizeof(TMTLINE) + n * sizeof(TMTCHAR)); 325 | if (!l) return NULL; 326 | 327 | clearline(vt, l, pc, n); 328 | return l; 329 | } 330 | 331 | static void 332 | freelines(TMT *vt, size_t s, size_t n, bool screen) 333 | { 334 | for (size_t i = s; vt->screen.lines && i < s + n; i++){ 335 | free(vt->screen.lines[i]); 336 | vt->screen.lines[i] = NULL; 337 | } 338 | if (screen) free(vt->screen.lines); 339 | } 340 | 341 | TMT * 342 | tmt_open(size_t nline, size_t ncol, TMTCALLBACK cb, void *p, 343 | const wchar_t *acs) 344 | { 345 | TMT *vt = calloc(1, sizeof(TMT)); 346 | if (!nline || !ncol || !vt) return free(vt), NULL; 347 | 348 | /* ASCII-safe defaults for box-drawing characters. */ 349 | vt->acschars = acs? acs : L"><^v#+:o##+++++~---_++++|<>*!fo"; 350 | vt->cb = cb; 351 | vt->p = p; 352 | 353 | if (!tmt_resize(vt, nline, ncol)) return tmt_close(vt), NULL; 354 | return vt; 355 | } 356 | 357 | void 358 | tmt_close(TMT *vt) 359 | { 360 | free(vt->tabs); 361 | freelines(vt, 0, vt->screen.nline, true); 362 | free(vt); 363 | } 364 | 365 | bool 366 | tmt_resize(TMT *vt, size_t nline, size_t ncol) 367 | { 368 | if (nline < 2 || ncol < 2) return false; 369 | if (nline < vt->screen.nline) 370 | freelines(vt, nline, vt->screen.nline - nline, false); 371 | 372 | TMTLINE **l = realloc(vt->screen.lines, nline * sizeof(TMTLINE *)); 373 | if (!l) return false; 374 | 375 | size_t pc = vt->screen.ncol; 376 | vt->screen.lines = l; 377 | vt->screen.ncol = ncol; 378 | for (size_t i = 0; i < nline; i++){ 379 | TMTLINE *nl = NULL; 380 | if (i >= vt->screen.nline) 381 | nl = vt->screen.lines[i] = allocline(vt, NULL, ncol, 0); 382 | else 383 | nl = allocline(vt, vt->screen.lines[i], ncol, pc); 384 | 385 | if (!nl) return false; 386 | vt->screen.lines[i] = nl; 387 | } 388 | vt->screen.nline = nline; 389 | 390 | vt->tabs = allocline(vt, vt->tabs, ncol, 0); 391 | if (!vt->tabs) return free(l), false; 392 | vt->tabs->chars[0].c = vt->tabs->chars[ncol - 1].c = L'*'; 393 | for (size_t i = 0; i < ncol; i++) if (i % TAB == 0) 394 | vt->tabs->chars[i].c = L'*'; 395 | 396 | fixcursor(vt); 397 | dirtylines(vt, 0, nline); 398 | notify(vt, true, true); 399 | return true; 400 | } 401 | 402 | static void 403 | writecharatcurs(TMT *vt, wchar_t w) 404 | { 405 | COMMON_VARS; 406 | 407 | #ifdef TMT_HAS_WCWIDTH 408 | extern int wcwidth(wchar_t c); 409 | if (wcwidth(w) > 1) w = TMT_INVALID_CHAR; 410 | if (wcwidth(w) < 0) return; 411 | #endif 412 | 413 | CLINE(vt)->chars[vt->curs.c].c = w; 414 | CLINE(vt)->chars[vt->curs.c].a = vt->attrs; 415 | CLINE(vt)->dirty = vt->dirty = true; 416 | 417 | if (c->c < s->ncol - 1) 418 | c->c++; 419 | else{ 420 | c->c = 0; 421 | c->r++; 422 | } 423 | 424 | if (c->r >= s->nline){ 425 | c->r = s->nline - 1; 426 | scrup(vt, 0, 1); 427 | } 428 | } 429 | 430 | static inline size_t 431 | testmbchar(TMT *vt) 432 | { 433 | mbstate_t ts = vt->ms; 434 | return vt->nmb? mbrtowc(NULL, vt->mb, vt->nmb, &ts) : (size_t)-2; 435 | } 436 | 437 | static inline wchar_t 438 | getmbchar(TMT *vt) 439 | { 440 | wchar_t c = 0; 441 | size_t n = mbrtowc(&c, vt->mb, vt->nmb, &vt->ms); 442 | vt->nmb = 0; 443 | return (n == (size_t)-1 || n == (size_t)-2)? TMT_INVALID_CHAR : c; 444 | } 445 | 446 | void 447 | tmt_write(TMT *vt, const char *s, size_t n) 448 | { 449 | TMTPOINT oc = vt->curs; 450 | n = n? n : strlen(s); 451 | 452 | for (size_t p = 0; p < n; p++){ 453 | if (handlechar(vt, s[p])) 454 | continue; 455 | else if (vt->acs) 456 | writecharatcurs(vt, tacs(vt, (unsigned char)s[p])); 457 | else if (vt->nmb >= BUF_MAX) 458 | writecharatcurs(vt, getmbchar(vt)); 459 | else{ 460 | switch (testmbchar(vt)){ 461 | case (size_t)-1: writecharatcurs(vt, getmbchar(vt)); break; 462 | case (size_t)-2: vt->mb[vt->nmb++] = s[p]; break; 463 | } 464 | 465 | if (testmbchar(vt) <= MB_LEN_MAX) 466 | writecharatcurs(vt, getmbchar(vt)); 467 | } 468 | } 469 | 470 | notify(vt, vt->dirty, memcmp(&oc, &vt->curs, sizeof(oc)) != 0); 471 | } 472 | 473 | const TMTSCREEN * 474 | tmt_screen(const TMT *vt) 475 | { 476 | return &vt->screen; 477 | } 478 | 479 | const TMTPOINT * 480 | tmt_cursor(const TMT *vt) 481 | { 482 | return &vt->curs; 483 | } 484 | 485 | void 486 | tmt_clean(TMT *vt) 487 | { 488 | for (size_t i = 0; i < vt->screen.nline; i++) 489 | vt->dirty = vt->screen.lines[i]->dirty = false; 490 | } 491 | 492 | void 493 | tmt_reset(TMT *vt) 494 | { 495 | vt->curs.r = vt->curs.c = vt->oldcurs.r = vt->oldcurs.c = vt->acs = (bool)0; 496 | resetparser(vt); 497 | vt->attrs = vt->oldattrs = defattrs; 498 | memset(&vt->ms, 0, sizeof(vt->ms)); 499 | clearlines(vt, 0, vt->screen.nline); 500 | CB(vt, TMT_MSG_CURSOR, "t"); 501 | notify(vt, true, true); 502 | } 503 | -------------------------------------------------------------------------------- /tmt.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Rob King 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the copyright holder nor the 12 | * names of contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS, 19 | * COPYRIGHT HOLDERS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef TMT_H 29 | #define TMT_H 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | /**** INVALID WIDE CHARACTER */ 36 | #ifndef TMT_INVALID_CHAR 37 | #define TMT_INVALID_CHAR ((wchar_t)0xfffd) 38 | #endif 39 | 40 | /**** INPUT SEQUENCES */ 41 | #define TMT_KEY_UP "\033[A" 42 | #define TMT_KEY_DOWN "\033[B" 43 | #define TMT_KEY_RIGHT "\033[C" 44 | #define TMT_KEY_LEFT "\033[D" 45 | #define TMT_KEY_HOME "\033[H" 46 | #define TMT_KEY_END "\033[Y" 47 | #define TMT_KEY_INSERT "\033[L" 48 | #define TMT_KEY_BACKSPACE "\x08" 49 | #define TMT_KEY_ESCAPE "\x1b" 50 | #define TMT_KEY_BACK_TAB "\033[Z" 51 | #define TMT_KEY_PAGE_UP "\033[V" 52 | #define TMT_KEY_PAGE_DOWN "\033[U" 53 | #define TMT_KEY_F1 "\033OP" 54 | #define TMT_KEY_F2 "\033OQ" 55 | #define TMT_KEY_F3 "\033OR" 56 | #define TMT_KEY_F4 "\033OS" 57 | #define TMT_KEY_F5 "\033OT" 58 | #define TMT_KEY_F6 "\033OU" 59 | #define TMT_KEY_F7 "\033OV" 60 | #define TMT_KEY_F8 "\033OW" 61 | #define TMT_KEY_F9 "\033OX" 62 | #define TMT_KEY_F10 "\033OY" 63 | 64 | /**** BASIC DATA STRUCTURES */ 65 | typedef struct TMT TMT; 66 | 67 | typedef enum{ 68 | TMT_COLOR_DEFAULT = -1, 69 | TMT_COLOR_BLACK = 1, 70 | TMT_COLOR_RED, 71 | TMT_COLOR_GREEN, 72 | TMT_COLOR_YELLOW, 73 | TMT_COLOR_BLUE, 74 | TMT_COLOR_MAGENTA, 75 | TMT_COLOR_CYAN, 76 | TMT_COLOR_WHITE, 77 | TMT_COLOR_MAX 78 | } tmt_color_t; 79 | 80 | typedef struct TMTATTRS TMTATTRS; 81 | struct TMTATTRS{ 82 | bool bold; 83 | bool dim; 84 | bool underline; 85 | bool blink; 86 | bool reverse; 87 | bool invisible; 88 | tmt_color_t fg; 89 | tmt_color_t bg; 90 | }; 91 | 92 | typedef struct TMTCHAR TMTCHAR; 93 | struct TMTCHAR{ 94 | wchar_t c; 95 | TMTATTRS a; 96 | }; 97 | 98 | typedef struct TMTPOINT TMTPOINT; 99 | struct TMTPOINT{ 100 | size_t r; 101 | size_t c; 102 | }; 103 | 104 | typedef struct TMTLINE TMTLINE; 105 | struct TMTLINE{ 106 | bool dirty; 107 | TMTCHAR chars[]; 108 | }; 109 | 110 | typedef struct TMTSCREEN TMTSCREEN; 111 | struct TMTSCREEN{ 112 | size_t nline; 113 | size_t ncol; 114 | 115 | TMTLINE **lines; 116 | }; 117 | 118 | /**** CALLBACK SUPPORT */ 119 | typedef enum{ 120 | TMT_MSG_MOVED, 121 | TMT_MSG_UPDATE, 122 | TMT_MSG_ANSWER, 123 | TMT_MSG_BELL, 124 | TMT_MSG_CURSOR 125 | } tmt_msg_t; 126 | 127 | typedef void (*TMTCALLBACK)(tmt_msg_t m, struct TMT *v, const void *r, void *p); 128 | 129 | /**** PUBLIC FUNCTIONS */ 130 | TMT *tmt_open(size_t nline, size_t ncol, TMTCALLBACK cb, void *p, 131 | const wchar_t *acs); 132 | void tmt_close(TMT *vt); 133 | bool tmt_resize(TMT *vt, size_t nline, size_t ncol); 134 | void tmt_write(TMT *vt, const char *s, size_t n); 135 | const TMTSCREEN *tmt_screen(const TMT *vt); 136 | const TMTPOINT *tmt_cursor(const TMT *vt); 137 | void tmt_clean(TMT *vt); 138 | void tmt_reset(TMT *vt); 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /winpty-agent.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColonelPhantom/lite-xl-tmt/1181923f4ac9f398d6f9ad592c845e14d2350656/winpty-agent.exe -------------------------------------------------------------------------------- /winpty.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColonelPhantom/lite-xl-tmt/1181923f4ac9f398d6f9ad592c845e14d2350656/winpty.dll -------------------------------------------------------------------------------- /winpty/winpty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2016 Ryan Prichard 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WINPTY_H 24 | #define WINPTY_H 25 | 26 | #include 27 | 28 | #include "winpty_constants.h" 29 | 30 | /* On 32-bit Windows, winpty functions have the default __cdecl (not __stdcall) 31 | * calling convention. (64-bit Windows has only a single calling convention.) 32 | * When compiled with __declspec(dllexport), with either MinGW or MSVC, the 33 | * winpty functions are unadorned--no underscore prefix or '@nn' suffix--so 34 | * GetProcAddress can be used easily. */ 35 | #ifdef COMPILING_WINPTY_DLL 36 | #define WINPTY_API __declspec(dllexport) 37 | #else 38 | #define WINPTY_API __declspec(dllimport) 39 | #endif 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* The winpty API uses wide characters, instead of UTF-8, to avoid conversion 46 | * complications related to surrogates. Windows generally tolerates unpaired 47 | * surrogates in text, which makes conversion to and from UTF-8 ambiguous and 48 | * complicated. (There are different UTF-8 variants that deal with UTF-16 49 | * surrogates differently.) */ 50 | 51 | 52 | 53 | /***************************************************************************** 54 | * Error handling. */ 55 | 56 | /* All the APIs have an optional winpty_error_t output parameter. If a 57 | * non-NULL argument is specified, then either the API writes NULL to the 58 | * value (on success) or writes a newly allocated winpty_error_t object. The 59 | * object must be freed using winpty_error_free. */ 60 | 61 | /* An error object. */ 62 | typedef struct winpty_error_s winpty_error_t; 63 | typedef winpty_error_t *winpty_error_ptr_t; 64 | 65 | /* An error code -- one of WINPTY_ERROR_xxx. */ 66 | typedef DWORD winpty_result_t; 67 | 68 | /* Gets the error code from the error object. */ 69 | WINPTY_API winpty_result_t winpty_error_code(winpty_error_ptr_t err); 70 | 71 | /* Returns a textual representation of the error. The string is freed when 72 | * the error is freed. */ 73 | WINPTY_API LPCWSTR winpty_error_msg(winpty_error_ptr_t err); 74 | 75 | /* Free the error object. Every error returned from the winpty API must be 76 | * freed. */ 77 | WINPTY_API void winpty_error_free(winpty_error_ptr_t err); 78 | 79 | 80 | 81 | /***************************************************************************** 82 | * Configuration of a new agent. */ 83 | 84 | /* The winpty_config_t object is not thread-safe. */ 85 | typedef struct winpty_config_s winpty_config_t; 86 | 87 | /* Allocate a winpty_config_t value. Returns NULL on error. There are no 88 | * required settings -- the object may immediately be used. agentFlags is a 89 | * set of zero or more WINPTY_FLAG_xxx values. An unrecognized flag results 90 | * in an assertion failure. */ 91 | WINPTY_API winpty_config_t * 92 | winpty_config_new(UINT64 agentFlags, winpty_error_ptr_t *err /*OPTIONAL*/); 93 | 94 | /* Free the cfg object after passing it to winpty_open. */ 95 | WINPTY_API void winpty_config_free(winpty_config_t *cfg); 96 | 97 | WINPTY_API void 98 | winpty_config_set_initial_size(winpty_config_t *cfg, int cols, int rows); 99 | 100 | /* Set the mouse mode to one of the WINPTY_MOUSE_MODE_xxx constants. */ 101 | WINPTY_API void 102 | winpty_config_set_mouse_mode(winpty_config_t *cfg, int mouseMode); 103 | 104 | /* Amount of time to wait for the agent to startup and to wait for any given 105 | * agent RPC request. Must be greater than 0. Can be INFINITE. */ 106 | WINPTY_API void 107 | winpty_config_set_agent_timeout(winpty_config_t *cfg, DWORD timeoutMs); 108 | 109 | 110 | 111 | /***************************************************************************** 112 | * Start the agent. */ 113 | 114 | /* The winpty_t object is thread-safe. */ 115 | typedef struct winpty_s winpty_t; 116 | 117 | /* Starts the agent. Returns NULL on error. This process will connect to the 118 | * agent over a control pipe, and the agent will open data pipes (e.g. CONIN 119 | * and CONOUT). */ 120 | WINPTY_API winpty_t * 121 | winpty_open(const winpty_config_t *cfg, 122 | winpty_error_ptr_t *err /*OPTIONAL*/); 123 | 124 | /* A handle to the agent process. This value is valid for the lifetime of the 125 | * winpty_t object. Do not close it. */ 126 | WINPTY_API HANDLE winpty_agent_process(winpty_t *wp); 127 | 128 | 129 | 130 | /***************************************************************************** 131 | * I/O pipes. */ 132 | 133 | /* Returns the names of named pipes used for terminal I/O. Each input or 134 | * output direction uses a different half-duplex pipe. The agent creates 135 | * these pipes, and the client can connect to them using ordinary I/O methods. 136 | * The strings are freed when the winpty_t object is freed. 137 | * 138 | * winpty_conerr_name returns NULL unless WINPTY_FLAG_CONERR is specified. 139 | * 140 | * N.B.: CreateFile does not block when connecting to a local server pipe. If 141 | * the server pipe does not exist or is already connected, then it fails 142 | * instantly. */ 143 | WINPTY_API LPCWSTR winpty_conin_name(winpty_t *wp); 144 | WINPTY_API LPCWSTR winpty_conout_name(winpty_t *wp); 145 | WINPTY_API LPCWSTR winpty_conerr_name(winpty_t *wp); 146 | 147 | 148 | 149 | /***************************************************************************** 150 | * winpty agent RPC call: process creation. */ 151 | 152 | /* The winpty_spawn_config_t object is not thread-safe. */ 153 | typedef struct winpty_spawn_config_s winpty_spawn_config_t; 154 | 155 | /* winpty_spawn_config strings do not need to live as long as the config 156 | * object. They are copied. Returns NULL on error. spawnFlags is a set of 157 | * zero or more WINPTY_SPAWN_FLAG_xxx values. An unrecognized flag results in 158 | * an assertion failure. 159 | * 160 | * env is a a pointer to an environment block like that passed to 161 | * CreateProcess--a contiguous array of NUL-terminated "VAR=VAL" strings 162 | * followed by a final NUL terminator. 163 | * 164 | * N.B.: If you want to gather all of the child's output, you may want the 165 | * WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN flag. 166 | */ 167 | WINPTY_API winpty_spawn_config_t * 168 | winpty_spawn_config_new(UINT64 spawnFlags, 169 | LPCWSTR appname /*OPTIONAL*/, 170 | LPCWSTR cmdline /*OPTIONAL*/, 171 | LPCWSTR cwd /*OPTIONAL*/, 172 | LPCWSTR env /*OPTIONAL*/, 173 | winpty_error_ptr_t *err /*OPTIONAL*/); 174 | 175 | /* Free the cfg object after passing it to winpty_spawn. */ 176 | WINPTY_API void winpty_spawn_config_free(winpty_spawn_config_t *cfg); 177 | 178 | /* 179 | * Spawns the new process. 180 | * 181 | * The function initializes all output parameters to zero or NULL. 182 | * 183 | * On success, the function returns TRUE. For each of process_handle and 184 | * thread_handle that is non-NULL, the HANDLE returned from CreateProcess is 185 | * duplicated from the agent and returned to the winpty client. The client is 186 | * responsible for closing these HANDLES. 187 | * 188 | * On failure, the function returns FALSE, and if err is non-NULL, then *err 189 | * is set to an error object. 190 | * 191 | * If the agent's CreateProcess call failed, then *create_process_error is set 192 | * to GetLastError(), and the WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED error 193 | * is returned. 194 | * 195 | * winpty_spawn can only be called once per winpty_t object. If it is called 196 | * before the output data pipe(s) is/are connected, then collected output is 197 | * buffered until the pipes are connected, rather than being discarded. 198 | * 199 | * N.B.: GetProcessId works even if the process has exited. The PID is not 200 | * recycled until the NT process object is freed. 201 | * (https://blogs.msdn.microsoft.com/oldnewthing/20110107-00/?p=11803) 202 | */ 203 | WINPTY_API BOOL 204 | winpty_spawn(winpty_t *wp, 205 | const winpty_spawn_config_t *cfg, 206 | HANDLE *process_handle /*OPTIONAL*/, 207 | HANDLE *thread_handle /*OPTIONAL*/, 208 | DWORD *create_process_error /*OPTIONAL*/, 209 | winpty_error_ptr_t *err /*OPTIONAL*/); 210 | 211 | 212 | 213 | /***************************************************************************** 214 | * winpty agent RPC calls: everything else */ 215 | 216 | /* Change the size of the Windows console window. */ 217 | WINPTY_API BOOL 218 | winpty_set_size(winpty_t *wp, int cols, int rows, 219 | winpty_error_ptr_t *err /*OPTIONAL*/); 220 | 221 | /* Frees the winpty_t object and the OS resources contained in it. This 222 | * call breaks the connection with the agent, which should then close its 223 | * console, terminating the processes attached to it. 224 | * 225 | * This function must not be called if any other threads are using the 226 | * winpty_t object. Undefined behavior results. */ 227 | WINPTY_API void winpty_free(winpty_t *wp); 228 | 229 | 230 | 231 | /****************************************************************************/ 232 | 233 | #ifdef __cplusplus 234 | } 235 | #endif 236 | 237 | #endif /* WINPTY_H */ 238 | -------------------------------------------------------------------------------- /winpty/winpty_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Ryan Prichard 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WINPTY_CONSTANTS_H 24 | #define WINPTY_CONSTANTS_H 25 | 26 | /* 27 | * You may want to include winpty.h instead, which includes this header. 28 | * 29 | * This file is split out from winpty.h so that the agent can access the 30 | * winpty flags without also declaring the libwinpty APIs. 31 | */ 32 | 33 | /***************************************************************************** 34 | * Error codes. */ 35 | 36 | #define WINPTY_ERROR_SUCCESS 0 37 | #define WINPTY_ERROR_OUT_OF_MEMORY 1 38 | #define WINPTY_ERROR_SPAWN_CREATE_PROCESS_FAILED 2 39 | #define WINPTY_ERROR_LOST_CONNECTION 3 40 | #define WINPTY_ERROR_AGENT_EXE_MISSING 4 41 | #define WINPTY_ERROR_UNSPECIFIED 5 42 | #define WINPTY_ERROR_AGENT_DIED 6 43 | #define WINPTY_ERROR_AGENT_TIMEOUT 7 44 | #define WINPTY_ERROR_AGENT_CREATION_FAILED 8 45 | 46 | 47 | 48 | /***************************************************************************** 49 | * Configuration of a new agent. */ 50 | 51 | /* Create a new screen buffer (connected to the "conerr" terminal pipe) and 52 | * pass it to child processes as the STDERR handle. This flag also prevents 53 | * the agent from reopening CONOUT$ when it polls -- regardless of whether the 54 | * active screen buffer changes, winpty continues to monitor the original 55 | * primary screen buffer. */ 56 | #define WINPTY_FLAG_CONERR 0x1ull 57 | 58 | /* Don't output escape sequences. */ 59 | #define WINPTY_FLAG_PLAIN_OUTPUT 0x2ull 60 | 61 | /* Do output color escape sequences. These escapes are output by default, but 62 | * are suppressed with WINPTY_FLAG_PLAIN_OUTPUT. Use this flag to reenable 63 | * them. */ 64 | #define WINPTY_FLAG_COLOR_ESCAPES 0x4ull 65 | 66 | /* On XP and Vista, winpty needs to put the hidden console on a desktop in a 67 | * service window station so that its polling does not interfere with other 68 | * (visible) console windows. To create this desktop, it must change the 69 | * process' window station (i.e. SetProcessWindowStation) for the duration of 70 | * the winpty_open call. In theory, this change could interfere with the 71 | * winpty client (e.g. other threads, spawning children), so winpty by default 72 | * spawns a special agent process to create the hidden desktop. Spawning 73 | * processes on Windows is slow, though, so if 74 | * WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION is set, winpty changes this 75 | * process' window station instead. 76 | * See https://github.com/rprichard/winpty/issues/58. */ 77 | #define WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION 0x8ull 78 | 79 | #define WINPTY_FLAG_MASK (0ull \ 80 | | WINPTY_FLAG_CONERR \ 81 | | WINPTY_FLAG_PLAIN_OUTPUT \ 82 | | WINPTY_FLAG_COLOR_ESCAPES \ 83 | | WINPTY_FLAG_ALLOW_CURPROC_DESKTOP_CREATION \ 84 | ) 85 | 86 | /* QuickEdit mode is initially disabled, and the agent does not send mouse 87 | * mode sequences to the terminal. If it receives mouse input, though, it 88 | * still writes MOUSE_EVENT_RECORD values into CONIN. */ 89 | #define WINPTY_MOUSE_MODE_NONE 0 90 | 91 | /* QuickEdit mode is initially enabled. As CONIN enters or leaves mouse 92 | * input mode (i.e. where ENABLE_MOUSE_INPUT is on and ENABLE_QUICK_EDIT_MODE 93 | * is off), the agent enables or disables mouse input on the terminal. 94 | * 95 | * This is the default mode. */ 96 | #define WINPTY_MOUSE_MODE_AUTO 1 97 | 98 | /* QuickEdit mode is initially disabled, and the agent enables the terminal's 99 | * mouse input mode. It does not disable terminal mouse mode (until exit). */ 100 | #define WINPTY_MOUSE_MODE_FORCE 2 101 | 102 | 103 | 104 | /***************************************************************************** 105 | * winpty agent RPC call: process creation. */ 106 | 107 | /* If the spawn is marked "auto-shutdown", then the agent shuts down console 108 | * output once the process exits. The agent stops polling for new console 109 | * output, and once all pending data has been written to the output pipe, the 110 | * agent closes the pipe. (At that point, the pipe may still have data in it, 111 | * which the client may read. Once all the data has been read, further reads 112 | * return EOF.) */ 113 | #define WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN 1ull 114 | 115 | /* After the agent shuts down output, and after all output has been written 116 | * into the pipe(s), exit the agent by closing the console. If there any 117 | * surviving processes still attached to the console, they are killed. 118 | * 119 | * Note: With this flag, an RPC call (e.g. winpty_set_size) issued after the 120 | * agent exits will fail with an I/O or dead-agent error. */ 121 | #define WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN 2ull 122 | 123 | /* All the spawn flags. */ 124 | #define WINPTY_SPAWN_FLAG_MASK (0ull \ 125 | | WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN \ 126 | | WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN \ 127 | ) 128 | 129 | 130 | 131 | #endif /* WINPTY_CONSTANTS_H */ 132 | --------------------------------------------------------------------------------