+ int i, start, end;
+ 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 < state->grid_width - 8)
+ {
+ state->cursor_x = (state->cursor_x & ~7) + 8;
+ }
+ else
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y < state->grid_height - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ }
+ break;
+ case 10: /* LF */
+ 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 < state->grid_height - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ break;
+ case 13: /* CR */
+ state->cursor_x = 0;
+ cell = &state->cells[state->grid_width * 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 - I don't want to load several fonts for
+ the maybe two programs world-wide that use that */
+ 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:
+ 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 >= state->grid_width - 1)
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y >= state->grid_height - 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 < state->grid_height - 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 */
+ /* No, I don't support UTF-8, since the phosphor font
+ isn't even Unicode anyway. 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 > state->grid_width)
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y < state->grid_height - 1)
+ state->cursor_y++;
+ else
+ scroll (state);
+ }
+ cell = &state->cells[state->grid_width * 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]) >= state->grid_height - 1)
+ state->cursor_y = state->grid_height - 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]) >= state->grid_width - 1)
+ state->cursor_x = state->grid_width - 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)) >= state->grid_height - 1)
+ state->cursor_y = state->grid_height - 1;
+ state->escstate = 0;
+ break;
+ case '`':
+ case 'G':
+ if ((state->cursor_x = (state->csiparam[0] - 1)) >= state->grid_width - 1)
+ state->cursor_x = state->grid_width - 1;
+ state->escstate = 0;
+ break;
+ case 'f':
+ case 'H':
+ if ((state->cursor_y = (state->csiparam[0] - 1)) >= state->grid_height - 1)
+ state->cursor_y = state->grid_height - 1;
+ if ((state->cursor_x = (state->csiparam[1] - 1)) >= state->grid_width - 1)
+ state->cursor_x = state->grid_width - 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 = state->grid_height * state->grid_width;
+ if (state->csiparam[0] == 0)
+ start = state->grid_width * state->cursor_y + state->cursor_x;
+ if (state->csiparam[0] == 1)
+ end = state->grid_width * 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 = state->grid_width;
+ 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 '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;
+ }
+ set_cursor (state, True);