diff options
| author | Christian Clason <c.clason@uni-graz.at> | 2024-08-08 12:28:47 +0200 |
|---|---|---|
| committer | Christian Clason <c.clason@uni-graz.at> | 2024-08-10 10:26:07 +0200 |
| commit | fa79a8ad6deefeea81c1959d69aa4c8b2d993f99 (patch) | |
| tree | 256b79397d0266ba796c250ceac1a5256ad5187d | |
| parent | 0ec43cb4b56673d661d6bd1e39836d0a891be5cd (diff) | |
| download | rneovim-fa79a8ad6deefeea81c1959d69aa4c8b2d993f99.tar.gz rneovim-fa79a8ad6deefeea81c1959d69aa4c8b2d993f99.tar.bz2 rneovim-fa79a8ad6deefeea81c1959d69aa4c8b2d993f99.zip | |
build(deps): vendor libvterm at v0.3.3
Problem: Adding support for modern Nvim features (reflow, OSC 8, full
utf8/emoji support) requires coupling libvterm to Nvim internals
(e.g., utf8proc).
Solution: Vendor libvterm at v0.3.3.
33 files changed, 7126 insertions, 91 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55319bb012..ef921cc3a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -248,7 +248,6 @@ jobs: luajit \ lua-luv-dev # libtree-sitter-dev \ - # libvterm-dev # Remove comments from packages once we start using these external # dependencies. @@ -240,7 +240,7 @@ cmake --build build ### How to build without "bundled" dependencies 1. Manually install the dependencies: - - libuv libluv libutf8proc libvterm luajit lua-lpeg tree-sitter tree-sitter-c tree-sitter-lua tree-sitter-markdown tree-sitter-query tree-sitter-vim tree-sitter-vimdoc unibilium + - libuv libluv libutf8proc luajit lua-lpeg tree-sitter tree-sitter-c tree-sitter-lua tree-sitter-markdown tree-sitter-query tree-sitter-vim tree-sitter-vimdoc unibilium 2. Run CMake: ```sh cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo @@ -248,7 +248,7 @@ cmake --build build ``` If all the dependencies are not available in the package, you can use only some of the bundled dependencies as follows (example of using `ninja`): ```sh - cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_TS=ON + cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_TS=ON cmake --build .deps cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo cmake --build build @@ -261,7 +261,7 @@ cmake --build build ```sh sudo apt install luajit libluajit-5.1-dev lua-lpeg libunibilium-dev -cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LIBUV=ON -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_TS=ON -DUSE_BUNDLED_UTF8PROC=ON +cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LIBUV=ON -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_TS=ON -DUSE_BUNDLED_UTF8PROC=ON cmake --build .deps cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo cmake --build build @@ -275,7 +275,7 @@ cmake --build build ``` - Example of using a package with some dependencies: ``` - make BUNDLED_CMAKE_FLAG="-DUSE_BUNDLED=OFF -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_TS=ON -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_LIBUV=ON" + make BUNDLED_CMAKE_FLAG="-DUSE_BUNDLED=OFF -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_TS=ON -DUSE_BUNDLED_LIBUV=ON" ``` ## Build prerequisites diff --git a/MAINTAIN.md b/MAINTAIN.md index f7f0c5769c..442fd996a6 100644 --- a/MAINTAIN.md +++ b/MAINTAIN.md @@ -129,8 +129,6 @@ Some can be auto-bumped by `scripts/bump_deps.lua`. * [gettext](https://ftp.gnu.org/pub/gnu/gettext/) * [libiconv](https://ftp.gnu.org/pub/gnu/libiconv) * [libuv](https://github.com/libuv/libuv) -* [libvterm](https://www.leonerd.org.uk/code/libvterm/) - * Downloading from the original source is unreliable, so we use our [mirror](https://github.com/neovim/libvterm) instead. * [lua-compat](https://github.com/keplerproject/lua-compat-5.3) * [tree-sitter](https://github.com/tree-sitter/tree-sitter) * [unibilium](https://github.com/neovim/unibilium) @@ -146,6 +144,8 @@ These dependencies are "vendored" (inlined), we must update the sources manually * `src/xdiff/`: [xdiff](https://github.com/git/git/tree/master/xdiff) * `src/cjson/`: [lua-cjson](https://github.com/openresty/lua-cjson) * `src/klib/`: [Klib](https://github.com/attractivechaos/klib) +* `src/vterm/`: [libvterm](https://www.leonerd.org.uk/code/libvterm/), + [mirror](https://github.com/neovim/libvterm) * `runtime/lua/vim/inspect.lua`: [inspect.lua](https://github.com/kikito/inspect.lua) * `src/nvim/tui/terminfo_defs.h`: terminfo definitions * Run `scripts/update_terminfo.sh` to update these definitions. diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 05db090765..43f50b4485 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -27,7 +27,6 @@ set(DEPS_IGNORE_SHA FALSE) option(USE_BUNDLED "Use bundled dependencies." ON) option(USE_BUNDLED_LIBUV "Use the bundled libuv." ${USE_BUNDLED}) -option(USE_BUNDLED_LIBVTERM "Use the bundled libvterm." ${USE_BUNDLED}) option(USE_BUNDLED_LPEG "Use the bundled lpeg." ${USE_BUNDLED}) # PUC Lua is only used for tests, unless explicitly requested. option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF) @@ -96,10 +95,6 @@ if(USE_BUNDLED_UNIBILIUM) include(BuildUnibilium) endif() -if(USE_BUNDLED_LIBVTERM) - include(BuildLibvterm) -endif() - if(USE_BUNDLED_LIBUV) include(BuildLibuv) endif() diff --git a/cmake.deps/CMakePresets.json b/cmake.deps/CMakePresets.json index 7d9f473581..043124c29c 100644 --- a/cmake.deps/CMakePresets.json +++ b/cmake.deps/CMakePresets.json @@ -16,7 +16,6 @@ "description": "Build neovim with external deps on ubuntu", "cacheVariables": { "USE_BUNDLED":"OFF", - "USE_BUNDLED_LIBVTERM":"ON", "USE_BUNDLED_TS":"ON", "USE_BUNDLED_UTF8PROC":"ON" }, diff --git a/cmake.deps/cmake/BuildLibvterm.cmake b/cmake.deps/cmake/BuildLibvterm.cmake deleted file mode 100644 index 3415d8debe..0000000000 --- a/cmake.deps/cmake/BuildLibvterm.cmake +++ /dev/null @@ -1,8 +0,0 @@ -get_externalproject_options(libvterm ${DEPS_IGNORE_SHA}) -ExternalProject_Add(libvterm - DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libvterm - PATCH_COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibvtermCMakeLists.txt - ${DEPS_BUILD_DIR}/src/libvterm/CMakeLists.txt - CMAKE_ARGS ${DEPS_CMAKE_ARGS} - ${EXTERNALPROJECT_OPTIONS}) diff --git a/cmake.deps/cmake/LibvtermCMakeLists.txt b/cmake.deps/cmake/LibvtermCMakeLists.txt deleted file mode 100644 index c197523786..0000000000 --- a/cmake.deps/cmake/LibvtermCMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -project(libvterm C) - -add_compile_options(-w) - -include(GNUInstallDirs) - -include_directories(${CMAKE_SOURCE_DIR}/include) -include_directories(${CMAKE_BINARY_DIR}) - -file(GLOB VTERM_SOURCES ${CMAKE_SOURCE_DIR}/src/*.c) -add_library(vterm ${VTERM_SOURCES}) -install(TARGETS vterm ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -install(FILES include/vterm.h include/vterm_keycodes.h - DESTINATION include) - -if(NOT WIN32) - file(GLOB BIN_SOURCES ${CMAKE_SOURCE_DIR}/bin/*.c) - foreach(EXE_C ${BIN_SOURCES}) - get_filename_component(target_name ${EXE_C} NAME_WE) - add_executable(${target_name} ${EXE_C}) - target_link_libraries(${target_name} vterm) - install(TARGETS ${target_name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - endforeach() -endif() - -# vim: set ft=cmake: diff --git a/cmake.deps/deps.txt b/cmake.deps/deps.txt index 63ec369f76..03e10f2026 100644 --- a/cmake.deps/deps.txt +++ b/cmake.deps/deps.txt @@ -10,9 +10,6 @@ LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333 UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487 -LIBVTERM_URL https://github.com/neovim/libvterm/archive/0a15c6e983b0db7ef8276e0792414a805d01bdaf.tar.gz -LIBVTERM_SHA256 c4683e7a2d71c04781fd0ab7719a94202800e97a9e091514c16983bb732b0fa7 - LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a diff --git a/cmake/FindLibvterm.cmake b/cmake/FindLibvterm.cmake deleted file mode 100644 index 68c2646d47..0000000000 --- a/cmake/FindLibvterm.cmake +++ /dev/null @@ -1,31 +0,0 @@ -find_path2(LIBVTERM_INCLUDE_DIR vterm.h) -find_library2(LIBVTERM_LIBRARY vterm) - -if(LIBVTERM_INCLUDE_DIR AND EXISTS "${LIBVTERM_INCLUDE_DIR}/vterm.h") - file(STRINGS ${LIBVTERM_INCLUDE_DIR}/vterm.h VTERM_VERSION_MAJOR REGEX "#define VTERM_VERSION_MAJOR") - string(REGEX MATCH "[0-9]+" VTERM_VERSION_MAJOR ${VTERM_VERSION_MAJOR}) - - file(STRINGS ${LIBVTERM_INCLUDE_DIR}/vterm.h VTERM_VERSION_MINOR REGEX "#define VTERM_VERSION_MINOR") - string(REGEX MATCH "[0-9]+" VTERM_VERSION_MINOR ${VTERM_VERSION_MINOR}) - - file(STRINGS ${LIBVTERM_INCLUDE_DIR}/vterm.h VTERM_VERSION_PATCH REGEX "#define VTERM_VERSION_PATCH") - - # The following is needed to give a coherent error for versions 0.3.2 and - # smaller. - if(VTERM_VERSION_PATCH) - string(REGEX MATCH "[0-9]+" VTERM_VERSION_PATCH ${VTERM_VERSION_PATCH}) - string(PREPEND VTERM_VERSION_PATCH ".") - endif() - - set(VTERM_VERSION ${VTERM_VERSION_MAJOR}.${VTERM_VERSION_MINOR}${VTERM_VERSION_PATCH}) -endif() - -find_package_handle_standard_args(Libvterm - REQUIRED_VARS LIBVTERM_INCLUDE_DIR LIBVTERM_LIBRARY - VERSION_VAR VTERM_VERSION) - -add_library(libvterm INTERFACE) -target_include_directories(libvterm SYSTEM BEFORE INTERFACE ${LIBVTERM_INCLUDE_DIR}) -target_link_libraries(libvterm INTERFACE ${LIBVTERM_LIBRARY}) - -mark_as_advanced(LIBVTERM_INCLUDE_DIR LIBVTERM_LIBRARY) diff --git a/contrib/local.mk.example b/contrib/local.mk.example index 61fc0b95b8..bdb889dfcd 100644 --- a/contrib/local.mk.example +++ b/contrib/local.mk.example @@ -45,7 +45,6 @@ # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_GETTEXT=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_LIBICONV=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_LIBUV=OFF -# DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_LIBVTERM=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_LUAJIT=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_LUV=OFF # DEPS_CMAKE_FLAGS += -DUSE_BUNDLED_TS=OFF diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt index 9a2380b162..5119613b55 100644 --- a/runtime/doc/dev_vimpatch.txt +++ b/runtime/doc/dev_vimpatch.txt @@ -139,7 +139,6 @@ TYPES OF "NOT APPLICABLE" VIM PATCHES ~ - NA files: `src/gui_*`, `src/gvim_*`, `src/GvimExt/*`, `src/testdir/test_gui*` - `balloon` changes: Nvim does not support balloon feature - NA files: `src/beval_*`, `src/testdir/test_balloon_*` -- libvterm changes: Nvim does not vendor libvterm in `src/`. - Screendump tests from `test_popupwin.vim`, `test_popupwin_textprop.vim`: https://github.com/neovim/neovim/pull/12741#issuecomment-704677141 - json changes: incompatible API https://github.com/neovim/neovim/pull/4131 diff --git a/src/clint.py b/src/clint.py index 67185a7340..cc144543a0 100755 --- a/src/clint.py +++ b/src/clint.py @@ -880,6 +880,7 @@ def CheckIncludes(filename, lines, error): "mpack/object.h", "nvim/func_attr.h", "termkey/termkey.h", + "vterm/vterm.h", ] for i in check_includes_ignore: diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index d153c9e3ef..87c9506709 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -30,7 +30,6 @@ target_link_libraries(main_lib INTERFACE ${LUV_LIBRARY}) find_package(Iconv REQUIRED) find_package(Libuv 1.28.0 REQUIRED) -find_package(Libvterm 0.3.3 REQUIRED) find_package(Lpeg REQUIRED) find_package(Treesitter 0.22.6 REQUIRED) find_package(Unibilium 2.0 REQUIRED) @@ -38,7 +37,6 @@ find_package(UTF8proc REQUIRED) target_link_libraries(main_lib INTERFACE iconv - libvterm lpeg treesitter unibilium @@ -366,8 +364,8 @@ file(MAKE_DIRECTORY ${TOUCHES_DIR} ${GENERATED_DIR} ${GENERATED_INCLUDES_DIR}) file(GLOB NVIM_SOURCES CONFIGURE_DEPENDS *.c) file(GLOB NVIM_HEADERS CONFIGURE_DEPENDS *.h) -file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../termkey/*.c) -file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../termkey/*.h) +file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../termkey/*.c ../vterm/*.c) +file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../termkey/*.h ../vterm/*.h) file(GLOB NLUA0_SOURCES CONFIGURE_DEPENDS ../mpack/*.c) diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index 852059f78b..024719806c 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -16,6 +16,9 @@ #include <sys/stat.h> #include <windows.h> +// vterm.h defines an `unsigned int small` in a struct, triggering error C2632 +#undef small + // Windows does not have S_IFLNK but libuv defines it // and sets the flag for us when calling uv_fs_stat. #include <uv.h> diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 507a9e3a2a..abc9b3534b 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -40,8 +40,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <vterm.h> -#include <vterm_keycodes.h> #include "klib/kvec.h" #include "nvim/api/private/helpers.h" @@ -94,6 +92,8 @@ #include "nvim/ui.h" #include "nvim/vim_defs.h" #include "nvim/window.h" +#include "vterm/vterm.h" +#include "vterm/vterm_keycodes.h" typedef struct { VimState state; diff --git a/src/vterm/LICENSE b/src/vterm/LICENSE new file mode 100644 index 0000000000..0d051634b2 --- /dev/null +++ b/src/vterm/LICENSE @@ -0,0 +1,23 @@ + + +The MIT License + +Copyright (c) 2008 Paul Evans <leonerd@leonerd.org.uk> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/vterm/encoding.c b/src/vterm/encoding.c new file mode 100644 index 0000000000..434ac3f99b --- /dev/null +++ b/src/vterm/encoding.c @@ -0,0 +1,230 @@ +#include "vterm_internal.h" + +#define UNICODE_INVALID 0xFFFD + +#if defined(DEBUG) && DEBUG > 1 +# define DEBUG_PRINT_UTF8 +#endif + +struct UTF8DecoderData { + // number of bytes remaining in this codepoint + int bytes_remaining; + + // number of bytes total in this codepoint once it's finished + // (for detecting overlongs) + int bytes_total; + + int this_cp; +}; + +static void init_utf8(VTermEncoding *enc, void *data_) +{ + struct UTF8DecoderData *data = data_; + + data->bytes_remaining = 0; + data->bytes_total = 0; +} + +static void decode_utf8(VTermEncoding *enc, void *data_, + uint32_t cp[], int *cpi, int cplen, + const char bytes[], size_t *pos, size_t bytelen) +{ + struct UTF8DecoderData *data = data_; + +#ifdef DEBUG_PRINT_UTF8 + printf("BEGIN UTF-8\n"); +#endif + + for(; *pos < bytelen && *cpi < cplen; (*pos)++) { + unsigned char c = bytes[*pos]; + +#ifdef DEBUG_PRINT_UTF8 + printf(" pos=%zd c=%02x rem=%d\n", *pos, c, data->bytes_remaining); +#endif + + if(c < 0x20) // C0 + return; + + else if(c >= 0x20 && c < 0x7f) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + cp[(*cpi)++] = c; +#ifdef DEBUG_PRINT_UTF8 + printf(" UTF-8 char: U+%04x\n", c); +#endif + data->bytes_remaining = 0; + } + + else if(c == 0x7f) // DEL + return; + + else if(c >= 0x80 && c < 0xc0) { + if(!data->bytes_remaining) { + cp[(*cpi)++] = UNICODE_INVALID; + continue; + } + + data->this_cp <<= 6; + data->this_cp |= c & 0x3f; + data->bytes_remaining--; + + if(!data->bytes_remaining) { +#ifdef DEBUG_PRINT_UTF8 + printf(" UTF-8 raw char U+%04x bytelen=%d ", data->this_cp, data->bytes_total); +#endif + // Check for overlong sequences + switch(data->bytes_total) { + case 2: + if(data->this_cp < 0x0080) data->this_cp = UNICODE_INVALID; + break; + case 3: + if(data->this_cp < 0x0800) data->this_cp = UNICODE_INVALID; + break; + case 4: + if(data->this_cp < 0x10000) data->this_cp = UNICODE_INVALID; + break; + case 5: + if(data->this_cp < 0x200000) data->this_cp = UNICODE_INVALID; + break; + case 6: + if(data->this_cp < 0x4000000) data->this_cp = UNICODE_INVALID; + break; + } + // Now look for plain invalid ones + if((data->this_cp >= 0xD800 && data->this_cp <= 0xDFFF) || + data->this_cp == 0xFFFE || + data->this_cp == 0xFFFF) + data->this_cp = UNICODE_INVALID; +#ifdef DEBUG_PRINT_UTF8 + printf(" char: U+%04x\n", data->this_cp); +#endif + cp[(*cpi)++] = data->this_cp; + } + } + + else if(c >= 0xc0 && c < 0xe0) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + data->this_cp = c & 0x1f; + data->bytes_total = 2; + data->bytes_remaining = 1; + } + + else if(c >= 0xe0 && c < 0xf0) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + data->this_cp = c & 0x0f; + data->bytes_total = 3; + data->bytes_remaining = 2; + } + + else if(c >= 0xf0 && c < 0xf8) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + data->this_cp = c & 0x07; + data->bytes_total = 4; + data->bytes_remaining = 3; + } + + else if(c >= 0xf8 && c < 0xfc) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + data->this_cp = c & 0x03; + data->bytes_total = 5; + data->bytes_remaining = 4; + } + + else if(c >= 0xfc && c < 0xfe) { + if(data->bytes_remaining) + cp[(*cpi)++] = UNICODE_INVALID; + + data->this_cp = c & 0x01; + data->bytes_total = 6; + data->bytes_remaining = 5; + } + + else { + cp[(*cpi)++] = UNICODE_INVALID; + } + } +} + +static VTermEncoding encoding_utf8 = { + .init = &init_utf8, + .decode = &decode_utf8, +}; + +static void decode_usascii(VTermEncoding *enc, void *data, + uint32_t cp[], int *cpi, int cplen, + const char bytes[], size_t *pos, size_t bytelen) +{ + int is_gr = bytes[*pos] & 0x80; + + for(; *pos < bytelen && *cpi < cplen; (*pos)++) { + unsigned char c = bytes[*pos] ^ is_gr; + + if(c < 0x20 || c == 0x7f || c >= 0x80) + return; + + cp[(*cpi)++] = c; + } +} + +static VTermEncoding encoding_usascii = { + .decode = &decode_usascii, +}; + +struct StaticTableEncoding { + const VTermEncoding enc; + const uint32_t chars[128]; +}; + +static void decode_table(VTermEncoding *enc, void *data, + uint32_t cp[], int *cpi, int cplen, + const char bytes[], size_t *pos, size_t bytelen) +{ + struct StaticTableEncoding *table = (struct StaticTableEncoding *)enc; + int is_gr = bytes[*pos] & 0x80; + + for(; *pos < bytelen && *cpi < cplen; (*pos)++) { + unsigned char c = bytes[*pos] ^ is_gr; + + if(c < 0x20 || c == 0x7f || c >= 0x80) + return; + + if(table->chars[c]) + cp[(*cpi)++] = table->chars[c]; + else + cp[(*cpi)++] = c; + } +} + +#include "encoding/DECdrawing.inc" +#include "encoding/uk.inc" + +static struct { + VTermEncodingType type; + char designation; + VTermEncoding *enc; +} +encodings[] = { + { ENC_UTF8, 'u', &encoding_utf8 }, + { ENC_SINGLE_94, '0', (VTermEncoding*)&encoding_DECdrawing }, + { ENC_SINGLE_94, 'A', (VTermEncoding*)&encoding_uk }, + { ENC_SINGLE_94, 'B', &encoding_usascii }, + { 0 }, +}; + +/* This ought to be INTERNAL but isn't because it's used by unit testing */ +VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation) +{ + for(int i = 0; encodings[i].designation; i++) + if(encodings[i].type == type && encodings[i].designation == designation) + return encodings[i].enc; + return NULL; +} diff --git a/src/vterm/encoding/DECdrawing.inc b/src/vterm/encoding/DECdrawing.inc new file mode 100644 index 0000000000..627397bcc2 --- /dev/null +++ b/src/vterm/encoding/DECdrawing.inc @@ -0,0 +1,36 @@ +static const struct StaticTableEncoding encoding_DECdrawing = { + { .decode = &decode_table }, + { + [0x60] = 0x25C6, // BLACK DIAMOND + [0x61] = 0x2592, // MEDIUM SHADE (checkerboard) + [0x62] = 0x2409, // SYMBOL FOR HORIZONTAL TAB + [0x63] = 0x240C, // SYMBOL FOR FORM FEED + [0x64] = 0x240D, // SYMBOL FOR CARRIAGE RETURN + [0x65] = 0x240A, // SYMBOL FOR LINE FEED + [0x66] = 0x00B0, // DEGREE SIGN + [0x67] = 0x00B1, // PLUS-MINUS SIGN (plus or minus) + [0x68] = 0x2424, // SYMBOL FOR NEW LINE + [0x69] = 0x240B, // SYMBOL FOR VERTICAL TAB + [0x6a] = 0x2518, // BOX DRAWINGS LIGHT UP AND LEFT (bottom-right corner) + [0x6b] = 0x2510, // BOX DRAWINGS LIGHT DOWN AND LEFT (top-right corner) + [0x6c] = 0x250C, // BOX DRAWINGS LIGHT DOWN AND RIGHT (top-left corner) + [0x6d] = 0x2514, // BOX DRAWINGS LIGHT UP AND RIGHT (bottom-left corner) + [0x6e] = 0x253C, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL (crossing lines) + [0x6f] = 0x23BA, // HORIZONTAL SCAN LINE-1 + [0x70] = 0x23BB, // HORIZONTAL SCAN LINE-3 + [0x71] = 0x2500, // BOX DRAWINGS LIGHT HORIZONTAL + [0x72] = 0x23BC, // HORIZONTAL SCAN LINE-7 + [0x73] = 0x23BD, // HORIZONTAL SCAN LINE-9 + [0x74] = 0x251C, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT + [0x75] = 0x2524, // BOX DRAWINGS LIGHT VERTICAL AND LEFT + [0x76] = 0x2534, // BOX DRAWINGS LIGHT UP AND HORIZONTAL + [0x77] = 0x252C, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + [0x78] = 0x2502, // BOX DRAWINGS LIGHT VERTICAL + [0x79] = 0x2A7D, // LESS-THAN OR SLANTED EQUAL-TO + [0x7a] = 0x2A7E, // GREATER-THAN OR SLANTED EQUAL-TO + [0x7b] = 0x03C0, // GREEK SMALL LETTER PI + [0x7c] = 0x2260, // NOT EQUAL TO + [0x7d] = 0x00A3, // POUND SIGN + [0x7e] = 0x00B7, // MIDDLE DOT + } +}; diff --git a/src/vterm/encoding/uk.inc b/src/vterm/encoding/uk.inc new file mode 100644 index 0000000000..5c7700226b --- /dev/null +++ b/src/vterm/encoding/uk.inc @@ -0,0 +1,6 @@ +static const struct StaticTableEncoding encoding_uk = { + { .decode = &decode_table }, + { + [0x23] = 0x00a3, // £ + } +}; diff --git a/src/vterm/fullwidth.inc b/src/vterm/fullwidth.inc new file mode 100644 index 0000000000..a703529a76 --- /dev/null +++ b/src/vterm/fullwidth.inc @@ -0,0 +1,111 @@ + { 0x1100, 0x115f }, + { 0x231a, 0x231b }, + { 0x2329, 0x232a }, + { 0x23e9, 0x23ec }, + { 0x23f0, 0x23f0 }, + { 0x23f3, 0x23f3 }, + { 0x25fd, 0x25fe }, + { 0x2614, 0x2615 }, + { 0x2648, 0x2653 }, + { 0x267f, 0x267f }, + { 0x2693, 0x2693 }, + { 0x26a1, 0x26a1 }, + { 0x26aa, 0x26ab }, + { 0x26bd, 0x26be }, + { 0x26c4, 0x26c5 }, + { 0x26ce, 0x26ce }, + { 0x26d4, 0x26d4 }, + { 0x26ea, 0x26ea }, + { 0x26f2, 0x26f3 }, + { 0x26f5, 0x26f5 }, + { 0x26fa, 0x26fa }, + { 0x26fd, 0x26fd }, + { 0x2705, 0x2705 }, + { 0x270a, 0x270b }, + { 0x2728, 0x2728 }, + { 0x274c, 0x274c }, + { 0x274e, 0x274e }, + { 0x2753, 0x2755 }, + { 0x2757, 0x2757 }, + { 0x2795, 0x2797 }, + { 0x27b0, 0x27b0 }, + { 0x27bf, 0x27bf }, + { 0x2b1b, 0x2b1c }, + { 0x2b50, 0x2b50 }, + { 0x2b55, 0x2b55 }, + { 0x2e80, 0x2e99 }, + { 0x2e9b, 0x2ef3 }, + { 0x2f00, 0x2fd5 }, + { 0x2ff0, 0x2ffb }, + { 0x3000, 0x303e }, + { 0x3041, 0x3096 }, + { 0x3099, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x3190, 0x31ba }, + { 0x31c0, 0x31e3 }, + { 0x31f0, 0x321e }, + { 0x3220, 0x3247 }, + { 0x3250, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa490, 0xa4c6 }, + { 0xa960, 0xa97c }, + { 0xac00, 0xd7a3 }, + { 0xf900, 0xfaff }, + { 0xfe10, 0xfe19 }, + { 0xfe30, 0xfe52 }, + { 0xfe54, 0xfe66 }, + { 0xfe68, 0xfe6b }, + { 0xff01, 0xff60 }, + { 0xffe0, 0xffe6 }, + { 0x16fe0, 0x16fe3 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18af2 }, + { 0x1b000, 0x1b11e }, + { 0x1b150, 0x1b152 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1f004, 0x1f004 }, + { 0x1f0cf, 0x1f0cf }, + { 0x1f18e, 0x1f18e }, + { 0x1f191, 0x1f19a }, + { 0x1f200, 0x1f202 }, + { 0x1f210, 0x1f23b }, + { 0x1f240, 0x1f248 }, + { 0x1f250, 0x1f251 }, + { 0x1f260, 0x1f265 }, + { 0x1f300, 0x1f320 }, + { 0x1f32d, 0x1f335 }, + { 0x1f337, 0x1f37c }, + { 0x1f37e, 0x1f393 }, + { 0x1f3a0, 0x1f3ca }, + { 0x1f3cf, 0x1f3d3 }, + { 0x1f3e0, 0x1f3f0 }, + { 0x1f3f4, 0x1f3f4 }, + { 0x1f3f8, 0x1f43e }, + { 0x1f440, 0x1f440 }, + { 0x1f442, 0x1f4fc }, + { 0x1f4ff, 0x1f53d }, + { 0x1f54b, 0x1f54e }, + { 0x1f550, 0x1f567 }, + { 0x1f57a, 0x1f57a }, + { 0x1f595, 0x1f596 }, + { 0x1f5a4, 0x1f5a4 }, + { 0x1f5fb, 0x1f64f }, + { 0x1f680, 0x1f6c5 }, + { 0x1f6cc, 0x1f6cc }, + { 0x1f6d0, 0x1f6d2 }, + { 0x1f6d5, 0x1f6d5 }, + { 0x1f6eb, 0x1f6ec }, + { 0x1f6f4, 0x1f6fa }, + { 0x1f7e0, 0x1f7eb }, + { 0x1f90d, 0x1f971 }, + { 0x1f973, 0x1f976 }, + { 0x1f97a, 0x1f9a2 }, + { 0x1f9a5, 0x1f9aa }, + { 0x1f9ae, 0x1f9ca }, + { 0x1f9cd, 0x1f9ff }, + { 0x1fa70, 0x1fa73 }, + { 0x1fa78, 0x1fa7a }, + { 0x1fa80, 0x1fa82 }, + { 0x1fa90, 0x1fa95 }, diff --git a/src/vterm/keyboard.c b/src/vterm/keyboard.c new file mode 100644 index 0000000000..d31c8be12d --- /dev/null +++ b/src/vterm/keyboard.c @@ -0,0 +1,226 @@ +#include "vterm_internal.h" + +#include <stdio.h> + +#include "utf8.h" + |