-
Notifications
You must be signed in to change notification settings - Fork 1
/
athr_terminal_curses.c
88 lines (76 loc) · 2.14 KB
/
athr_terminal_curses.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include "athr_terminal_curses.h"
#include "athr_logger.h"
#include "athr_terminal.h"
#include <curses.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <term.h>
#include <unistd.h>
#define error(msg) athr_logger_error(athr_logger_format(msg))
unsigned athr_terminal_curses_width(void)
{
static volatile int failed_before = 0;
int cols = -1;
int tty_fd = -1;
char const *const term = getenv("TERM");
if (!term)
{
if (!failed_before) error("TERM environment variable not set");
failed_before = 1;
goto done;
}
char const *const cterm_path = ctermid(NULL);
if (!cterm_path || !cterm_path[0])
{
if (!failed_before) error("ctermid() failed");
return athr_terminal_fallback_width();
}
tty_fd = open(cterm_path, O_RDWR);
if (tty_fd == -1)
{
if (!failed_before) error("open() failed");
failed_before = 1;
goto done;
}
int setupterm_err;
if (setupterm((char *)term, tty_fd, &setupterm_err) == ERR)
{
switch (setupterm_err)
{
case -1:
if (!failed_before)
error("setupterm() failed: terminfo database not found");
failed_before = 1;
goto done;
case 0:
if (!failed_before)
error("setupterm() failed: TERM=%s not found in database or "
"too generic");
failed_before = 1;
goto done;
case 1:
if (!failed_before)
error("setupterm() failed: terminal is hardcopy");
failed_before = 1;
goto done;
} // err
}
cols = tigetnum((char *)"cols");
if (cols < 0)
{
if (!failed_before) error("tigetnum() failed");
failed_before = 1;
}
struct term *termp = set_curterm(NULL);
(void)del_curterm(termp);
done:
if (tty_fd != -1) close(tty_fd);
return cols < 0 ? athr_terminal_fallback_width() : (unsigned)cols;
}