Termpaint¶
Termpaint is a low level terminal interface library for character-cell terminals in the tradition of VT1xx (like xterm, etc).
It’s designed to be portable and flexible to integrate. It covers event handling and rendering.
Features¶
- works with and without an central event loop 
- robust input handling, unknown key events are gracefully filtered out 
- truecolor, soft line breaks, explicit control of trailing whitespace 
- double and curly underlines, custom underline colors 
- flexible support for program supplied additional formatting like hyperlinks 
- block, underline and bar cursor shape 
- simple grid of character cell design, support for wide characters 
- does not depend on correctly set $TERM or terminfo database 
- mouse event handling 
- tagged paste 
- mostly utf-8 based, string width routines also handle utf-16 and utf-32 
- offscreen surfaces/layers 
- interface with opaque structures designed for ABI stability (but breaking changes are still happening) 
- possible to use where allocation failure needs to be handled gracefully 
- does not use global variables where possible, can handle multiple terminals in one process 
- input parsing subset usable standalone 
- permissively licensed: Boost Software License 1.0 
Does not contain:
- ready made user interface elements (form, menu or similar) 
- window or panel abstractions 
- support for non utf-8 capable terminals 
Termpaint is meant as a basic building block to build more specific libraries upon. There are a lot of different higher layer styles, so it’s cleaner to have separate libraries for this.
Minimal example¶
A “hello world”, using the internal default operating system integration and opinionated default setup.
See Getting started for full source.
    termpaint_integration *integration;
    termpaint_terminal *terminal;
    termpaint_surface *surface;
    bool quit = false;
    integration = termpaintx_full_integration_setup_terminal_fullscreen(
                "+kbdsig +kbdsigint",
                event_callback, &quit,
                &terminal);
    surface = termpaint_terminal_get_surface(terminal);
    termpaint_surface_clear(surface,
                TERMPAINT_DEFAULT_COLOR, TERMPAINT_DEFAULT_COLOR);
    termpaint_surface_write_with_colors(surface,
                0, 0,
                "Hello World",
                TERMPAINT_DEFAULT_COLOR, TERMPAINT_DEFAULT_COLOR);
    termpaint_terminal_flush(terminal, false);
    while (!quit) {
        if (!termpaintx_full_integration_do_iteration(integration)) {
            // some kind of error
            break;
        }
    }
    termpaint_terminal_free_with_restore(terminal);
void event_callback(void *userdata, termpaint_event *event) {
    bool *quit = userdata;
    if (event->type == TERMPAINT_EV_CHAR) {
        if (event->c.length == 1 && event->c.string[0] == 'q') {
            *quit = true;
        }
    }
    if (event->type == TERMPAINT_EV_KEY) {
        if (event->key.atom == termpaint_input_escape()) {
            *quit = true;
        }
    }
}
Support¶
- It’s known to work on
- xterm 
- vte 
- rxvt-unicode 
- mintty 
- iTerm2 
- microsoft terminal 
- putty 
- konsole 
- linux 
- freebsd 
- and more. 
 
The core library (but not the OS integration and the meson build system) only depend on C11 (plus a few common string functions like strdup).
