+ /* 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.)
+ */
+ if (state->cursor_x >= cols)
+ {
+ state->cursor_x = 0;
+ if (state->cursor_y >= rows - 1)
+ a2_scroll (st);
+ else
+ state->cursor_y++;
+ }
+
+ a2_goto(st, state->cursor_y, state->cursor_x); /* clips range */
+ a2_ascii_printc (st, c,
+ state->termattrib.bf.bold,
+ state->termattrib.bf.blink,
+ state->termattrib.bf.rev,
+ False);
+ state->cursor_x++;
+
+ break;
+ }
+ break;
+ case 1:
+ switch (c)
+ {
+ case 24: /* CAN */
+ case 26: /* SUB */
+ state->escstate = 0;
+ break;
+ case 'c': /* Reset */
+ a2_cls(st);
+ state->escstate = 0;
+ break;
+ case 'D': /* Linefeed */
+ if (state->cursor_y < rows - 1)
+ state->cursor_y++;
+ else
+ a2_scroll (st);
+ 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
+ a2_scroll (st);
+ }
+ }
+ 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)
+ 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)
+ 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)
+ state->cursor_y = rows - 1;
+ state->escstate = 0;
+ break;
+ case '`':
+ case 'G':
+ if ((state->cursor_x = (state->csiparam[0] - 1)) >= cols)
+ state->cursor_x = cols - 1;
+ state->escstate = 0;
+ break;
+ case 'f':
+ case 'H':
+ if ((state->cursor_y = (state->csiparam[0] - 1)) >= rows)
+ state->cursor_y = rows - 1;
+ if ((state->cursor_x = (state->csiparam[1] - 1)) >= cols)
+ 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;
+
+ a2_goto(st, state->cursor_y, state->cursor_x);
+ for (i = start; i < end; i++)
+ {
+ a2_ascii_printc(st, ' ', False, False, False, False);
+ }
+ 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;
+
+ a2_goto(st, state->cursor_y, state->cursor_x);
+ for (i = start; i < end; i++)
+ {
+ a2_ascii_printc(st, ' ', False, False, False, False);
+ }
+ state->escstate = 0;
+ break;
+ case 'm': /* Set attributes */
+ for (i = 0; i <= state->curparam; i++)
+ {
+ switch(state->csiparam[i])
+ {
+ case 0:
+ state->termattrib.w = 0;
+ break;
+ case 1:
+ state->termattrib.bf.bold = 1;
+ break;
+ case 5:
+ state->termattrib.bf.blink = 1;
+ break;
+ case 7:
+ state->termattrib.bf.rev = 1;
+ break;
+ case 21:
+ case 22:
+ state->termattrib.bf.bold = 0;
+ break;
+ case 25:
+ state->termattrib.bf.blink = 0;
+ break;
+ case 27:
+ state->termattrib.bf.rev = 0;
+ break;
+ }
+ }
+ 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;