termptyesc: fix truecolors parsing + tests

This commit is contained in:
Boris Faure 2018-12-15 23:41:46 +01:00
parent 3cc3f3ee2a
commit add8b71778
3 changed files with 333 additions and 52 deletions

View File

@ -100,7 +100,7 @@ _csi_arg_get(Termpty *ty, Eina_Unicode **ptr)
Eina_Unicode *b = *ptr;
int sum = 0;
if (!b)
if ((b == NULL) || (*b == '\0'))
{
*ptr = NULL;
return -CSI_ARG_NO_VALUE;
@ -128,6 +128,7 @@ _csi_arg_get(Termpty *ty, Eina_Unicode **ptr)
if (sum > INT32_MAX/10 )
{
ERR("Invalid sequence: argument is too large");
ty->decoding_error = EINA_TRUE;
goto error;
}
sum *= 10;
@ -135,7 +136,7 @@ _csi_arg_get(Termpty *ty, Eina_Unicode **ptr)
b++;
}
if (*b == ';')
if ((*b == ';') || (*b == ':'))
{
if (b[1])
b++;
@ -540,41 +541,66 @@ _handle_esc_csi_reset_mode(Termpty *ty, Eina_Unicode cc, Eina_Unicode *b,
}
static int
_csi_truecolor_arg_get(Eina_Unicode **ptr)
_csi_truecolor_arg_get(Termpty *ty, Eina_Unicode **ptr)
{
Eina_Unicode *b = *ptr;
int sum = 0;
char separator;
if (!b)
goto error;
if ((b == NULL) || (*b == '\0'))
{
*ptr = NULL;
return -CSI_ARG_NO_VALUE;
}
if ((*b == ';') || (*b == ':'))
/* by construction, shall be the same separator as the following ones */
separator = *(b-1);
if ((separator != ';') && (separator != ':'))
{
*ptr = NULL;
return -CSI_ARG_NO_VALUE;
}
if (*b == separator)
{
b++;
*ptr = b;
return 0;
return -CSI_ARG_NO_VALUE;
}
if (!*b)
goto error;
if (*b == '\0')
{
*ptr = NULL;
return -CSI_ARG_NO_VALUE;
}
while ((*b >= '0') && (*b <= '9'))
{
if (sum > INT32_MAX/10 )
goto error;
{
*ptr = NULL;
ERR("Invalid sequence: argument is too large");
ty->decoding_error = EINA_TRUE;
return -CSI_ARG_ERROR;
}
sum *= 10;
sum += *b - '0';
b++;
}
if ((*b == ';') || (*b == ':'))
if (*b == separator)
{
b++;
*ptr = b;
return sum;
error:
}
else if (*b == '\0')
{
*ptr = NULL;
return -1;
}
else
{
*ptr = b;
}
return sum;
}
@ -631,68 +657,171 @@ _approximate_truecolor_rgb(Termpty *ty, int r0, int g0, int b0)
static int
_handle_esc_csi_truecolor_rgb(Termpty *ty, Eina_Unicode **ptr)
{
int r0, g0, b0, other;
int r, g, b;
Eina_Unicode *u = *ptr;
char separator;
r0 = _csi_truecolor_arg_get(ptr);
g0 = _csi_truecolor_arg_get(ptr);
b0 = _csi_truecolor_arg_get(ptr);
other = _csi_truecolor_arg_get(ptr);
if (other >= 0)
if ((u == NULL) || (*u == '\0'))
{
r0 = g0;
g0 = b0;
b0 = other;
return COL_DEF;
}
separator = *(u-1);
if ((r0 < 0) || (g0 < 0) || (b0 < 0))
r = _csi_truecolor_arg_get(ty, ptr);
g = _csi_truecolor_arg_get(ty, ptr);
b = _csi_truecolor_arg_get(ty, ptr);
if ((r == -CSI_ARG_ERROR) ||
(g == -CSI_ARG_ERROR) ||
(b == -CSI_ARG_ERROR))
return COL_DEF;
return _approximate_truecolor_rgb(ty, r0, g0, b0);
if (separator == ':' && *ptr)
{
if (**ptr != ';')
{
/* then the first parameter was a color-space-id (ignored) */
r = g;
g = b;
b = _csi_truecolor_arg_get(ty, ptr);
/* Skip other parameters */
while ((*ptr) && (**ptr != ';'))
{
_csi_truecolor_arg_get(ty, ptr);
}
}
if ((*ptr) && (**ptr == ';'))
{
*ptr = (*ptr) + 1;
}
}
if (r == -CSI_ARG_NO_VALUE)
r = 0;
if (g == -CSI_ARG_NO_VALUE)
g = 0;
if (b == -CSI_ARG_NO_VALUE)
b = 0;
return _approximate_truecolor_rgb(ty, r, g, b);
}
static int
_handle_esc_csi_truecolor_cmy(Termpty *ty, Eina_Unicode **ptr)
{
int r0, g0, b0, c0, m0, y0;
int r, g, b, c, m, y;
Eina_Unicode *u = *ptr;
char separator;
if ((u == NULL) || (*u == '\0'))
{
return COL_DEF;
}
separator = *(u-1);
/* Considering CMY stored as percents */
c0 = _csi_truecolor_arg_get(ptr);
m0 = _csi_truecolor_arg_get(ptr);
y0 = _csi_truecolor_arg_get(ptr);
c = _csi_truecolor_arg_get(ty, ptr);
m = _csi_truecolor_arg_get(ty, ptr);
y = _csi_truecolor_arg_get(ty, ptr);
if ((c0 < 0) || (m0 < 0) || (y0 < 0))
if ((c == -CSI_ARG_ERROR) ||
(m == -CSI_ARG_ERROR) ||
(y == -CSI_ARG_ERROR))
return COL_DEF;
r0 = 255 - ((c0 * 255) / 100);
g0 = 255 - ((m0 * 255) / 100);
b0 = 255 - ((y0 * 255) / 100);
if (separator == ':' && *ptr)
{
if (**ptr != ';')
{
/* then the first parameter was a color-space-id (ignored) */
c = m;
m = y;
y = _csi_truecolor_arg_get(ty, ptr);
/* Skip other parameters */
while ((*ptr) && (**ptr != ';'))
{
_csi_truecolor_arg_get(ty, ptr);
}
}
if ((*ptr) && (**ptr == ';'))
{
*ptr = (*ptr) + 1;
}
}
return _approximate_truecolor_rgb(ty, r0, g0, b0);
if (c == -CSI_ARG_NO_VALUE)
c = 0;
if (m == -CSI_ARG_NO_VALUE)
m = 0;
if (y == -CSI_ARG_NO_VALUE)
y = 0;
r = 255 - ((c * 255) / 100);
g = 255 - ((m * 255) / 100);
b = 255 - ((y * 255) / 100);
return _approximate_truecolor_rgb(ty, r, g, b);
}
static int
_handle_esc_csi_truecolor_cmyk(Termpty *ty, Eina_Unicode **ptr)
{
int r0, g0, b0, c0, m0, y0, k0;
int r, g, b, c, m, y, k;
Eina_Unicode *u = *ptr;
char separator;
if ((u == NULL) || (*u == '\0'))
{
return COL_DEF;
}
separator = *(u-1);
/* Considering CMYK stored as percents */
c0 = _csi_truecolor_arg_get(ptr);
m0 = _csi_truecolor_arg_get(ptr);
y0 = _csi_truecolor_arg_get(ptr);
k0 = _csi_truecolor_arg_get(ptr);
c = _csi_truecolor_arg_get(ty, ptr);
m = _csi_truecolor_arg_get(ty, ptr);
y = _csi_truecolor_arg_get(ty, ptr);
k = _csi_truecolor_arg_get(ty, ptr);
if ((c0 < 0) || (m0 < 0) || (y0 < 0) || (k0 < 0))
if ((c == -CSI_ARG_ERROR) ||
(m == -CSI_ARG_ERROR) ||
(y == -CSI_ARG_ERROR) ||
(k == -CSI_ARG_ERROR))
return COL_DEF;
c0 = c0 * (100 - k0) + k0;
m0 = m0 * (100 - k0) + k0;
y0 = y0 * (100 - k0) + k0;
if (separator == ':' && *ptr)
{
if (**ptr != ';')
{
/* then the first parameter was a color-space-id (ignored) */
c = m;
m = y;
y = k;
k = _csi_truecolor_arg_get(ty, ptr);
/* Skip other parameters */
while ((*ptr) && (**ptr != ';'))
{
_csi_truecolor_arg_get(ty, ptr);
}
}
if ((*ptr) && (**ptr == ';'))
{
*ptr = (*ptr) + 1;
}
}
r0 = 255 - ((c0 * 255) / 100);
g0 = 255 - ((m0 * 255) / 100);
b0 = 255 - ((y0 * 255) / 100);
if (c == -CSI_ARG_NO_VALUE)
c = 0;
if (m == -CSI_ARG_NO_VALUE)
m = 0;
if (y == -CSI_ARG_NO_VALUE)
y = 0;
if (k == -CSI_ARG_NO_VALUE)
k = 0;
return _approximate_truecolor_rgb(ty, r0, g0, b0);
r = (255 * (100 - c) * (100 - k)) / 100 / 100;
g = (255 * (100 - m) * (100 - k)) / 100 / 100;
b = (255 * (100 - y) * (100 - k)) / 100 / 100;
return _approximate_truecolor_rgb(ty, r, g, b);
}
static void
@ -715,7 +844,6 @@ _handle_esc_csi_color_set(Termpty *ty, Eina_Unicode **ptr,
{
case -CSI_ARG_ERROR:
return;
/* TODO: -CSI_ARG_NO_VALUE */
case -CSI_ARG_NO_VALUE:
EINA_FALLTHROUGH;
case 0: // reset to normal

152
tests/sgr-truecolors.sh Executable file
View File

@ -0,0 +1,152 @@
#!/bin/sh
# pick 2 colors as RGB (orange for background, blue for foreground)
# compute the values for CMY and CMYK colorspaces
# Have 4 colums for each kind of format used in TrueColor escape codes
#BG-48: #f49019
# R:244 G:144 B:25
# C:4 M:43 Y:90
# C:0 M:41 Y:90 K:4
#FG-38: #3896c7
# R:56 G:150 B:199
# C:78 M:41 Y:22
# C:72 M:25 Y:0 K:22
# cursor to 0,0 and clear line
printf '\033[H\033[2K'
# formats for each columns
printf '\033[1;1H\033[0m38:2:n:n:nm'
printf '\033[1;13H\033[0m38:2:42:n:n:nm'
printf '\033[1;28H\033[0m38:2:42:n:n:n:4m'
printf '\033[1;45H\033[0m38;2;n;n;nm'
##
# RGB
##
printf '\033[3;1H\033[0;1;37mRGB'
# 1
printf '\033[4;1H\033[0;1;37m1'
printf '\033[48:2:244:144:25m'
printf '\033[38:2:56:150:199m'
printf '\033[4;5H▗▖'
printf '\033[5;5H▝▘'
# 2
printf '\033[4;13H\033[0;1;37m2'
printf '\033[48:2:42:244:144:25m'
printf '\033[38:2:42:56:150:199m'
printf '\033[4;17H▗▖'
printf '\033[5;17H▝▘'
# 3
printf '\033[4;28H\033[0;1;37m3'
printf '\033[48:2:42:244:144:25:4m'
printf '\033[38:2:42:56:150:199:4m'
printf '\033[4;32H▗▖'
printf '\033[5;32H▝▘'
# 4
printf '\033[4;45H\033[0;1;37m4'
printf '\033[48;2;244;144;25m'
printf '\033[38;2;56;150;199m'
printf '\033[4;49H▗▖'
printf '\033[5;49H▝▘'
# Same but on one sequence
printf '\033[6;1H\033[0mSame but fg+bg on one sequence'
#1
printf '\033[7;1H\033[0;1;37m1'
printf '\033[48:2:244:144:25;38:2:56:150:199m'
printf '\033[7;5H▗▖'
printf '\033[8;5H▝▘'
# 2
printf '\033[7;13H\033[0;1;37m2'
printf '\033[1;13H\033[0m38:2:42:n:n:nm'
printf '\033[48:2:42:244:144:25;38:2:42:56:150:199m'
printf '\033[7;17H▗▖'
printf '\033[8;17H▝▘'
# 3
printf '\033[7;28H\033[0;1;37m3'
printf '\033[48:2:42:244:144:25:4;38:2:42:56:150:199:4m'
printf '\033[7;32H▗▖'
printf '\033[8;32H▝▘'
# 4
printf '\033[7;45H\033[0;1;37m4'
printf '\033[48;2;244;144;25;38;2;56;150;199m'
printf '\033[7;49H▗▖'
printf '\033[8;49H▝▘'
##
# CMY
##
printf '\033[10;1H\033[0;1;37mCMY'
# 1
printf '\033[11;1H\033[0;1;37m1'
printf '\033[48:3:4:43:90m'
printf '\033[38:3:78:41:22m'
printf '\033[11;5H▗▖'
printf '\033[12;5H▝▘'
# 2
printf '\033[11;13H\033[0;1;37m2'
printf '\033[48:3:42:4:43:90m'
printf '\033[38:3:42:78:41:22m'
printf '\033[11;17H▗▖'
printf '\033[12;17H▝▘'
# 3
printf '\033[11;28H\033[0;1;37m3'
printf '\033[48:3:42:4:43:90:4m'
printf '\033[38:3:42:78:41:22:4m'
printf '\033[11;32H▗▖'
printf '\033[12;32H▝▘'
# 4
printf '\033[11;45H\033[0;1;37m4'
printf '\033[48;3;4;43;90m'
printf '\033[38;3;78;41;22m'
printf '\033[11;49H▗▖'
printf '\033[12;49H▝▘'
##
# CMYK
##
printf '\033[14;1H\033[0;1;37mCMYK'
# 1
printf '\033[15;1H\033[0;1;37m1'
printf '\033[48:4::0:41:90:4m'
printf '\033[38:4::72:25:0:22m'
printf '\033[15;5H▗▖'
printf '\033[16;5H▝▘'
# 2
printf '\033[15;13H\033[0;1;37m2'
printf '\033[48:4:42:0:41:90:4m'
printf '\033[38:4:42:72:25:0:22m'
printf '\033[15;17H▗▖'
printf '\033[16;17H▝▘'
# 3
printf '\033[15;28H\033[0;1;37m3'
printf '\033[48:4:42:0:41:90:4:4m'
printf '\033[38:4:42:72:25:0:22:4m'
printf '\033[15;32H▗▖'
printf '\033[16;32H▝▘'
# 4
printf '\033[15;45H\033[0;1;37m4'
printf '\033[48;4;0;41;90;4m'
printf '\033[38;4;72;25;0;22m'
printf '\033[15;49H▗▖'
printf '\033[16;49H▝▘'

View File

@ -27,3 +27,4 @@ dsr-pp.sh 0f0a7d5beccefbad4f4984fc4611276e
dsr-udk.sh f3a20968a2f25bfd36875dbc5f64ab16
colors.sh 532494a2e56c102ee10ab1a9b8f176d7
sgr-leading-trailing-semicolon.sh d7701f1193bde63412a9b969f17e10ec
sgr-truecolors.sh 9db4becc728bb9f1730f3573dc7fc668