Blob Blame History Raw
From be5022138495d2e509735dec7486a040d3e2eb2d Mon Sep 17 00:00:00 2001
From: David Herrmann <dh.herrmann@gmail.com>
Date: Thu, 2 Oct 2014 19:31:43 +0200
Subject: [PATCH] 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.
---
 src/libsystemd-terminal/term-screen.c | 66 +++++++++++++++++++++++++++++++++++
 src/libsystemd-terminal/term.h        | 12 +++++++
 2 files changed, 78 insertions(+)

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);