mirror of
https://github.com/buserror/mii_emu.git
synced 2025-02-16 15:30:30 +00:00
106 lines
2.3 KiB
C
106 lines
2.3 KiB
C
/*
|
|
* mish_vt.c
|
|
*
|
|
* Copyright (C) 2020 Michel Pollet <buserror@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "mish_priv_vt.h"
|
|
|
|
#ifndef ARRAY_SIZE
|
|
#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0]))
|
|
#endif
|
|
|
|
/*
|
|
* Handle sequences of VT100 and UTF8 chars.
|
|
*
|
|
* Uses the sequence 's' as temporary buffer, and returns 1 when a complete
|
|
* sequence OR a glyph has been decoded.
|
|
*/
|
|
int
|
|
_mish_vt_sequence_char(
|
|
mish_vt_sequence_p s,
|
|
uint8_t ch)
|
|
{
|
|
// if previous sequence was done, reset it.
|
|
if (s->done)
|
|
s->flags = s->seq = s->glyph = s->pc = s->p[0] = 0;
|
|
switch (s->seq) {
|
|
case MISH_VT_RAW: {
|
|
switch (ch) {
|
|
case 0x1b:
|
|
s->seq = MISH_VT_ESC;
|
|
break;
|
|
default: {
|
|
if (ch & 0x80) { // UTF8 !??!
|
|
int mask = 0x40;
|
|
s->seq_want = 0;
|
|
while ((ch & mask) && s->seq_want < 5) {
|
|
s->seq_want++;
|
|
mask >>= 1;
|
|
}
|
|
// clear header bits (ought to be 2; 1 allows encoding of 0xffffff)
|
|
s->glyph = ch & (0xff >> (s->seq_want + 1));
|
|
s->seq = MISH_VT_UTF8;
|
|
} else {
|
|
s->seq = (s->seq << 8) | ch;
|
|
s->glyph = ch; // technically it's a glyph
|
|
s->done = 1;
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
case MISH_VT_ESC: {
|
|
if (ch == '[')
|
|
s->seq = MISH_VT_CSI;
|
|
else {
|
|
s->seq = (s->seq << 8) | ch;
|
|
s->done = 1;
|
|
}
|
|
} break;
|
|
case MISH_VT_CSIQ:
|
|
case MISH_VT_CSI: {
|
|
switch (ch) {
|
|
case '?': {
|
|
// note this would still accept somelike like CSI ? 00?; 1
|
|
if ((s->seq == MISH_VT_CSIQ) || s->pc) {
|
|
s->done = s->error = 1;
|
|
} else
|
|
s->seq = MISH_VT_CSIQ;
|
|
} break;
|
|
case '0' ... '9':
|
|
s->p[s->pc] = (s->p[s->pc] * 10) + (ch - '0');
|
|
break;
|
|
case ';': {
|
|
if (s->pc < ARRAY_SIZE(s->p)) {
|
|
s->pc++;
|
|
s->p[s->pc] = 0;
|
|
} else {
|
|
s->done = s->error = 1;
|
|
}
|
|
} break;
|
|
default:
|
|
if (s->p[s->pc])
|
|
s->pc++;
|
|
s->seq = (s->seq << 8) | ch;
|
|
s->done = 1;
|
|
break;
|
|
}
|
|
} break;
|
|
case MISH_VT_UTF8: {
|
|
s->glyph = (s->glyph << 6) | (ch & 0x3f);
|
|
if (s->seq_want) s->seq_want--;
|
|
s->done = s->seq_want == 0;
|
|
} break;
|
|
}
|
|
#ifdef MISH_VT_DEBUG
|
|
if (s->done)
|
|
fprintf(stderr, "in %x(%c) state %x done:%d error:%d pc:%d/%d\n",
|
|
ch, ch < ' '?'.':ch,s->seq, s->done, s->error,
|
|
s->pc, (int)ARRAY_SIZE(s->p));
|
|
#endif
|
|
return s->done;
|
|
}
|