aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bin/termptyesc.c234
-rwxr-xr-xtests/sgr-truecolors.sh152
-rw-r--r--tests/tests.results1
3 files changed, 334 insertions, 53 deletions
diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c
index d1a0d9a..623e7ea 100644
--- a/src/bin/termptyesc.c
+++ b/src/bin/termptyesc.c
@@ -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 == NULL) || (*b == '\0'))
+ {
+ *ptr = NULL;
+ return -CSI_ARG_NO_VALUE;
+ }
- if (!b)
- goto error;
+ /* 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 == ';') || (*b == ':'))
+ 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 == ':'))
- b++;
-
- *ptr = b;
+ if (*b == separator)
+ {
+ b++;
+ *ptr = b;
+ }
+ else if (*b == '\0')
+ {
+ *ptr = NULL;
+ }
+ else
+ {
+ *ptr = b;
+ }
return sum;
-
-error:
- *ptr = NULL;
- return -1;
}
@@ -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;
}
-
- if ((r0 < 0) || (g0 < 0) || (b0 < 0))
+ separator = *(u-1);
+
+ 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;
+ }
+ }
+
+ if (c == -CSI_ARG_NO_VALUE)
+ c = 0;
+ if (m == -CSI_ARG_NO_VALUE)
+ m = 0;
+ if (y == -CSI_ARG_NO_VALUE)
+ y = 0;
- return _approximate_truecolor_rgb(ty, r0, g0, b0);
+ 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;
+ }
+ }
+
+ 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;
- r0 = 255 - ((c0 * 255) / 100);
- g0 = 255 - ((m0 * 255) / 100);
- b0 = 255 - ((y0 * 255) / 100);
+ 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, r0, g0, b0);
+ 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
diff --git a/tests/sgr-truecolors.sh b/tests/sgr-truecolors.sh
new file mode 100755
index 0000000..fcff3d9
--- /dev/null
+++ b/tests/sgr-truecolors.sh
@@ -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▝▘'
diff --git a/tests/tests.results b/tests/tests.results
index 4a2be95..182cac2 100644
--- a/tests/tests.results
+++ b/tests/tests.results
@@ -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