Compare commits

...

33 Commits

Author SHA1 Message Date
f9a102456f Fix certain non-GNU build configurations
All checks were successful
Alpine 3.19 Success
2024-04-10 18:33:23 +02:00
63dde38bff CMakeLists.txt: declare compatibility with 3.27
All checks were successful
Alpine 3.19 Success
Sadly, the 3.5 deprecation warning doesn't go away after this.
2023-08-01 03:23:25 +02:00
8844026f26 Silence compiler warnings in test targets
-Wunused-parameter
2023-08-01 03:06:39 +02:00
c64457d4cd Find ncursesw on OpenIndiana 2023-07-24 08:09:41 +02:00
97cbd7e80c Make the generated pkg-config file more reliable 2023-06-29 02:39:28 +02:00
2518b53e5a Fix usage of a nonstandard escape sequence 2023-06-14 16:23:08 +02:00
8265f075b1 Fix mouse when key_mouse contains 1006 sequence 2021-11-04 14:14:56 +01:00
2f348c79b7 Update .gitignore 2021-10-30 03:29:59 +02:00
18d16c1edb Add clang-format configuration, clean up 2021-10-30 02:53:18 +02:00
94a77a10d8 Ensure we turn off focus tracking on exit 2021-06-29 05:28:04 +02:00
d39c35e59e Enable focus tracking opportunistically 2021-06-29 05:10:33 +02:00
d47bcfb203 Make note of urxvt 9.25's 1006 support 2021-06-29 05:00:43 +02:00
ff08195973 Fix formatting 2021-06-29 04:59:15 +02:00
f7912a8ce7 CMakeLists.txt: make this build in OpenBSD 2020-10-29 15:53:04 +01:00
42d2bef93a CMakeLists.txt: omit end{if,foreach} expressions
Their usefulness was almost negative.
2020-10-29 15:46:27 +01:00
065cd3b3e1 README.adoc: update to reflect the current state 2020-10-26 14:09:53 +01:00
65797ee4f1 Bump minimum CMake version to 3.0
A nice, round number.  This allows us to remove some boilerplate.
2020-10-26 13:52:55 +01:00
279d010e0f Fix a spurious "implicit fallthrough" warning 2020-10-26 13:37:51 +01:00
8c4e867760 Fix strfkey with focus events 2020-09-14 18:06:17 +02:00
dd3f77a0aa Get rid of one CMake dev warning 2020-09-14 18:00:31 +02:00
0bfb13655c Implement de/focus event parsing
So far there is no way to set it up, I'm not sure how to go about it.
2020-09-14 17:55:41 +02:00
78c0cd443d Name change 2020-09-14 15:20:50 +02:00
6a99d97ad0 Remove .travis.yml
We don't depend on any proprietary services no longer.  I'll have to
make my own replacements with blackjack and hookers.  Until then,
the file stays in the commit log as an example.
2018-06-24 05:29:06 +02:00
30e0eee1a8 Update README 2018-06-24 01:05:45 +02:00
9adbb8c897 Update mail address 2018-06-24 01:05:34 +02:00
953789650e CMakeLists.txt: fix variable name 2018-06-24 01:03:40 +02:00
93641a7c98 Update README 2017-06-20 06:36:07 +02:00
ed67424ca7 Put tests in a "namespace" 2017-06-20 06:35:37 +02:00
61095da7c3 Travis CI: brevify notifications 2017-06-20 06:35:23 +02:00
5b05b96ec0 Backport TERMKEY_FLAG_NOSTART and fix two leaks
...that are notably still present in the original library.
2016-12-30 08:30:59 +01:00
a9b41e41b7 Fix use of an uninitialized value 2016-11-03 02:36:40 +01:00
059cb81817 Try to fix terminfo loading
It could lead to crashing the PTY under OpenBSD and ncurses.

Fixed some unibiliums leaks while at it.
2016-11-03 02:36:35 +01:00
c1251f3978 Fix condition in demo-glib.c 2016-11-03 02:24:35 +01:00
31 changed files with 267 additions and 142 deletions

27
.clang-format Normal file
View File

@@ -0,0 +1,27 @@
# clang-format is fairly limited, and these rules are approximate:
# - array initializers can get terribly mangled with clang-format 12.0,
# - sometimes it still aligns with space characters,
# - struct name NL { NL ... NL } NL name; is unachievable.
BasedOnStyle: GNU
ColumnLimit: 80
IndentWidth: 4
TabWidth: 4
UseTab: ForContinuationAndIndentation
BreakBeforeBraces: Allman
SpaceAfterCStyleCast: true
AlignAfterOpenBracket: DontAlign
AlignOperands: DontAlign
AlignConsecutiveMacros: Consecutive
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
IndentGotoLabels: false
# IncludeCategories has some potential, but it may also break the build.
# Note that the documentation says the value should be "Never".
SortIncludes: false
# This is a compromise, it generally works out aesthetically better.
BinPackArguments: false
# Unfortunately, this can't be told to align to column 40 or so.
SpacesBeforeTrailingComments: 2

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@
/termo.files /termo.files
/termo.creator* /termo.creator*
/termo.includes /termo.includes
/termo.cflags
/termo.cxxflags

View File

@@ -1,33 +0,0 @@
language: c
notifications:
irc:
channels: "irc.janouch.name#dev"
use_notice: true
skip_join: true
env:
global:
- secure: "rzavv9NhQeZ3Zn6g9WgabUuTsXG1ncc+dWyXw3ytN15uWa4UelVzjAYvr31XeyXwsqZi3rDRHuz8ooIi1NLeLewozpEdkyakLjZOAnggqCnkF/yw/secuRo8MzweGXAefF+7cR2JYyH/E/PfMfAY8Qb0NnfEV1j7X9GCN2sJcxA="
addons:
coverity_scan:
project:
name: "pjanouch/termo"
description: "Terminal key input library"
notification_email: p.janouch@gmail.com
build_command_prepend: "cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON"
build_command: "make all demos"
branch_pattern: coverity_scan
compiler:
- clang
- gcc
before_install:
- sudo apt-get update -qq
install:
- sudo apt-get install -y libncursesw5-dev libglib2.0-dev
before_script:
- mkdir build
- cd build
script:
- cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTING=ON
- make all demos
- ctest -V
- cpack -G DEB

View File

@@ -1,21 +1,13 @@
project (termo C) cmake_minimum_required (VERSION 3.0...3.27)
cmake_minimum_required (VERSION 2.8.5) project (termo VERSION 0.1.0 LANGUAGES C)
if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC) if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra")
endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUC) endif ()
# Version # Version
set (project_VERSION_MAJOR 0) set (project_API_VERSION ${PROJECT_VERSION_MAJOR})
set (project_VERSION_MINOR 1)
set (project_VERSION_PATCH 0)
set (project_VERSION ${project_VERSION_MAJOR})
set (project_VERSION ${project_VERSION}.${project_VERSION_MINOR})
set (project_VERSION ${project_VERSION}.${project_VERSION_PATCH})
set (project_API_VERSION ${project_VERSION_MAJOR})
# Names # Names
set (project_LIB_NAME "termo-${project_API_VERSION}") set (project_LIB_NAME "termo-${project_API_VERSION}")
@@ -49,38 +41,46 @@ set (lib_headers
# Project libraries # Project libraries
# We need ncurses for one of the demos, so we're always looking # We need ncurses for one of the demos, so we're always looking
if (NCURSESW_FOUND) if (Ncursesw_FOUND)
include_directories (${NCURSESW_INCLUDE_DIRS}) include_directories (${Ncursesw_INCLUDE_DIRS})
set (curses_libraries ${NCURSESW_LIBRARIES}) set (curses_libraries ${Ncursesw_LIBRARIES})
elseif (CURSES_FOUND) elseif (CURSES_FOUND)
include_directories (${CURSES_INCLUDE_DIR}) include_directories (${CURSES_INCLUDE_DIR})
set (curses_libraries ${CURSES_LIBRARY}) set (curses_libraries ${CURSES_LIBRARY})
endif (NCURSESW_FOUND) endif ()
if (unibilium_FOUND) if (unibilium_FOUND)
include_directories (${unibilium_INCLUDE_DIRS}) include_directories (${unibilium_INCLUDE_DIRS})
set (lib_libraries ${unibilium_LIBRARIES}) set (lib_libraries ${unibilium_LIBRARIES})
add_definitions (-DHAVE_UNIBILIUM) add_definitions (-DHAVE_UNIBILIUM)
elseif (curses_libraries) elseif (curses_libraries)
include_directories (${NCURSESW_INCLUDE_DIRS}) include_directories (${Ncursesw_INCLUDE_DIRS})
set (lib_libraries ${curses_libraries}) set (lib_libraries ${curses_libraries})
else (CURSES_FOUND) else ()
message (SEND_ERROR "Unibilium not found, Curses not found") message (SEND_ERROR "Unibilium not found, Curses not found")
endif (unibilium_FOUND) endif ()
# -liconv may or may not be a part of libc
find_path (iconv_INCLUDE_DIRS iconv.h)
include_directories (${iconv_INCLUDE_DIRS})
find_library (iconv_LIBRARIES iconv)
if (iconv_LIBRARIES)
list (APPEND lib_libraries ${iconv_LIBRARIES})
endif ()
# Create the library targets # Create the library targets
add_library (termo SHARED ${lib_sources} ${lib_headers}) add_library (termo SHARED ${lib_sources} ${lib_headers})
target_link_libraries (termo ${lib_libraries}) target_link_libraries (termo ${lib_libraries})
set_target_properties (termo PROPERTIES set_target_properties (termo PROPERTIES
OUTPUT_NAME ${project_LIB_NAME} OUTPUT_NAME ${project_LIB_NAME}
VERSION ${project_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${project_API_VERSION}) SOVERSION ${project_API_VERSION})
add_library (termo-static STATIC ${lib_sources} ${lib_headers}) add_library (termo-static STATIC ${lib_sources} ${lib_headers})
target_link_libraries (termo-static ${lib_libraries}) target_link_libraries (termo-static ${lib_libraries})
set_target_properties (termo-static PROPERTIES set_target_properties (termo-static PROPERTIES
OUTPUT_NAME ${project_LIB_NAME} OUTPUT_NAME ${project_LIB_NAME}
VERSION ${project_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${project_API_VERSION}) SOVERSION ${project_API_VERSION})
# A fix for: relocation R_X86_64_32 against `a local symbol' can not be # A fix for: relocation R_X86_64_32 against `a local symbol' can not be
@@ -89,7 +89,7 @@ set_target_properties (termo-static PROPERTIES
# This should enable linking the static library into a shared one. # This should enable linking the static library into a shared one.
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set_target_properties (termo-static PROPERTIES COMPILE_FLAGS "-fPIC") set_target_properties (termo-static PROPERTIES COMPILE_FLAGS "-fPIC")
endif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") endif ()
# Demos # Demos
add_executable (demo-async EXCLUDE_FROM_ALL demo-async.c) add_executable (demo-async EXCLUDE_FROM_ALL demo-async.c)
@@ -108,7 +108,7 @@ if (glib_FOUND)
target_link_libraries (demo-glib target_link_libraries (demo-glib
termo-static ${lib_libraries} ${glib_LIBRARIES}) termo-static ${lib_libraries} ${glib_LIBRARIES})
list (APPEND demos demo-glib) list (APPEND demos demo-glib)
endif (glib_FOUND) endif ()
add_custom_target (demos DEPENDS ${demos}) add_custom_target (demos DEPENDS ${demos})
@@ -127,7 +127,7 @@ configure_file (config-version.cmake.in
install (FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake install (FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${project_VERSION}) DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION})
# Do some unit tests # Do some unit tests
option (BUILD_TESTING "Build tests" OFF) option (BUILD_TESTING "Build tests" OFF)
@@ -147,6 +147,7 @@ set (project_tests
30mouse 30mouse
31position 31position
32modereport 32modereport
33focus
39csi) 39csi)
if (BUILD_TESTING) if (BUILD_TESTING)
@@ -156,35 +157,32 @@ if (BUILD_TESTING)
foreach (name ${project_tests}) foreach (name ${project_tests})
add_executable (test-${name} tests/${name}.c ${test_common_sources}) add_executable (test-${name} tests/${name}.c ${test_common_sources})
target_link_libraries (test-${name} termo-static ${lib_libraries}) target_link_libraries (test-${name} termo-static ${lib_libraries})
add_test (test-${name} test-${name}) add_test (NAME ${PROJECT_NAME}.${name} COMMAND test-${name})
endforeach (name) endforeach ()
endif (BUILD_TESTING) endif ()
# pkg-config # pkg-config
file (WRITE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc" file (WRITE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
"Name: ${PROJECT_NAME}\n" "Name: ${PROJECT_NAME}\n"
"Description: Terminal key input library\n" "Description: Terminal key input library\n"
"Version: ${project_VERSION}\n" "Version: ${PROJECT_VERSION}\n"
"Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -l${project_LIB_NAME}\n" "Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -l${project_LIB_NAME}\n"
"Libs.private: ${lib_libraries}\n" "Libs.private: ${lib_libraries}\n"
"Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/${project_INCLUDE_NAME}\n") "Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR}/${project_INCLUDE_NAME}\n")
install (FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc" install (FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# CPack # CPack
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Terminal key input library") set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Terminal key input library")
set (CPACK_PACKAGE_VENDOR "Premysl Janouch") set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p.janouch@gmail.com>") set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set (CPACK_PACKAGE_VERSION_MAJOR ${project_VERSION_MAJOR})
set (CPACK_PACKAGE_VERSION_MINOR ${project_VERSION_MINOR})
set (CPACK_PACKAGE_VERSION_PATCH ${project_VERSION_PATCH})
set (CPACK_GENERATOR "TGZ;ZIP") set (CPACK_GENERATOR "TGZ;ZIP")
set (CPACK_PACKAGE_FILE_NAME set (CPACK_PACKAGE_FILE_NAME
"${CMAKE_PROJECT_NAME}-${project_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set (CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}-${project_VERSION}") set (CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_SOURCE_GENERATOR "TGZ;ZIP") set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user") set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${project_VERSION}") set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}")
include (CPack) include (CPack)

View File

@@ -1,5 +1,5 @@
Copyright (c) 2007-2014 Paul Evans <leonerd@leonerd.org.uk> Copyright (c) 2007-2014 Paul Evans <leonerd@leonerd.org.uk>
Copyright (c) 2014 Přemysl Janouch <p.janouch@gmail.com> Copyright (c) 2014-2021 Přemysl Eric Janouch <p@janouch.name>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -2,23 +2,24 @@ termo
===== =====
'termo' is a library providing an alternative to ncurses' handling of terminal 'termo' is a library providing an alternative to ncurses' handling of terminal
input. ncurses does a really terrible job at that, mainly wrt. mouse support input. ncurses does a terrible job at that, mainly wrt. mouse support which was
which seems to be utterly broken. If you can drag things in a terminal even completely broken for a few years, making it impossible to drag things
application, such as in VIM, I can assure you it's not using ncurses for that. around in applications. While that one bit has been fixed, it continues to lack
(At least not with ncurses older than 6.0.) support for rxvt-unicode's 1015 mode and it's generally incapable of relaying
certain key combinations.
Since terminal I/O is really complicated and full of special cases, this project Since terminal I/O is really complicated and full of special cases, this project
doesn't aspire to also replace the output part of ncurses, but is rather doesn't aspire to also replace the output part of ncurses, but is rather
complementary to it. In the end it makes use of its terminfo library. complementary to it. In the end it makes use of its terminfo library.
The API isn't stable yet. Tell me what needs to be done so I can fix it first. The API can be considered stable. This project is in maintenance mode.
Building and Installing Building and Installing
----------------------- -----------------------
Build dependencies: cmake >= 2.8.5, pkg-config + Build dependencies: cmake >= 3.0, pkg-config +
Optional dependencies: Unibilium (alternative for curses), GLib (for the demos) Optional dependencies: Unibilium (alternative for curses), GLib (for the demos)
$ git clone https://github.com/pjanouch/termo.git $ git clone https://git.janouch.name/p/termo.git
$ mkdir termo/build $ mkdir termo/build
$ cd termo/build $ cd termo/build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug
@@ -39,7 +40,7 @@ statically linked against the library, and hence they can be run as they are:
What's Different From the Original termkey? What's Different From the Original termkey?
------------------------------------------- -------------------------------------------
The main change is throwing away any UTF-8 dependent code, making the library The main change is throwing out any UTF-8 dependent code, making the library
capable of handling all unibyte and multibyte encodings supported by iconv on capable of handling all unibyte and multibyte encodings supported by iconv on
your system. The characters are still presented as Unicode in the end, however, your system. The characters are still presented as Unicode in the end, however,
as the other sensible option is wchar_t and that doesn't really work well, see as the other sensible option is wchar_t and that doesn't really work well, see
@@ -55,19 +56,21 @@ CMake-based projects and simply import the target. No package maintainer action
is needed for you to enjoy the benefits of proper terminal input. is needed for you to enjoy the benefits of proper terminal input.
The rest is just me going silly over formatting and various unimportant stuff. The rest is just me going silly over formatting and various unimportant stuff.
Oh, and I've deleted the manpages. It needs more Doxygen. :) TBD Oh, and I've deleted the manpages.
Contributing and Support Contributing and Support
------------------------ ------------------------
Use this project's GitHub to report any bugs, request features, or submit pull Use https://git.janouch.name/p/termo to report any bugs, request features,
requests. If you want to discuss this project, or maybe just hang out with or submit pull requests. `git send-email` is tolerated. If you want to discuss
the developer, feel free to join me at irc://irc.janouch.name, channel #dev. the project, feel free to join me at ircs://irc.janouch.name, channel #dev.
Bitcoin donations are accepted at: 12r5uEWEgcHC46xd64tt3hHt9EUvYYDHe9
License License
------- -------
'termo' is based on the 'termkey' library, originally written by Paul Evans 'termo' is based on the 'termkey' library, originally written by Paul Evans
<leonerd@leonerd.org.uk>, with additional changes made by Přemysl Janouch <leonerd@leonerd.org.uk>, with additional changes made by Přemysl Eric Janouch
<p.janouch@gmail.com>. <p@janouch.name>.
You may use the software under the terms of the MIT license, the text of which You may use the software under the terms of the MIT license, the text of which
is included within the package, see the file LICENSE. is included within the package, see the file LICENSE.

View File

@@ -1,17 +1,17 @@
# Public Domain # Public Domain
find_package (PkgConfig REQUIRED) find_package (PkgConfig REQUIRED)
pkg_check_modules (NCURSESW QUIET ncursesw) pkg_check_modules (Ncursesw QUIET ncursesw)
# OpenBSD doesn't provide a pkg-config file # OpenBSD doesn't provide a pkg-config file
set (required_vars NCURSESW_LIBRARIES) set (required_vars Ncursesw_LIBRARIES)
if (NOT NCURSESW_FOUND) if (NOT Ncursesw_FOUND)
find_library (NCURSESW_LIBRARIES NAMES ncursesw) find_library (Ncursesw_LIBRARIES NAMES ncursesw)
find_path (NCURSESW_INCLUDE_DIRS ncurses.h) find_path (Ncursesw_INCLUDE_DIRS ncurses.h PATH_SUFFIXES ncurses)
list (APPEND required_vars NCURSESW_INCLUDE_DIRS) list (APPEND required_vars Ncursesw_INCLUDE_DIRS)
endif (NOT NCURSESW_FOUND) endif (NOT Ncursesw_FOUND)
include (FindPackageHandleStandardArgs) include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS (NCURSESW DEFAULT_MSG ${required_vars}) FIND_PACKAGE_HANDLE_STANDARD_ARGS (Ncursesw DEFAULT_MSG ${required_vars})
mark_as_advanced (NCURSESW_LIBRARIES NCURSESW_INCLUDE_DIRS) mark_as_advanced (Ncursesw_LIBRARIES Ncursesw_INCLUDE_DIRS)

View File

@@ -28,7 +28,7 @@ key_timer (gpointer data)
static gboolean static gboolean
stdin_io (GIOChannel *source, GIOCondition condition, gpointer data) stdin_io (GIOChannel *source, GIOCondition condition, gpointer data)
{ {
if (condition && G_IO_IN) if (condition & G_IO_IN)
{ {
if (timeout_id) if (timeout_id)
g_source_remove (timeout_id); g_source_remove (timeout_id);

2
demo.c
View File

@@ -10,7 +10,7 @@
#include "termo.h" #include "termo.h"
int int
main(int argc, char *argv[]) main (int argc, char *argv[])
{ {
TERMO_CHECK_VERSION; TERMO_CHECK_VERSION;
setlocale (LC_CTYPE, ""); setlocale (LC_CTYPE, "");

View File

@@ -331,6 +331,33 @@ handle_csi_m (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
return TERMO_RES_NONE; return TERMO_RES_NONE;
} }
//
// Handler for CSI I / CSI O focus events
//
static termo_result_t
handle_csi_IO (termo_t *tk, termo_key_t *key, int cmd, long *arg, int args)
{
(void) tk;
(void) arg;
(void) args;
switch (cmd &= 0xff)
{
case 'I':
key->type = TERMO_TYPE_FOCUS;
key->code.focused = true;
return TERMO_RES_KEY;
case 'O':
key->type = TERMO_TYPE_FOCUS;
key->code.focused = false;
return TERMO_RES_KEY;
default:
return TERMO_RES_NONE;
}
return TERMO_RES_NONE;
}
termo_result_t termo_result_t
termo_interpret_mouse (termo_t *tk, const termo_key_t *key, termo_interpret_mouse (termo_t *tk, const termo_key_t *key,
termo_mouse_event_t *event, int *button, int *line, int *col) termo_mouse_event_t *event, int *button, int *line, int *col)
@@ -671,6 +698,9 @@ register_keys (void)
csi_handlers['M' - 0x20] = &handle_csi_m; csi_handlers['M' - 0x20] = &handle_csi_m;
csi_handlers['m' - 0x20] = &handle_csi_m; csi_handlers['m' - 0x20] = &handle_csi_m;
csi_handlers['I' - 0x20] = &handle_csi_IO;
csi_handlers['O' - 0x20] = &handle_csi_IO;
csi_handlers['R' - 0x20] = &handle_csi_R; csi_handlers['R' - 0x20] = &handle_csi_R;
csi_handlers['y' - 0x20] = &handle_csi_y; csi_handlers['y' - 0x20] = &handle_csi_y;

View File

@@ -177,6 +177,7 @@ static bool
load_terminfo (termo_ti_t *ti, const char *term) load_terminfo (termo_ti_t *ti, const char *term)
{ {
const char *mouse_report_string = NULL; const char *mouse_report_string = NULL;
bool result = false;
#ifdef HAVE_UNIBILIUM #ifdef HAVE_UNIBILIUM
unibi_term *unibi = unibi_from_term (term); unibi_term *unibi = unibi_from_term (term);
@@ -191,8 +192,12 @@ load_terminfo (termo_ti_t *ti, const char *term)
// Have to cast away the const. But it's OK - we know terminfo won't // Have to cast away the const. But it's OK - we know terminfo won't
// really modify term // really modify term
int err; int err;
TERMINAL *saved_term = set_curterm (NULL);
if (setupterm ((char *) term, 1, &err) != OK) if (setupterm ((char *) term, 1, &err) != OK)
{
set_curterm (saved_term);
return false; return false;
}
for (int i = 0; strfnames[i]; i++) for (int i = 0; strfnames[i]; i++)
{ {
@@ -227,8 +232,7 @@ load_terminfo (termo_ti_t *ti, const char *term)
if (node && !insert_seq (ti, value, node)) if (node && !insert_seq (ti, value, node))
{ {
free (node); free (node);
// FIXME: unibi leak goto fail;
return false;
} }
} }
@@ -242,34 +246,32 @@ load_terminfo (termo_ti_t *ti, const char *term)
set_mouse_string = tigetstr ("XM"); set_mouse_string = tigetstr ("XM");
#endif #endif
if (!set_mouse_string || set_mouse_string == (char *) -1) if (!set_mouse_string || set_mouse_string == (char *) -1)
ti->set_mouse_string = strdup ("\E[?1000%?%p1%{1}%=%th%el%;"); ti->set_mouse_string = strdup ("\x1b[?1000%?%p1%{1}%=%th%el%;");
else else
ti->set_mouse_string = strdup (set_mouse_string); ti->set_mouse_string = strdup (set_mouse_string);
bool have_mouse = false; // We handle 1006 and 1015 unconditionally in driver-csi.c,
if (!mouse_report_string && strstr (term, "xterm")) // and don't want to have the handling diverted by recent terminfo;
mouse_report_string = "\x1b[M"; // let's hardcode the ancient 1000 sequence locally
if (mouse_report_string) if (mouse_report_string)
{ {
have_mouse = true;
trie_node_t *node = malloc (sizeof *node); trie_node_t *node = malloc (sizeof *node);
if (!node) if (!node)
return false; goto fail;
node->type = TYPE_MOUSE; node->type = TYPE_MOUSE;
if (!insert_seq (ti, mouse_report_string, node)) if (!insert_seq (ti, "\x1b[M", node))
{ {
free (node); free (node);
// FIXME: unibi leak goto fail;
return false;
} }
} }
if (!have_mouse) if (!mouse_report_string && strstr (term, "xterm") != term)
ti->tk->guessed_mouse_proto = TERMO_MOUSE_PROTO_NONE; ti->tk->guessed_mouse_proto = TERMO_MOUSE_PROTO_NONE;
else if (strstr (term, "rxvt") == term) else if (strstr (term, "rxvt") == term)
// urxvt generally doesn't understand the SGR protocol. // urxvt didn't understand the SGR protocol until version 9.25,
// it's safest to keep using 1015.
ti->tk->guessed_mouse_proto = TERMO_MOUSE_PROTO_RXVT; ti->tk->guessed_mouse_proto = TERMO_MOUSE_PROTO_RXVT;
else else
// SGR (1006) is the superior protocol. If it's not supported by the // SGR (1006) is the superior protocol. If it's not supported by the
@@ -305,11 +307,14 @@ load_terminfo (termo_ti_t *ti, const char *term)
else else
ti->stop_string = NULL; ti->stop_string = NULL;
result = true;
fail:
#ifdef HAVE_UNIBILIUM #ifdef HAVE_UNIBILIUM
unibi_destroy (unibi); unibi_destroy (unibi);
#else
del_curterm (set_curterm (saved_term));
#endif #endif
return result;
return true;
} }
static bool static bool
@@ -357,6 +362,8 @@ mouse_reset (termo_ti_t *ti)
&& write_string (ti->tk, "\x1b[?1002l") && write_string (ti->tk, "\x1b[?1002l")
&& write_string (ti->tk, "\x1b[?1003l") && write_string (ti->tk, "\x1b[?1003l")
&& write_string (ti->tk, "\x1b[?1004l")
&& write_string (ti->tk, "\x1b[?1005l") && write_string (ti->tk, "\x1b[?1005l")
&& write_string (ti->tk, "\x1b[?1006l") && write_string (ti->tk, "\x1b[?1006l")
&& write_string (ti->tk, "\x1b[?1015l"); && write_string (ti->tk, "\x1b[?1015l");
@@ -404,8 +411,12 @@ start_driver (termo_t *tk, void *info)
// Disable everything mouse-related first // Disable everything mouse-related first
if (!mouse_reset (ti)) if (!mouse_reset (ti))
return false; return false;
// Enable focus tracking opportunistically and automatically,
// as it basically doesn't have any negative consequences at all
return mouse_set_proto (ti, tk->mouse_proto, true) return mouse_set_proto (ti, tk->mouse_proto, true)
&& mouse_set_tracking_mode (ti, tk->mouse_tracking, true); && mouse_set_tracking_mode (ti, tk->mouse_tracking, true)
&& write_string (ti->tk, "\x1b[?1004h");
} }
static int static int
@@ -419,7 +430,8 @@ stop_driver (termo_t *tk, void *info)
if (tk->mouse_proto == TERMO_MOUSE_PROTO_NONE) if (tk->mouse_proto == TERMO_MOUSE_PROTO_NONE)
return true; return true;
return mouse_set_proto (ti, tk->mouse_proto, false) return mouse_set_proto (ti, tk->mouse_proto, false)
&& mouse_set_tracking_mode (ti, tk->mouse_tracking, false); && mouse_set_tracking_mode (ti, tk->mouse_tracking, false)
&& write_string (ti->tk, "\x1b[?1004l");
} }
static void * static void *

View File

@@ -1,8 +1,8 @@
#ifndef TERMO_CONFIG_H #ifndef TERMO_CONFIG_H
#define TERMO_CONFIG_H #define TERMO_CONFIG_H
#define TERMO_VERSION_MAJOR @project_VERSION_MAJOR@ #define TERMO_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define TERMO_VERSION_MINOR @project_VERSION_MINOR@ #define TERMO_VERSION_MINOR @PROJECT_VERSION_MINOR@
#endif // ! TERMO_CONFIG_H #endif // ! TERMO_CONFIG_H

38
termo.c
View File

@@ -156,6 +156,9 @@ print_key (termo_t *tk, termo_key_t *key)
ev, button, line, col); ev, button, line, col);
break; break;
} }
case TERMO_TYPE_FOCUS:
fprintf (stderr, "%s\n", key->code.focused ? "Focused" : "Defocused");
break;
case TERMO_TYPE_POSITION: case TERMO_TYPE_POSITION:
{ {
int line, col; int line, col;
@@ -425,12 +428,12 @@ termo_new (int fd, const char *encoding, int flags)
termo_set_flags (tk, flags); termo_set_flags (tk, flags);
const char *term = getenv ("TERM"); const char *term = getenv ("TERM");
if (termo_init (tk, term, encoding) if (!termo_init (tk, term, encoding))
&& termo_start (tk))
return tk;
// FIXME: resource leak on termo_start() failure
free (tk); free (tk);
else if (!(flags & TERMO_FLAG_NOSTART) && !termo_start (tk))
termo_free (tk);
else
return tk;
return NULL; return NULL;
} }
@@ -445,13 +448,12 @@ termo_new_abstract (const char *term, const char *encoding, int flags)
termo_set_flags (tk, flags); termo_set_flags (tk, flags);
if (!termo_init (tk, term, encoding)) if (!termo_init (tk, term, encoding))
{
free (tk); free (tk);
return NULL; else if (!(flags & TERMO_FLAG_NOSTART) && !termo_start (tk))
} termo_free (tk);
else
termo_start (tk);
return tk; return tk;
return NULL;
} }
void void
@@ -904,21 +906,20 @@ peekkey (termo_t *tk, termo_key_t *key, int flags, size_t *nbytep)
switch (ret) switch (ret)
{ {
size_t halfsize;
case TERMO_RES_KEY: case TERMO_RES_KEY:
{
#ifdef DEBUG #ifdef DEBUG
print_key (tk, key); fprintf (stderr, "\n"); print_key (tk, key); fprintf (stderr, "\n");
#endif #endif
// Slide the data down to stop it running away // Slide the data down to stop it running away
size_t halfsize = tk->buffsize / 2; halfsize = tk->buffsize / 2;
if (tk->buffstart > halfsize) if (tk->buffstart > halfsize)
{ {
memcpy (tk->buffer, tk->buffer + halfsize, halfsize); memcpy (tk->buffer, tk->buffer + halfsize, halfsize);
tk->buffstart -= halfsize; tk->buffstart -= halfsize;
} }
// Fallthrough // Fall-through
}
case TERMO_RES_EOF: case TERMO_RES_EOF:
case TERMO_RES_ERROR: case TERMO_RES_ERROR:
return ret; return ret;
@@ -1013,7 +1014,7 @@ peekkey_simple (termo_t *tk, termo_key_t *key, int flags, size_t *nbytep)
// XXX: this way DEL is never recognised as backspace, even if it is // XXX: this way DEL is never recognised as backspace, even if it is
// specified in the terminfo entry key_backspace. Just because it // specified in the terminfo entry key_backspace. Just because it
// doesn't form an escape sequence. // doesn't form an escape sequence.
uint32_t codepoint; uint32_t codepoint = MULTIBYTE_INVALID;
termo_result_t res = parse_multibyte termo_result_t res = parse_multibyte
(tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep); (tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
@@ -1023,7 +1024,6 @@ peekkey_simple (termo_t *tk, termo_key_t *key, int flags, size_t *nbytep)
// caller demands an answer. About the best thing we can do here // caller demands an answer. About the best thing we can do here
// is eat as many bytes as we have, and emit a MULTIBYTE_INVALID. // is eat as many bytes as we have, and emit a MULTIBYTE_INVALID.
// If the remaining bytes arrive later, they'll be invalid too. // If the remaining bytes arrive later, they'll be invalid too.
codepoint = MULTIBYTE_INVALID;
*nbytep = tk->buffcount; *nbytep = tk->buffcount;
res = TERMO_RES_KEY; res = TERMO_RES_KEY;
} }
@@ -1574,6 +1574,9 @@ termo_strfkey_generic (termo_t *tk, char *buffer, size_t len,
} }
break; break;
} }
case TERMO_TYPE_FOCUS:
l = snprintf (buffer + pos, len - pos, "Focus(%d)", key->code.focused);
break;
case TERMO_TYPE_POSITION: case TERMO_TYPE_POSITION:
l = snprintf (buffer + pos, len - pos, "Position"); l = snprintf (buffer + pos, len - pos, "Position");
break; break;
@@ -1828,6 +1831,8 @@ termo_keycmp (termo_t *tk,
return cmp; return cmp;
break; break;
} }
case TERMO_TYPE_FOCUS:
return key1.code.focused - key2.code.focused;
case TERMO_TYPE_POSITION: case TERMO_TYPE_POSITION:
{ {
int line1, col1, line2, col2; int line1, col1, line2, col2;
@@ -1851,4 +1856,3 @@ termo_keycmp (termo_t *tk,
} }
return key1.modifiers - key2.modifiers; return key1.modifiers - key2.modifiers;
} }

View File

@@ -97,6 +97,7 @@ enum termo_type
TERMO_TYPE_MOUSE, TERMO_TYPE_MOUSE,
TERMO_TYPE_POSITION, TERMO_TYPE_POSITION,
TERMO_TYPE_MODEREPORT, TERMO_TYPE_MODEREPORT,
TERMO_TYPE_FOCUS,
// add other recognised types here // add other recognised types here
TERMO_TYPE_UNKNOWN_CSI = -1 TERMO_TYPE_UNKNOWN_CSI = -1
@@ -159,6 +160,7 @@ struct termo_key
uint32_t codepoint; // TERMO_TYPE_KEY uint32_t codepoint; // TERMO_TYPE_KEY
int number; // TERMO_TYPE_FUNCTION int number; // TERMO_TYPE_FUNCTION
termo_sym_t sym; // TERMO_TYPE_KEYSYM termo_sym_t sym; // TERMO_TYPE_KEYSYM
int focused; // TERMO_TYPE_FOCUS
// TERMO_TYPE_MODEREPORT // TERMO_TYPE_MODEREPORT
// opaque, see termo_interpret_modereport() // opaque, see termo_interpret_modereport()
@@ -192,7 +194,9 @@ enum
// Allow Ctrl-C to be read as normal, disabling SIGINT // Allow Ctrl-C to be read as normal, disabling SIGINT
TERMO_FLAG_CTRLC = 1 << 6, TERMO_FLAG_CTRLC = 1 << 6,
// Return ERROR on signal (EINTR) rather than retry // Return ERROR on signal (EINTR) rather than retry
TERMO_FLAG_EINTR = 1 << 7 TERMO_FLAG_EINTR = 1 << 7,
// Do not call termkey_start() in constructor
TERMO_FLAG_NOSTART = 1 << 8
}; };
enum enum

View File

@@ -5,6 +5,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
plan_tests (6); plan_tests (6);

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;

View File

@@ -5,6 +5,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;

View File

@@ -9,6 +9,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
int fd[2]; int fd[2];
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;

View File

@@ -2,8 +2,12 @@
#include "../termo.h" #include "../termo.h"
#include "taplib.h" #include "taplib.h"
int main (int argc, char *argv[]) int
main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_sym_t sym; termo_sym_t sym;
const char *end; const char *end;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
char buffer[16]; char buffer[16];

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
const char *endp; const char *endp;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key1, key2; termo_key_t key1, key2;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
const char *endp; const char *endp;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
termo_mouse_event_t ev; termo_mouse_event_t ev;

View File

@@ -1,8 +1,12 @@
#include "../termo.h" #include "../termo.h"
#include "taplib.h" #include "taplib.h"
int main (int argc, char *argv[]) int
main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
int line, col; int line, col;

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
int initial, mode, value; int initial, mode, value;

31
tests/33focus.c Normal file
View File

@@ -0,0 +1,31 @@
#include "../termo.h"
#include "taplib.h"
int
main (int argc, char *argv[])
{
(void) argc;
(void) argv;
termo_t *tk;
termo_key_t key;
plan_tests (6);
tk = termo_new_abstract ("vt100", NULL, 0);
termo_push_bytes (tk, "\e[I", 3);
is_int (termo_getkey (tk, &key), TERMO_RES_KEY,
"getkey yields RES_KEY for focus in");
is_int (key.type, TERMO_TYPE_FOCUS, "key.type for focus in");
is_int (key.code.focused, 1, "focused indicator for focus in");
termo_push_bytes (tk, "\e[O", 3);
is_int (termo_getkey (tk, &key), TERMO_RES_KEY,
"getkey yields RES_KEY for focus out");
is_int (key.type, TERMO_TYPE_FOCUS, "key.type for focus out");
is_int (key.code.focused, 0, "focused indicator for focus out");
termo_destroy (tk);
return exit_status ();
}

View File

@@ -4,6 +4,9 @@
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
(void) argc;
(void) argv;
termo_t *tk; termo_t *tk;
termo_key_t key; termo_key_t key;
long args[16]; long args[16];

View File

@@ -73,7 +73,7 @@ is_str (const char *got, const char *expect, char *name)
} }
int int
exit_status(void) exit_status (void)
{ {
return g_exit_status; return g_exit_status;
} }