diff options
author | Thomas Adam <thomas@xteddy.org> | 2020-03-31 10:01:29 +0100 |
---|---|---|
committer | Thomas Adam <thomas@xteddy.org> | 2020-03-31 10:01:29 +0100 |
commit | c9cd8f9b5dd030790b097263e7bf1674efabeb72 (patch) | |
tree | 539f12ed41c544f51edcaa44849903de02660ded /screen.c | |
parent | 588865152a1bb70d77758b68a2869b794aa31dd4 (diff) | |
parent | 3bbd66c0137fe95c348ce333ea7eec9507db7659 (diff) | |
download | rtmux-c9cd8f9b5dd030790b097263e7bf1674efabeb72.tar.gz rtmux-c9cd8f9b5dd030790b097263e7bf1674efabeb72.tar.bz2 rtmux-c9cd8f9b5dd030790b097263e7bf1674efabeb72.zip |
Merge branch 'obsd-master'
Diffstat (limited to 'screen.c')
-rw-r--r-- | screen.c | 84 |
1 files changed, 84 insertions, 0 deletions
@@ -75,6 +75,8 @@ void screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) { s->grid = grid_create(sx, sy, hlimit); + s->saved_grid = NULL; + s->title = xstrdup(""); s->titles = NULL; @@ -98,6 +100,11 @@ screen_reinit(struct screen *s) s->mode = MODE_CURSOR | MODE_WRAP; + if (s->saved_grid != NULL) + screen_alternate_off(s, NULL, 0); + s->saved_cx = UINT_MAX; + s->saved_cy = UINT_MAX; + screen_reset_tabs(s); grid_clear_lines(s->grid, s->grid->hsize, s->grid->sy, 8); @@ -115,6 +122,8 @@ screen_free(struct screen *s) free(s->title); free(s->ccolour); + if (s->saved_grid != NULL) + grid_destroy(s->saved_grid); grid_destroy(s->grid); screen_free_titles(s); @@ -501,3 +510,78 @@ screen_reflow(struct screen *s, u_int new_x) log_debug("%s: reflow took %llu.%06u seconds", __func__, (unsigned long long)tv.tv_sec, (u_int)tv.tv_usec); } + +/* + * Enter alternative screen mode. A copy of the visible screen is saved and the + * history is not updated. + */ +void +screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) +{ + u_int sx, sy; + + if (s->saved_grid != NULL) + return; + sx = screen_size_x(s); + sy = screen_size_y(s); + + s->saved_grid = grid_create(sx, sy, 0); + grid_duplicate_lines(s->saved_grid, 0, s->grid, screen_hsize(s), sy); + if (cursor) { + s->saved_cx = s->cx; + s->saved_cy = s->cy; + } + memcpy(&s->saved_cell, gc, sizeof s->saved_cell); + + grid_view_clear(s->grid, 0, 0, sx, sy, 8); + + s->grid->flags &= ~GRID_HISTORY; +} + +/* Exit alternate screen mode and restore the copied grid. */ +void +screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) +{ + u_int sx, sy; + + /* + * Restore the cursor position and cell. This happens even if not + * currently in the alternate screen. + */ + if (cursor && s->saved_cx != UINT_MAX && s->saved_cy != UINT_MAX) { + s->cx = s->saved_cx; + if (s->cx > screen_size_x(s) - 1) + s->cx = screen_size_x(s) - 1; + s->cy = s->saved_cy; + if (s->cy > screen_size_y(s) - 1) + s->cy = screen_size_y(s) - 1; + if (gc != NULL) + memcpy(gc, &s->saved_cell, sizeof *gc); + } + + if (s->saved_grid == NULL) + return; + sx = screen_size_x(s); + sy = screen_size_y(s); + + /* + * If the current size is bigger, temporarily resize to the old size + * before copying back. + */ + if (sy > s->saved_grid->sy) + screen_resize(s, sx, s->saved_grid->sy, 1); + + /* Restore the saved grid. */ + grid_duplicate_lines(s->grid, screen_hsize(s), s->saved_grid, 0, sy); + + /* + * Turn history back on (so resize can use it) and then resize back to + * the current size. + */ + s->grid->flags |= GRID_HISTORY; + if (sy > s->saved_grid->sy || sx != s->saved_grid->sx) + screen_resize(s, sx, sy, 1); + + grid_destroy(s->saved_grid); + s->saved_grid = NULL; +} |