Notcurses 3.0.13
a blingful library for TUIs and character graphics
Loading...
Searching...
No Matches
termdesc.h
Go to the documentation of this file.
1#ifndef NOTCURSES_TERMDESC
2#define NOTCURSES_TERMDESC
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8// internal header, not installed
9
10#include "version.h"
11#include "builddef.h"
12#include <stdint.h>
13#include <pthread.h>
14#include <stdbool.h>
15#include <notcurses/notcurses.h>
16#include "sprite.h"
17#include "blit.h"
18#include "fbuf.h"
19#include "in.h"
20
21// kitty keyboard protocol pop, used at end when kitty is verified.
22#define KKEYBOARD_POP "\x1b[<u"
23
24// disable key modifier options; this corresponds to a resource value of
25// "-1", which cannot be set with the [>m sequence. supposedly, "[>m" by
26// itself ought reset all of them, but this doesn't seem to work FIXME.
27#define XTMODKEYSUNDO "\x1b[>2m\x1b[>4m"
28
29struct ncpile;
30struct sprixel;
31struct notcurses;
32struct ncsharedstats;
33
34// we store all our escape sequences in a single large block, and use
35// 16-bit one-biased byte-granularity indices to get the location in said
36// block. we'd otherwise be using 32 or 64-bit pointers to get locations
37// scattered all over memory. this way the lookup elements require two or four
38// times fewer cachelines total, and the actual escape sequences are packed
39// tightly into minimal cachelines. if an escape is not defined, that index
40// is 0. the first escape defined has an index of 1, and so on. an escape
41// thus cannot actually start at byte 65535.
42
43// indexes into the table of fixed-width (16-bit) indices
44typedef enum {
45 ESCAPE_CUP, // "cup" move cursor to absolute x, y position
46 ESCAPE_HPA, // "hpa" move cursor to absolute horizontal position
47 ESCAPE_VPA, // "vpa" move cursor to absolute vertical position
48 ESCAPE_SETAF, // "setaf" set foreground color
49 ESCAPE_SETAB, // "setab" set background color
50 ESCAPE_OP, // "op" set foreground and background color to defaults
51 ESCAPE_FGOP, // set foreground only to default
52 ESCAPE_BGOP, // set background only to default
53 ESCAPE_SGR0, // "sgr0" turn off all styles
54 ESCAPE_CIVIS, // "civis" make the cursor invisiable
55 ESCAPE_CNORM, // "cnorm" restore the cursor to normal
56 ESCAPE_OC, // "oc" restore original colors
57 ESCAPE_SITM, // "sitm" start italics
58 ESCAPE_RITM, // "ritm" end italics
59 ESCAPE_CUU, // "cuu" move n cells up
60 ESCAPE_CUB, // "cub" move n cells back (left)
61 ESCAPE_CUF, // "cuf" move n cells forward (right)
62 ESCAPE_BOLD, // "bold" enter bold mode
63 ESCAPE_NOBOLD, // disable bold (ANSI but not terminfo, SGR 22)
64 ESCAPE_CUD, // "cud" move n cells down
65 ESCAPE_SMKX, // "smkx" keypad_xmit (keypad transmit mode)
66 ESCAPE_RMKX, // "rmkx" keypad_local
67 ESCAPE_EL, // "el" clear to end of line, inclusive
68 ESCAPE_SMCUP, // "smcup" enter alternate screen
69 ESCAPE_RMCUP, // "rmcup" leave alternate screen
70 ESCAPE_SMXX, // "smxx" start struckout
71 ESCAPE_SMUL, // "smul" start underline
72 ESCAPE_RMUL, // "rmul" end underline
73 ESCAPE_SMULX, // "Smulx" deparameterized: start extended underline
74 ESCAPE_SMULNOX, // "Smulx" deparameterized: kill underline
75 ESCAPE_RMXX, // "rmxx" end struckout
76 ESCAPE_IND, // "ind" scroll 1 line up
77 ESCAPE_INDN, // "indn" scroll n lines up
78 ESCAPE_SC, // "sc" push the cursor onto the stack
79 ESCAPE_RC, // "rc" pop the cursor off the stack
80 ESCAPE_CLEAR, // "clear" clear screen and home cursor
81 ESCAPE_INITC, // "initc" set up palette entry
82 ESCAPE_U7, // "u7" cursor position report
83 // Application synchronized updates, not present in terminfo
84 // (https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec)
85 ESCAPE_BSUM, // Begin Synchronized Update Mode
86 ESCAPE_ESUM, // End Synchronized Update Mode
87 ESCAPE_SAVECOLORS, // XTPUSHCOLORS (push palette/fg/bg)
88 ESCAPE_RESTORECOLORS, // XTPOPCOLORS (pop palette/fg/bg)
89 ESCAPE_DECERA, // rectangular erase
92
93// when we read a cursor report, we put it on the queue for internal
94// processing. this is necessary since it can be arbitrarily interleaved with
95// other input when stdin is connected to our terminal. these are already
96// processed to be 0-based.
97typedef struct cursorreport {
98 int x, y;
101
102// terminal interface description. most of these are acquired from terminfo(5)
103// (using a database entry specified by TERM). some are determined via
104// heuristics based off terminal interrogation or the TERM environment
105// variable. some are determined via ioctl(2). treat all of them as if they
106// can change over the program's life (don't cache them locally).
107typedef struct tinfo {
108 uint16_t escindices[ESCAPE_MAX]; // table of 1-biased indices into esctable
109 int ttyfd; // connected to true terminal, might be -1
110 char* esctable; // packed table of escape sequences
111 nccapabilities caps; // exported to the user, when requested
112 unsigned pixy; // total pixel geometry, height
113 unsigned pixx; // total pixel geometry, width
114 // we use the cell's size in pixels for pixel blitting. this information can
115 // be acquired on all terminals with pixel support.
116 unsigned cellpxy; // cell pixel height, might be 0
117 unsigned cellpxx; // cell pixel width, might be 0
118 unsigned dimy, dimx; // most recent cell geometry
119
120 unsigned supported_styles; // bitmask over NCSTYLE_* driven via sgr/ncv
121
122 // kitty interprets an RGB background that matches the default background
123 // color *as* the default background, meaning it'll be translucent if
124 // background_opaque is in use. detect this, and avoid the default if so.
125 // bg_collides_default is either:
126 // 0xfexxxxxxx (unknown), 0x00RRGGBB (no collide), or 0x01RRGGBB (collides).
128
129 // 0xffxxxxxxx (unknown), or 0x00RRGGBB (foreground)
130 uint32_t fg_default;
131
132 // bitmap support. if we support bitmaps, pixel_implementation will be a
133 // value other than NCPIXEL_NONE.
135 // wipe out a cell's worth of pixels from within a sprixel. for sixel, this
136 // means leaving out the pixels (and likely resizes the string). for kitty,
137 // this means dialing down their alpha to 0 (in equivalent space).
138 int (*pixel_wipe)(struct sprixel* s, int y, int x);
139 // perform the inverse of pixel_wipe, restoring an annihilated sprixcell.
140 int (*pixel_rebuild)(struct sprixel* s, int y, int x, uint8_t* auxvec);
141 // called in phase 1 when INVALIDATED; this damages cells that have been
142 // redrawn in a sixel (when old was not transparent, and new is not opaque).
143 // it leaves the sprixel in INVALIDATED so that it's drawn in phase 2.
144 void (*pixel_refresh)(const struct ncpile* p, struct sprixel* s);
145 int (*pixel_remove)(int id, fbuf* f); // kitty only, issue actual delete command
146 int (*pixel_init)(struct tinfo* ti, int fd); // called when support is detected
147 int (*pixel_draw)(const struct tinfo*, const struct ncpile* p,
148 struct sprixel* s, fbuf* f, int y, int x);
149 int (*pixel_draw_late)(const struct tinfo*, struct sprixel* s, int yoff, int xoff);
150 // execute move (erase old graphic, place at new location) if non-NULL
151 int (*pixel_move)(struct sprixel* s, fbuf* f, unsigned noscroll, int yoff, int xoff);
152 int (*pixel_scrub)(const struct ncpile* p, struct sprixel* s);
153 int (*pixel_clear_all)(fbuf* f); // called during context startup
154 // make a loaded graphic visible. only used with kitty.
155 int (*pixel_commit)(fbuf* f, struct sprixel* s, unsigned noscroll);
156 // scroll all graphics up. only used with fbcon.
157 void (*pixel_scroll)(const struct ncpile* p, struct tinfo*, int rows);
158 void (*pixel_cleanup)(struct tinfo*); // called at shutdown
159 uint8_t* (*pixel_trans_auxvec)(const struct ncpile* p); // create tranparent auxvec
160 // sprixel parameters. there are several different sprixel protocols, of
161 // which we support sixel and kitty. the kitty protocol is used based
162 // on TERM heuristics. otherwise, we attempt to detect sixel support, and
163 // query the details of the implementation.
164 int color_registers; // sixel color registers (post pixel_query_done)
165 unsigned sixel_maxx; // maximum theoretical sixel width
166 // in sixel, we can't render to the bottom row, lest we force a one-line
167 // scroll. we thus clamp sixel_maxy_pristine to the minimum of
168 // sixel_maxy_pristine (the reported sixel_maxy), and the number of rows
169 // less one times the cell height. sixel_maxy is thus recomputed whenever
170 // we get a resize event. it is only defined if we have sixel_maxy_pristine,
171 // so kitty graphics (which don't force a scroll) never deal with this.
172 unsigned sixel_maxy; // maximum working sixel height
173 unsigned sixel_maxy_pristine; // maximum theoretical sixel height, as queried
174 unsigned sprixel_scale_height;// sprixel must be a multiple of this many rows
175 void* sixelengine; // opaque threaded engine used by sixel dispatch
176 const char* termname; // terminal name from environment variables/init
177 char* termversion; // terminal version (freeform) from query responses
178 queried_terminals_e qterm; // detected terminal class
179 // we heap-allocate this one (if we use it), as it's not fully defined on Windows
180 struct termios *tpreserved;// terminal state upon entry
181 struct inputctx* ictx; // new input layer
182 unsigned stdio_blocking_save; // was stdio blocking at entry? restore on stop.
183 // ought we issue gratuitous HPAs to work around ambiguous widths?
185
186 // if we get a reply to our initial \e[18t cell geometry query, it will
187 // replace these values. note that LINES/COLUMNS cannot be used to limit
188 // the output region; use margins for that, if necessary.
189 int default_rows; // LINES environment var / lines terminfo / 24
190 int default_cols; // COLUMNS environment var / cols terminfo / 80
191
192 ncpalette originalpalette; // palette as read from initial queries
193 int maxpaletteread; // maximum palette entry read
194 pthread_t gpmthread; // thread handle for GPM watcher
195 int gpmfd; // connection to GPM daemon
196 char mouseproto; // DECSET level (100x, '0', '2', '3')
197 bool pixelmice; // do we support pixel-precision mice?
198#ifdef __linux__
199 int linux_fb_fd; // linux framebuffer device fd
200 char* linux_fb_dev; // device corresponding to linux_fb_dev
201 uint8_t* linux_fbuffer; // mmap()ed framebuffer
202 size_t linux_fb_len; // size of map
203#elif defined(__MINGW32__)
204 HANDLE inhandle;
205 HANDLE outhandle;
206#endif
207
208 // kitty keyboard protocol level. we initialize this to UINT_MAX, in case we
209 // crash while running the initialization automata (in that case, we want to
210 // pop the keyboard support level, which we normally do only if we detected
211 // actual support. at that point, we obviously haven't detected anything).
212 // after getting the initialization package back, if it's still UINT_MAX, we
213 // set it to 0, and also indicate a lack of support via kittykbdsupport (we
214 // need distinguish between level 0, used with DRAININPUT, and an absolute
215 // lack of support, in which case we move to XTMODKEYS, for notcurses-info).
216 unsigned kbdlevel; // kitty keyboard support level
217 bool kittykbdsupport; // do we support the kitty keyboard protocol?
218 bool bce; // is the bce property advertised?
219 bool in_alt_screen; // are we in the alternate screen?
221
222// retrieve the terminfo(5)-style escape 'e' from tdesc (NULL if undefined).
223static inline __attribute__ ((pure)) const char*
224get_escape(const tinfo* tdesc, escape_e e){
225 unsigned idx = tdesc->escindices[e];
226 if(idx){
227 return tdesc->esctable + idx - 1;
228 }
229 return NULL;
230}
231
232static inline uint16_t
233term_supported_styles(const tinfo* ti){
234 return ti->supported_styles;
235}
236
237// prepare |ti| from the terminfo database and other sources. set |utf8| if
238// we've verified UTF8 output encoding. set |noaltscreen| to inhibit alternate
239// screen detection. |stats| may be NULL; either way, it will be handed to the
240// input layer so that its stats can be recorded.
241int interrogate_terminfo(tinfo* ti, FILE* out, unsigned utf8,
242 unsigned noaltscreen, unsigned nocbreak,
243 unsigned nonewfonts, int* cursor_y, int* cursor_x,
244 struct ncsharedstats* stats, int lmargin, int tmargin,
245 int rmargin, int bmargin, unsigned draininput)
246 __attribute__ ((nonnull (1, 2, 9)));
247
249
250// return a heap-allocated copy of termname + termversion
251char* termdesc_longterm(const tinfo* ti);
252
253int locate_cursor(tinfo* ti, unsigned* cursor_y, unsigned* cursor_x);
254
255int grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
256 size_t* tlen, size_t* tused);
257
258static inline int
259ncfputs(const char* ext, FILE* out){
260 int r;
261#ifdef __USE_GNU
262 r = fputs_unlocked(ext, out);
263#else
264 r = fputs(ext, out);
265#endif
266 return r;
267}
268
269static inline int
270ncfputc(char c, FILE* out){
271#ifdef __USE_GNU
272 return putc_unlocked(c, out);
273#else
274 return putc(c, out);
275#endif
276}
277
278// reliably flush a FILE*...except you can't, so far as i can tell. at least
279// on glibc, a single fflush() error latches the FILE* error, but ceases to
280// perform any work (even following a clearerr()), despite returning 0 from
281// that point on. thus, after a fflush() error, even on EAGAIN and friends,
282// you can't use the stream any further. doesn't this make fflush() pretty
283// much useless? it sure would seem to, which is why we use an fbuf for
284// all our important I/O, which we then blit with blocking_write(). if you
285// care about your data, you'll do the same.
286static inline int
287ncflush(FILE* out){
288 if(ferror(out)){
289 logerror("Not attempting a flush following error\n");
290 }
291 if(fflush(out) == EOF){
292 logerror("Unrecoverable error flushing io (%s)\n", strerror(errno));
293 return -1;
294 }
295 return 0;
296}
297
298static inline int
299term_emit(const char* seq, FILE* out, bool flush){
300 if(!seq){
301 return -1;
302 }
303 if(ncfputs(seq, out) == EOF){
304 logerror("Error emitting %lub escape (%s)\n",
305 (unsigned long)strlen(seq), strerror(errno));
306 return -1;
307 }
308 return flush ? ncflush(out) : 0;
309}
310
311// |drain| is set iff we're draining input.
312int enter_alternate_screen(int ttyfd, FILE* ttyfp, tinfo* ti, unsigned drain);
313int leave_alternate_screen(int ttyfd, FILE* ttyfp, tinfo* ti, unsigned drain);
314
315int cbreak_mode(tinfo* ti);
316
317// execute termios's TIOCGWINSZ ioctl(). returns -1 on failure.
318int tiocgwinsz(int fd, struct winsize* ws);
319
320#ifdef __cplusplus
321}
322#endif
323
324#endif
const nccell * c
Definition egcpool.h:296
uint32_t idx
Definition egcpool.h:298
__attribute__((nonnull(1, 2))) static inline int egcpool_stash(egcpool *pool
int r
Definition fbuf.h:226
queried_terminals_e
Definition in.h:31
#define logerror(fmt,...)
Definition logging.h:32
int y
Definition notcurses.h:1905
int int x
Definition notcurses.h:1905
ncpixelimpl_e
Definition notcurses.h:1672
struct cursorreport * next
Definition termdesc.h:99
Definition fbuf.h:25
Definition in.c:52
unsigned drain
Definition in.c:99
ncsharedstats * stats
Definition in.c:100
int lmargin
Definition in.c:66
int tmargin
Definition in.c:66
int bmargin
Definition in.c:67
tinfo * ti
Definition in.c:91
int rmargin
Definition in.c:67
queried_terminals_e qterm
Definition termdesc.h:178
unsigned supported_styles
Definition termdesc.h:120
int maxpaletteread
Definition termdesc.h:193
ncpixelimpl_e pixel_implementation
Definition termdesc.h:134
void * sixelengine
Definition termdesc.h:175
unsigned cellpxx
Definition termdesc.h:117
int(* pixel_init)(struct tinfo *ti, int fd)
Definition termdesc.h:146
const char * termname
Definition termdesc.h:176
int(* pixel_draw_late)(const struct tinfo *, struct sprixel *s, int yoff, int xoff)
Definition termdesc.h:149
unsigned gratuitous_hpa
Definition termdesc.h:184
int(* pixel_remove)(int id, fbuf *f)
Definition termdesc.h:145
bool bce
Definition termdesc.h:218
char mouseproto
Definition termdesc.h:196
int(* pixel_rebuild)(struct sprixel *s, int y, int x, uint8_t *auxvec)
Definition termdesc.h:140
unsigned pixx
Definition termdesc.h:113
bool pixelmice
Definition termdesc.h:197
int gpmfd
Definition termdesc.h:195
unsigned pixy
Definition termdesc.h:112
uint32_t bg_collides_default
Definition termdesc.h:127
unsigned kbdlevel
Definition termdesc.h:216
int(* pixel_wipe)(struct sprixel *s, int y, int x)
Definition termdesc.h:138
unsigned dimx
Definition termdesc.h:118
void(* pixel_cleanup)(struct tinfo *)
Definition termdesc.h:158
int(* pixel_commit)(fbuf *f, struct sprixel *s, unsigned noscroll)
Definition termdesc.h:155
int(* pixel_scrub)(const struct ncpile *p, struct sprixel *s)
Definition termdesc.h:152
ncpalette originalpalette
Definition termdesc.h:192
bool kittykbdsupport
Definition termdesc.h:217
unsigned sprixel_scale_height
Definition termdesc.h:174
nccapabilities caps
Definition termdesc.h:111
struct termios * tpreserved
Definition termdesc.h:180
bool in_alt_screen
Definition termdesc.h:219
char * esctable
Definition termdesc.h:110
void(* pixel_refresh)(const struct ncpile *p, struct sprixel *s)
Definition termdesc.h:144
unsigned sixel_maxx
Definition termdesc.h:165
uint32_t fg_default
Definition termdesc.h:130
int default_rows
Definition termdesc.h:189
int(* pixel_draw)(const struct tinfo *, const struct ncpile *p, struct sprixel *s, fbuf *f, int y, int x)
Definition termdesc.h:147
unsigned dimy
Definition termdesc.h:118
unsigned sixel_maxy
Definition termdesc.h:172
int(* pixel_clear_all)(fbuf *f)
Definition termdesc.h:153
unsigned stdio_blocking_save
Definition termdesc.h:182
char * termversion
Definition termdesc.h:177
unsigned sixel_maxy_pristine
Definition termdesc.h:173
struct inputctx * ictx
Definition termdesc.h:181
pthread_t gpmthread
Definition termdesc.h:194
int(* pixel_move)(struct sprixel *s, fbuf *f, unsigned noscroll, int yoff, int xoff)
Definition termdesc.h:151
int default_cols
Definition termdesc.h:190
void(* pixel_scroll)(const struct ncpile *p, struct tinfo *, int rows)
Definition termdesc.h:157
unsigned cellpxy
Definition termdesc.h:116
int color_registers
Definition termdesc.h:164
int ttyfd
Definition termdesc.h:109
uint16_t escindices[ESCAPE_MAX]
Definition termdesc.h:108
return NULL
Definition termdesc.h:229
escape_e
Definition termdesc.h:44
@ ESCAPE_CUU
Definition termdesc.h:59
@ ESCAPE_RMKX
Definition termdesc.h:66
@ ESCAPE_CIVIS
Definition termdesc.h:54
@ ESCAPE_SC
Definition termdesc.h:78
@ ESCAPE_BOLD
Definition termdesc.h:62
@ ESCAPE_CUP
Definition termdesc.h:45
@ ESCAPE_CUD
Definition termdesc.h:64
@ ESCAPE_CNORM
Definition termdesc.h:55
@ ESCAPE_MAX
Definition termdesc.h:90
@ ESCAPE_SMULX
Definition termdesc.h:73
@ ESCAPE_SETAB
Definition termdesc.h:49
@ ESCAPE_RESTORECOLORS
Definition termdesc.h:88
@ ESCAPE_CUF
Definition termdesc.h:61
@ ESCAPE_IND
Definition termdesc.h:76
@ ESCAPE_NOBOLD
Definition termdesc.h:63
@ ESCAPE_VPA
Definition termdesc.h:47
@ ESCAPE_SMXX
Definition termdesc.h:70
@ ESCAPE_ESUM
Definition termdesc.h:86
@ ESCAPE_OP
Definition termdesc.h:50
@ ESCAPE_OC
Definition termdesc.h:56
@ ESCAPE_RMCUP
Definition termdesc.h:69
@ ESCAPE_SMCUP
Definition termdesc.h:68
@ ESCAPE_SMKX
Definition termdesc.h:65
@ ESCAPE_FGOP
Definition termdesc.h:51
@ ESCAPE_SITM
Definition termdesc.h:57
@ ESCAPE_SAVECOLORS
Definition termdesc.h:87
@ ESCAPE_RMXX
Definition termdesc.h:75
@ ESCAPE_DECERA
Definition termdesc.h:89
@ ESCAPE_INDN
Definition termdesc.h:77
@ ESCAPE_BSUM
Definition termdesc.h:85
@ ESCAPE_SMUL
Definition termdesc.h:71
@ ESCAPE_CLEAR
Definition termdesc.h:80
@ ESCAPE_INITC
Definition termdesc.h:81
@ ESCAPE_RITM
Definition termdesc.h:58
@ ESCAPE_SETAF
Definition termdesc.h:48
@ ESCAPE_U7
Definition termdesc.h:82
@ ESCAPE_BGOP
Definition termdesc.h:52
@ ESCAPE_HPA
Definition termdesc.h:46
@ ESCAPE_RMUL
Definition termdesc.h:72
@ ESCAPE_RC
Definition termdesc.h:79
@ ESCAPE_SMULNOX
Definition termdesc.h:74
@ ESCAPE_EL
Definition termdesc.h:67
@ ESCAPE_CUB
Definition termdesc.h:60
@ ESCAPE_SGR0
Definition termdesc.h:53
int grow_esc_table(tinfo *ti, const char *tstr, escape_e esc, size_t *tlen, size_t *tused)
Definition termdesc.c:14
int enter_alternate_screen(int ttyfd, FILE *ttyfp, tinfo *ti, unsigned drain)
Definition termdesc.c:559
int locate_cursor(tinfo *ti, unsigned *cursor_y, unsigned *cursor_x)
Definition termdesc.c:1558
int cbreak_mode(tinfo *ti)
Definition termdesc.c:1595
int void free_terminfo_cache(tinfo *ti)
Definition termdesc.c:197
int interrogate_terminfo(tinfo *ti, FILE *out, unsigned utf8, unsigned noaltscreen, unsigned nocbreak, unsigned nonewfonts, int *cursor_y, int *cursor_x, struct ncsharedstats *stats, int lmargin, int tmargin, int rmargin, int bmargin, unsigned draininput) __attribute__((nonnull(1
char * termdesc_longterm(const tinfo *ti)
Definition termdesc.c:1535
static escape_e e
Definition termdesc.h:224
int leave_alternate_screen(int ttyfd, FILE *ttyfp, tinfo *ti, unsigned drain)
Definition termdesc.c:611
int tiocgwinsz(int fd, struct winsize *ws)
Definition termdesc.c:1576