X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-terminal%2Fterm-screen.c;h=acd7cc966a34e52cdcfd15985152f9ed323948de;hb=be795898c0d2fa21e3389b89793dcd45c47f8b9f;hp=c8a81658cb23a2a1cbd0292b76b305f0b36b9746;hpb=3ae49a8fdb7d21c065fcf2b1f7459a32f963c087;p=elogind.git diff --git a/src/libsystemd-terminal/term-screen.c b/src/libsystemd-terminal/term-screen.c index c8a81658c..acd7cc966 100644 --- a/src/libsystemd-terminal/term-screen.c +++ b/src/libsystemd-terminal/term-screen.c @@ -77,6 +77,7 @@ int term_screen_new(term_screen **out, term_screen_write_fn write_fn, void *writ screen->state.gl = &screen->g0; screen->state.gr = &screen->g1; screen->saved = screen->state; + screen->saved_alt = screen->saved; r = term_page_new(&screen->page_main); if (r < 0) @@ -367,6 +368,23 @@ static void screen_restore_state(term_screen *screen, term_state *from) { screen->state = *from; } +static void screen_reset_page(term_screen *screen, term_page *page) { + term_page_set_scroll_region(page, 0, page->height); + term_page_erase(page, 0, 0, page->width, page->height, &screen->state.attr, screen->age, false); +} + +static void screen_change_alt(term_screen *screen, bool set) { + if (set) { + screen->page = screen->page_alt; + screen->history = NULL; + } else { + screen->page = screen->page_main; + screen->history = screen->history_main; + } + + screen->page->age = screen->age; +} + static inline void set_reset(term_screen *screen, unsigned int flag, bool set) { if (set) screen->flags |= flag; @@ -374,59 +392,117 @@ static inline void set_reset(term_screen *screen, unsigned int flag, bool set) { screen->flags &= ~flag; } -static void screen_mode_change(term_screen *screen, unsigned int mode, bool dec, bool set) { +static void screen_mode_change_ansi(term_screen *screen, unsigned mode, bool set) { + switch (mode) { + case 20: + /* + * LNM: line-feed/new-line mode + * TODO + */ + set_reset(screen, TERM_FLAG_NEWLINE_MODE, set); + + break; + default: + log_debug("terminal: failed to %s unknown ANSI mode %u", set ? "set" : "unset", mode); + } +} + +static void screen_mode_change_dec(term_screen *screen, unsigned int mode, bool set) { switch (mode) { case 1: - if (dec) { - /* - * DECCKM: cursor-keys - * TODO - */ - set_reset(screen, TERM_FLAG_CURSOR_KEYS, set); - } + /* + * DECCKM: cursor-keys + * TODO + */ + set_reset(screen, TERM_FLAG_CURSOR_KEYS, set); break; case 6: - if (dec) { - /* - * DECOM: origin-mode - * TODO - */ - screen->state.origin_mode = set; - } + /* + * DECOM: origin-mode + * TODO + */ + screen->state.origin_mode = set; break; case 7: - if (dec) { - /* - * DECAWN: auto-wrap mode - * TODO - */ - screen->state.auto_wrap = set; - } + /* + * DECAWN: auto-wrap mode + * TODO + */ + screen->state.auto_wrap = set; break; - case 20: - if (!dec) { - /* - * LNM: line-feed/new-line mode - * TODO - */ - set_reset(screen, TERM_FLAG_NEWLINE_MODE, set); - } + case 25: + /* + * DECTCEM: text-cursor-enable + * TODO + */ + set_reset(screen, TERM_FLAG_HIDE_CURSOR, !set); + screen_age_cursor(screen); break; - case 25: - if (dec) { - /* - * DECTCEM: text-cursor-enable - * TODO - */ - set_reset(screen, TERM_FLAG_HIDE_CURSOR, !set); - screen_age_cursor(screen); - } + case 47: + /* + * XTERM-ASB: alternate-screen-buffer + * This enables/disables the alternate screen-buffer. + * It effectively saves the current page content and + * allows you to restore it when changing to the + * original screen-buffer again. + */ + screen_change_alt(screen, set); + + break; + case 1047: + /* + * XTERM-ASBPE: alternate-screen-buffer-post-erase + * This is the same as XTERM-ASB but erases the + * alternate screen-buffer before switching back to the + * original buffer. Use it to discard any data on the + * alternate screen buffer when done. + */ + if (!set) + screen_reset_page(screen, screen->page_alt); + + screen_change_alt(screen, set); + + break; + case 1048: + /* + * XTERM-ASBCS: alternate-screen-buffer-cursor-state + * This has the same effect as DECSC/DECRC, but uses a + * separate state buffer. It is usually used in + * combination with alternate screen buffers to provide + * stacked state storage. + */ + if (set) + screen_save_state(screen, &screen->saved_alt); + else + screen_restore_state(screen, &screen->saved_alt); + + break; + case 1049: + /* + * XTERM-ASBX: alternate-screen-buffer-extended + * This combines XTERM-ASBPE and XTERM-ASBCS somewhat. + * When enabling, state is saved, alternate screen + * buffer is activated and cleared. + * When disabled, alternate screen buffer is cleared, + * then normal screen buffer is enabled and state is + * restored. + */ + if (set) + screen_save_state(screen, &screen->saved_alt); + + screen_reset_page(screen, screen->page_alt); + screen_change_alt(screen, set); + + if (!set) + screen_restore_state(screen, &screen->saved_alt); break; + default: + log_debug("terminal: failed to %s unknown DEC mode %u", set ? "set" : "unset", mode); } } @@ -1966,8 +2042,7 @@ static int screen_DECSTBM(term_screen *screen, const term_seq *seq) { bottom = screen->page->height; } - term_page_set_scroll_region(screen->page_main, top - 1, bottom - top + 1); - term_page_set_scroll_region(screen->page_alt, top - 1, bottom - top + 1); + term_page_set_scroll_region(screen->page, top - 1, bottom - top + 1); screen_cursor_clear_wrap(screen); screen_cursor_set(screen, 0, 0); @@ -2679,7 +2754,7 @@ static int screen_RM_ANSI(term_screen *screen, const term_seq *seq) { unsigned int i; for (i = 0; i < seq->n_args; ++i) - screen_mode_change(screen, seq->args[i], false, false); + screen_mode_change_ansi(screen, seq->args[i], false); return 0; } @@ -2693,7 +2768,7 @@ static int screen_RM_DEC(term_screen *screen, const term_seq *seq) { unsigned int i; for (i = 0; i < seq->n_args; ++i) - screen_mode_change(screen, seq->args[i], true, false); + screen_mode_change_dec(screen, seq->args[i], false); return 0; } @@ -2973,7 +3048,7 @@ static int screen_SM_ANSI(term_screen *screen, const term_seq *seq) { unsigned int i; for (i = 0; i < seq->n_args; ++i) - screen_mode_change(screen, seq->args[i], false, true); + screen_mode_change_ansi(screen, seq->args[i], true); return 0; } @@ -2987,7 +3062,7 @@ static int screen_SM_DEC(term_screen *screen, const term_seq *seq) { unsigned int i; for (i = 0; i < seq->n_args; ++i) - screen_mode_change(screen, seq->args[i], true, true); + screen_mode_change_dec(screen, seq->args[i], true); return 0; } @@ -4047,7 +4122,7 @@ int term_screen_feed_keyboard(term_screen *screen, unsigned int mods) { _cleanup_free_ char *dyn = NULL; static const size_t padding = 1; - char buf[128], *start, *p = buf; + char buf[128], *start, *p; assert_return(screen, -EINVAL); @@ -4143,6 +4218,7 @@ void term_screen_soft_reset(term_screen *screen) { screen->saved = screen->state; screen->saved.cursor_x = 0; screen->saved.cursor_y = 0; + screen->saved_alt = screen->saved; screen->page = screen->page_main; screen->history = screen->history_main;