+ 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);
+ /* FALLTHROUGH */
+ case 'B':
+ move(curs.x, curs.y + def(esc_args[0], 1), 1);
+ seen_disp_event = TRUE;
+ break;
+ 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 'a': /* move right N cols */
+ compatibility(ANSI);
+ /* FALLTHROUGH */
+ 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 sometimes DIM, eg on the GIGI and Linux
+ * case 8:
+ * This is sometimes INVIS various ANSI.
+ * 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 10: /* SCO acs off */
+ compatibility(SCOANSI);
+ sco_acs = 0; break;
+ case 11: /* SCO acs on */
+ compatibility(SCOANSI);
+ sco_acs = 1; break;
+ case 12: /* SCO acs on flipped */
+ compatibility(SCOANSI);
+ sco_acs = 2; 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 = (' ' | ATTR_ASCII |
+ (curr_attr &
+ (ATTR_FGMASK | ATTR_BGMASK)));
+ }
+ 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 'Z': /* BackTab for xterm */
+ compatibility(OTHER);
+ {
+ int i = def(esc_args[0], 1);
+ pos old_curs = curs;
+
+ for(;i>0 && curs.x>0; i--) {
+ do {
+ curs.x--;
+ } while (curs.x >0 && !tabs[curs.x]);
+ }
+ fix_cpos;
+ check_selection(old_curs, curs);
+ }
+ break;
+ case ANSI('L', '='):
+ compatibility(OTHER);
+ use_bce = (esc_args[0] <= 0);
+ erase_char = ERASE_CHAR;
+ if (use_bce)
+ erase_char = (' ' | ATTR_ASCII |
+ (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,50 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;
+ }