Before passing the pasted text to the decoder, we now replace \r\n,
and \n, with \r.
The URI decoder was looking for a \n, which meant we failed to split
up the list and instead pasted a single “multi-line” URI.
We failed to convert the byte-indices to cell indices, resulting in a
box cursor covering the entire pre-edit string.
Note that in addition to fixing the translation from byte index to
cell index, the rendered had to be updated to dirty one extra cell
from the original grid.
Without this, we left trailing cursors behind us when the user deleted
text from the pre-edit string.
When rendering the search input box, do the same ad-hoc workaround for
combining characters with a positive x-offset as we do when rendering
normal grid cells.
In this case, we don’t *know* when we’re dealing with combining
characters. But we can detect zero-width characters. For these, check
their glyph’s x-offset. If positive, adjust it like we do when
rendering combining glyphs in the main grid, to ensure the glyph is
positioned over the _previous_ character, not the next.
When ‘selection-target’ is set to ‘none’, selecting text does not copy
the text to _any_ clipboard.
This patch also refactors the value parsing to be data driven.
The freebsd/latest image is still FreeBSD-12, with clang-8. It
generate false positive warnings:
../../foot/search.c:357:21: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
mbstate_t ps = {0};
This fixes an out-of-range comparison in 32-bit builds:
client.c:289:19: error: result of comparison of constant 4294967296 with expression of type 'size_t' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare]
if (total_len >= 1llu << (8 * sizeof(uint32_t)) ||
~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ncurses on FreeBSD still uses termcap(5) while foot works fine with
xterm-256color sans status line and visible bell. Having more than
one ncurses version installed may break other applications.
Document -Dterminfo=false uses --term=xterm-256color by default
Base compiler on BSDs doesn't look where packages are installed to
avoid tainting build environment. When system fcft is installed to
the same prefix as wayland-client it passes CFLAGS that satisfy both
but when using subprojects/fcft there's a build error.
xdg-shell.c:33:10: fatal error: 'wayland-util.h' file not found
xdg-decoration-unstable-v1.c:28:10: fatal error: 'wayland-util.h' file not found
xdg-output-unstable-v1.c:28:10: fatal error: 'wayland-util.h' file not found
presentation-time.c:28:10: fatal error: 'wayland-util.h' file not found
primary-selection-unstable-v1.c:28:10: fatal error: 'wayland-util.h' file not found
text-input-unstable-v3.c:33:10: fatal error: 'wayland-util.h' file not found
In file included from ../../foot/grid.c:1:
In file included from ../../foot/grid.h:5:
In file included from ../../foot/terminal.h:19:
../../foot/wayland.h:8:10: fatal error: 'wayland-client.h' file not found
In file included from ../../foot/selection.c:1:
../../foot/selection.h:4:10: fatal error: 'wayland-client.h' file not found
epoll/timerfd are Linux-only but BSDs have a shim via kqueue.
libwayland on FreeBSD uses epoll-shim by default, so the build may
fail at linking instead of compilation stage.
csi.c:13:10: fatal error: 'sys/timerfd.h' file not found
#include <sys/timerfd.h>
^~~~~~~~~~~~~~~
selection.c:10:10: fatal error: 'sys/epoll.h' file not found
#include <sys/epoll.h>
^~~~~~~~~~~~~
terminal.c:15:10: fatal error: 'sys/epoll.h' file not found
#include <sys/epoll.h>
^~~~~~~~~~~~~
ld: error: undefined symbol: timerfd_create
>>> referenced by pgo.c:154 (pgo/pgo.c:154)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced by pgo.c:158 (pgo/pgo.c:158)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced by terminal.c:2022 (terminal.c:2022)
>>> terminal.c.o:(cursor_blink_rearm_timer) in archive libpgolib.a
>>> referenced 7 more times
ld: error: undefined symbol: epoll_shim_close
>>> referenced by pgo.c:160 (pgo/pgo.c:160)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced by pgo.c:258 (pgo/pgo.c:258)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced by pgo.c:277 (pgo/pgo.c:277)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced 14 more times
ld: error: undefined symbol: epoll_shim_read
>>> referenced by pgo.c:251 (pgo/pgo.c:251)
>>> pgo.p/pgo_pgo.c.o:(main)
>>> referenced by terminal.c:237 (terminal.c:237)
>>> terminal.c.o:(fdm_ptmx) in archive libpgolib.a
>>> referenced by terminal.c:363 (terminal.c:363)
>>> terminal.c.o:(fdm_blink) in archive libpgolib.a
>>> referenced 8 more times
ld: error: undefined symbol: timerfd_settime
>>> referenced by terminal.c:301 (terminal.c:301)
>>> terminal.c.o:(fdm_ptmx) in archive libpgolib.a
>>> referenced by terminal.c:309 (terminal.c:309)
>>> terminal.c.o:(fdm_ptmx) in archive libpgolib.a
>>> referenced by terminal.c:2041 (terminal.c:2041)
>>> terminal.c.o:(cursor_blink_rearm_timer) in archive libpgolib.a
>>> referenced 11 more times
ld: error: undefined symbol: timerfd_gettime
>>> referenced by selection.c:1165 (selection.c:1165)
>>> selection.c.o:(selection_start_scroll_timer) in archive libpgolib.a
foot uses a number of functions not in any POSIX version. On non-glibc
systems defining _POSIX_C_SOURCE usually hides non-compliant interfaces.
In file included from grid.c:1:
In file included from grid.h:4:
terminal.h:45:15: error: expected parameter declarator
static_assert(sizeof(struct attributes) == 8, "bad size");
^
terminal.h:45:15: error: expected ')'
terminal.h:45:14: note: to match this '('
static_assert(sizeof(struct attributes) == 8, "bad size");
^
terminal.h:45:1: error: type specifier missing, defaults to 'int' [-Werror,-Wimplicit-int]
static_assert(sizeof(struct attributes) == 8, "bad size");
^
terminal.h:55:15: error: expected parameter declarator
static_assert(sizeof(struct cell) == 12, "bad size");
^
terminal.h:55:15: error: expected ')'
terminal.h:55:14: note: to match this '('
static_assert(sizeof(struct cell) == 12, "bad size");
^
terminal.h:55:1: error: type specifier missing, defaults to 'int' [-Werror,-Wimplicit-int]
static_assert(sizeof(struct cell) == 12, "bad size");
^
grid.c:317:32: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int width = max(1, wcwidth(wc));
^
grid.c:317:32: note: did you mean '__wcwidth'?
/usr/include/_ctype.h:161:1: note: '__wcwidth' declared here
__wcwidth(__ct_rune_t _c)
^
selection.c:1695:9: error: implicit declaration of function 'pipe2' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (pipe2(fds, O_CLOEXEC) == -1) {
^
selection.c:1695:9: note: did you mean 'pipe'?
/usr/include/unistd.h:358:6: note: 'pipe' declared here
int pipe(int *);
^
selection.c:1842:9: error: implicit declaration of function 'pipe2' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (pipe2(fds, O_CLOEXEC) == -1) {
^
selection.c:2129:9: error: implicit declaration of function 'pipe2' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (pipe2(fds, O_CLOEXEC) == -1) {
^
vt.c:241:12: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
assert(wcwidth(c) == 1);
^
vt.c:241:12: note: did you mean '__wcwidth'?
/usr/include/_ctype.h:161:1: note: '__wcwidth' declared here
__wcwidth(__ct_rune_t _c)
^
vt.c:544:17: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int width = wcwidth(wc);
^
csi.c:713:35: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
const int width = wcwidth(term->vt.last_printed);
^
csi.c:713:35: note: did you mean '__wcwidth'?
/usr/include/_ctype.h:161:1: note: '__wcwidth' declared here
__wcwidth(__ct_rune_t _c)
^
ime.c:169:25: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int width = max(wcwidth(term->ime.preedit.text[i]), 1);
^
ime.c:169:25: note: did you mean '__wcwidth'?
/usr/include/_ctype.h:161:1: note: '__wcwidth' declared here
__wcwidth(__ct_rune_t _c)
^
quirks.c:81:22: error: implicit declaration of function 'strcasestr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
is_kde = strcasestr(cur_desktop, "kde") != NULL;
^
quirks.c:81:53: error: comparison between pointer and integer ('int' and 'void *') [-Werror,-Wpointer-integer-compare]
is_kde = strcasestr(cur_desktop, "kde") != NULL;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~
config.c:89:15: error: expected ')'
static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT,
^
util.h:5:18: note: expanded from macro 'ALEN'
#define ALEN(v) (sizeof(v) / sizeof((v)[0]))
^
config.c:358:12: error: implicit declaration of function 'strcasecmp' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
return strcasecmp(s, "on") == 0 ||
^
config.c:358:12: note: did you mean 'wcscasecmp'?
/usr/include/wchar.h:223:5: note: 'wcscasecmp' declared here
int wcscasecmp(const wchar_t *, const wchar_t *);
^
config.c:510:23: error: implicit declaration of function 'strcasecmp' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
bool center = strcasecmp(mode, "center") == 0;
^
config.c:1243:13: error: implicit declaration of function 'strcasecmp' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (strcasecmp(value, "none") == 0) {
^
config.c:1330:13: error: implicit declaration of function 'strcasecmp' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (strcasecmp(value, "none") == 0) {
^
config.c:1534:13: error: implicit declaration of function 'strcasecmp' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (strcasecmp(value, "none") == 0) {
^
spawn.c:20:9: error: implicit declaration of function 'pipe2' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (pipe2(pipe_fds, O_CLOEXEC) < 0) {
^
spawn.c:20:9: note: did you mean 'pipe'?
/usr/include/unistd.h:358:6: note: 'pipe' declared here
int pipe(int *);
^
spawn.c:52:5: error: implicit declaration of function 'static_assert' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch");
^
server.c:309:21: error: implicit declaration of function 'accept4' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int client_fd = accept4(
^
server.c:309:21: note: did you mean 'accept'?
/usr/include/sys/socket.h:679:5: note: 'accept' declared here
int accept(int, struct sockaddr * __restrict, socklen_t * __restrict);
^
server.c:310:59: error: use of undeclared identifier 'SOCK_CLOEXEC'
server->fd, (struct sockaddr *)&addr, &addr_size, SOCK_CLOEXEC | SOCK_NONBLOCK);
^
server.c:310:74: error: use of undeclared identifier 'SOCK_NONBLOCK'
server->fd, (struct sockaddr *)&addr, &addr_size, SOCK_CLOEXEC | SOCK_NONBLOCK);
^
server.c:341:44: error: use of undeclared identifier 'SOCK_CLOEXEC'
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
^
server.c:341:59: error: use of undeclared identifier 'SOCK_NONBLOCK'
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
^
server.c:371:44: error: use of undeclared identifier 'SOCK_CLOEXEC'
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
^
server.c:371:59: error: use of undeclared identifier 'SOCK_NONBLOCK'
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
^
shm.c:138:26: error: use of undeclared identifier '_SC_PAGE_SIZE'
long n = sysconf(_SC_PAGE_SIZE);
^
shm.c:279:15: error: implicit declaration of function 'memfd_create' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
pool_fd = memfd_create("foot-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
^
shm.c:279:15: note: did you mean 'timer_create'?
/usr/include/time.h:170:5: note: 'timer_create' declared here
int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict);
^
shm.c:279:60: error: use of undeclared identifier 'MFD_CLOEXEC'
pool_fd = memfd_create("foot-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
^
shm.c:279:74: error: use of undeclared identifier 'MFD_ALLOW_SEALING'
pool_fd = memfd_create("foot-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
^
shm.c:350:15: error: use of undeclared identifier 'F_SEAL_GROW'
F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0)
^
shm.c:350:29: error: use of undeclared identifier 'F_SEAL_SHRINK'
F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0)
^
shm.c:350:71: error: use of undeclared identifier 'F_SEAL_SEAL'
F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0)
^
shm.c:349:24: error: use of undeclared identifier 'F_ADD_SEALS'
if (fcntl(pool_fd, F_ADD_SEALS,
^
slave.c:151:28: error: implicit declaration of function 'ptsname' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
const char *pts_name = ptsname(ptmx);
^
slave.c:151:28: note: did you mean 'ttyname'?
/usr/include/unistd.h:371:7: note: 'ttyname' declared here
char *ttyname(int);
^
slave.c:151:17: error: incompatible integer to pointer conversion initializing 'const char *' with an expression of type 'int' [-Werror,-Wint-conversion]
const char *pts_name = ptsname(ptmx);
^ ~~~~~~~~~~~~~
slave.c:153:9: error: implicit declaration of function 'grantpt' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (grantpt(ptmx) == -1) {
^
slave.c:157:9: error: implicit declaration of function 'unlockpt' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (unlockpt(ptmx) == -1) {
^
slave.c:252:9: error: implicit declaration of function 'pipe2' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (pipe2(fork_pipe, O_CLOEXEC) < 0) {
^
slave.c:252:9: note: did you mean 'pipe'?
/usr/include/unistd.h:358:6: note: 'pipe' declared here
int pipe(int *);
^
render.c:1166:28: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
int width = max(1, wcwidth(cell->wc));
^
render.c:1166:28: note: did you mean '__wcwidth'?
/usr/include/_ctype.h:161:1: note: '__wcwidth' declared here
__wcwidth(__ct_rune_t _c)
^
render.c:1932:9: error: implicit declaration of function 'gettimeofday' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
gettimeofday(&start_time, NULL);
^
render.c:2240:28: error: implicit declaration of function 'wcwidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
widths[i] = max(1, wcwidth(text[i]));
^
render.c:2243:32: error: implicit declaration of function 'wcswidth' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
const size_t total_cells = wcswidth(text, text_len);
^
render.c:2243:32: note: did you mean 'wcwidth'?
render.c:1166:28: note: 'wcwidth' declared here
int width = max(1, wcwidth(cell->wc));
^
util.h:7:27: note: expanded from macro 'max'
#define max(x, y) ((x) > (y) ? (x) : (y))
^
input.c:1540:9: error: implicit declaration of function 'gettimeofday' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
gettimeofday(&now, NULL);
^
prctl is Linux-only but pthread_setname_np is same as PR_SET_NAME.
Solaris and FreeBSD >= 13 have pthread_setname_np similar to Linux.
DragonFly, OpenBSD, FreeBSD < 13 lack pthread_setname_np but provide
pthread_set_name_np which doesn't return a value. NetBSD requires 3
arguments for pthread_setname_np where the last one is void *.
render.c:8:10: fatal error: 'sys/prctl.h' file not found
#include <sys/prctl.h>
^~~~~~~~~~~~~
render.c🔢9: error: implicit declaration of function 'prctl' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (prctl(PR_SET_NAME, proc_title, 0, 0, 0) < 0)
^
render.c🔢15: error: use of undeclared identifier 'PR_SET_NAME'
if (prctl(PR_SET_NAME, proc_title, 0, 0, 0) < 0)
^
shm.c:301:26: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
can_punch_hole = fallocate(
^
shm.c:302:22: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:302:45: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:432:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:434:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:434:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:501:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:503:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:503:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:597:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:599:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:599:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
These two buttons were encoded using the *exact* same numbers as
button 4 and 5 (scroll wheel up/down), making it impossible to
distinguish them.
The relevant section from XTerm’s control sequences documentation is:
Some wheel mice can send additional button events, e.g., by tilting the
scroll wheel left and right.
Additional buttons are encoded like the wheel mice,
o by adding 64 (for buttons 6 and 7), or
o by adding 128 (for buttons 8 through 11).