diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-10-02 19:31:43 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-10-03 15:57:00 +0200 |
commit | be5022138495d2e509735dec7486a040d3e2eb2d (patch) | |
tree | 15627c29994b8e0c85e863d9ea332552f22e77ce | |
parent | 1bfa594cf26a9880c489cdcb5911bfb3440aa566 (diff) |
terminal: add screen renderer
We don't want to expose the term_screen internals for rendering.
Therefore, provide an iterator that allows external renderers to draw
terminals.
-rw-r--r-- | src/libsystemd-terminal/term-screen.c | 66 | ||||
-rw-r--r-- | src/libsystemd-terminal/term.h | 12 |
2 files changed, 78 insertions, 0 deletions
diff --git a/src/libsystemd-terminal/term-screen.c b/src/libsystemd-terminal/term-screen.c index 2f3f6f91cb..b442b96050 100644 --- a/src/libsystemd-terminal/term-screen.c +++ b/src/libsystemd-terminal/term-screen.c @@ -3892,3 +3892,69 @@ int term_screen_set_answerback(term_screen *screen, const char *answerback) { return 0; } + +int term_screen_draw(term_screen *screen, + int (*draw_fn) (term_screen *screen, + void *userdata, + unsigned int x, + unsigned int y, + const term_attr *attr, + const uint32_t *ch, + size_t n_ch, + unsigned int ch_width), + void *userdata, + uint64_t *fb_age) { + uint64_t cell_age, line_age, age = 0; + term_charbuf_t ch_buf; + const uint32_t *ch_str; + unsigned int i, j, cw; + term_page *page; + term_line *line; + term_cell *cell; + size_t ch_n; + int r; + + assert(screen); + assert(draw_fn); + + if (fb_age) + age = *fb_age; + + page = screen->page; + + for (j = 0; j < page->height; ++j) { + line = page->lines[j]; + line_age = MAX(line->age, page->age); + + for (i = 0; i < page->width; ++i) { + cell = &line->cells[i]; + cell_age = MAX(cell->age, line_age); + + if (age != 0 && cell_age <= age) + continue; + + ch_str = term_char_resolve(cell->ch, &ch_n, &ch_buf); + + /* Character-width of 0 is used for cleared cells. + * Always treat this as single-cell character, so + * renderers can assume ch_width is set properpy. */ + cw = MAX(cell->cwidth, 1U); + + r = draw_fn(screen, + userdata, + i, + j, + &cell->attr, + ch_str, + ch_n, + cw); + if (r != 0) + return r; + } + } + + if (fb_age) + *fb_age = screen->age++; + + return 0; +} diff --git a/src/libsystemd-terminal/term.h b/src/libsystemd-terminal/term.h index d5b934fc59..a3ca252e31 100644 --- a/src/libsystemd-terminal/term.h +++ b/src/libsystemd-terminal/term.h @@ -147,3 +147,15 @@ void term_screen_soft_reset(term_screen *screen); void term_screen_hard_reset(term_screen *screen); int term_screen_set_answerback(term_screen *screen, const char *answerback); + +int term_screen_draw(term_screen *screen, + int (*draw_fn) (term_screen *screen, + void *userdata, + unsigned int x, + unsigned int y, + const term_attr *attr, + const uint32_t *ch, + size_t n_ch, + unsigned int ch_width), + void *userdata, + uint64_t *fb_age); |