+ switch (ch) {
+ case 'h':
+ spiceterm_set_mode (vt, 1);
+ break;
+ case 'l':
+ spiceterm_set_mode (vt, 0);
+ break;
+ case 'm':
+ if (!vt->esc_count) {
+ vt->esc_count++; // default parameter 0
+ }
+ spiceterm_csi_m (vt);
+ break;
+ case 'n':
+ /* report cursor position */
+ /* TODO: send ESC[row;colR */
+ break;
+ case 'A':
+ /* move cursor up */
+ if (vt->esc_buf[0] == 0) {
+ vt->esc_buf[0] = 1;
+ }
+ vt->cy -= vt->esc_buf[0];
+ if (vt->cy < 0) {
+ vt->cy = 0;
+ }
+ break;
+ case 'B':
+ case 'e':
+ /* move cursor down */
+ if (vt->esc_buf[0] == 0) {
+ vt->esc_buf[0] = 1;
+ }
+ vt->cy += vt->esc_buf[0];
+ if (vt->cy >= vt->height) {
+ vt->cy = vt->height - 1;
+ }
+ break;
+ case 'C':
+ case 'a':
+ /* move cursor right */
+ if (vt->esc_buf[0] == 0) {
+ vt->esc_buf[0] = 1;
+ }
+ vt->cx += vt->esc_buf[0];
+ if (vt->cx >= vt->width) {
+ vt->cx = vt->width - 1;
+ }
+ break;
+ case 'D':
+ /* move cursor left */
+ if (vt->esc_buf[0] == 0) {
+ vt->esc_buf[0] = 1;
+ }
+ vt->cx -= vt->esc_buf[0];
+ if (vt->cx < 0) {
+ vt->cx = 0;
+ }
+ break;
+ case 'G':
+ case '`':
+ /* move cursor to column */
+ spiceterm_gotoxy (vt, vt->esc_buf[0] - 1, vt->cy);
+ break;
+ case 'd':
+ /* move cursor to row */
+ spiceterm_gotoxy (vt, vt->cx , vt->esc_buf[0] - 1);
+ break;
+ case 'f':
+ case 'H':
+ /* move cursor to row, column */
+ spiceterm_gotoxy (vt, vt->esc_buf[1] - 1, vt->esc_buf[0] - 1);
+ break;
+ case 'J':
+ switch (vt->esc_buf[0]) {
+ case 0:
+ /* clear to end of screen */
+ for (y = vt->cy; y < vt->height; y++) {
+ for (x = 0; x < vt->width; x++) {
+ if (y == vt->cy && x < vt->cx) {
+ continue;
+ }
+ spiceterm_clear_xy (vt, x, y);
+ }
+ }
+ break;
+ case 1:
+ /* clear from beginning of screen */
+ for (y = 0; y <= vt->cy; y++) {
+ for (x = 0; x < vt->width; x++) {
+ if (y == vt->cy && x > vt->cx) {
+ break;
+ }
+ spiceterm_clear_xy (vt, x, y);
+ }
+ }
+ break;
+ case 2:
+ /* clear entire screen */
+ for (y = 0; y <= vt->height; y++) {
+ for (x = 0; x < vt->width; x++) {
+ spiceterm_clear_xy (vt, x, y);
+ }
+ }
+ break;
+ }
+ break;
+ case 'K':
+ switch (vt->esc_buf[0]) {
+ case 0:
+ /* clear to eol */
+ for(x = vt->cx; x < vt->width; x++) {
+ spiceterm_clear_xy (vt, x, vt->cy);
+ }
+ break;
+ case 1:
+ /* clear from beginning of line */
+ for (x = 0; x <= vt->cx; x++) {
+ spiceterm_clear_xy (vt, x, vt->cy);
+ }
+ break;
+ case 2:
+ /* clear entire line */
+ for(x = 0; x < vt->width; x++) {
+ spiceterm_clear_xy (vt, x, vt->cy);
+ }
+ break;
+ }
+ break;
+ case 'L':
+ /* insert line */
+ c = vt->esc_buf[0];
+
+ if (c > vt->height - vt->cy)
+ c = vt->height - vt->cy;
+ else if (!c)
+ c = 1;
+
+ spiceterm_scroll_down (vt, vt->cy, vt->region_bottom, c);
+ break;
+ case 'M':
+ /* delete line */
+ c = vt->esc_buf[0];
+
+ if (c > vt->height - vt->cy)
+ c = vt->height - vt->cy;
+ else if (!c)
+ c = 1;
+
+ spiceterm_scroll_up (vt, vt->cy, vt->region_bottom, c, 1);
+ break;
+ case 'T':
+ /* scroll down */
+ c = vt->esc_buf[0];
+ if (!c) c = 1;
+ spiceterm_scroll_down (vt, vt->region_top, vt->region_bottom, c);
+ break;
+ case 'S':
+ /* scroll up */
+ c = vt->esc_buf[0];
+ if (!c) c = 1;
+ spiceterm_scroll_up (vt, vt->region_top, vt->region_bottom, c, 1);
+ break;
+ case 'P':
+ /* delete c character */
+ c = vt->esc_buf[0];
+
+ if (c > vt->width - vt->cx)
+ c = vt->width - vt->cx;
+ else if (!c)
+ c = 1;
+
+ for (x = vt->cx; x < vt->width - c; x++) {
+ int y1 = (vt->y_base + vt->cy) % vt->total_height;
+ TextCell *dst = &vt->cells[y1 * vt->width + x];
+ TextCell *src = dst + c;
+ *dst = *src;
+ spiceterm_update_xy (vt, x + c, vt->cy);
+ src->ch = ' ';
+ src->attrib = vt->default_attrib;
+ spiceterm_update_xy (vt, x, vt->cy);
+ }
+ break;
+ case 's':
+ /* save cursor position */
+ spiceterm_save_cursor (vt);
+ break;
+ case 'u':
+ /* restore cursor position */
+ spiceterm_restore_cursor (vt);
+ break;
+ case 'X':
+ /* erase c characters */
+ c = vt->esc_buf[0];
+ if (!c) c = 1;
+
+ if (c > (vt->width - vt->cx)) c = vt->width - vt->cx;
+
+ for(i = 0; i < c; i++) {
+ spiceterm_clear_xy (vt, vt->cx + i, vt->cy);
+ }
+ break;
+ case '@':
+ /* insert c character */
+ c = vt->esc_buf[0];
+ if (c > (vt->width - vt->cx)) {
+ c = vt->width - vt->cx;
+ }
+ if (!c) c = 1;
+
+ for (x = vt->width - c; x >= vt->cx; x--) {
+ int y1 = (vt->y_base + vt->cy) % vt->total_height;
+ TextCell *src = &vt->cells[y1 * vt->width + x];
+ TextCell *dst = src + c;
+ *dst = *src;
+ spiceterm_update_xy (vt, x + c, vt->cy);
+ src->ch = ' ';
+ src->attrib = vt->cur_attrib;
+ spiceterm_update_xy (vt, x, vt->cy);
+ }
+
+ break;
+ case 'r':
+ /* set region */
+ if (!vt->esc_buf[0])
+ vt->esc_buf[0]++;
+ if (!vt->esc_buf[1])
+ vt->esc_buf[1] = vt->height;
+ /* Minimum allowed region is 2 lines */
+ if (vt->esc_buf[0] < vt->esc_buf[1] &&
+ vt->esc_buf[1] <= vt->height) {
+ vt->region_top = vt->esc_buf[0] - 1;
+ vt->region_bottom = vt->esc_buf[1];
+ vt->cx = 0;
+ vt->cy = vt->region_top;
+ DPRINTF(1, "set region %d %d", vt->region_top, vt->region_bottom);
+ }
+
+ break;
+ default:
+ if (debug) {
+ debug_print_escape_buffer(vt, __func__, " unhandled escape", qes, ch);
+ }
+ break;
+ }
+ vt->esc_ques = 0;
+ break;
+ case ESsetG0: // Set G0
+ vt->tty_state = ESnormal;
+
+ if (ch == '0')
+ vt->g0enc = GRAF_MAP;
+ else if (ch == 'B')
+ vt->g0enc = LAT1_MAP;
+ else if (ch == 'U')
+ vt->g0enc = IBMPC_MAP;
+ else if (ch == 'K')
+ vt->g0enc = USER_MAP;
+
+ if (vt->charset == 0)
+ vt->cur_enc = vt->g0enc;
+
+ break;
+ case ESsetG1: // Set G1
+ vt->tty_state = ESnormal;
+
+ if (ch == '0')
+ vt->g1enc = GRAF_MAP;
+ else if (ch == 'B')
+ vt->g1enc = LAT1_MAP;
+ else if (ch == 'U')
+ vt->g1enc = IBMPC_MAP;
+ else if (ch == 'K')
+ vt->g1enc = USER_MAP;
+
+ if (vt->charset == 1)
+ vt->cur_enc = vt->g1enc;
+
+ break;
+ case ESidquery: // vt100 query id
+ vt->tty_state = ESnormal;
+
+ if (ch == 'c') {
+ DPRINTF(1, "ESC[>c Query term ID");
+ spiceterm_respond_esc (vt, TERMIDCODE);
+ }
+ break;
+ case ESpercent:
+ vt->tty_state = ESnormal;
+ switch (ch) {
+ case '@': /* defined in ISO 2022 */
+ vt->utf8 = 0;
+ break;
+ case 'G': /* prelim official escape code */
+ case '8': /* retained for compatibility */
+ vt->utf8 = 1;
+ break;
+ }
+ break;
+ default: // ESnormal
+ vt->tty_state = ESnormal;
+
+ switch(ch) {
+ case 0:
+ break;
+ case 7: /* alert aka. bell */
+ // fixme:
+ //rfbSendBell(vt->screen);
+ break;
+ case 8: /* backspace */
+ if (vt->cx > 0)
+ vt->cx--;
+ break;
+ case 9: /* tabspace */
+ if (vt->cx + (8 - (vt->cx % 8)) > vt->width) {
+ vt->cx = 0;
+ spiceterm_put_lf (vt);
+ } else {
+ vt->cx = vt->cx + (8 - (vt->cx % 8));
+ }
+ break;
+ case 10: /* LF,*/
+ case 11: /* VT */
+ case 12: /* FF */
+ spiceterm_put_lf (vt);
+ break;
+ case 13: /* carriage return */
+ vt->cx = 0;
+ break;
+ case 14:
+ /* SI (shift in), select character set 1 */
+ vt->charset = 1;
+ vt->cur_enc = vt->g1enc;
+ /* fixme: display controls = 1 */
+ break;
+ case 15:
+ /* SO (shift out), select character set 0 */
+ vt->charset = 0;
+ vt->cur_enc = vt->g0enc;
+ /* fixme: display controls = 0 */
+ break;
+ case 27: /* esc */
+ vt->tty_state = ESesc;
+ break;
+ case 127: /* delete */
+ /* ignore */
+ break;
+ case 128+27: /* csi */
+ vt->tty_state = ESsquare;
+ break;
+ default:
+ if (vt->cx >= vt->width) {
+ /* line wrap */
+ vt->cx = 0;
+ spiceterm_put_lf (vt);
+ }
+
+ int y1 = (vt->y_base + vt->cy) % vt->total_height;
+ TextCell *c = &vt->cells[y1*vt->width + vt->cx];
+ c->attrib = vt->cur_attrib;
+ c->ch = ch;
+ spiceterm_update_xy (vt, vt->cx, vt->cy);
+ vt->cx++;
+ break;
+ }
+ break;