1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-22 06:38:37 -05:00

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 :-)

[originally from svn r328]
This commit is contained in:
Simon Tatham 1999-11-30 10:52:07 +00:00
parent 8446532e4a
commit a8d5838ebc
6 changed files with 115 additions and 112 deletions

View File

@ -62,6 +62,15 @@ GLOBAL int has_focus;
GLOBAL int app_cursor_keys, app_keypad_keys; 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) #define WM_NETEVENT (WM_USER + 1)
typedef enum { typedef enum {

3
raw.c
View File

@ -56,6 +56,9 @@ static void c_write (char *buf, int len) {
if (new_head != inbuf_reap) { if (new_head != inbuf_reap) {
inbuf[inbuf_head] = *buf++; inbuf[inbuf_head] = *buf++;
inbuf_head = new_head; inbuf_head = new_head;
} else {
term_out();
if( inbuf_head == inbuf_reap ) len++; else break;
} }
} }
} }

3
ssh.c
View File

@ -101,6 +101,9 @@ static void c_write (char *buf, int len) {
if (new_head != inbuf_reap) { if (new_head != inbuf_reap) {
inbuf[inbuf_head] = *buf++; inbuf[inbuf_head] = *buf++;
inbuf_head = new_head; inbuf_head = new_head;
} else {
term_out();
if( inbuf_head == inbuf_reap ) len++; else break;
} }
} }
} }

View File

@ -174,6 +174,9 @@ static void c_write (char *buf, int len) {
if (new_head != inbuf_reap) { if (new_head != inbuf_reap) {
inbuf[inbuf_head] = *buf++; inbuf[inbuf_head] = *buf++;
inbuf_head = new_head; inbuf_head = new_head;
} else {
term_out();
if( inbuf_head == inbuf_reap ) len++; else break;
} }
} }
} }

View File

@ -1,3 +1,4 @@
++ terminal.c.new Mon Nov 22 15:02:03 1999
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
@ -60,9 +61,18 @@ static int nl_count;
static int scroll_heuristic; static int scroll_heuristic;
static enum { static enum {
TOPLEVEL, IGNORE_NEXT, TOPLEVEL,
SEEN_ESC, SEEN_CSI, SET_GL, SET_GR, SEEN_ESC,
SEEN_OSC, SEEN_OSC_P, SEEN_OSC_W, OSC_STRING, OSC_MAYBE_ST, 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 SEEN_ESCHASH
} termstate; } termstate;
@ -141,6 +151,11 @@ void term_update(void) {
Context ctx; Context ctx;
ctx = get_ctx(); ctx = get_ctx();
if (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); do_paint (ctx, TRUE);
free_ctx (ctx); free_ctx (ctx);
nl_count = 0; 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); size = (lines < 0 ? -lines : lines) * (cols+1);
scroll_size = (botline - topline + 1) * (cols+1) - size; 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, * Since we're going to scroll the top line and we're on the
* let's also affect the scrollback buffer. * scrolling screen let's also affect the scrollback buffer.
*/ */
sbtop -= lines * (cols+1); sbtop -= lines * (cols+1);
if (sbtop < text) if (sbtop < text)
@ -511,7 +526,7 @@ static void toggle_mode (int mode, int query, int state) {
break; break;
case 5: /* reverse video */ case 5: /* reverse video */
rvideo = state; rvideo = state;
disptop = scrtop; seen_disp_event = TRUE;
break; break;
case 6: /* DEC origin mode */ case 6: /* DEC origin mode */
dec_om = state; dec_om = state;
@ -562,7 +577,6 @@ static void do_osc(void) {
*/ */
void term_out(void) { void term_out(void) {
int c; int c;
int must_update = FALSE;
while ( (c = inbuf_getc()) != -1) { while ( (c = inbuf_getc()) != -1) {
#ifdef LOG #ifdef LOG
@ -572,17 +586,14 @@ void term_out(void) {
if (fp) fputc (c, fp); if (fp) fputc (c, fp);
} }
#endif #endif
switch (termstate) { if( termstate < DO_CTRLS && (c&0x60) == 0 ) {
case TOPLEVEL:
do_toplevel:
switch (c) { switch (c) {
case '\005': /* terminal type query */ case '\005': /* terminal type query */
ldisc->send ("\033[?1;2c", 7); ldisc->send ("PuTTY\r", 6);
break; break;
case '\007': case '\007':
beep(); beep();
disptop = scrtop; disptop = scrtop;
must_update = TRUE;
break; break;
case '\b': case '\b':
if (curs_x == 0 && curs_y > 0) if (curs_x == 0 && curs_y > 0)
@ -592,8 +603,7 @@ void term_out(void) {
else else
curs_x--; curs_x--;
fix_cpos; fix_cpos;
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case '\016': case '\016':
cset = 1; cset = 1;
@ -618,8 +628,7 @@ void term_out(void) {
curs_x = 0; curs_x = 0;
wrapnext = FALSE; wrapnext = FALSE;
fix_cpos; fix_cpos;
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case '\013': case '\013':
case '\014': case '\014':
@ -628,11 +637,11 @@ void term_out(void) {
scroll (marg_t, marg_b, 1, TRUE); scroll (marg_t, marg_b, 1, TRUE);
else if (curs_y < rows-1) else if (curs_y < rows-1)
curs_y++; curs_y++;
if (cfg.lfhascr) if (cfg.lfhascr)
curs_x = 0; curs_x = 0;
fix_cpos; fix_cpos;
wrapnext = FALSE; wrapnext = FALSE;
disptop = scrtop; seen_disp_event = 1;
nl_count++; nl_count++;
break; break;
case '\t': case '\t':
@ -646,37 +655,39 @@ void term_out(void) {
fix_cpos; fix_cpos;
check_selection (old_cpos, cpos); check_selection (old_cpos, cpos);
} }
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
default: }
if (c >= ' ' && c != 0234) { }
if (wrapnext) { else switch (termstate) {
cpos[1] = ATTR_WRAPPED; case TOPLEVEL:
if (curs_y == marg_b) if (c >= ' ' && c != 0234) {
scroll (marg_t, marg_b, 1, TRUE); if (wrapnext) {
else if (curs_y < rows-1) cpos[1] = ATTR_WRAPPED;
curs_y++; if (curs_y == marg_b)
curs_x = 0; scroll (marg_t, marg_b, 1, TRUE);
fix_cpos; else if (curs_y < rows-1)
wrapnext = FALSE; curs_y++;
nl_count++; curs_x = 0;
} fix_cpos;
if (insert) wrapnext = FALSE;
insch (1); nl_count++;
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;
} }
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; break;
case IGNORE_NEXT: case IGNORE_NEXT:
termstate = TOPLEVEL; termstate = TOPLEVEL;
break; break;
@ -695,11 +706,6 @@ void term_out(void) {
case SEEN_ESC: case SEEN_ESC:
termstate = TOPLEVEL; termstate = TOPLEVEL;
switch (c) { 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? */ case ' ': /* some weird sequence? */
termstate = IGNORE_NEXT; termstate = IGNORE_NEXT;
break; break;
@ -724,8 +730,7 @@ void term_out(void) {
break; break;
case '8': /* restore cursor */ case '8': /* restore cursor */
save_cursor (FALSE); save_cursor (FALSE);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case '=': case '=':
app_keypad_keys = TRUE; app_keypad_keys = TRUE;
@ -740,7 +745,7 @@ void term_out(void) {
curs_y++; curs_y++;
fix_cpos; fix_cpos;
wrapnext = FALSE; wrapnext = FALSE;
disptop = scrtop; seen_disp_event = TRUE;
nl_count++; nl_count++;
break; break;
case 'E': /* exactly equivalent to CR-LF */ case 'E': /* exactly equivalent to CR-LF */
@ -753,7 +758,7 @@ void term_out(void) {
fix_cpos; fix_cpos;
wrapnext = FALSE; wrapnext = FALSE;
nl_count++; nl_count++;
disptop = scrtop; seen_disp_event = TRUE;
break; break;
case 'M': /* reverse index - backwards LF */ case 'M': /* reverse index - backwards LF */
if (curs_y == marg_t) if (curs_y == marg_t)
@ -762,8 +767,7 @@ void term_out(void) {
curs_y--; curs_y--;
fix_cpos; fix_cpos;
wrapnext = FALSE; wrapnext = FALSE;
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'Z': /* terminal type query */ case 'Z': /* terminal type query */
ldisc->send ("\033[?6c", 5); ldisc->send ("\033[?6c", 5);
@ -772,7 +776,7 @@ void term_out(void) {
power_on(); power_on();
fix_cpos; fix_cpos;
disptop = scrtop; disptop = scrtop;
must_update = TRUE; seen_disp_event = TRUE;
break; break;
case '#': /* ESC # 8 fills screen with Es :-) */ case '#': /* ESC # 8 fills screen with Es :-) */
termstate = SEEN_ESCHASH; termstate = SEEN_ESCHASH;
@ -785,11 +789,6 @@ void term_out(void) {
case SEEN_CSI: case SEEN_CSI:
termstate = TOPLEVEL; /* default */ termstate = TOPLEVEL; /* default */
switch (c) { 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 '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
if (esc_nargs <= ARGS_MAX) { if (esc_nargs <= ARGS_MAX) {
@ -811,44 +810,36 @@ void term_out(void) {
break; break;
case 'A': /* move up N lines */ case 'A': /* move up N lines */
move (curs_x, curs_y - def(esc_args[0], 1), 1); move (curs_x, curs_y - def(esc_args[0], 1), 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'B': case 'e': /* move down N lines */ case 'B': case 'e': /* move down N lines */
move (curs_x, curs_y + def(esc_args[0], 1), 1); move (curs_x, curs_y + def(esc_args[0], 1), 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'C': case 'a': /* move right N cols */ case 'C': case 'a': /* move right N cols */
move (curs_x + def(esc_args[0], 1), curs_y, 1); move (curs_x + def(esc_args[0], 1), curs_y, 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'D': /* move left N cols */ case 'D': /* move left N cols */
move (curs_x - def(esc_args[0], 1), curs_y, 1); move (curs_x - def(esc_args[0], 1), curs_y, 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'E': /* move down N lines and CR */ case 'E': /* move down N lines and CR */
move (0, curs_y + def(esc_args[0], 1), 1); move (0, curs_y + def(esc_args[0], 1), 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'F': /* move up N lines and CR */ case 'F': /* move up N lines and CR */
move (0, curs_y - def(esc_args[0], 1), 1); move (0, curs_y - def(esc_args[0], 1), 1);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'G': case '`': /* set horizontal posn */ case 'G': case '`': /* set horizontal posn */
move (def(esc_args[0], 1) - 1, curs_y, 0); move (def(esc_args[0], 1) - 1, curs_y, 0);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'd': /* set vertical posn */ case 'd': /* set vertical posn */
move (curs_x, (dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1, move (curs_x, (dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1,
(dec_om ? 2 : 0)); (dec_om ? 2 : 0));
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'H': case 'f': /* set horz and vert posns at once */ case 'H': case 'f': /* set horz and vert posns at once */
if (esc_nargs < 2) if (esc_nargs < 2)
@ -856,8 +847,7 @@ void term_out(void) {
move (def(esc_args[1], 1) - 1, move (def(esc_args[1], 1) - 1,
(dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1, (dec_om ? marg_t : 0) + def(esc_args[0], 1) - 1,
(dec_om ? 2 : 0)); (dec_om ? 2 : 0));
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'J': /* erase screen or parts of it */ case 'J': /* erase screen or parts of it */
{ {
@ -867,7 +857,7 @@ void term_out(void) {
erase_lots(FALSE, !!(i & 2), !!(i & 1)); erase_lots(FALSE, !!(i & 2), !!(i & 1));
} }
disptop = scrtop; disptop = scrtop;
must_update = TRUE; seen_disp_event = TRUE;
break; break;
case 'K': /* erase line or parts of it */ case 'K': /* erase line or parts of it */
{ {
@ -876,30 +866,25 @@ void term_out(void) {
i = 0; i = 0;
erase_lots(TRUE, !!(i & 2), !!(i & 1)); erase_lots(TRUE, !!(i & 2), !!(i & 1));
} }
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'L': /* insert lines */ case 'L': /* insert lines */
if (curs_y <= marg_b) if (curs_y <= marg_b)
scroll (curs_y, marg_b, -def(esc_args[0], 1), FALSE); scroll (curs_y, marg_b, -def(esc_args[0], 1), FALSE);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'M': /* delete lines */ case 'M': /* delete lines */
if (curs_y <= marg_b) if (curs_y <= marg_b)
scroll (curs_y, marg_b, def(esc_args[0], 1), FALSE); scroll (curs_y, marg_b, def(esc_args[0], 1), TRUE);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case '@': /* insert chars */ case '@': /* insert chars */
insch (def(esc_args[0], 1)); insch (def(esc_args[0], 1));
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'P': /* delete chars */ case 'P': /* delete chars */
insch (-def(esc_args[0], 1)); insch (-def(esc_args[0], 1));
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 'c': /* terminal type query */ case 'c': /* terminal type query */
ldisc->send ("\033[?6c", 5); ldisc->send ("\033[?6c", 5);
@ -950,8 +935,7 @@ void term_out(void) {
*/ */
curs_y = 0; curs_y = 0;
fix_cpos; fix_cpos;
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
} }
} }
break; break;
@ -1004,8 +988,7 @@ void term_out(void) {
break; break;
case 'u': /* restore cursor */ case 'u': /* restore cursor */
save_cursor (FALSE); save_cursor (FALSE);
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
break; break;
case 't': /* set page size - ie window height */ case 't': /* set page size - ie window height */
request_resize (cols, def(esc_args[0], 24)); request_resize (cols, def(esc_args[0], 24));
@ -1020,8 +1003,7 @@ void term_out(void) {
check_selection (cpos, cpos+n); check_selection (cpos, cpos+n);
while (n--) while (n--)
*p++ = ERASE_CHAR; *p++ = ERASE_CHAR;
disptop = scrtop; seen_disp_event = TRUE;
must_update = TRUE;
} }
break; break;
case 'x': /* report terminal characteristics */ case 'x': /* report terminal characteristics */
@ -1055,11 +1037,6 @@ void term_out(void) {
case SEEN_OSC: case SEEN_OSC:
osc_w = FALSE; osc_w = FALSE;
switch (c) { 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 */ case 'P': /* Linux palette sequence */
termstate = SEEN_OSC_P; termstate = SEEN_OSC_P;
osc_strlen = 0; osc_strlen = 0;
@ -1133,11 +1110,6 @@ void term_out(void) {
break; break;
case SEEN_OSC_W: case SEEN_OSC_W:
switch (c) { 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 '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
esc_args[0] = 10 * esc_args[0] + c - '0'; esc_args[0] = 10 * esc_args[0] + c - '0';
@ -1154,7 +1126,7 @@ void term_out(void) {
while (n--) while (n--)
*p++ = ATTR_DEFAULT | 'E'; *p++ = ATTR_DEFAULT | 'E';
disptop = scrtop; disptop = scrtop;
must_update = TRUE; seen_disp_event = TRUE;
check_selection (scrtop, scrtop + rows * (cols+1)); check_selection (scrtop, scrtop + rows * (cols+1));
} }
termstate = TOPLEVEL; termstate = TOPLEVEL;
@ -1163,7 +1135,7 @@ void term_out(void) {
check_selection (cpos, cpos+1); check_selection (cpos, cpos+1);
} }
if (must_update || nl_count > MAXNL) if (nl_count > MAXNL)
term_update(); term_update();
} }

View File

@ -310,6 +310,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
inbuf_reap = inbuf_head = 0; inbuf_reap = inbuf_head = 0;
outbuf_reap = outbuf_head = 0; outbuf_reap = outbuf_head = 0;
/*
* Choose unscroll method
*/
unscroll_event = US_DISP;
/* /*
* Prepare the mouse handler. * Prepare the mouse handler.
*/ */
@ -1224,6 +1229,14 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
*/ */
ret = GetKeyboardState(keystate); 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 * Windows does not always want to distinguish left and right
* Alt or Control keys. Thus we keep track of them ourselves. * Alt or Control keys. Thus we keep track of them ourselves.