LIBTTY(3)

πŸ’– libtty β€” bestie edition πŸ’–

okay so this is libtty(3) from the termrec world, and it's literally a library for handling vt100-like pseudo-terminals. she's giving terminal emulator core, no cap ✨


🌸 SYNOPSIS 🌸

#include <tty.h>

Link with -ltty. that's it, that's the whole vibe πŸŽ€


✨ DESCRIPTION ✨

πŸ¦‹ Functions:

  • tty tty_init(int sx, int sy, int resizable); β€” makes you a brand new vt100 terminal, sized sxΓ—sy. if you want the user to be allowed to change that size, set resizable to non-zero. that's the only thing resizable controls, periodt.
  • int tty_resize(tty vt, int nsx, int nsy); β€” resizes the vt to nsxΓ—nsy. and bestie, this works even on terminals marked as non-resizable, because that flag only stops user input from resizing β€” it does not stop you. you have main character energy, you get to resize whenever πŸ’…
  • void tty_reset(tty vt); β€” clears the screen and the attributes. fresh start, clean slate, we love a glow-up.
  • void tty_free(tty vt); β€” deallocates the vt and all its internal structures. say bye bye πŸ‘‹
  • void tty_write(tty vt, const char *buf, int len); β€” writes len bytes into the terminal, parsing them as vt100 codes. the parser is doing the most so you don't have to.
  • void tty_printf(tty vt, const char *fmt, ...); β€” does a printf into the terminal. yes, printf, but make it terminal.
  • tty tty_copy(tty vt); β€” allocates a new vt100 terminal that's an exact copy of an existing one, including its internal state. it's giving identical twin. one thing though: attached event callbacks are not copied. πŸ™ˆ
  • uint32_t tty_color_convert(uint32_t c, uint32_t to); β€” converts color values between modes: VT100_COLOR_OFF, VT100_COLOR_16, VT100_COLOR_256, VT100_COLOR_RGB. color theory but make it a function call 🌈

πŸ‘‘ Inside the terminal

you'll most likely be interested in these fields of the structure, bestie:

tty {
int sx,sy;             // screen size
int cx,cy;             // cursor position
attrchar *scr;         // screen buffer
int attr;              // current attribute
char *title;           // window title

scr is an array of character/attribute pairs β€” more exactly, each element is a struct "{ ucs ch; int attr; }". the array is a flat one of vt->sx*vt->sy elements, arranged row by row. a screen coordinate x,y is stored at x+y*vt->sy.

for other fields, please RTFS the header itself: tty.h β€” yes, literally go read the source, it's right there and it's iconic πŸ”₯


πŸŽ€ TTY event callbacks

okay so you've written some data to the terminal. now you probably want to put it somewhere. what now?? well β€” the tty structure has a number of event hooks that you can attach your functions to. these hooks are callbacks inside the tty structure that you can set. the callback fields are:

  • void *l_data; β€” it's a place to put your private data in. your little stash, your emotional support pointer 🫢
  • void (*l_char)(tty vt, int x, int y, ucs ch, int attr, int width); β€” fires after a character has been written to the screen. the cursor advances by width, which might be 1 (regular) or 2 (CJK "fullwidth"). wide characters ate πŸ’…
  • void (*l_cursor)(tty vt, int x, int y); β€” fires after the cursor has moved.
  • void (*l_clear)(tty vt, int x, int y, int len); β€” fires after a chunk of screen has been cleared.
    • if an endpoint spills outside of the current line, it will go all the way to an end of screen. no half measures ✨
    • if the cursor moves, you'll get a separate l_cursor, although it is already in place during the l_clear call.
  • void (*l_scroll)(tty vt, int nl); β€” fires after the region s1<=y<s2 is scrolled nl lines (nl<0 -> backwards, nl>0 -> forward). there's no separate l_cursor event here β€” cx and cy are already updated. she's efficient like that.
  • void (*l_flag)(tty vt, int f, int v); β€” fires when a flag changes to v. flags that are likely to be of interest to you are:
    • VT100_FLAG_CURSOR β€” cursor visibility πŸ‘€
    • VT100_FLAG_KPAD β€” application keypad mode (more detailed codes for keypad arrow keys)
  • void (*l_osc)(tty vt, int cmd, const char *str); β€” fires when a string command has been issued. most commands alter a color palette, but the most interesting one is 0: "set window title". naming your window is such a slay.
  • void (*l_resize)(tty vt, int sx, int sy); β€” fires after the terminal has been resized.
  • void (*l_flush)(tty vt); β€” fires when a write chunk ends. flush queen 🚽✨
  • void (*l_bell)(tty vt); β€” fires upon a beep. πŸ””
  • void (*l_free)(tty vt); β€” fires before the terminal is destroyed. it's the goodbye hug 😭

🌈 Vt-on-vt redirection

for the case when you want the output to go to a real terminal, there are these three:

  • void vtvt_attach(tty vt, FILE *f, int dump); β€” attaches the FILE stream f to terminal vt. usually, f will be stdout. whenever the contents of vt changes, appropriate data will be written to the stream as well. if dump is non-zero, the current state will be drawn; otherwise, only subsequent changes will be shown. the redirection will last until the terminal is destroyed by tty_free().
  • void vtvt_resize(tty vt, int sx, int sy); β€” tells libtty that the real terminal has been resized. (for resizing the virtual one, please use tty_resize() instead, bestie β€” don't mix them up πŸ™ˆ)
  • void vtvt_dump(tty vt); β€” forces a full-screen redraw of the current contents of vt. a little refresh, a little self-care 🌸

πŸ’œ SEE ALSO πŸ’œ


no cap, go read libttyrec(3) too, she's the sister page and she's also iconic πŸ‘‘

okay that's the whole page, mwah, thanks for reading bestie πŸ’–

this was version 0.19, dated 2024-04-01, from the termrec family β€” and that's the sign-off, periodt βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from