summaryrefslogtreecommitdiffstats
path: root/src/bar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bar.c')
-rw-r--r--src/bar.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/src/bar.c b/src/bar.c
index b928373..3258df0 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -1,21 +1,26 @@
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD
-#include "prelude.h"
#include "bar.h"
+
#include "alloc.h"
#include "atomic.h"
+#include "bfs.h"
#include "bfstd.h"
#include "bit.h"
#include "dstring.h"
#include "sighook.h"
+
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
struct bfs_bar {
int fd;
@@ -28,10 +33,16 @@ struct bfs_bar {
/** Get the terminal size, if possible. */
static int bfs_bar_getsize(struct bfs_bar *bar) {
-#ifdef TIOCGWINSZ
+#if BFS_HAS_TCGETWINSIZE || defined(TIOCGWINSZ)
struct winsize ws;
- if (ioctl(bar->fd, TIOCGWINSZ, &ws) != 0) {
- return -1;
+
+# if BFS_HAS_TCGETWINSIZE
+ int ret = tcgetwinsize(bar->fd, &ws);
+# else
+ int ret = ioctl(bar->fd, TIOCGWINSZ, &ws);
+# endif
+ if (ret != 0) {
+ return ret;
}
store(&bar->width, ws.ws_col, relaxed);
@@ -72,8 +83,26 @@ static char *ass_itoa(char *str, unsigned int n) {
return str + len;
}
+/** Reset the scrollable region and hide the bar. */
+static int bfs_bar_reset(struct bfs_bar *bar) {
+ return bfs_bar_puts(bar,
+ "\0337" // DECSC: Save cursor
+ "\033[r" // DECSTBM: Reset scrollable region
+ "\0338" // DECRC: Restore cursor
+ "\033[J" // ED: Erase display from cursor to end
+ );
+}
+
+/** Hide the bar if the terminal is shorter than this. */
+#define BFS_BAR_MIN_HEIGHT 3
+
/** Update the size of the scrollable region. */
static int bfs_bar_resize(struct bfs_bar *bar) {
+ unsigned int height = load(&bar->height, relaxed);
+ if (height < BFS_BAR_MIN_HEIGHT) {
+ return bfs_bar_reset(bar);
+ }
+
static const char PREFIX[] =
"\033D" // IND: Line feed, possibly scrolling
"\033[1A" // CUU: Move cursor up 1 row
@@ -87,10 +116,8 @@ static int bfs_bar_resize(struct bfs_bar *bar) {
char esc_seq[sizeof(PREFIX) + ITOA_DIGITS + sizeof(SUFFIX)];
// DECSTBM takes the height as the second argument
- unsigned int height = load(&bar->height, relaxed) - 1;
-
char *cur = stpcpy(esc_seq, PREFIX);
- cur = ass_itoa(cur, height);
+ cur = ass_itoa(cur, height - 1);
cur = stpcpy(cur, SUFFIX);
return bfs_bar_write(bar, esc_seq, cur - esc_seq);
@@ -105,16 +132,6 @@ static void bfs_bar_sigwinch(int sig, siginfo_t *info, void *arg) {
}
#endif
-/** Reset the scrollable region and hide the bar. */
-static int bfs_bar_reset(struct bfs_bar *bar) {
- return bfs_bar_puts(bar,
- "\0337" // DECSC: Save cursor
- "\033[r" // DECSTBM: Reset scrollable region
- "\0338" // DECRC: Restore cursor
- "\033[J" // ED: Erase display from cursor to end
- );
-}
-
/** Signal handler for process-terminating signals. */
static void bfs_bar_sigexit(int sig, siginfo_t *info, void *arg) {
struct bfs_bar *bar = arg;
@@ -122,7 +139,7 @@ static void bfs_bar_sigexit(int sig, siginfo_t *info, void *arg) {
}
/** printf() to the status bar with a single write(). */
-attr(printf(2, 3))
+_printf(2, 3)
static int bfs_bar_printf(struct bfs_bar *bar, const char *format, ...) {
va_list args;
va_start(args, format);
@@ -144,14 +161,7 @@ struct bfs_bar *bfs_bar_show(void) {
return NULL;
}
- char term[L_ctermid];
- ctermid(term);
- if (strlen(term) == 0) {
- errno = ENOTTY;
- goto fail;
- }
-
- bar->fd = open(term, O_RDWR | O_CLOEXEC);
+ bar->fd = open_cterm(O_RDWR | O_CLOEXEC);
if (bar->fd < 0) {
goto fail;
}
@@ -190,6 +200,10 @@ unsigned int bfs_bar_width(const struct bfs_bar *bar) {
int bfs_bar_update(struct bfs_bar *bar, const char *str) {
unsigned int height = load(&bar->height, relaxed);
+ if (height < BFS_BAR_MIN_HEIGHT) {
+ return 0;
+ }
+
return bfs_bar_printf(bar,
"\0337" // DECSC: Save cursor
"\033[%u;0f" // HVP: Move cursor to row, column