Zbigniew Jędrzejewski-Szmek 62fe94
From c7afe4f3d74f0487c913ce49abc58fe59aaeac12 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: Tom Gundersen <teg@jklm.no>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Sun, 5 Oct 2014 15:26:54 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] terminal/screen: add support for alternate screen buffers
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
Hook up SM/RM 47/1047-1049 and enable alternate screen buffers for term
Zbigniew Jędrzejewski-Szmek 62fe94
applications.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
(David: rebased on top of -git, renamed helpers and added docs)
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/term-internal.h |  1 +
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/term-screen.c   | 89 ++++++++++++++++++++++++++++++++-
Zbigniew Jędrzejewski-Szmek 62fe94
 2 files changed, 88 insertions(+), 2 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/term-internal.h b/src/libsystemd-terminal/term-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
index c78b9aa70a..53713dd64d 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/libsystemd-terminal/term-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/term-internal.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -646,4 +646,5 @@ struct term_screen {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         term_state state;
Zbigniew Jędrzejewski-Szmek 62fe94
         term_state saved;
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_state saved_alt;
Zbigniew Jędrzejewski-Szmek 62fe94
 };
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/term-screen.c b/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
index c8a81658cb..54bb04752c 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -77,6 +77,7 @@ int term_screen_new(term_screen **out, term_screen_write_fn write_fn, void *writ
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->state.gl = &screen->g0;
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->state.gr = &screen->g1;
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->saved = screen->state;
Zbigniew Jędrzejewski-Szmek 62fe94
+        screen->saved_alt = screen->saved;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         r = term_page_new(&screen->page_main);
Zbigniew Jędrzejewski-Szmek 62fe94
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -367,6 +368,23 @@ static void screen_restore_state(term_screen *screen, term_state *from) {
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->state = *from;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+static void screen_reset_page(term_screen *screen, term_page *page) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_page_set_scroll_region(page, 0, page->height);
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_page_erase(page, 0, 0, page->width, page->height, &screen->state.attr, screen->age, false);
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static void screen_change_alt(term_screen *screen, bool set) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (set) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                screen->page = screen->page_alt;
Zbigniew Jędrzejewski-Szmek 62fe94
+                screen->history = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else {
Zbigniew Jędrzejewski-Szmek 62fe94
+                screen->page = screen->page_main;
Zbigniew Jędrzejewski-Szmek 62fe94
+                screen->history = screen->history_main;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        screen->page->age = screen->age;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 static inline void set_reset(term_screen *screen, unsigned int flag, bool set) {
Zbigniew Jędrzejewski-Szmek 62fe94
         if (set)
Zbigniew Jędrzejewski-Szmek 62fe94
                 screen->flags |= flag;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -427,6 +445,73 @@ static void screen_mode_change(term_screen *screen, unsigned int mode, bool dec,
Zbigniew Jędrzejewski-Szmek 62fe94
                 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case 47:
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (dec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * XTERM-ASB: alternate-screen-buffer
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * This enables/disables the alternate screen-buffer.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * It effectively saves the current page content and
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * allows you to restore it when changing to the
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * original screen-buffer again.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         */
Zbigniew Jędrzejewski-Szmek 62fe94
+                        screen_change_alt(screen, set);
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case 1047:
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (dec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * XTERM-ASBPE: alternate-screen-buffer-post-erase
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * This is the same as XTERM-ASB but erases the
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * alternate screen-buffer before switching back to the
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * original buffer. Use it to discard any data on the
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * alternate screen buffer when done.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         */
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (!set)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                screen_reset_page(screen, screen->page_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        screen_change_alt(screen, set);
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case 1048:
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (dec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * XTERM-ASBCS: alternate-screen-buffer-cursor-state
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * This has the same effect as DECSC/DECRC, but uses a
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * separate state buffer. It is usually used in
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * combination with alternate screen buffers to provide
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * stacked state storage.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         */
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (set)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                screen_save_state(screen, &screen->saved_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        else
Zbigniew Jędrzejewski-Szmek 62fe94
+                                screen_restore_state(screen, &screen->saved_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        case 1049:
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (dec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        /*
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * XTERM-ASBX: alternate-screen-buffer-extended
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * This combines XTERM-ASBPE and XTERM-ASBCS somewhat.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * When enabling, state is saved, alternate screen
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * buffer is activated and cleared.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * When disabled, alternate screen buffer is cleared,
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * then normal screen buffer is enabled and state is
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * restored.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         */
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (set)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                screen_save_state(screen, &screen->saved_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        screen_reset_page(screen, screen->page_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        screen_change_alt(screen, set);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (!set)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                screen_restore_state(screen, &screen->saved_alt);
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1966,8 +2051,7 @@ static int screen_DECSTBM(term_screen *screen, const term_seq *seq) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 bottom = screen->page->height;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        term_page_set_scroll_region(screen->page_main, top - 1, bottom - top + 1);
Zbigniew Jędrzejewski-Szmek 62fe94
-        term_page_set_scroll_region(screen->page_alt, top - 1, bottom - top + 1);
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_page_set_scroll_region(screen->page, top - 1, bottom - top + 1);
Zbigniew Jędrzejewski-Szmek 62fe94
         screen_cursor_clear_wrap(screen);
Zbigniew Jędrzejewski-Szmek 62fe94
         screen_cursor_set(screen, 0, 0);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -4143,6 +4227,7 @@ void term_screen_soft_reset(term_screen *screen) {
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->saved = screen->state;
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->saved.cursor_x = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->saved.cursor_y = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        screen->saved_alt = screen->saved;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->page = screen->page_main;
Zbigniew Jędrzejewski-Szmek 62fe94
         screen->history = screen->history_main;