From: simon Date: Thu, 6 Mar 2003 12:51:12 +0000 (+0000) Subject: Richard B's patch to push erased text into the scrollback on ESC[2J X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/commitdiff_plain/876e5d5e627d117190851e41c0fb3d2d08cac70d Richard B's patch to push erased text into the scrollback on ESC[2J clears, and also to temporarily push the primary screen contents into the scrollback while the alternate screen is active and bring it back afterwards. git-svn-id: svn://svn.tartarus.org/sgt/putty@2910 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/config.c b/config.c index ebcd6077..922bfa14 100644 --- a/config.c +++ b/config.c @@ -980,6 +980,10 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist, ctrl_checkbox(s, "Reset scrollback on display activity", 'p', HELPCTX(window_scrollback), dlg_stdcheckbox_handler, I(offsetof(Config,scroll_on_disp))); + ctrl_checkbox(s, "Push erased text into scrollback", 'e', + HELPCTX(window_erased), + dlg_stdcheckbox_handler, + I(offsetof(Config,erase_to_scrollback))); /* * The Window/Appearance panel. diff --git a/doc/config.but b/doc/config.but index 4bf4c251..18af04cf 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1,4 +1,4 @@ -\versionid $Id: config.but,v 1.57 2003/03/05 22:07:40 simon Exp $ +\versionid $Id: config.but,v 1.58 2003/03/06 12:51:12 simon Exp $ \C{config} Configuring PuTTY @@ -856,6 +856,22 @@ terminal contents. You can disable this behaviour by turning off screen revert when you press a key, by turning on \q{Reset scrollback on keypress}. +\S{config-scrollback} \q{Push erased text into scrollback} + +\cfg{winhelp-topic}{window.erased} + +When this option is enabled, the contents of the terminal screen +will be pushed into the scrollback when a server-side application +clears the screen, so that your scrollback will contain a better +record of what was on your screen in the past. + +If the application switches to the alternate screen (see +\k{config-features-altscreen} for more about this), then the +contents of the primary screen will be visible in the scrollback +until the application switches back again. + +This option is enabled by default. + \H{config-appearance} The Appearance panel The Appearance configuration panel allows you to control aspects of diff --git a/putty.h b/putty.h index 256c61b2..5490a723 100644 --- a/putty.h +++ b/putty.h @@ -380,6 +380,7 @@ struct config_tag { int fullscreenonaltenter; int scroll_on_key; int scroll_on_disp; + int erase_to_scrollback; int compose_key; int ctrlaltkeys; char wintitle[256]; /* initial window title */ diff --git a/settings.c b/settings.c index 790b9334..c6700a03 100644 --- a/settings.c +++ b/settings.c @@ -309,6 +309,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg) write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen); write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key); write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp); + write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback); write_setting_i(sesskey, "LockSize", cfg->resize_action); write_setting_i(sesskey, "BCE", cfg->bce); write_setting_i(sesskey, "BlinkText", cfg->blinktext); @@ -572,6 +573,7 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg) gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen); gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key); gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp); + gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback); gppi(sesskey, "LockSize", 0, &cfg->resize_action); gppi(sesskey, "BCE", 1, &cfg->bce); gppi(sesskey, "BlinkText", 0, &cfg->blinktext); diff --git a/terminal.c b/terminal.c index f3b2c8a3..4d0fdd04 100644 --- a/terminal.c +++ b/terminal.c @@ -110,6 +110,19 @@ static unsigned long *resizeline(unsigned long *line, int cols) } /* + * Get the number of lines in the scrollback. + */ +static int sblines(Terminal *term) +{ + int sblines = count234(term->scrollback); + if (term->cfg.erase_to_scrollback && + term->alt_which && term->alt_screen) { + sblines += term->alt_sblines; + } + return sblines; +} + +/* * Retrieve a line of the screen or of the scrollback, according to * whether the y coordinate is non-negative or negative * (respectively). @@ -124,8 +137,19 @@ static unsigned long *lineptr(Terminal *term, int y, int lineno) whichtree = term->screen; treeindex = y; } else { - whichtree = term->scrollback; - treeindex = y + count234(term->scrollback); + int altlines = 0; + if (term->cfg.erase_to_scrollback && + term->alt_which && term->alt_screen) { + altlines = term->alt_sblines; + } + if (y < -altlines) { + whichtree = term->scrollback; + treeindex = y + altlines + count234(term->scrollback); + } else { + whichtree = term->alt_screen; + treeindex = y + term->alt_sblines; + /* treeindex = y + count234(term->alt_screen); */ + } } line = index234(whichtree, treeindex); @@ -331,6 +355,7 @@ void term_clrsb(Terminal *term) while ((line = delpos234(term->scrollback, 0)) != NULL) { sfree(line); } + term->alt_sblines = 0; update_sbar(term); } @@ -374,6 +399,7 @@ Terminal *term_init(Config *mycfg, struct unicode_data *ucsdata, term->curstype = 0; term->screen = term->alt_screen = term->scrollback = NULL; + term->alt_sblines = 0; term->disptop = 0; term->disptext = term->dispcurs = NULL; term->tabs = NULL; @@ -519,6 +545,7 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines) freetree234(term->alt_screen); } term->alt_screen = newalt; + term->alt_sblines = 0; term->tabs = srealloc(term->tabs, newcols * sizeof(*term->tabs)); { @@ -565,6 +592,25 @@ void term_provide_resize_fn(Terminal *term, resize_fn(resize_ctx, term->cols, term->rows); } +/* Find the bottom line on the screen that has any content. + * If only the top line has content, returns 0. + * If no lines have content, return -1. + */ +static int find_last_nonempty_line(Terminal * term, tree234 * screen) +{ + int i; + for (i = count234(screen) - 1; i >= 0; i--) { + unsigned long *line = index234(screen, i); + int j; + int cols = line[0]; + for (j = 0; j < cols; j++) { + if (line[j + 1] != term->erase_char) break; + } + if (j != cols) break; + } + return i; +} + /* * Swap screens. If `reset' is TRUE and we have been asked to * switch to the alternate screen, we must bring most of its @@ -586,6 +632,7 @@ static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos) ttr = term->alt_screen; term->alt_screen = term->screen; term->screen = ttr; + term->alt_sblines = find_last_nonempty_line(term, term->alt_screen) + 1; t = term->curs.x; if (!reset && !keep_cur_pos) term->curs.x = term->alt_x; @@ -643,10 +690,7 @@ static void swap_screen(Terminal *term, int which, int reset, int keep_cur_pos) */ static void update_sbar(Terminal *term) { - int nscroll; - - nscroll = count234(term->scrollback); - + int nscroll = sblines(term); set_sbar(term->frontend, nscroll + term->rows, nscroll + term->disptop, term->rows); } @@ -711,7 +755,7 @@ static void scroll(Terminal *term, int topline, int botline, int lines, int sb) while (lines > 0) { line = delpos234(term->screen, topline); if (sb && term->savelines > 0) { - int sblen = count234(term->scrollback); + int sblen = sblines(term); /* * We must add this line to the scrollback. We'll * remove a line from the top of the scrollback to @@ -974,7 +1018,6 @@ static void erase_lots(Terminal *term, { pos start, end; int erase_lattr; - unsigned long *ldata; if (line_only) { start.y = term->curs.y; @@ -1004,18 +1047,33 @@ static void erase_lots(Terminal *term, if (start.y == 0 && start.x == 0 && end.y == term->rows) term_invalidate(term); - ldata = lineptr(start.y); - while (poslt(start, end)) { - if (start.x == term->cols) { - if (!erase_lattr) - ldata[start.x] &= ~(LATTR_WRAPPED | LATTR_WRAPPED2); - else - ldata[start.x] = LATTR_NORM; - } else { - ldata[start.x] = term->erase_char; - } - if (incpos(start) && start.y < term->rows) - ldata = lineptr(start.y); + if (term->cfg.erase_to_scrollback && + start.y == 0 && start.x == 0 && end.x == 0 && erase_lattr) { + /* If it's a whole number of lines, starting at the top, and + * we're fully erasing them, erase by scrolling and keep the + * lines in the scrollback. */ + int scrolllines = end.y; + if (end.y == term->rows) { + /* Shrink until we find a non-empty row.*/ + scrolllines = find_last_nonempty_line(term, term->screen) + 1; + } + if (scrolllines > 0) + scroll(term, 0, scrolllines - 1, scrolllines, TRUE); + fix_cpos; + } else { + unsigned long *ldata = lineptr(start.y); + while (poslt(start, end)) { + if (start.x == term->cols) { + if (!erase_lattr) + ldata[start.x] &= ~(LATTR_WRAPPED | LATTR_WRAPPED2); + else + ldata[start.x] = LATTR_NORM; + } else { + ldata[start.x] = term->erase_char; + } + if (incpos(start) && start.y < term->rows) + ldata = lineptr(start.y); + } } } @@ -3428,7 +3486,7 @@ void term_paint(Terminal *term, Context ctx, */ void term_scroll(Terminal *term, int rel, int where) { - int sbtop = -count234(term->scrollback); + int sbtop = -sblines(term); #ifdef OPTIMISE_SCROLL int olddisptop = term->disptop; int shift; @@ -3605,7 +3663,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect) void term_copyall(Terminal *term) { pos top; - top.y = -count234(term->scrollback); + top.y = -sblines(term); top.x = 0; clipme(term, top, term->curs, 0); } @@ -3732,7 +3790,7 @@ static pos sel_spread_half(Terminal *term, pos p, int dir) { unsigned long *ldata; short wvalue; - int topy = -count234(term->scrollback); + int topy = -sblines(term); ldata = lineptr(p.y); diff --git a/terminal.h b/terminal.h index 28f06c0c..d969ecc9 100644 --- a/terminal.h +++ b/terminal.h @@ -118,6 +118,7 @@ struct terminal_tag { int alt_cset, alt_sco_acs, alt_utf; int alt_t, alt_b; int alt_which; + int alt_sblines; /* # of lines on alternate screen that should be used for scrollback. */ #define ARGS_MAX 32 /* max # of esc sequence arguments */ #define ARG_DEFAULT 0 /* if an arg isn't specified */ diff --git a/winhelp.h b/winhelp.h index 04e1214b..d17db6b4 100644 --- a/winhelp.h +++ b/winhelp.h @@ -43,6 +43,7 @@ #define WINHELP_CTX_window_size "window.size" #define WINHELP_CTX_window_resize "window.resize" #define WINHELP_CTX_window_scrollback "window.scrollback" +#define WINHELP_CTX_window_erased "window.erased" #define WINHELP_CTX_behaviour_closewarn "behaviour.closewarn" #define WINHELP_CTX_behaviour_altf4 "behaviour.altf4" #define WINHELP_CTX_behaviour_altspace "behaviour.altspace"