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,
^
Current maximum is provided by sysconf(_SC_HOST_NAME_MAX) instead.
uri.c:269:20: error: use of undeclared identifier 'HOST_NAME_MAX'
char this_host[HOST_NAME_MAX];
^
terminal.c:3:10: fatal error: 'malloc.h' file not found
#include <malloc.h>
^~~~~~~~~~
terminal.c:1512:9: error: implicit declaration of function 'sigaction' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
sigaction(SIGALRM, &(const struct sigaction){.sa_handler = &sig_alarm}, NULL);
^
terminal.c:1532:21: error: implicit declaration of function 'kill' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
kill(term->slave, kill_signal);
^
wayland-client-protocol.h:
Negative values for either rate or delay are illegal. A rate of
zero will disable any repeating (regardless of the value of
delay).
This fixes a division-by-zero crash.
The user provided callback may call reaper_del(), in which case we
will crash when we also try to remove the child from the list.
Remove it from the list before the callback means reaper_del() (if
called by the callback) will just loop through the entire list without
finding the pid and thus do nothing.
When we are shutting down the terminal, we explicitly wait for the
child application to terminate (with a timeout, after which the child
process is killed).
I.e. there’s no need to let the reaper handle it. In fact, doing so
leads to a crash since we will have destroyed (and thus free:d) the
terminal instance when the reaper callback is called.
When tweak.allow-overflowing-double-width-glyphs=yes, then certain
glyphs are allowed to overflow into the neighbouring cell.
However, if the cell “owning” the double-width glyph is erased (_only_
that cell), then the cell overflowed into is not redrawn, causing
part of the double-width glyph to remain on screen.
To avoid checking for these glyphs when printing to the terminal (i.e
at parse time), simply mark both cells as dirty when we render the
overflowing glyph.
Yes, this means that the cells will always be re-rendered. We count on
them only making up a small portion of the screen.
Shutdown the terminal when the client process terminates, not when the
ptmx file descriptor is closed.
This fixes an issue where the terminal remains running after the
client process has terminated, if it spawned child processes that
inherited the ptmx file descriptor.