switch (c) { case ' ':	        compatibility(VT220); termstate = IGNORE_NEXT; break;
switch (ANSI(c, esc_query)) {
void term_out(void){    int c, inbuf_reap;    for (inbuf_reap = 0; inbuf_reap < inbuf_head; inbuf_reap++) {	c = inbuf[inbuf_reap];	/*	 * Optionally log the session traffic to a file. Useful for	 * debugging and possibly also useful for actual logging.	 */	logtraffic((unsigned char) c, LGTYP_DEBUG);	/* Note only VT220+ are 8-bit VT102 is seven bit, it shouldn't even	 * be able to display 8-bit characters, but I'll let that go 'cause	 * of i18n.	 */	if (((c & 0x60) == 0 || c == '\177') &&	    termstate < DO_CTRLS && ((c & 0x80) == 0 || has_compat(VT220))) {	    switch (c) {	      case '\005':	       /* terminal type query */		/* Strictly speaking this is VT100 but a VT100 defaults to		 * no response. Other terminals respond at their option.		 *		 * Don't put a CR in the default string as this tends to		 * upset some weird software.		 *		 * An xterm returns "xterm" (5 characters)		 */		compatibility(ANSIMIN);		{		    char abuf[256], *s, *d;		    int state = 0;		    for (s = cfg.answerback, d = abuf; *s; s++) {			if (state) {			    if (*s >= 'a' && *s <= 'z')				*d++ = (*s - ('a' - 1));			    else if ((*s >= '@' && *s <= '_') ||				     *s == '?' || (*s & 0x80))				*d++ = ('@' ^ *s);			    else if (*s == '~')				*d++ = '^';			    state = 0;			} else if (*s == '^') {			    state = 1;			} else			    *d++ = xlat_kbd2tty((unsigned char) *s);		    }		    ldisc_send(abuf, d - abuf);		}		break;	      case '\007':		{		    struct beeptime *newbeep;		    long ticks;		    ticks = GetTickCount();		    if (!beep_overloaded) {			newbeep = smalloc(sizeof(struct beeptime));			newbeep->ticks = ticks;			newbeep->next = NULL;			if (!beephead)			    beephead = newbeep;			else			    beeptail->next = newbeep;			beeptail = newbeep;			nbeeps++;		    }		    /*		     * Throw out any beeps that happened more than		     * t seconds ago.		     */		    while (beephead &&			   beephead->ticks < ticks - cfg.bellovl_t) {			struct beeptime *tmp = beephead;			beephead = tmp->next;			sfree(tmp);			if (!beephead)			    beeptail = NULL;			nbeeps--;		    }		    if (cfg.bellovl && beep_overloaded &&			ticks - lastbeep >= cfg.bellovl_s) {			/*			 * If we're currently overloaded and the			 * last beep was more than s seconds ago,			 * leave overload mode.			 */			beep_overloaded = FALSE;		    } else if (cfg.bellovl && !beep_overloaded &&			       nbeeps >= cfg.bellovl_n) {			/*			 * Now, if we have n or more beeps			 * remaining in the queue, go into overload			 * mode.			 */			beep_overloaded = TRUE;		    }		    lastbeep = ticks;		    /*		     * Perform an actual beep if we're not overloaded.		     */		    if ((!cfg.bellovl || !beep_overloaded)			&& cfg.beep != 0) {			if (cfg.beep != 2)			    beep(cfg.beep);			else if (cfg.beep == 2) {			    in_vbell = TRUE;			    vbell_timeout = ticks + VBELL_TIMEOUT;			    term_update();			}		    }		    disptop = 0;		}		break;	      case '\b':		if (curs.x == 0 && (curs.y == 0 || wrap == 0));		else if (curs.x == 0 && curs.y > 0)		    curs.x = cols - 1, curs.y--;		else if (wrapnext)		    wrapnext = FALSE;		else		    curs.x--;		fix_cpos;		seen_disp_event = TRUE;		break;	      case '\016':		compatibility(VT100);		cset = 1;		break;	      case '\017':		compatibility(VT100);		cset = 0;		break;	      case '\033':		if (vt52_mode)		    termstate = VT52_ESC;		else {		    compatibility(ANSIMIN);		    termstate = SEEN_ESC;		}		break;	      case 0233:		compatibility(VT220);		termstate = SEEN_CSI;		esc_nargs = 1;		esc_args[0] = ARG_DEFAULT;		esc_query = FALSE;		break;	      case 0235:		compatibility(VT220);		termstate = SEEN_OSC;		esc_args[0] = 0;		break;	      case '\r':		curs.x = 0;		wrapnext = FALSE;		fix_cpos;		seen_disp_event = TRUE;		paste_hold = 0;		logtraffic((unsigned char) c, LGTYP_ASCII);		break;	      case '\014':		if (has_compat(SCOANSI)) {		    move(0, 0, 0);		    erase_lots(FALSE, FALSE, TRUE);		    disptop = 0;		    wrapnext = FALSE;		    seen_disp_event = 1;		    break;		}	      case '\013':		compatibility(VT100);	      case '\n':		if (curs.y == marg_b)		    scroll(marg_t, marg_b, 1, TRUE);		else if (curs.y < rows - 1)		    curs.y++;		if (cfg.lfhascr)		    curs.x = 0;		fix_cpos;		wrapnext = FALSE;		seen_disp_event = 1;		paste_hold = 0;		logtraffic((unsigned char) c, LGTYP_ASCII);		break;	      case '\t':		{		    pos old_curs = curs;		    unsigned long *ldata = lineptr(curs.y);		    do {			curs.x++;		    } while (curs.x < cols - 1 && !tabs[curs.x]);		    if ((ldata[cols] & LATTR_MODE) != LATTR_NORM) {			if (curs.x >= cols / 2)			    curs.x = cols / 2 - 1;		    } else {			if (curs.x >= cols)			    curs.x = cols - 1;		    }		    fix_cpos;		    check_selection(old_curs, curs);		}		seen_disp_event = TRUE;		break;	      case '\177':	       /* Destructive backspace				          This does nothing on a real VT100 */		compatibility(OTHER);		if (curs.x && !wrapnext)		    curs.x--;		wrapnext = FALSE;		fix_cpos;		*cpos = (' ' | curr_attr | ATTR_ASCII);		break;	    }	} else	    switch (termstate) {	      case TOPLEVEL:		/* Only graphic characters get this far, ctrls are stripped above */		if (wrapnext && wrap) {		    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;		}		if (insert)		    insch(1);		if (selstate != NO_SELECTION) {		    pos cursplus = curs;		    incpos(cursplus);		    check_selection(curs, cursplus);		}		switch (cset_attr[cset]) {		    /*		     * Linedraw characters are different from 'ESC ( B'		     * only for a small range. For ones outside that		     * range, make sure we use the same font as well as		     * the same encoding.		     */		  case ATTR_LINEDRW:		    if (c < 0x5f || c > 0x7F)			*cpos++ =			    xlat_tty2scr((unsigned char) c) | curr_attr |			    ATTR_ASCII;		    else if (c == 0x5F)			*cpos++ = ' ' | curr_attr | ATTR_ASCII;		    else			*cpos++ =			    ((unsigned char) c) | curr_attr | ATTR_LINEDRW;		    break;		  case ATTR_GBCHR:		    /* If UK-ASCII, make the '#' a LineDraw Pound */		    if (c == '#') {			*cpos++ = '}' | curr_attr | ATTR_LINEDRW;			break;		    }		  /*FALLTHROUGH*/ default:		    *cpos = xlat_tty2scr((unsigned char) c) | curr_attr |			(c <= 0x7F ? cset_attr[cset] : ATTR_ASCII);		    logtraffic((unsigned char) c, LGTYP_ASCII);		    cpos++;		    break;		}		curs.x++;		if (curs.x == cols) {		    cpos--;		    curs.x--;		    wrapnext = TRUE;		}		seen_disp_event = 1;		break;	      case IGNORE_NEXT:		termstate = TOPLEVEL;		break;	      case OSC_MAYBE_ST:		/*		 * This state is virtually identical to SEEN_ESC, with the		 * exception that we have an OSC sequence in the pipeline,		 * and _if_ we see a backslash, we process it.		 */		if (c == '\\') {		    do_osc();		    termstate = TOPLEVEL;		    break;		}		/* else fall through */	      case SEEN_ESC:		termstate = TOPLEVEL;		switch (c) {		  case ' ':	       /* some weird sequence? */		    compatibility(VT220);		    termstate = IGNORE_NEXT;		    break;		  case '[':	       /* enter CSI mode */		    termstate = SEEN_CSI;		    esc_nargs = 1;		    esc_args[0] = ARG_DEFAULT;		    esc_query = FALSE;		    break;		  case ']':	       /* xterm escape sequences */		    /* Compatibility is nasty here, xterm, linux, decterm yuk! */		    compatibility(OTHER);		    termstate = SEEN_OSC;		    esc_args[0] = 0;		    break;		  case '(':	       /* should set GL */		    compatibility(VT100);		    termstate = SET_GL;		    break;		  case ')':	       /* should set GR */		    compatibility(VT100);		    termstate = SET_GR;		    break;		  case '7':	       /* save cursor */		    compatibility(VT100);		    save_cursor(TRUE);		    break;		  case '8':	       /* restore cursor */		    compatibility(VT100);		    save_cursor(FALSE);		    seen_disp_event = TRUE;		    break;		  case '=':		    compatibility(VT100);		    app_keypad_keys = TRUE;		    break;		  case '>':		    compatibility(VT100);		    app_keypad_keys = FALSE;		    break;		  case 'D':	       /* exactly equivalent to LF */		    compatibility(VT100);		    if (curs.y == marg_b)			scroll(marg_t, marg_b, 1, TRUE);		    else if (curs.y < rows - 1)			curs.y++;		    fix_cpos;		    wrapnext = FALSE;		    seen_disp_event = TRUE;		    break;		  case 'E':	       /* exactly equivalent to CR-LF */		    compatibility(VT100);		    curs.x = 0;		    if (curs.y == marg_b)			scroll(marg_t, marg_b, 1, TRUE);		    else if (curs.y < rows - 1)			curs.y++;		    fix_cpos;		    wrapnext = FALSE;		    seen_disp_event = TRUE;		    break;		  case 'M':	       /* reverse index - backwards LF */		    compatibility(VT100);		    if (curs.y == marg_t)			scroll(marg_t, marg_b, -1, TRUE);		    else if (curs.y > 0)			curs.y--;		    fix_cpos;		    wrapnext = FALSE;		    seen_disp_event = TRUE;		    break;		  case 'Z':	       /* terminal type query */		    compatibility(VT100);		    ldisc_send(id_string, strlen(id_string));		    break;		  case 'c':	       /* restore power-on settings */		    compatibility(VT100);		    power_on();		    if (reset_132) {			request_resize(80, rows, 1);			reset_132 = 0;		    }		    fix_cpos;		    disptop = 0;		    seen_disp_event = TRUE;		    break;		  case '#':	       /* ESC # 8 fills screen with Es :-) */		    compatibility(VT100);		    termstate = SEEN_ESCHASH;		    break;		  case 'H':	       /* set a tab */		    compatibility(VT100);		    tabs[curs.x] = TRUE;		    break;		}		break;	      case SEEN_CSI:		termstate = TOPLEVEL;  /* default */		if (isdigit(c)) {		    if (esc_nargs <= ARGS_MAX) {			if (esc_args[esc_nargs - 1] == ARG_DEFAULT)			    esc_args[esc_nargs - 1] = 0;			esc_args[esc_nargs - 1] =			    10 * esc_args[esc_nargs - 1] + c - '0';		    }		    termstate = SEEN_CSI;		} else if (c == ';') {		    if (++esc_nargs <= ARGS_MAX)			esc_args[esc_nargs - 1] = ARG_DEFAULT;		    termstate = SEEN_CSI;		} else if (c < '@') {		    if (esc_query)			esc_query = -1;		    else if (c == '?')			esc_query = TRUE;		    else			esc_query = c;		    termstate = SEEN_CSI;		} 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 'e':       /* move down N lines */			compatibility(ANSI);		      case 'B':			move(curs.x, curs.y + def(esc_args[0], 1), 1);			seen_disp_event = TRUE;			break;		      case 'a':       /* move right N cols */			compatibility(ANSI);		      case ANSI('c', '>'):	/* report xterm version */			compatibility(OTHER);			/* this reports xterm version 136 so that VIM can			   use the drag messages from the mouse reporting */			ldisc_send("\033[>0;136;0c", 11);			break;		      case 'C':			move(curs.x + def(esc_args[0], 1), curs.y, 1);			seen_disp_event = TRUE;			break;		      case 'D':       /* move left N cols */			move(curs.x - def(esc_args[0], 1), curs.y, 1);			seen_disp_event = TRUE;			break;		      case 'E':       /* move down N lines and CR */			compatibility(ANSI);			move(0, curs.y + def(esc_args[0], 1), 1);			seen_disp_event = TRUE;			break;		      case 'F':       /* move up N lines and CR */			compatibility(ANSI);			move(0, curs.y - def(esc_args[0], 1), 1);			seen_disp_event = TRUE;			break;		      case 'G':		      case '`':       /* set horizontal posn */			compatibility(ANSI);			move(def(esc_args[0], 1) - 1, curs.y, 0);			seen_disp_event = TRUE;			break;		      case 'd':       /* set vertical posn */			compatibility(ANSI);			move(curs.x,			     (dec_om ? marg_t : 0) + def(esc_args[0],							 1) - 1,			     (dec_om ? 2 : 0));			seen_disp_event = TRUE;			break;		      case 'H':		      case 'f':       /* set horz and vert posns at once */			if (esc_nargs < 2)			    esc_args[1] = ARG_DEFAULT;			move(def(esc_args[1], 1) - 1,			     (dec_om ? marg_t : 0) + def(esc_args[0],							 1) - 1,			     (dec_om ? 2 : 0));			seen_disp_event = TRUE;			break;		      case 'J':       /* erase screen or parts of it */			{			    unsigned int i = def(esc_args[0], 0) + 1;			    if (i > 3)				i = 0;			    erase_lots(FALSE, !!(i & 2), !!(i & 1));			}			disptop = 0;			seen_disp_event = TRUE;			break;		      case 'K':       /* erase line or parts of it */			{			    unsigned int i = def(esc_args[0], 0) + 1;			    if (i > 3)				i = 0;			    erase_lots(TRUE, !!(i & 2), !!(i & 1));			}			seen_disp_event = TRUE;			break;		      case 'L':       /* insert lines */			compatibility(VT102);			if (curs.y <= marg_b)			    scroll(curs.y, marg_b, -def(esc_args[0], 1),				   FALSE);			fix_cpos;			seen_disp_event = TRUE;			break;		      case 'M':       /* delete lines */			compatibility(VT102);			if (curs.y <= marg_b)			    scroll(curs.y, marg_b, def(esc_args[0], 1),				   TRUE);			fix_cpos;			seen_disp_event = TRUE;			break;		      case '@':       /* insert chars */			/* XXX VTTEST says this is vt220, vt510 manual says vt102 */			compatibility(VT102);			insch(def(esc_args[0], 1));			seen_disp_event = TRUE;			break;		      case 'P':       /* delete chars */			compatibility(VT102);			insch(-def(esc_args[0], 1));			seen_disp_event = TRUE;			break;		      case 'c':       /* terminal type query */			compatibility(VT100);			/* This is the response for a VT102 */			ldisc_send(id_string, strlen(id_string));			break;		      case 'n':       /* cursor position query */			if (esc_args[0] == 6) {			    char buf[32];			    sprintf(buf, "\033[%d;%dR", curs.y + 1,				    curs.x + 1);			    ldisc_send(buf, strlen(buf));			} else if (esc_args[0] == 5) {			    ldisc_send("\033[0n", 4);			}			break;		      case 'h':       /* toggle modes to high */		      case ANSI_QUE('h'):			compatibility(VT100);			{			    int i;			    for (i = 0; i < esc_nargs; i++)				toggle_mode(esc_args[i], esc_query, TRUE);			}			break;		      case 'l':       /* toggle modes to low */		      case ANSI_QUE('l'):			compatibility(VT100);			{			    int i;			    for (i = 0; i < esc_nargs; i++)				toggle_mode(esc_args[i], esc_query, FALSE);			}			break;		      case 'g':       /* clear tabs */			compatibility(VT100);			if (esc_nargs == 1) {			    if (esc_args[0] == 0) {				tabs[curs.x] = FALSE;			    } else if (esc_args[0] == 3) {				int i;				for (i = 0; i < cols; i++)				    tabs[i] = FALSE;			    }			}			break;		      case 'r':       /* set scroll margins */			compatibility(VT100);			if (esc_nargs <= 2) {			    int top, bot;			    top = def(esc_args[0], 1) - 1;			    bot = (esc_nargs <= 1				   || esc_args[1] ==				   0 ? rows : def(esc_args[1], rows)) - 1;			    if (bot >= rows)				bot = rows - 1;			    /* VTTEST Bug 9 - if region is less than 2 lines			     * don't change region.			     */			    if (bot - top > 0) {				marg_t = top;				marg_b = bot;				curs.x = 0;				/*				 * I used to think the cursor should be				 * placed at the top of the newly marginned				 * area. Apparently not: VMS TPU falls over				 * if so.				 *				 * Well actually it should for Origin mode - RDB				 */				curs.y = (dec_om ? marg_t : 0);				fix_cpos;				seen_disp_event = TRUE;			    }			}			break;		      case 'm':       /* set graphics rendition */			{			    /* 			     * A VT100 without the AVO only had one attribute, either			     * underline or reverse video depending on the cursor type,			     * this was selected by CSI 7m.			     *			     * case 2:			     *  This is DIM on the VT100-AVO and VT102			     * case 5:			     *  This is BLINK on the VT100-AVO and VT102+			     * case 8:			     *  This is INVIS on the VT100-AVO and VT102			     * case 21:			     *  This like 22 disables BOLD, DIM and INVIS			     *			     * The ANSI colours appear on any terminal that has colour			     * (obviously) but the interaction between sgr0 and the			     * colours varies but is usually related to the background			     * colour erase item.			     * The interaction between colour attributes and the mono			     * ones is also very implementation dependent.			     *			     * The 39 and 49 attributes are likely to be unimplemented.			     */			    int i;			    for (i = 0; i < esc_nargs; i++) {				switch (def(esc_args[i], 0)) {				  case 0:	/* restore defaults */				    curr_attr = ATTR_DEFAULT;				    break;				  case 1:	/* enable bold */				    compatibility(VT100AVO);				    curr_attr |= ATTR_BOLD;				    break;				  case 21:	/* (enable double underline) */				    compatibility(OTHER);				  case 4:	/* enable underline */				    compatibility(VT100AVO);				    curr_attr |= ATTR_UNDER;				    break;				  case 5:	/* enable blink */				    compatibility(VT100AVO);				    curr_attr |= ATTR_BLINK;				    break;				  case 7:	/* enable reverse video */				    curr_attr |= ATTR_REVERSE;				    break;				  case 22:	/* disable bold */				    compatibility2(OTHER, VT220);				    curr_attr &= ~ATTR_BOLD;				    break;				  case 24:	/* disable underline */				    compatibility2(OTHER, VT220);				    curr_attr &= ~ATTR_UNDER;				    break;				  case 25:	/* disable blink */				    compatibility2(OTHER, VT220);				    curr_attr &= ~ATTR_BLINK;				    break;				  case 27:	/* disable reverse video */				    compatibility2(OTHER, VT220);				    curr_attr &= ~ATTR_REVERSE;				    break;				  case 30:				  case 31:				  case 32:				  case 33:				  case 34:				  case 35:				  case 36:				  case 37:				    /* foreground */				    curr_attr &= ~ATTR_FGMASK;				    curr_attr |=					(esc_args[i] - 30) << ATTR_FGSHIFT;				    break;				  case 39:	/* default-foreground */				    curr_attr &= ~ATTR_FGMASK;				    curr_attr |= ATTR_DEFFG;				    break;				  case 40:				  case 41:				  case 42:				  case 43:				  case 44:				  case 45:				  case 46:				  case 47:				    /* background */				    curr_attr &= ~ATTR_BGMASK;				    curr_attr |=					(esc_args[i] - 40) << ATTR_BGSHIFT;				    break;				  case 49:	/* default-background */				    curr_attr &= ~ATTR_BGMASK;				    curr_attr |= ATTR_DEFBG;				    break;				}			    }			    if (use_bce)				erase_char =				    (' ' |				     (curr_attr &				      (ATTR_FGMASK | ATTR_BGMASK |				       ATTR_BLINK)));			}			break;		      case 's':       /* save cursor */			save_cursor(TRUE);			break;		      case 'u':       /* restore cursor */			save_cursor(FALSE);			seen_disp_event = TRUE;			break;		      case 't':       /* set page size - ie window height */			/*			 * VT340/VT420 sequence DECSLPP, DEC only allows values			 *  24/25/36/48/72/144 other emulators (eg dtterm) use			 * illegal values (eg first arg 1..9) for window changing 			 * and reports.			 */			compatibility(VT340TEXT);			if (esc_nargs <= 1			    && (esc_args[0] < 1 || esc_args[0] >= 24)) {			    request_resize(cols, def(esc_args[0], 24), 0);			    deselect();			}			break;		      case 'S':			compatibility(SCOANSI);			scroll(marg_t, marg_b, def(esc_args[0], 1), TRUE);			fix_cpos;			wrapnext = FALSE;			seen_disp_event = TRUE;			break;		      case 'T':			compatibility(SCOANSI);			scroll(marg_t, marg_b, -def(esc_args[0], 1), TRUE);			fix_cpos;			wrapnext = FALSE;			seen_disp_event = TRUE;			break;		      case ANSI('|', '*'):			/* VT420 sequence DECSNLS			 * Set number of lines on screen			 * VT420 uses VGA like hardware and can support any size in			 * reasonable range (24..49 AIUI) with no default specified.			 */			compatibility(VT420);			if (esc_nargs == 1 && esc_args[0] > 0) {			    request_resize(cols,					   def(esc_args[0], cfg.height),					   0);			    deselect();			}			break;		      case ANSI('|', '$'):			/* VT340/VT420 sequence DECSCPP			 * Set number of columns per page			 * Docs imply range is only 80 or 132, but I'll allow any.			 */			compatibility(VT340TEXT);			if (esc_nargs <= 1) {			    request_resize(def(esc_args[0], cfg.width),					   rows, 0);			    deselect();			}			break;		      case 'X':       /* write N spaces w/o moving cursor */			/* XXX VTTEST says this is vt220, vt510 manual says vt100 */			compatibility(ANSIMIN);			{			    int n = def(esc_args[0], 1);			    pos cursplus;			    unsigned long *p = cpos;			    if (n > cols - curs.x)				n = cols - curs.x;			    cursplus = curs;			    cursplus.x += n;			    check_selection(curs, cursplus);			    while (n--)				*p++ = erase_char;			    seen_disp_event = TRUE;			}			break;		      case 'x':       /* report terminal characteristics */			compatibility(VT100);			{			    char buf[32];			    int i = def(esc_args[0], 0);			    if (i == 0 || i == 1) {				strcpy(buf, "\033[2;1;1;112;112;1;0x");				buf[2] += i;				ldisc_send(buf, 20);			    }			}			break;		      case ANSI('L', '='):			compatibility(OTHER);			use_bce = (esc_args[0] <= 0);			erase_char = ERASE_CHAR;			if (use_bce)			    erase_char =				(' ' |				 (curr_attr &				  (ATTR_FGMASK | ATTR_BGMASK)));			break;		      case ANSI('E', '='):			compatibility(OTHER);			blink_is_real = (esc_args[0] >= 1);			break;		      case ANSI('p', '"'):			/* Allow the host to make this emulator a 'perfect' VT102.			 * This first appeared in the VT220, but we do need to get 			 * back to PuTTY mode so I won't check it.			 *			 * The arg in 40..42 are a PuTTY extension.			 * The 2nd arg, 8bit vs 7bit is not checked.			 *			 * Setting VT102 mode should also change the Fkeys to			 * generate PF* codes as a real VT102 has no Fkeys.			 * The VT220 does this, F11..F13 become ESC,BS,LF other Fkeys			 * send nothing.			 *			 * Note ESC c will NOT change this!			 */			switch (esc_args[0]) {			  case 61:			    compatibility_level &= ~TM_VTXXX;			    compatibility_level |= TM_VT102;			    break;			  case 62:			    compatibility_level &= ~TM_VTXXX;			    compatibility_level |= TM_VT220;			    break;			  default:			    if (esc_args[0] > 60 && esc_args[0] < 70)				compatibility_level |= TM_VTXXX;			    break;			  case 40:			    compatibility_level &= TM_VTXXX;			    break;			  case 41:			    compatibility_level = TM_PUTTY;			    break;			  case 42:			    compatibility_level = TM_SCOANSI;			    break;			  case ARG_DEFAULT:			    compatibility_level = TM_PUTTY;			    break;			  case 50:			    break;			}			/* Change the response to CSI c */			if (esc_args[0] == 50) {			    int i;			    char lbuf[64];			    strcpy(id_string, "\033[?");			    for (i = 1; i < esc_nargs; i++) {				if (i != 1)				    strcat(id_string, ";");				sprintf(lbuf, "%d", esc_args[i]);				strcat(id_string, lbuf);			    }			    strcat(id_string, "c");			}#if 0			/* Is this a good idea ? 			 * Well we should do a soft reset at this point ...			 */			if (!has_compat(VT420) && has_compat(VT100)) {			    if (reset_132)				request_resize(132, 24, 1);			    else				request_resize(80, 24, 1);			}#endif			break;		    }		break;	      case SET_GL:	      case SET_GR:		/* VT100 only here, checked above */		switch (c) {		  case 'A':		    cset_attr[termstate == SET_GL ? 0 : 1] = ATTR_GBCHR;		    break;		  case '0':		    cset_attr[termstate == SET_GL ? 0 : 1] = ATTR_LINEDRW;		    break;		  case 'B':		  default:	       /* specifically, 'B' */		    cset_attr[termstate == SET_GL ? 0 : 1] = ATTR_ASCII;		    break;		}		if (!has_compat(VT220) || c != '%')		    termstate = TOPLEVEL;		break;	      case SEEN_OSC:		osc_w = FALSE;		switch (c) {		  case 'P':	       /* Linux palette sequence */		    termstate = SEEN_OSC_P;		    osc_strlen = 0;		    break;		  case 'R':	       /* Linux palette reset */		    palette_reset();		    term_invalidate();		    termstate = TOPLEVEL;		    break;		  case 'W':	       /* word-set */		    termstate = SEEN_OSC_W;		    osc_w = TRUE;		    break;		  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';		    break;		  case 'L':		    /*		     * Grotty hack to support xterm and DECterm title		     * sequences concurrently.		     */		    if (esc_args[0] == 2) {			esc_args[0] = 1;			break;		    }		    /* else fall through */		  default:		    termstate = OSC_STRING;		    osc_strlen = 0;		}		break;	      case OSC_STRING:		/*		 * 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		     * processing of it, whereas ESC goes back to SEEN_ESC		     * mode unless it is followed by \, in which case it is		     * synonymous with ST in the first place.		     */		    do_osc();		    termstate = TOPLEVEL;		} else if (c == '\033')		    termstate = OSC_MAYBE_ST;		else if (osc_strlen < OSC_STR_MAX)		    osc_string[osc_strlen++] = c;		break;	      case SEEN_OSC_P:		{		    int max = (osc_strlen == 0 ? 21 : 16);		    int val;		    if (c >= '0' && c <= '9')			val = c - '0';		    else if (c >= 'A' && c <= 'A' + max - 10)			val = c - 'A' + 10;		    else if (c >= 'a' && c <= 'a' + max - 10)			val = c - 'a' + 10;		    else			termstate = TOPLEVEL;		    osc_string[osc_strlen++] = val;		    if (osc_strlen >= 7) {			palette_set(osc_string[0],				    osc_string[1] * 16 + osc_string[2],				    osc_string[3] * 16 + osc_string[4],				    osc_string[5] * 16 + osc_string[6]);			term_invalidate();			termstate = TOPLEVEL;		    }		}		break;	      case SEEN_OSC_W:		switch (c) {		  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';		    break;		  default:		    termstate = OSC_STRING;		    osc_strlen = 0;		}		break;	      case SEEN_ESCHASH:		{		    unsigned long nlattr;		    unsigned long *ldata;		    int i, j;		    pos scrtop, scrbot;		    switch (c) {		      case '8':			for (i = 0; i < rows; i++) {			    ldata = lineptr(i);			    for (j = 0; j < cols; j++)				ldata[j] = ATTR_DEFAULT | 'E';			    ldata[cols] = 0;			}			disptop = 0;			seen_disp_event = TRUE;			scrtop.x = scrtop.y = 0;			scrbot.x = 0;			scrbot.y = rows;			check_selection(scrtop, scrbot);			break;		      case '3':		      case '4':		      case '5':		      case '6':			switch (c) {			  case '3':			    nlattr = LATTR_TOP;			    break;			  case '4':			    nlattr = LATTR_BOT;			    break;			  case '5':			    nlattr = LATTR_NORM;			    break;			  case '6':			    nlattr = LATTR_WIDE;			    break;			}			ldata = lineptr(curs.y);			ldata[cols] &= ~LATTR_MODE;			ldata[cols] |= nlattr;		    }		}		termstate = TOPLEVEL;		break;	      case VT52_ESC:		termstate = TOPLEVEL;		seen_disp_event = TRUE;		switch (c) {		  case 'A':		    move(curs.x, curs.y - 1, 1);		    break;		  case 'B':		    move(curs.x, curs.y + 1, 1);		    break;		  case 'C':		    move(curs.x + 1, curs.y, 1);		    break;		  case 'D':		    move(curs.x - 1, curs.y, 1);		    break;		  case 'F':		    cset_attr[cset = 0] = ATTR_LINEDRW;		    break;		  case 'G':		    cset_attr[cset = 0] = ATTR_ASCII;		    break;		  case 'H':		    move(0, 0, 0);		    break;		  case 'I':		    if (curs.y == 0)			scroll(0, rows - 1, -1, TRUE);		    else if (curs.y > 0)			curs.y--;		    fix_cpos;		    wrapnext = FALSE;		    break;		  case 'J':		    erase_lots(FALSE, FALSE, TRUE);		    disptop = 0;		    break;		  case 'K':		    erase_lots(TRUE, FALSE, TRUE);		    break;		  case 'V':		    /* XXX Print cursor line */		    break;		  case 'W':		    /* XXX Start controller mode */		    break;		  case 'X':		    /* XXX Stop controller mode */		    break;		  case 'Y':		    termstate = VT52_Y1;		    break;		  case 'Z':		    ldisc_send("\033/Z", 3);		    break;		  case '=':		    app_keypad_keys = TRUE;		    break;		  case '>':		    app_keypad_keys = FALSE;		    break;		  case '<':		    /* XXX This should switch to VT100 mode not current or default		     *     VT mode. But this will only have effect in a VT220+		     *     emulation.		     */		    vt52_mode = FALSE;		    break;		  case '^':		    /* XXX Enter auto print mode */		    break;		  case '_':		    /* XXX Exit auto print mode */		    break;		  case ']':		    /* XXX Print screen */		    break;		}		break;	      case VT52_Y1:		termstate = VT52_Y2;		move(curs.x, c - ' ', 0);		break;	      case VT52_Y2:		termstate = TOPLEVEL;		move(c - ' ', curs.y, 0);		break;	    }	if (selstate != NO_SELECTION) {	    pos cursplus = curs;	    incpos(cursplus);	    check_selection(curs, cursplus);	}    }    inbuf_head = 0;}