summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-10-02 19:31:43 +0200
committerDavid Herrmann <dh.herrmann@gmail.com>2014-10-03 15:57:00 +0200
commitbe5022138495d2e509735dec7486a040d3e2eb2d (patch)
tree15627c29994b8e0c85e863d9ea332552f22e77ce
parent1bfa594cf26a9880c489cdcb5911bfb3440aa566 (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.c66
-rw-r--r--src/libsystemd-terminal/term.h12
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);