From cabfd08c97213abe46f996a93407f8209fc38b94 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 30 Nov 1999 10:52:07 +0000 Subject: [PATCH] Robert de Bath's multi-purpose patch, slightly modified. - ^E answerback is now `PuTTY'. - The framework is now in place for the scrollback to reset to bottom on display _or_ keyboard events _or_ both. An actual configurable option isn't yet present, but most of the code is in place. - Try to deal with the problems where incoming data gets dropped after decoding but before display. - Scrollback behaviour has changed: instead of keying it off `scroll' versus `delete top line', things now go into the scrollback from _either_ of those but only if the primary screen is selected. Should fix problems with `less' and talkers. - must_update variable has gone because rdb correctly observed that it didn't seem to be doing a great deal :-) git-svn-id: svn://svn.tartarus.org/sgt/putty@328 cda61777-01e9-0310-a592-d414129be87e --- putty.h | 9 +++ raw.c | 3 + ssh.c | 3 + telnet.c | 3 + terminal.c | 196 ++++++++++++++++++++++++++----------------------------------- window.c | 13 ++++ 6 files changed, 115 insertions(+), 112 deletions(-) diff --git a/putty.h b/putty.h index 273a8118..477a81e4 100644 --- a/putty.h +++ b/putty.h @@ -62,6 +62,15 @@ GLOBAL int has_focus; GLOBAL int app_cursor_keys, app_keypad_keys; +GLOBAL int seen_key_event; +GLOBAL int seen_disp_event; + +typedef enum { + US_NONE = 0, US_KEY = 1, US_DISP = 2, US_BOTH = 3 +} Unscroll_Trigger; + +GLOBAL Unscroll_trigger unscroll_event; + #define WM_NETEVENT (WM_USER + 1) typedef enum { diff --git a/raw.c b/raw.c index 05e453aa..31c1746a 100644 --- a/raw.c +++ b/raw.c @@ -56,6 +56,9 @@ static void c_write (char *buf, int len) { if (new_head != inbuf_reap) { inbuf[inbuf_head] = *buf++; inbuf_head = new_head; + } else { + term_out(); + if( inbuf_head == inbuf_reap ) len++; else break; } } } diff --git a/ssh.c b/ssh.c index d3df6bcb..caf98ce0 100644 --- a/ssh.c +++ b/ssh.c @@ -101,6 +101,9 @@ static void c_write (char *buf, int len) { if (new_head != inbuf_reap) { inbuf[inbuf_head] = *buf++; inbuf_head = new_head; + } else { + term_out(); + if( inbuf_head == inbuf_reap ) len++; else break; } } } diff --git a/telnet.c b/telnet.c index 94bef162..24962bbd 100644 --- a/telnet.c +++ b/telnet.c @@ -174,6 +174,9 @@ static void c_write (char *buf, int len) { if (new_head != inbuf_reap) { inbuf[inbuf_head] = *buf++; inbuf_head = new_head; + } else { + term_out(); + if( inbuf_head == inbuf_reap ) len++; else break; } } } diff --git a/terminal.c b/terminal.c index 0218c098..ab6ffd00 100644 --- a/terminal.c +++ b/terminal.c @@ -1,3 +1,4 @@ +++ terminal.c.new Mon Nov 22 15:02:03 1999 #include #include @@ -60,9 +61,18 @@ static int nl_count; static int scroll_heuristic; static enum { - TOPLEVEL, IGNORE_NEXT, - SEEN_ESC, SEEN_CSI, SET_GL, SET_GR, - SEEN_OSC, SEEN_OSC_P, SEEN_OSC_W, OSC_STRING, OSC_MAYBE_ST, + TOPLEVEL, + SEEN_ESC, + SEEN_CSI, + SEEN_OSC, + SEEN_OSC_W, + + DO_CTRLS, + + IGNORE_NEXT, + SET_GL, SET_GR, + SEEN_OSC_P, + OSC_STRING, OSC_MAYBE_ST, SEEN_ESCHASH } termstate; @@ -141,6 +151,11 @@ void term_update(void) { Context ctx; ctx = get_ctx(); if (ctx) { + if ( (seen_key_event && (unscroll_event & US_KEY)) && + (seen_disp_event && (unscroll_event & US_DISP)) ) { + disptop = scrtop; + seen_disp_event = seen_key_event = 0; + } do_paint (ctx, TRUE); free_ctx (ctx); nl_count = 0; @@ -345,10 +360,10 @@ static void scroll (int topline, int botline, int lines, int sb) { size = (lines < 0 ? -lines : lines) * (cols+1); scroll_size = (botline - topline + 1) * (cols+1) - size; - if (lines > 0 && topline == 0 && botline == (rows-1) && sb) { + if (lines > 0 && topline == 0 && alt_which == 0 && sb) { /* - * Since we're going to scroll the whole screen upwards, - * let's also affect the scrollback buffer. + * Since we're going to scroll the top line and we're on the + * scrolling screen let's also affect the scrollback buffer. */ sbtop -= lines * (cols+1); if (sbtop < text) @@ -511,7 +526,7 @@ static void toggle_mode (int mode, int query, int state) { break; case 5: /* reverse video */ rvideo = state; - disptop = scrtop; + seen_disp_event = TRUE; break; case 6: /* DEC origin mode */ dec_om = state; @@ -562,7 +577,6 @@ static void do_osc(void) { */ void term_out(void) { int c; - int must_update = FALSE; while ( (c = inbuf_getc()) != -1) { #ifdef LOG @@ -572,17 +586,14 @@ void term_out(void) { if (fp) fputc (c, fp); } #endif - switch (termstate) { - case TOPLEVEL: - do_toplevel: + if( termstate < DO_CTRLS && (c&0x60) == 0 ) { switch (c) { case '\005': /* terminal type query */ - ldisc->send ("\033[?1;2c", 7); + ldisc->send ("PuTTY\r", 6); break; case '\007': beep(); disptop = scrtop; - must_update = TRUE; break; case '\b': if (curs_x == 0 && curs_y > 0) @@ -592,8 +603,7 @@ void term_out(void) { else curs_x--; fix_cpos; - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case '\016': cset = 1; @@ -618,8 +628,7 @@ void term_out(void) { curs_x = 0; wrapnext = FALSE; fix_cpos; - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case '\013': case '\014': @@ -628,11 +637,11 @@ void term_out(void) { scroll (marg_t, marg_b, 1, TRUE); else if (curs_y < rows-1) curs_y++; - if (cfg.lfhascr) - curs_x = 0; + if (cfg.lfhascr) + curs_x = 0; fix_cpos; wrapnext = FALSE; - disptop = scrtop; + seen_disp_event = 1; nl_count++; break; case '\t': @@ -646,37 +655,39 @@ void term_out(void) { fix_cpos; check_selection (old_cpos, cpos); } - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; - default: - if (c >= ' ' && c != 0234) { - if (wrapnext) { - cpos[1] = ATTR_WRAPPED; - if (curs_y == marg_b) - scroll (marg_t, marg_b, 1, TRUE); - else if (curs_y < rows-1) - curs_y++; - curs_x = 0; - fix_cpos; - wrapnext = FALSE; - nl_count++; - } - if (insert) - insch (1); - check_selection (cpos, cpos+1); - *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr | - (c <= 0x7F ? cset_attr[cset] : ATTR_ASCII); - curs_x++; - if (curs_x == cols) { - cpos--; - curs_x--; - wrapnext = wrap; - } - disptop = scrtop; + } + } + else switch (termstate) { + case TOPLEVEL: + if (c >= ' ' && c != 0234) { + if (wrapnext) { + cpos[1] = ATTR_WRAPPED; + if (curs_y == marg_b) + scroll (marg_t, marg_b, 1, TRUE); + else if (curs_y < rows-1) + curs_y++; + curs_x = 0; + fix_cpos; + wrapnext = FALSE; + nl_count++; + } + if (insert) + insch (1); + check_selection (cpos, cpos+1); + *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr | + (c <= 0x7F ? cset_attr[cset] : ATTR_ASCII); + curs_x++; + if (curs_x == cols) { + cpos--; + curs_x--; + wrapnext = wrap; } + seen_disp_event = 1; } break; + case IGNORE_NEXT: termstate = TOPLEVEL; break; @@ -695,11 +706,6 @@ void term_out(void) { case SEEN_ESC: termstate = TOPLEVEL; switch (c) { - case '\005': case '\007': case '\b': case '\016': case '\017': - case '\033': case 0233: case 0234: case 0235: case '\r': - case '\013': case '\014': case '\n': case '\t': - termstate = TOPLEVEL; - goto do_toplevel; /* hack... */ case ' ': /* some weird sequence? */ termstate = IGNORE_NEXT; break; @@ -724,8 +730,7 @@ void term_out(void) { break; case '8': /* restore cursor */ save_cursor (FALSE); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case '=': app_keypad_keys = TRUE; @@ -740,7 +745,7 @@ void term_out(void) { curs_y++; fix_cpos; wrapnext = FALSE; - disptop = scrtop; + seen_disp_event = TRUE; nl_count++; break; case 'E': /* exactly equivalent to CR-LF */ @@ -753,7 +758,7 @@ void term_out(void) { fix_cpos; wrapnext = FALSE; nl_count++; - disptop = scrtop; + seen_disp_event = TRUE; break; case 'M': /* reverse index - backwards LF */ if (curs_y == marg_t) @@ -762,8 +767,7 @@ void term_out(void) { curs_y--; fix_cpos; wrapnext = FALSE; - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'Z': /* terminal type query */ ldisc->send ("\033[?6c", 5); @@ -772,7 +776,7 @@ void term_out(void) { power_on(); fix_cpos; disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case '#': /* ESC # 8 fills screen with Es :-) */ termstate = SEEN_ESCHASH; @@ -785,11 +789,6 @@ void term_out(void) { case SEEN_CSI: termstate = TOPLEVEL; /* default */ switch (c) { - case '\005': case '\007': case '\b': case '\016': case '\017': - case '\033': case 0233: case 0234: case 0235: case '\r': - case '\013': case '\014': case '\n': case '\t': - termstate = TOPLEVEL; - goto do_toplevel; /* hack... */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (esc_nargs <= ARGS_MAX) { @@ -811,44 +810,36 @@ void term_out(void) { break; case 'A': /* move up N lines */ move (curs_x, curs_y - def(esc_args[0], 1), 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'B': case 'e': /* move down N lines */ move (curs_x, curs_y + def(esc_args[0], 1), 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'C': case 'a': /* move right N cols */ move (curs_x + def(esc_args[0], 1), curs_y, 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'D': /* move left N cols */ move (curs_x - def(esc_args[0], 1), curs_y, 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'E': /* move down N lines and CR */ move (0, curs_y + def(esc_args[0], 1), 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'F': /* move up N lines and CR */ move (0, curs_y - def(esc_args[0], 1), 1); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'G': case '`': /* set horizontal posn */ move (def(esc_args[0], 1) - 1, curs_y, 0); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'd': /* set vertical posn */ move (curs_x, (dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1, (dec_om ? 2 : 0)); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'H': case 'f': /* set horz and vert posns at once */ if (esc_nargs < 2) @@ -856,8 +847,7 @@ void term_out(void) { move (def(esc_args[1], 1) - 1, (dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1, (dec_om ? 2 : 0)); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'J': /* erase screen or parts of it */ { @@ -867,7 +857,7 @@ void term_out(void) { erase_lots(FALSE, !!(i & 2), !!(i & 1)); } disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'K': /* erase line or parts of it */ { @@ -876,30 +866,25 @@ void term_out(void) { i = 0; erase_lots(TRUE, !!(i & 2), !!(i & 1)); } - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'L': /* insert lines */ if (curs_y <= marg_b) scroll (curs_y, marg_b, -def(esc_args[0], 1), FALSE); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'M': /* delete lines */ if (curs_y <= marg_b) - scroll (curs_y, marg_b, def(esc_args[0], 1), FALSE); - disptop = scrtop; - must_update = TRUE; + scroll (curs_y, marg_b, def(esc_args[0], 1), TRUE); + seen_disp_event = TRUE; break; case '@': /* insert chars */ insch (def(esc_args[0], 1)); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'P': /* delete chars */ insch (-def(esc_args[0], 1)); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 'c': /* terminal type query */ ldisc->send ("\033[?6c", 5); @@ -950,8 +935,7 @@ void term_out(void) { */ curs_y = 0; fix_cpos; - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; } } break; @@ -1004,8 +988,7 @@ void term_out(void) { break; case 'u': /* restore cursor */ save_cursor (FALSE); - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; break; case 't': /* set page size - ie window height */ request_resize (cols, def(esc_args[0], 24)); @@ -1020,8 +1003,7 @@ void term_out(void) { check_selection (cpos, cpos+n); while (n--) *p++ = ERASE_CHAR; - disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; } break; case 'x': /* report terminal characteristics */ @@ -1055,11 +1037,6 @@ void term_out(void) { case SEEN_OSC: osc_w = FALSE; switch (c) { - case '\005': case '\007': case '\b': case '\016': case '\017': - case '\033': case 0233: case 0234: case 0235: case '\r': - case '\013': case '\014': case '\n': case '\t': - termstate = TOPLEVEL; - goto do_toplevel; /* hack... */ case 'P': /* Linux palette sequence */ termstate = SEEN_OSC_P; osc_strlen = 0; @@ -1133,11 +1110,6 @@ void term_out(void) { break; case SEEN_OSC_W: switch (c) { - case '\005': case '\007': case '\b': case '\016': case '\017': - case '\033': case 0233: case 0234: case 0235: case '\r': - case '\013': case '\014': case '\n': case '\t': - termstate = TOPLEVEL; - goto do_toplevel; /* hack... */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': esc_args[0] = 10 * esc_args[0] + c - '0'; @@ -1154,7 +1126,7 @@ void term_out(void) { while (n--) *p++ = ATTR_DEFAULT | 'E'; disptop = scrtop; - must_update = TRUE; + seen_disp_event = TRUE; check_selection (scrtop, scrtop + rows * (cols+1)); } termstate = TOPLEVEL; @@ -1163,7 +1135,7 @@ void term_out(void) { check_selection (cpos, cpos+1); } - if (must_update || nl_count > MAXNL) + if (nl_count > MAXNL) term_update(); } diff --git a/window.c b/window.c index c7c652bb..fd46be4c 100644 --- a/window.c +++ b/window.c @@ -310,6 +310,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { inbuf_reap = inbuf_head = 0; outbuf_reap = outbuf_head = 0; + /* + * Choose unscroll method + */ + unscroll_event = US_DISP; + /* * Prepare the mouse handler. */ @@ -1225,6 +1230,14 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) { ret = GetKeyboardState(keystate); /* + * Record that we pressed key so the scroll window can be reset, but + * be careful to avoid Shift-UP/Down + */ + if( wParam != VK_SHIFT && wParam != VK_PRIOR && wParam != VK_NEXT ) { + seen_key_event = 1; + } + + /* * Windows does not always want to distinguish left and right * Alt or Control keys. Thus we keep track of them ourselves. * See also the WM_KEYUP handler. -- 2.11.0