]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
vt: save/restore unicode screen buffer for alternate screen
authorNicolas Pitre <npitre@baylibre.com>
Tue, 27 Jan 2026 22:56:01 +0000 (17:56 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Mar 2026 08:15:58 +0000 (09:15 +0100)
The alternate screen support added by commit 23743ba64709 ("vt: add
support for smput/rmput escape codes") only saves and restores the
regular screen buffer (vc_origin), but completely ignores the corresponding
unicode screen buffer (vc_uni_lines) creating a messed-up display.

Add vc_saved_uni_lines to save the unicode screen buffer when entering
the alternate screen, and restore it when leaving. Also ensure proper
cleanup in reset_terminal() and vc_deallocate().

Fixes: 23743ba64709 ("vt: add support for smput/rmput escape codes")
Cc: stable <stable@kernel.org>
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Link: https://patch.msgid.link/5o2p6qp3-91pq-0p17-or02-1oors4417ns7@onlyvoer.pbz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/vt/vt.c
include/linux/console_struct.h

index c1f152d8b03b6add73194831b9a221b2cb267633..e2df99e3d45809febf008cb0fb9d4fea72dd116c 100644 (file)
@@ -1339,6 +1339,8 @@ struct vc_data *vc_deallocate(unsigned int currcons)
                        kfree(vc->vc_saved_screen);
                        vc->vc_saved_screen = NULL;
                }
+               vc_uniscr_free(vc->vc_saved_uni_lines);
+               vc->vc_saved_uni_lines = NULL;
        }
        return vc;
 }
@@ -1884,6 +1886,8 @@ static void enter_alt_screen(struct vc_data *vc)
        vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL);
        if (vc->vc_saved_screen == NULL)
                return;
+       vc->vc_saved_uni_lines = vc->vc_uni_lines;
+       vc->vc_uni_lines = NULL;
        vc->vc_saved_rows = vc->vc_rows;
        vc->vc_saved_cols = vc->vc_cols;
        save_cur(vc);
@@ -1905,6 +1909,8 @@ static void leave_alt_screen(struct vc_data *vc)
                dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols;
                memcpy(dest, src, 2 * cols);
        }
+       vc_uniscr_set(vc, vc->vc_saved_uni_lines);
+       vc->vc_saved_uni_lines = NULL;
        restore_cur(vc);
        /* Update the entire screen */
        if (con_should_update(vc))
@@ -2227,6 +2233,8 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        if (vc->vc_saved_screen != NULL) {
                kfree(vc->vc_saved_screen);
                vc->vc_saved_screen = NULL;
+               vc_uniscr_free(vc->vc_saved_uni_lines);
+               vc->vc_saved_uni_lines = NULL;
                vc->vc_saved_rows = 0;
                vc->vc_saved_cols = 0;
        }
index 13b35637bd5aee63197cc39f9afff32f31c3ca59..d5ca855116df45c9a9ace99610854bd0345a708d 100644 (file)
@@ -160,6 +160,7 @@ struct vc_data {
        struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */
        u32 **vc_uni_lines;                     /* unicode screen content */
        u16             *vc_saved_screen;
+       u32             **vc_saved_uni_lines;
        unsigned int    vc_saved_cols;
        unsigned int    vc_saved_rows;
        /* additional information is in vt_kern.h */