static int esc_args[ARGS_MAX];
static int esc_nargs;
static int esc_query;
+#define ANSI(x,y) ((x)+((y)<<8))
+#define ANSI_QUE(x) ANSI(x,TRUE)
#define OSC_STR_MAX 2048
static int osc_strlen;
Context ctx;
ctx = get_ctx();
if (ctx) {
- if ( (seen_key_event && (unscroll_event & US_KEY)) &&
+ if ( (seen_key_event && (unscroll_event & US_KEY)) ||
(seen_disp_event && (unscroll_event & US_DISP)) ) {
disptop = scrtop;
seen_disp_event = seen_key_event = 0;
unsigned long *newtext, *newdisp, *newwant, *newalt;
int i, j, crows, ccols;
+ int save_alt_which = alt_which;
+
if (newrows == rows && newcols == cols && newsavelines == savelines)
return; /* nothing to do */
+ deselect();
+ swap_screen(0);
+
alt_t = marg_t = 0;
alt_b = marg_b = newrows - 1;
savelines = newsavelines;
fix_cpos;
- deselect();
+ swap_screen(save_alt_which);
+
update_sbar();
term_update();
}
int c;
while ( (c = inbuf_getc()) != -1) {
-#ifdef LOG
- {
+ /*
+ * Optionally log the session traffic to a file. Useful for
+ * debugging and possibly also useful for actual logging.
+ */
+ if (logfile) {
static FILE *fp = NULL;
- if (!fp) fp = fopen("putty.log", "wb");
+ if (!fp) fp = fopen(logfile, "wb");
if (fp) fputc (c, fp);
}
-#endif
if( termstate < DO_CTRLS && (c&0x60) == 0 ) {
switch (c) {
case '\005': /* terminal type query */
}
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;
+ /* Only graphic characters get this far, ctrls are stripped above */
+ 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:
break;
case SEEN_CSI:
termstate = TOPLEVEL; /* default */
- switch (c) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
+ if( isdigit(c) )
+ {
if (esc_nargs <= ARGS_MAX) {
if (esc_args[esc_nargs-1] == ARG_DEFAULT)
esc_args[esc_nargs-1] = 0;
10 * esc_args[esc_nargs-1] + c - '0';
}
termstate = SEEN_CSI;
- break;
- case ';':
+ }
+ else if( c == ';' )
+ {
if (++esc_nargs <= ARGS_MAX)
esc_args[esc_nargs-1] = ARG_DEFAULT;
termstate = SEEN_CSI;
- break;
- case '?':
- esc_query = TRUE;
+ }
+ else if( c < '@' )
+ {
+ if( esc_query ) esc_query = -1;
+ else if( c == '?' ) esc_query = TRUE;
+ else esc_query = c;
termstate = SEEN_CSI;
- break;
+ }
+ else switch (ANSI(c,esc_query)) {
case 'A': /* move up N lines */
move (curs_x, curs_y - def(esc_args[0], 1), 1);
seen_disp_event = TRUE;
}
break;
case 'h': /* toggle a mode to high */
+ case ANSI_QUE('h'):
toggle_mode (esc_args[0], esc_query, TRUE);
break;
case 'l': /* toggle a mode to low */
+ case ANSI_QUE('l'):
toggle_mode (esc_args[0], esc_query, FALSE);
break;
case 'g': /* clear tabs */
}
break;
case 'r': /* set scroll margins */
- if (!esc_query && esc_nargs <= 2) {
+ if (esc_nargs <= 2) {
int top, bot;
top = def(esc_args[0], 1) - 1;
if (top < 0)
cset_attr[termstate == SET_GL ? 0 : 1] = ATTR_ASCII;
break;
}
- termstate = TOPLEVEL;
+ if( c != '%' )
+ termstate = TOPLEVEL;
break;
case SEEN_OSC:
osc_w = FALSE;
}
break;
case OSC_STRING:
- if (c == 0234 || c == '\007') {
+ /*
+ * This OSC stuff is EVIL. It takes just one character to get into
+ * sysline mode and it's not initially obvious how to get out.
+ * So I've added CR and LF as string aborts.
+ * This shouldn't effect compatibility as I believe embedded
+ * control characters are supposed to be interpreted (maybe?)
+ * and they don't display anything useful anyway.
+ *
+ * -- RDB
+ */
+ if (c == '\n' || c == '\r') {
+ termstate = TOPLEVEL;
+ } else if (c == 0234 || c == '\007' ) {
/*
* These characters terminate the string; ST and BEL
* terminate the sequence and trigger instant