X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/1d3989edde7cc7e838749d9faff2d283a7520754..8f9b6a1a1ab2eb675175662cf05204d4e86cb1e5:/terminal.c diff --git a/terminal.c b/terminal.c index de6a2e93..27856896 100644 --- a/terminal.c +++ b/terminal.c @@ -205,7 +205,7 @@ static int paste_len, paste_pos, paste_hold; */ static void do_paint(Context, int); static void erase_lots(int, int, int); -static void swap_screen(int); +static void swap_screen(int, int, int); static void update_sbar(void); static void deselect(void); static void term_print_finish(void); @@ -312,9 +312,9 @@ static void power_on(void) wordness[i] = cfg.wordness[i]; } if (screen) { - swap_screen(1); + swap_screen(1, FALSE, FALSE); erase_lots(FALSE, TRUE, TRUE); - swap_screen(0); + swap_screen(0, FALSE, FALSE); erase_lots(FALSE, TRUE, TRUE); } } @@ -328,10 +328,9 @@ void term_update(void) ctx = get_ctx(); if (ctx) { int need_sbar_update = seen_disp_event; - if ((seen_key_event && (cfg.scroll_on_key)) || - (seen_disp_event && (cfg.scroll_on_disp))) { + if (seen_disp_event && cfg.scroll_on_disp) { disptop = 0; /* return to main screen */ - seen_disp_event = seen_key_event = 0; + seen_disp_event = 0; need_sbar_update = TRUE; } if (need_sbar_update) @@ -343,6 +342,37 @@ void term_update(void) } /* + * Called from front end when a keypress occurs, to trigger + * anything magical that needs to happen in that situation. + */ +void term_seen_key_event(void) +{ + /* + * On any keypress, clear the bell overload mechanism + * completely, on the grounds that large numbers of + * beeps coming from deliberate key action are likely + * to be intended (e.g. beeps from filename completion + * blocking repeatedly). + */ + beep_overloaded = FALSE; + while (beephead) { + struct beeptime *tmp = beephead; + beephead = tmp->next; + sfree(tmp); + } + beeptail = NULL; + nbeeps = 0; + + /* + * Reset the scrollback on keypress, if we're doing that. + */ + if (cfg.scroll_on_key) { + disptop = 0; /* return to main screen */ + seen_disp_event = 1; + } +} + +/* * Same as power_on(), but an external function. */ void term_pwron(void) @@ -363,7 +393,7 @@ void term_pwron(void) void term_reconfig(void) { if (cfg.no_alt_screen) - swap_screen(0); + swap_screen(0, FALSE, FALSE); if (cfg.no_mouse_rep) { xterm_mouse = 0; set_raw_mouse_mode(0); @@ -424,7 +454,7 @@ void term_size(int newrows, int newcols, int newsavelines) return; /* nothing to do */ deselect(); - swap_screen(0); + swap_screen(0, FALSE, FALSE); alt_t = marg_t = 0; alt_b = marg_b = newrows - 1; @@ -527,7 +557,7 @@ void term_size(int newrows, int newcols, int newsavelines) savelines = newsavelines; fix_cpos; - swap_screen(save_alt_which); + swap_screen(save_alt_which, FALSE, FALSE); update_sbar(); term_update(); @@ -535,56 +565,76 @@ void term_size(int newrows, int newcols, int newsavelines) } /* - * Swap screens. + * Swap screens. If `reset' is TRUE and we have been asked to + * switch to the alternate screen, we must bring most of its + * configuration from the main screen and erase the contents of the + * alternate screen completely. (This is even true if we're already + * on it! Blame xterm.) */ -static void swap_screen(int which) +static void swap_screen(int which, int reset, int keep_cur_pos) { int t; tree234 *ttr; - if (which == alt_which) - return; + if (!which) + reset = FALSE; /* do no weird resetting if which==0 */ + + if (which != alt_which) { + alt_which = which; + + ttr = alt_screen; + alt_screen = screen; + screen = ttr; + t = curs.x; + if (!reset && !keep_cur_pos) + curs.x = alt_x; + alt_x = t; + t = curs.y; + if (!reset && !keep_cur_pos) + curs.y = alt_y; + alt_y = t; + t = marg_t; + if (!reset) marg_t = alt_t; + alt_t = t; + t = marg_b; + if (!reset) marg_b = alt_b; + alt_b = t; + t = dec_om; + if (!reset) dec_om = alt_om; + alt_om = t; + t = wrap; + if (!reset) wrap = alt_wrap; + alt_wrap = t; + t = wrapnext; + if (!reset) wrapnext = alt_wnext; + alt_wnext = t; + t = insert; + if (!reset) insert = alt_ins; + alt_ins = t; + t = cset; + if (!reset) cset = alt_cset; + alt_cset = t; + t = utf; + if (!reset) utf = alt_utf; + alt_utf = t; + t = sco_acs; + if (!reset) sco_acs = alt_sco_acs; + alt_sco_acs = t; + } - alt_which = which; - - ttr = alt_screen; - alt_screen = screen; - screen = ttr; - t = curs.x; - curs.x = alt_x; - alt_x = t; - t = curs.y; - curs.y = alt_y; - alt_y = t; - t = marg_t; - marg_t = alt_t; - alt_t = t; - t = marg_b; - marg_b = alt_b; - alt_b = t; - t = dec_om; - dec_om = alt_om; - alt_om = t; - t = wrap; - wrap = alt_wrap; - alt_wrap = t; - t = wrapnext; - wrapnext = alt_wnext; - alt_wnext = t; - t = insert; - insert = alt_ins; - alt_ins = t; - t = cset; - cset = alt_cset; - alt_cset = t; - t = utf; - utf = alt_utf; - alt_utf = t; - t = sco_acs; - sco_acs = alt_sco_acs; - alt_sco_acs = t; + if (reset && screen) { + /* + * Yes, this _is_ supposed to honour background-colour-erase. + */ + erase_lots(FALSE, TRUE, TRUE); + } - fix_cpos; + /* + * This might not be possible if we're called during + * initialisation. + */ + if (screen) + fix_cpos; } /* @@ -958,7 +1008,7 @@ static void toggle_mode(int mode, int query, int state) case 47: /* alternate screen */ compatibility(OTHER); deselect(); - swap_screen(cfg.no_alt_screen ? 0 : state); + swap_screen(cfg.no_alt_screen ? 0 : state, FALSE, FALSE); disptop = 0; break; case 1000: /* xterm mouse 1 */ @@ -969,6 +1019,27 @@ static void toggle_mode(int mode, int query, int state) xterm_mouse = state ? 2 : 0; set_raw_mouse_mode(state); break; + case 1047: /* alternate screen */ + compatibility(OTHER); + deselect(); + swap_screen(cfg.no_alt_screen ? 0 : state, TRUE, TRUE); + disptop = 0; + break; + case 1048: /* save/restore cursor */ + save_cursor(state); + if (!state) seen_disp_event = TRUE; + break; + case 1049: /* cursor & alternate screen */ + if (state) + save_cursor(state); + if (!state) seen_disp_event = TRUE; + compatibility(OTHER); + deselect(); + swap_screen(cfg.no_alt_screen ? 0 : state, TRUE, FALSE); + if (!state) + save_cursor(state); + disptop = 0; + break; } else switch (mode) { case 4: /* set insert mode */ @@ -1133,7 +1204,6 @@ void term_out(void) else print_state = 0; if (print_state == 4) { - printing = only_printing = FALSE; term_print_finish(); } continue; @@ -1915,8 +1985,6 @@ void term_out(void) print_state = 0; term_print_setup(); } else if (esc_args[0] == 4 && printing) { - printing = FALSE; - only_printing = FALSE; term_print_finish(); } } @@ -3453,9 +3521,11 @@ void term_do_paste(void) int len; get_clip(&data, &len); - if (data) { + if (data && len > 0) { wchar_t *p, *q; + term_seen_key_event(); /* pasted data counts */ + if (paste_buffer) sfree(paste_buffer); paste_pos = paste_hold = paste_len = 0;