+ int i;
+ int start, end;
+
+ /* Mostly duplicated in apple2-main.c */
+
+ switch (state->escstate)
+ {
+ case 0:
+ switch (c)
+ {
+ case 7: /* BEL */
+ /* Dummy case - we don't want the screensaver to beep */
+ /* #### But maybe this should flash the screen? */
+ break;
+ case 8: /* BS */
+ if (state->cursor_x > 0)
+ state->cursor_x--;
+ break;
+ case 9: /* HT */
+ if (state->cursor_x < cols - 8)
+ {
+ state->cursor_x = (state->cursor_x & ~7) + 8;
+ }
+ else
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y < rows - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ }
+ break;
+ case 10: /* LF */
+# ifndef HAVE_FORKPTY
+ state->cursor_x = 0; /* No ptys on iPhone; assume CRLF. */
+# endif
+ case 11: /* VT */
+ case 12: /* FF */
+ if(state->last_c == 13)
+ {
+ cell->state = NORMAL;
+ cell->p_char = state->chars[state->bk];
+ cell->changed = True;
+ }
+ if (state->cursor_y < rows - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ break;
+ case 13: /* CR */
+ state->cursor_x = 0;
+ cell = &state->cells[cols * state->cursor_y];
+ if((cell->p_char == NULL) || (cell->p_char->name == CURSOR_INDEX))
+ state->bk = ' ';
+ else
+ state->bk = cell->p_char->name;
+ break;
+ case 14: /* SO */
+ case 15: /* SI */
+ /* Dummy case - there is one and only one font. */
+ break;
+ case 24: /* CAN */
+ case 26: /* SUB */
+ /* Dummy case - these interrupt escape sequences, so
+ they don't do anything in this state */
+ break;
+ case 27: /* ESC */
+ state->escstate = 1;
+ break;
+ case 127: /* DEL */
+ /* Dummy case - this is supposed to be ignored */
+ break;
+ case 155: /* CSI */
+ state->escstate = 2;
+ for(i = 0; i < NPAR; i++)
+ state->csiparam[i] = 0;
+ state->curparam = 0;
+ break;
+ default:
+
+ PRINT: /* Come from states 102-106 */
+ c = process_unicrud (state, c);
+ if (! c)
+ break;
+
+ /* If the cursor is in column 39 and we print a character, then
+ that character shows up in column 39, and the cursor is no
+ longer visible on the screen (it's in "column 40".) If
+ another character is printed, then that character shows up in
+ column 0, and the cursor moves to column 1.
+
+ This is empirically what xterm and gnome-terminal do, so that
+ must be the right thing. (In xterm, the cursor vanishes,
+ whereas; in gnome-terminal, the cursor overprints the
+ character in col 39.)
+ */
+ cell->state = FLARE;
+ cell->p_char = state->chars[c];
+ cell->changed = True;
+ state->cursor_x++;
+
+ if (c != ' ' && cell->p_char->blank_p)
+ cell->p_char = state->chars[CURSOR_INDEX];
+
+ if (state->cursor_x >= cols - 1 /*####*/)
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y >= rows - 1)
+ scroll (state);
+ else
+ state->cursor_y++;
+ }
+ break;
+ }
+ break;
+ case 1:
+ switch (c)
+ {
+ case 24: /* CAN */
+ case 26: /* SUB */
+ state->escstate = 0;
+ break;
+ case 'c': /* Reset */
+ clear (state);
+ state->escstate = 0;
+ break;
+ case 'D': /* Linefeed */
+ if (state->cursor_y < rows - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ state->escstate = 0;
+ break;
+ case 'E': /* Newline */
+ state->cursor_x = 0;
+ state->escstate = 0;
+ break;
+ case 'M': /* Reverse newline */
+ if (state->cursor_y > 0)
+ state->cursor_y--;
+ state->escstate = 0;
+ break;
+ case '7': /* Save state */
+ state->saved_x = state->cursor_x;
+ state->saved_y = state->cursor_y;
+ state->escstate = 0;
+ break;
+ case '8': /* Restore state */
+ state->cursor_x = state->saved_x;
+ state->cursor_y = state->saved_y;
+ state->escstate = 0;
+ break;
+ case '[': /* CSI */
+ state->escstate = 2;
+ for(i = 0; i < NPAR; i++)
+ state->csiparam[i] = 0;
+ state->curparam = 0;
+ break;
+ case '%': /* Select charset */
+ /* @: Select default (ISO 646 / ISO 8859-1)
+ G: Select UTF-8
+ 8: Select UTF-8 (obsolete)
+
+ We can just ignore this and always process UTF-8, I think?
+ We must still catch the last byte, though.
+ */
+ case '(':
+ case ')':
+ /* I don't support different fonts either - see above
+ for SO and SI */
+ state->escstate = 3;
+ break;
+ default:
+ /* Escape sequences not supported:
+ *
+ * H - Set tab stop
+ * Z - Terminal identification
+ * > - Keypad change
+ * = - Other keypad change
+ * ] - OS command
+ */
+ state->escstate = 0;
+ break;
+ }
+ break;
+ case 2:
+ switch (c)
+ {
+ case 24: /* CAN */
+ case 26: /* SUB */
+ state->escstate = 0;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (state->curparam < NPAR)
+ state->csiparam[state->curparam] = (state->csiparam[state->curparam] * 10) + (c - '0');
+ break;
+ case ';':
+ state->csiparam[++state->curparam] = 0;
+ break;
+ case '[':
+ state->escstate = 3;
+ break;
+ case '@':
+ for (i = 0; i < state->csiparam[0]; i++)
+ {
+ if(++state->cursor_x > cols)
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y < rows - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ }
+ cell = &state->cells[cols * state->cursor_y + state->cursor_x];
+ if (cell->state == FLARE || cell->state == NORMAL)
+ {
+ cell->state = FADE;
+ cell->changed = True;
+ }
+ }
+ state->escstate = 0;
+ break;
+ case 'F':
+ state->cursor_x = 0;
+ case 'A':
+ if (state->csiparam[0] == 0)
+ state->csiparam[0] = 1;
+ if ((state->cursor_y -= state->csiparam[0]) < 0)
+ state->cursor_y = 0;
+ state->escstate = 0;
+ break;
+ case 'E':
+ state->cursor_x = 0;
+ case 'e':
+ case 'B':
+ if (state->csiparam[0] == 0)
+ state->csiparam[0] = 1;
+ if ((state->cursor_y += state->csiparam[0]) >= rows - 1 /*####*/)
+ state->cursor_y = rows - 1;
+ state->escstate = 0;
+ break;
+ case 'a':
+ case 'C':
+ if (state->csiparam[0] == 0)
+ state->csiparam[0] = 1;
+ if ((state->cursor_x += state->csiparam[0]) >= cols - 1 /*####*/)
+ state->cursor_x = cols - 1;
+ state->escstate = 0;
+ break;
+ case 'D':
+ if (state->csiparam[0] == 0)
+ state->csiparam[0] = 1;
+ if ((state->cursor_x -= state->csiparam[0]) < 0)
+ state->cursor_x = 0;
+ state->escstate = 0;
+ break;
+ case 'd':
+ if ((state->cursor_y = (state->csiparam[0] - 1)) >= rows - 1 /*####*/)
+ state->cursor_y = rows - 1;
+ state->escstate = 0;
+ break;
+ case '`':
+ case 'G':
+ if ((state->cursor_x = (state->csiparam[0] - 1)) >= cols - 1 /*####*/)
+ state->cursor_x = cols - 1;
+ state->escstate = 0;
+ break;
+ case 'f':
+ case 'H':
+ if ((state->cursor_y = (state->csiparam[0] - 1)) >= rows - 1 /*####*/)
+ state->cursor_y = rows - 1;
+ if ((state->cursor_x = (state->csiparam[1] - 1)) >= cols - 1 /*####*/)
+ state->cursor_x = cols - 1;
+ if(state->cursor_y < 0)
+ state->cursor_y = 0;
+ if(state->cursor_x < 0)
+ state->cursor_x = 0;
+ state->escstate = 0;
+ break;
+ case 'J':
+ start = 0;
+ end = rows * cols;
+ if (state->csiparam[0] == 0)
+ start = cols * state->cursor_y + state->cursor_x;
+ if (state->csiparam[0] == 1)
+ end = cols * state->cursor_y + state->cursor_x;
+ for (i = start; i < end; i++)
+ {
+ cell = &state->cells[i];
+ if (cell->state == FLARE || cell->state == NORMAL)
+ {
+ cell->state = FADE;
+ cell->changed = True;
+ }
+ }
+ set_cursor (state, True);
+ state->escstate = 0;
+ break;
+ case 'K':
+ start = 0;
+ end = cols;
+ if (state->csiparam[0] == 0)
+ start = state->cursor_x;
+ if (state->csiparam[1] == 1)
+ end = state->cursor_x;
+ for (i = start; i < end; i++)
+ {
+ if (cell->state == FLARE || cell->state == NORMAL)
+ {
+ cell->state = FADE;
+ cell->changed = True;
+ }
+ cell++;
+ }
+ state->escstate = 0;
+ break;
+ case 'm': /* Set attributes unimplemented (bold, blink, rev) */
+ state->escstate = 0;
+ break;
+ case 's': /* Save position */
+ state->saved_x = state->cursor_x;
+ state->saved_y = state->cursor_y;
+ state->escstate = 0;
+ break;
+ case 'u': /* Restore position */
+ state->cursor_x = state->saved_x;
+ state->cursor_y = state->saved_y;
+ state->escstate = 0;
+ break;
+ case '?': /* DEC Private modes */
+ if ((state->curparam != 0) || (state->csiparam[0] != 0))
+ state->escstate = 0;
+ break;
+ default:
+ /* Known unsupported CSIs:
+ *
+ * L - Insert blank lines
+ * M - Delete lines (I don't know what this means...)
+ * P - Delete characters
+ * X - Erase characters (difference with P being...?)
+ * c - Terminal identification
+ * g - Clear tab stop(s)
+ * h - Set mode (Mainly due to its complexity and lack of good
+ docs)
+ * l - Clear mode
+ * m - Set mode (Phosphor is, per defenition, green on black)
+ * n - Status report
+ * q - Set keyboard LEDs
+ * r - Set scrolling region (too exhausting - noone uses this,
+ right?)
+ */
+ state->escstate = 0;
+ break;
+ }
+ break;
+ case 3:
+ state->escstate = 0;
+ break;
+
+ case 102: /* states 102-106 are for UTF-8 decoding */
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ goto PRINT;
+
+ default:
+ abort();
+ }
+ set_cursor (state, True);