some more missing commands, added code pages, fixed the xterm size command and some other stuff. also FRAKTUR
This commit is contained in:
+2
-2
@@ -5,7 +5,7 @@
|
||||
#include <screen.h>
|
||||
|
||||
// Max nr of CSI parameters
|
||||
#define CSI_N_MAX 3
|
||||
#define CSI_N_MAX 10
|
||||
#define OSC_CHAR_MAX TERM_TITLE_LEN
|
||||
|
||||
extern void apars_handle_plainchar(char c);
|
||||
@@ -22,7 +22,7 @@ extern void apars_reset_utf8buffer(void);
|
||||
// defined in the makefile
|
||||
#if DEBUG_ANSI
|
||||
#define ansi_warn warn
|
||||
#define ansi_dbg warn
|
||||
#define ansi_dbg dbg
|
||||
#else
|
||||
#define ansi_warn(...)
|
||||
#define ansi_dbg(...)
|
||||
|
||||
@@ -22,9 +22,17 @@ static int utf_j = 0;
|
||||
void ICACHE_FLASH_ATTR
|
||||
apars_handle_plainchar(char c)
|
||||
{
|
||||
if (c == 7) return; // BELL - beep (TODO play beep in browser)
|
||||
|
||||
// collecting unicode glyphs...
|
||||
if (c & 0x80) {
|
||||
if (utf_i == 0) {
|
||||
// start
|
||||
if (c == 192 || c == 193 || c >= 245) {
|
||||
// forbidden codes
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((c & 0xE0) == 0xC0) {
|
||||
utf_i = 2;
|
||||
}
|
||||
@@ -34,15 +42,17 @@ apars_handle_plainchar(char c)
|
||||
else if ((c & 0xF8) == 0xF0) {
|
||||
utf_i = 4;
|
||||
}
|
||||
else {
|
||||
// chars over 127 that don't start unicode sequences
|
||||
goto fail;
|
||||
}
|
||||
|
||||
utf_collect[0] = c;
|
||||
utf_j = 1;
|
||||
}
|
||||
else {
|
||||
if ((c & 0xC0) != 0x80) {
|
||||
// bad UTF
|
||||
ansi_warn("Bad UTF-8");
|
||||
apars_reset_utf8buffer();
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
utf_collect[utf_j++] = c;
|
||||
@@ -54,9 +64,12 @@ apars_handle_plainchar(char c)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c == 14 || c == 15) { // pushIn, pushOut
|
||||
//ansi_warn("char %d ignored", c);
|
||||
// TODO implement for charset switching
|
||||
if (c == 14) {
|
||||
screen_set_charset_n(1);
|
||||
return;
|
||||
}
|
||||
if (c == 15) {
|
||||
screen_set_charset_n(0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,6 +77,11 @@ apars_handle_plainchar(char c)
|
||||
utf_collect[1] = 0; // just to make sure it's closed...
|
||||
screen_putchar(utf_collect);
|
||||
}
|
||||
|
||||
return;
|
||||
fail:
|
||||
ansi_warn("Bad UTF-8");
|
||||
apars_reset_utf8buffer();
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
@@ -77,8 +95,8 @@ apars_reset_utf8buffer(void)
|
||||
void ICACHE_FLASH_ATTR
|
||||
apars_handle_characterSet(char leadchar, char c)
|
||||
{
|
||||
// TODO implement for charset switching
|
||||
// ansi_warn("NOIMPL charset cmd %c%c", leadchar, c);
|
||||
if (leadchar == '(') screen_set_charset(0, c);
|
||||
else if (leadchar == ')') screen_set_charset(1, c);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
@@ -97,35 +115,10 @@ apars_handle_setXCtrls(char c)
|
||||
void ICACHE_FLASH_ATTR
|
||||
apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
||||
{
|
||||
/*
|
||||
Implemented codes (from Wikipedia)
|
||||
|
||||
CSI n A CUU – Cursor Up
|
||||
CSI n B CUD – Cursor Down
|
||||
CSI n C CUF – Cursor Forward
|
||||
CSI n D CUB – Cursor Back
|
||||
CSI n E CNL – Cursor Next Line
|
||||
CSI n F CPL – Cursor Previous Line
|
||||
CSI n G CHA – Cursor Horizontal Absolute
|
||||
CSI n ; m H CUP – Cursor Position
|
||||
CSI n J ED – Erase Display
|
||||
CSI n K EL – Erase in Line
|
||||
CSI n S SU – Scroll Up
|
||||
CSI n T SD – Scroll Down
|
||||
CSI n ; m f HVP – Horizontal and Vertical Position
|
||||
CSI n m SGR – Select Graphic Rendition (Implemented only some)
|
||||
CSI 6n DSR – Device Status Report
|
||||
CSI s SCP – Save Cursor Position
|
||||
CSI u RCP – Restore Cursor Position
|
||||
CSI ?25l DECTCEM Hides the cursor
|
||||
CSI ?25h DECTCEM Shows the cursor
|
||||
|
||||
and some others
|
||||
*/
|
||||
|
||||
int n1 = params[0];
|
||||
int n2 = params[1];
|
||||
// int n3 = params[2];
|
||||
int n3 = params[2];
|
||||
static char buf[20];
|
||||
|
||||
// defaults
|
||||
switch (keychar) {
|
||||
@@ -306,20 +299,53 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
||||
else if (n >= 40 && n <= 47) screen_set_bg((Color) (n - 40)); // ANSI normal bg
|
||||
else if (n == 39) screen_set_fg(termconf_scratch.default_fg); // default fg
|
||||
else if (n == 49) screen_set_bg(termconf_scratch.default_bg); // default bg
|
||||
else if (n == 7) screen_inverse(true); // inverse
|
||||
else if (n == 27) screen_inverse(false); // positive
|
||||
else if (n == 1) screen_set_bold(true); // bold
|
||||
else if (n == 21 || n == 22) screen_set_bold(false); // bold off
|
||||
|
||||
else if (n == 1) screen_attr_enable(ATTR_BOLD);
|
||||
else if (n == 2) screen_attr_enable(ATTR_FAINT);
|
||||
else if (n == 3) screen_attr_enable(ATTR_ITALIC);
|
||||
else if (n == 4) screen_attr_enable(ATTR_UNDERLINE);
|
||||
else if (n == 5 || n == 6) screen_attr_enable(ATTR_BLINK); // 6 - rapid blink, not supported
|
||||
else if (n == 7) screen_inverse_enable(true);
|
||||
else if (n == 9) screen_attr_enable(ATTR_STRIKE);
|
||||
|
||||
else if (n == 20) screen_attr_enable(ATTR_FRAKTUR);
|
||||
else if (n == 21) screen_attr_disable(ATTR_BOLD);
|
||||
else if (n == 22) screen_attr_disable(ATTR_FAINT);
|
||||
else if (n == 23) screen_attr_disable(ATTR_ITALIC|ATTR_FRAKTUR);
|
||||
else if (n == 24) screen_attr_disable(ATTR_UNDERLINE);
|
||||
else if (n == 25) screen_attr_disable(ATTR_BLINK);
|
||||
else if (n == 27) screen_inverse_enable(false);
|
||||
else if (n == 29) screen_attr_disable(ATTR_STRIKE);
|
||||
|
||||
else if (n >= 90 && n <= 97) screen_set_fg((Color) (n - 90 + 8)); // AIX bright fg
|
||||
else if (n >= 100 && n <= 107) screen_set_bg((Color) (n - 100 + 8)); // AIX bright bg
|
||||
else {
|
||||
ansi_warn("NOIMPL SGR attr %d", n);
|
||||
ansi_warn("NOIMPL SGR attr %d", n);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': // SunView code to set screen size (from GNU Screen)
|
||||
screen_resize(n1, n2);
|
||||
case 't': // xterm hacks
|
||||
switch(n1) {
|
||||
case 8: // set size
|
||||
screen_resize(n2, n3);
|
||||
break;
|
||||
case 18: // report size
|
||||
printf(buf, "\033[8;%d;%dt", termconf_scratch.height, termconf_scratch.width);
|
||||
UART_WriteString(UART0, buf, UART_TIMEOUT_US);
|
||||
break;
|
||||
case 11: // Report iconified -> is not iconified
|
||||
UART_WriteString(UART0, "\033[1t", UART_TIMEOUT_US);
|
||||
break;
|
||||
case 21: // Report title
|
||||
UART_WriteString(UART0, "\033]L", UART_TIMEOUT_US);
|
||||
UART_WriteString(UART0, termconf_scratch.title, UART_TIMEOUT_US);
|
||||
UART_WriteString(UART0, "\033\\", UART_TIMEOUT_US);
|
||||
break;
|
||||
case 24: // Set Height only
|
||||
screen_resize(n2, termconf_scratch.width);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
@@ -340,7 +366,7 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
||||
|
||||
case 'r':
|
||||
// TODO scrolling region
|
||||
ansi_warn("NOIMPL scrolling region");
|
||||
// ansi_warn("NOIMPL scrolling region");
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
@@ -358,6 +384,18 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
||||
ansi_warn("NOIMPL CSI setmode %d", n1);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (leadchar == '!') {
|
||||
info("SOFT RESET!");
|
||||
system_restart();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
// report capabilities (pretend we're vt4xx)
|
||||
UART_WriteString(UART0, "\033[?64;22;c", UART_TIMEOUT_US);
|
||||
break;
|
||||
|
||||
default:
|
||||
ansi_warn("Unknown CSI: %c", keychar);
|
||||
apars_handle_badseq();
|
||||
|
||||
+178
-69
@@ -8,6 +8,9 @@
|
||||
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
||||
TerminalConfigBundle termconf_scratch;
|
||||
|
||||
// forward declare
|
||||
static void utf8_remap(char* out, char g, char table);
|
||||
|
||||
#define W termconf_scratch.width
|
||||
#define H termconf_scratch.height
|
||||
|
||||
@@ -61,7 +64,7 @@ typedef struct __attribute__((packed)){
|
||||
char c[4]; // space for a full unicode character
|
||||
Color fg : 4;
|
||||
Color bg : 4;
|
||||
bool bold : 1;
|
||||
u8 attrs;
|
||||
} Cell;
|
||||
|
||||
/**
|
||||
@@ -75,10 +78,15 @@ static Cell screen[MAX_SCREEN_SIZE];
|
||||
static struct {
|
||||
int x; //!< X coordinate
|
||||
int y; //!< Y coordinate
|
||||
bool visible; //!< Visible
|
||||
bool inverse; //!< Inverse colors
|
||||
bool autowrap; //!< Wrapping when EOL
|
||||
bool bold; //!< Bold style
|
||||
bool visible; //!< Visible (not attribute, DEC special)
|
||||
bool inverse;
|
||||
u8 attrs;
|
||||
|
||||
char charset0;
|
||||
char charset1;
|
||||
int charsetN;
|
||||
|
||||
Color fg; //!< Foreground color for writing
|
||||
Color bg; //!< Background color for writing
|
||||
} cursor;
|
||||
@@ -89,10 +97,10 @@ static struct {
|
||||
static struct {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
// optionally saved attrs
|
||||
// mark that attrs are saved
|
||||
bool withAttrs;
|
||||
bool inverse;
|
||||
u8 attrs;
|
||||
bool inverse; // attribute that's not in the bitfield
|
||||
Color fg;
|
||||
Color bg;
|
||||
} cursor_sav;
|
||||
@@ -120,8 +128,8 @@ static inline void
|
||||
clear_range(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (to >= W*H) to = W*H-1;
|
||||
Color fg = cursor.inverse ? cursor.bg : cursor.fg;
|
||||
Color bg = cursor.inverse ? cursor.fg : cursor.bg;
|
||||
Color fg = (cursor.inverse) ? cursor.bg : cursor.fg;
|
||||
Color bg = (cursor.inverse) ? cursor.fg : cursor.bg;
|
||||
|
||||
Cell sample;
|
||||
sample.c[0] = ' ';
|
||||
@@ -130,7 +138,7 @@ clear_range(unsigned int from, unsigned int to)
|
||||
sample.c[3] = 0;
|
||||
sample.fg = fg;
|
||||
sample.bg = bg;
|
||||
sample.bold = false;
|
||||
sample.attrs = 0;
|
||||
|
||||
for (unsigned int i = from; i <= to; i++) {
|
||||
memcpy(&screen[i], &sample, sizeof(Cell));
|
||||
@@ -148,9 +156,12 @@ cursor_reset(void)
|
||||
cursor.fg = termconf_scratch.default_fg;
|
||||
cursor.bg = termconf_scratch.default_bg;
|
||||
cursor.visible = 1;
|
||||
cursor.inverse = 0;
|
||||
cursor.autowrap = 1;
|
||||
cursor.bold = 0;
|
||||
cursor.attrs = 0;
|
||||
|
||||
cursor.charset0 = 'B';
|
||||
cursor.charset1 = '0';
|
||||
cursor.charsetN = 0;
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -188,8 +199,8 @@ screen_reset_cursor(void)
|
||||
{
|
||||
cursor.fg = termconf_scratch.default_fg;
|
||||
cursor.bg = termconf_scratch.default_bg;
|
||||
cursor.inverse = 0;
|
||||
cursor.bold = 0;
|
||||
cursor.attrs = 0;
|
||||
cursor.inverse = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +273,7 @@ screen_fill_with_E(void)
|
||||
sample.c[3] = 0;
|
||||
sample.fg = termconf_scratch.default_fg;
|
||||
sample.bg = termconf_scratch.default_bg;
|
||||
sample.bold = false;
|
||||
sample.attrs = 0;
|
||||
|
||||
for (unsigned int i = 0; i <= W*H-1; i++) {
|
||||
memcpy(&screen[i], &sample, sizeof(Cell));
|
||||
@@ -531,11 +542,11 @@ screen_cursor_save(bool withAttrs)
|
||||
if (withAttrs) {
|
||||
cursor_sav.fg = cursor.fg;
|
||||
cursor_sav.bg = cursor.bg;
|
||||
cursor_sav.inverse = cursor.inverse;
|
||||
cursor_sav.attrs = cursor.attrs;
|
||||
} else {
|
||||
cursor_sav.fg = termconf_scratch.default_fg;
|
||||
cursor_sav.bg = termconf_scratch.default_bg;
|
||||
cursor_sav.inverse = 0;
|
||||
cursor_sav.attrs = 0; // avoid leftovers if the wrong restore is used
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +563,7 @@ screen_cursor_restore(bool withAttrs)
|
||||
if (withAttrs) {
|
||||
cursor.fg = cursor_sav.fg;
|
||||
cursor.bg = cursor_sav.bg;
|
||||
cursor.inverse = cursor_sav.inverse;
|
||||
cursor.attrs = cursor_sav.attrs;
|
||||
}
|
||||
|
||||
NOTIFY_DONE();
|
||||
@@ -604,43 +615,19 @@ screen_set_bg(Color color)
|
||||
cursor.bg = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cursor foreground and background color
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
screen_set_colors(Color fg, Color bg)
|
||||
void screen_attr_enable(u8 attrs)
|
||||
{
|
||||
screen_set_fg(fg);
|
||||
screen_set_bg(bg);
|
||||
cursor.attrs |= attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invert colors
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
screen_inverse(bool inverse)
|
||||
void screen_attr_disable(u8 attrs)
|
||||
{
|
||||
cursor.inverse = inverse;
|
||||
cursor.attrs &= ~attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make foreground bright.
|
||||
*
|
||||
* This relates to the '1' SGR command which originally means
|
||||
* "bold font". We interpret that as "Bright", similar to other
|
||||
* terminal emulators.
|
||||
*
|
||||
* Note that the bright colors can be used without bold using the 90+ codes
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
screen_set_bold(bool bold)
|
||||
void screen_inverse_enable(bool ena)
|
||||
{
|
||||
if (!bold) {
|
||||
cursor.fg = (Color) (cursor.fg % 8);
|
||||
} else {
|
||||
cursor.fg = (Color) ((cursor.fg % 8) + 8); // change anything to the bright colors
|
||||
}
|
||||
cursor.bold = bold;
|
||||
cursor.inverse = ena;
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -657,12 +644,26 @@ bool ICACHE_FLASH_ATTR screen_isCoordValid(int y, int x)
|
||||
return x >= 0 && y >= 0 && x < W && y < H;
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR screen_set_charset_n(int Gx)
|
||||
{
|
||||
if (Gx < 0 || Gx > 1) return; // bad n
|
||||
cursor.charsetN = Gx;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR screen_set_charset(int Gx, char charset)
|
||||
{
|
||||
if (Gx == 0) cursor.charset0 = charset;
|
||||
if (Gx == 1) cursor.charset1 = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a character in the cursor color, move to right with wrap.
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
screen_putchar(const char *ch)
|
||||
{
|
||||
char buf[4];
|
||||
NOTIFY_LOCK();
|
||||
|
||||
Cell *c = &screen[cursor.x + cursor.y * W];
|
||||
@@ -687,15 +688,11 @@ screen_putchar(const char *ch)
|
||||
cursor.y--;
|
||||
}
|
||||
}
|
||||
// erase target cell
|
||||
c = &screen[cursor.x + cursor.y * W];
|
||||
c->c[0] = ' ';
|
||||
c->c[1] = 0;
|
||||
c->c[2] = 0;
|
||||
c->c[3] = 0;
|
||||
// apparently backspace should not clear the cell
|
||||
goto done;
|
||||
|
||||
case 9: // TAB
|
||||
// TODO change if tab setting is ever implemented
|
||||
if (cursor.x<((W-1)-(W-1)%4)) {
|
||||
c->c[0] = ' ';
|
||||
c->c[1] = 0;
|
||||
@@ -715,8 +712,14 @@ screen_putchar(const char *ch)
|
||||
}
|
||||
}
|
||||
|
||||
// copy unicode char
|
||||
strncpy(c->c, ch, 4);
|
||||
if (ch[1] == 0 && ch[0] <= 0x7f) {
|
||||
// we have len=1 and ASCII
|
||||
utf8_remap(c->c, ch[0], (cursor.charsetN == 0) ? cursor.charset0 : cursor.charset1);
|
||||
}
|
||||
else {
|
||||
// copy unicode char
|
||||
strncpy(c->c, ch, 4);
|
||||
}
|
||||
|
||||
if (cursor.inverse) {
|
||||
c->fg = cursor.bg;
|
||||
@@ -725,7 +728,7 @@ screen_putchar(const char *ch)
|
||||
c->fg = cursor.fg;
|
||||
c->bg = cursor.bg;
|
||||
}
|
||||
c->bold = cursor.bold;
|
||||
c->attrs = cursor.attrs;
|
||||
|
||||
cursor.x++;
|
||||
// X wrap
|
||||
@@ -748,6 +751,84 @@ done:
|
||||
NOTIFY_DONE();
|
||||
}
|
||||
|
||||
/**
|
||||
* translates VT100 ACS escape codes to Unicode values.
|
||||
* Based on rxvt-unicode screen.C table.
|
||||
*/
|
||||
static const u16 vt100_to_unicode[62] =
|
||||
{
|
||||
// ? ? ? ? ? ? ?
|
||||
// A=UPARR B=DNARR C=RTARR D=LFARR E=FLBLK F=3/4BL G=SNOMN
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603,
|
||||
// H= I= J= K= L= M= N=
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// O= P= Q= R= S= T= U=
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// V= W= X= Y= Z= [= \=
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
// ? ? v->0 v->1 v->2 v->3 v->4
|
||||
// ]= ^= _=SPC `=DIAMN a=HSMED b=HT c=FF
|
||||
0, 0, 0x0020, 0x25c6, 0x2592, 0x2409, 0x240c,
|
||||
// v->5 v->6 v->7 v->8 v->9 v->a v->b
|
||||
// d=CR e=LF f=DEGRE g=PLSMN h=NL i=VT j=SL-BR
|
||||
0x240d, 0x240a, 0x00b0, 0x00b1, 0x2424, 0x240b, 0x2518,
|
||||
// v->c v->d v->e v->f v->10 v->11 v->12
|
||||
// k=SL-TR l=SL-TL m=SL-BL n=SL-+ o=SL-T1 p=SL-T2 q=SL-HZ
|
||||
0x2510, 0x250c, 0x2514, 0x253c, 0x23ba, 0x23bb, 0x2500,
|
||||
// v->13 v->14 v->15 v->16 v->17 v->18 v->19
|
||||
// r=SL-T4 s=SL-T5 t=SL-VR u=SL-VL v=SL-HU w=Sl-HD x=SL-VT
|
||||
0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c, 0x2502,
|
||||
// v->1a v->1b b->1c v->1d v->1e/a3 v->1f
|
||||
// y=LT-EQ z=GT-EQ {=PI |=NOTEQ }=POUND ~=DOT
|
||||
0x2264, 0x2265, 0x03c0, 0x2260, 0x20a4, 0x00b7
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF remap
|
||||
* @param out - output char[4]
|
||||
* @param g - ASCII char
|
||||
* @param table - table name (0, A, B)
|
||||
*/
|
||||
static void ICACHE_FLASH_ATTR
|
||||
utf8_remap(char *out, char g, char table)
|
||||
{
|
||||
u16 utf = 0;
|
||||
|
||||
switch (table)
|
||||
{
|
||||
case '0': /* DEC Special Character & Line Drawing Set */
|
||||
if ((g >= 0x41) && (g <= 0x7e) && (vt100_to_unicode[g - 0x41])) {
|
||||
utf = vt100_to_unicode[g - 0x41];
|
||||
}
|
||||
break;
|
||||
case 'A': /* UK, replaces # with GBP */
|
||||
if (g == '#') utf = 0x20a4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (utf > 0x7F) {
|
||||
// formulas taken from: https://gist.github.com/yamamushi/5823402
|
||||
if ((utf >= 0x80) && (utf <= 0x07FF)) {
|
||||
out[0] = (char) ((utf >> 0x06) ^ 0xC0);
|
||||
out[1] = (char) (((utf ^ 0xFFC0) | 0x80) & ~0x40);
|
||||
out[2]=0;
|
||||
}
|
||||
else if ((utf >= 0x0800) && (utf <= 0xFFFF)) {
|
||||
out[0] = (char) (((utf ^ 0xFC0FFF) >> 0x0C) | 0xE0);
|
||||
out[1] = (char) ((((utf ^ 0xFFF03F) >> 0x06) | 0x80) & ~0x40);
|
||||
out[2] = (char) (((utf ^ 0xFFFC0) | 0x80) & ~0x40);
|
||||
out[3]=0;
|
||||
} else {
|
||||
out[0] = g;
|
||||
out[1] = 0;
|
||||
}
|
||||
} else {
|
||||
out[0] = g;
|
||||
out[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//region Serialization
|
||||
|
||||
@@ -789,7 +870,7 @@ void screen_dd(void)
|
||||
struct ScreenSerializeState {
|
||||
Color lastFg;
|
||||
Color lastBg;
|
||||
bool lastBold;
|
||||
bool lastAttrs;
|
||||
char lastChar[4];
|
||||
int index;
|
||||
};
|
||||
@@ -798,8 +879,24 @@ void ICACHE_FLASH_ATTR
|
||||
encode2B(u16 number, WordB2 *stru)
|
||||
{
|
||||
stru->lsb = (u8) (number % 127);
|
||||
stru->msb = (u8) ((number - stru->lsb) / 127 + 1);
|
||||
number = (u16) ((number - stru->lsb) / 127);
|
||||
stru->lsb += 1;
|
||||
|
||||
stru->msb = (u8) (number + 1);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
encode3B(u32 number, WordB3 *stru)
|
||||
{
|
||||
stru->lsb = (u8) (number % 127);
|
||||
number = (number - stru->lsb) / 127;
|
||||
stru->lsb += 1;
|
||||
|
||||
stru->msb = (u8) (number % 127);
|
||||
number = (number - stru->msb) / 127;
|
||||
stru->msb += 1;
|
||||
|
||||
stru->xsb = (u8) (number + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -845,6 +942,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
|
||||
Cell *cell, *cell0;
|
||||
WordB2 w1, w2, w3, w4, w5;
|
||||
WordB3 lw1;
|
||||
|
||||
size_t remain = buf_len; int used = 0;
|
||||
char *bb = buffer;
|
||||
@@ -860,7 +958,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
ss->index = 0;
|
||||
ss->lastBg = 0;
|
||||
ss->lastFg = 0;
|
||||
ss->lastBold = false;
|
||||
ss->lastAttrs = 0;
|
||||
memset(ss->lastChar, 0, 4); // this ensures the first char is never "repeat"
|
||||
|
||||
encode2B((u16) H, &w1);
|
||||
@@ -870,8 +968,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
encode2B((u16) (
|
||||
cursor.fg |
|
||||
(cursor.bg<<4) |
|
||||
(cursor.bold?0x100:0) |
|
||||
(cursor.visible?0x200:0))
|
||||
(cursor.visible ? 1<<8 : 0))
|
||||
, &w5);
|
||||
|
||||
// H W X Y Attribs
|
||||
@@ -887,7 +984,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
while (i < W*H
|
||||
&& cell->fg == ss->lastFg
|
||||
&& cell->bg == ss->lastBg
|
||||
&& cell->bold == ss->lastBold
|
||||
&& cell->attrs == ss->lastAttrs
|
||||
&& strneq(cell->c, ss->lastChar, 4)) {
|
||||
// Repeat
|
||||
repCnt++;
|
||||
@@ -896,13 +993,25 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
|
||||
if (repCnt == 0) {
|
||||
// No repeat
|
||||
if (cell0->bold != ss->lastBold || cell0->fg != ss->lastFg || cell0->bg != ss->lastBg) {
|
||||
encode2B((u16) (
|
||||
bool changeAttrs = cell0->attrs != ss->lastAttrs;
|
||||
bool changeColors = (cell0->fg != ss->lastFg || cell0->bg != ss->lastBg);
|
||||
if (!changeAttrs && changeColors) {
|
||||
encode2B(cell0->fg | (cell0->bg<<4), &w1);
|
||||
bufprint("\x03%c%c", w1.lsb, w1.msb);
|
||||
}
|
||||
else if (changeAttrs && !changeColors) {
|
||||
// attrs only
|
||||
encode2B(cell0->attrs, &w1);
|
||||
bufprint("\x04%c%c", w1.lsb, w1.msb);
|
||||
}
|
||||
else if (changeAttrs && changeColors) {
|
||||
// colors and attrs
|
||||
encode3B((u32) (
|
||||
cell0->fg |
|
||||
(cell0->bg<<4) |
|
||||
(cell0->bold?0x100:0))
|
||||
, &w1);
|
||||
bufprint("\x01%c%c", w1.lsb, w1.msb);
|
||||
(cell0->attrs<<8))
|
||||
, &lw1);
|
||||
bufprint("\x01%c%c%c", lw1.lsb, lw1.msb, lw1.xsb);
|
||||
}
|
||||
|
||||
// copy the symbol, until first 0 or reached 4 bytes
|
||||
@@ -914,7 +1023,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
||||
|
||||
ss->lastFg = cell0->fg;
|
||||
ss->lastBg = cell0->bg;
|
||||
ss->lastBold = cell0->bold;
|
||||
ss->lastAttrs = cell0->attrs;
|
||||
memcpy(ss->lastChar, cell0->c, 4);
|
||||
|
||||
i++;
|
||||
|
||||
+23
-7
@@ -46,6 +46,14 @@ typedef enum {
|
||||
CHANGE_LABELS,
|
||||
} ScreenNotifyChangeTopic;
|
||||
|
||||
#define ATTR_BOLD (1<<0)
|
||||
#define ATTR_FAINT (1<<1)
|
||||
#define ATTR_ITALIC (1<<2)
|
||||
#define ATTR_UNDERLINE (1<<3)
|
||||
#define ATTR_BLINK (1<<4)
|
||||
#define ATTR_FRAKTUR (1<<5)
|
||||
#define ATTR_STRIKE (1<<6)
|
||||
|
||||
#define SCREEN_NOTIFY_DELAY_MS 20
|
||||
|
||||
typedef struct {
|
||||
@@ -95,6 +103,12 @@ typedef struct {
|
||||
u8 msb;
|
||||
} WordB2;
|
||||
|
||||
typedef struct {
|
||||
u8 lsb;
|
||||
u8 msb;
|
||||
u8 xsb;
|
||||
} WordB3;
|
||||
|
||||
/** Encode number to two nice ASCII bytes */
|
||||
void encode2B(u16 number, WordB2 *stru);
|
||||
|
||||
@@ -119,7 +133,7 @@ void screen_clear_in_line(unsigned int count);
|
||||
void screen_scroll_up(unsigned int lines);
|
||||
/** Shift screen downwards */
|
||||
void screen_scroll_down(unsigned int lines);
|
||||
/** esc # 8 - fill entire screen with E of default colors */
|
||||
/** esc # 8 - fill entire screen with E of default colors (DEC alignment display) */
|
||||
void screen_fill_with_E(void);
|
||||
|
||||
// --- insert / delete ---
|
||||
@@ -157,12 +171,14 @@ void screen_wrap_enable(bool enable);
|
||||
void screen_set_fg(Color color);
|
||||
/** Set cursor background coloor */
|
||||
void screen_set_bg(Color color);
|
||||
/** make foreground bright */
|
||||
void screen_set_bold(bool bold);
|
||||
/** Set cursor foreground and background color */
|
||||
void screen_set_colors(Color fg, Color bg);
|
||||
/** Invert colors */
|
||||
void screen_inverse(bool inverse);
|
||||
|
||||
// enable or disable attrs by bitmask
|
||||
void screen_attr_enable(u8 attrs);
|
||||
void screen_attr_disable(u8 attrs);
|
||||
void screen_inverse_enable(bool ena);
|
||||
|
||||
void screen_set_charset_n(int Gx);
|
||||
void screen_set_charset(int Gx, char charset);
|
||||
|
||||
/**
|
||||
* Set a character in the cursor color, move to right with wrap.
|
||||
|
||||
Reference in New Issue
Block a user