termiolink: rework color finder
This commit is contained in:
parent
2832f79b59
commit
10c720aa00
|
@ -19,4 +19,8 @@ void ty_sb_lskip(struct ty_sb *sb, size_t len);
|
||||||
void ty_sb_rskip(struct ty_sb *sb, size_t len);
|
void ty_sb_rskip(struct ty_sb *sb, size_t len);
|
||||||
void ty_sb_free(struct ty_sb *sb);
|
void ty_sb_free(struct ty_sb *sb);
|
||||||
|
|
||||||
|
#define sbstartswith(SB, ConstRef) \
|
||||||
|
(((SB)->len >= sizeof(ConstRef) -1) \
|
||||||
|
&& (!strncmp((SB)->buf, ConstRef, sizeof(ConstRef) - 1)))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include <Elementary.h>
|
#include <Elementary.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "termpty.h"
|
#include "termpty.h"
|
||||||
#include "backlog.h"
|
#include "backlog.h"
|
||||||
#include "termiolink.h"
|
#include "termiolink.h"
|
||||||
|
@ -626,35 +627,64 @@ end:
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((const))
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_is_authorized_in_color(const int codepoint)
|
_is_authorized_in_color(const int codepoint)
|
||||||
{
|
{
|
||||||
switch (codepoint)
|
static const Eina_Unicode authorized[] = {
|
||||||
|
'\t',
|
||||||
|
' ',
|
||||||
|
'#',
|
||||||
|
'(',
|
||||||
|
')',
|
||||||
|
'+',
|
||||||
|
',',
|
||||||
|
'/',
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
':',
|
||||||
|
'A',
|
||||||
|
'B',
|
||||||
|
'C',
|
||||||
|
'D',
|
||||||
|
'E',
|
||||||
|
'F',
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'd',
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g',
|
||||||
|
'h',
|
||||||
|
'l',
|
||||||
|
'n',
|
||||||
|
'o',
|
||||||
|
'r',
|
||||||
|
's',
|
||||||
|
't',
|
||||||
|
'u',
|
||||||
|
};
|
||||||
|
size_t imax = (sizeof(authorized) / sizeof(authorized[0])) - 1,
|
||||||
|
imin = 0;
|
||||||
|
size_t imaxmax = imax;
|
||||||
|
|
||||||
|
while (imax >= imin)
|
||||||
{
|
{
|
||||||
case '#': EINA_FALLTHROUGH;
|
size_t imid = (imin + imax) / 2;
|
||||||
case '0': EINA_FALLTHROUGH;
|
|
||||||
case '1': EINA_FALLTHROUGH;
|
if (authorized[imid] == codepoint) return EINA_TRUE;
|
||||||
case '2': EINA_FALLTHROUGH;
|
else if (authorized[imid] < codepoint) imin = imid + 1;
|
||||||
case '3': EINA_FALLTHROUGH;
|
else imax = imid - 1;
|
||||||
case '4': EINA_FALLTHROUGH;
|
if (imax > imaxmax) break;
|
||||||
case '5': EINA_FALLTHROUGH;
|
|
||||||
case '6': EINA_FALLTHROUGH;
|
|
||||||
case '7': EINA_FALLTHROUGH;
|
|
||||||
case '8': EINA_FALLTHROUGH;
|
|
||||||
case '9': EINA_FALLTHROUGH;
|
|
||||||
case 'a': EINA_FALLTHROUGH;
|
|
||||||
case 'A': EINA_FALLTHROUGH;
|
|
||||||
case 'b': EINA_FALLTHROUGH;
|
|
||||||
case 'B': EINA_FALLTHROUGH;
|
|
||||||
case 'c': EINA_FALLTHROUGH;
|
|
||||||
case 'C': EINA_FALLTHROUGH;
|
|
||||||
case 'd': EINA_FALLTHROUGH;
|
|
||||||
case 'D': EINA_FALLTHROUGH;
|
|
||||||
case 'e': EINA_FALLTHROUGH;
|
|
||||||
case 'E': EINA_FALLTHROUGH;
|
|
||||||
case 'f': EINA_FALLTHROUGH;
|
|
||||||
case 'F':
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -698,13 +728,228 @@ _parse_2hex(const char *s, uint8_t *v)
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_parse_sharp_color(struct ty_sb *sb,
|
||||||
|
uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
|
||||||
|
{
|
||||||
|
uint8_t r, g, b, a = 255;
|
||||||
|
|
||||||
|
/* skip sharp */
|
||||||
|
ty_sb_lskip(sb, 1);
|
||||||
|
switch (sb->len)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
if ((!_parse_hex(sb->buf[0], &r)) ||
|
||||||
|
(!_parse_hex(sb->buf[1], &g)) ||
|
||||||
|
(!_parse_hex(sb->buf[2], &b)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
r <<= 4;
|
||||||
|
g <<= 4;
|
||||||
|
b <<= 4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if ((!_parse_hex(sb->buf[0], &r)) ||
|
||||||
|
(!_parse_hex(sb->buf[1], &g)) ||
|
||||||
|
(!_parse_hex(sb->buf[2], &b)) ||
|
||||||
|
(!_parse_hex(sb->buf[3], &a)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
r <<= 4;
|
||||||
|
g <<= 4;
|
||||||
|
b <<= 4;
|
||||||
|
a <<= 4;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if ((!_parse_2hex(&sb->buf[0], &r)) ||
|
||||||
|
(!_parse_2hex(&sb->buf[2], &g)) ||
|
||||||
|
(!_parse_2hex(&sb->buf[4], &b)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if ((!_parse_2hex(&sb->buf[0], &r)) ||
|
||||||
|
(!_parse_2hex(&sb->buf[2], &g)) ||
|
||||||
|
(!_parse_2hex(&sb->buf[4], &b)) ||
|
||||||
|
(!_parse_2hex(&sb->buf[6], &a)))
|
||||||
|
return EINA_FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
*rp = r;
|
||||||
|
*gp = g;
|
||||||
|
*bp = b;
|
||||||
|
*ap = a;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_parse_uint8(struct ty_sb *sb,
|
||||||
|
uint8_t *vp)
|
||||||
|
{
|
||||||
|
uint16_t v = 0;
|
||||||
|
Eina_Bool ret = EINA_FALSE;
|
||||||
|
|
||||||
|
if (!sb->len) return EINA_FALSE;
|
||||||
|
|
||||||
|
while (sb->len && v < 255 && sb->buf[0] >= '0' && sb->buf[0] <= '9')
|
||||||
|
{
|
||||||
|
v = (v * 10) + sb->buf[0] - '0';
|
||||||
|
ty_sb_lskip(sb, 1);
|
||||||
|
ret = EINA_TRUE;
|
||||||
|
}
|
||||||
|
if (v > 255)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
*vp = v;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_parse_edc_color(struct ty_sb *sb,
|
||||||
|
uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
|
||||||
|
{
|
||||||
|
uint8_t r = 0, g = 0, b = 0, a = 255;
|
||||||
|
|
||||||
|
/* skip color */
|
||||||
|
ty_sb_lskip(sb, 5);
|
||||||
|
if (sb->buf[0] != ':')
|
||||||
|
ty_sb_lskip(sb, 1);
|
||||||
|
ty_sb_lskip(sb, 1); /* skip ':' */
|
||||||
|
ty_sb_spaces_ltrim(sb);
|
||||||
|
|
||||||
|
if (!sb->len) return EINA_FALSE;
|
||||||
|
if (sb->buf[0] == '#')
|
||||||
|
return _parse_sharp_color(sb, rp, gp, bp, ap);
|
||||||
|
|
||||||
|
if (!_parse_uint8(sb, &r)) return EINA_FALSE;
|
||||||
|
ty_sb_spaces_ltrim(sb);
|
||||||
|
if (!_parse_uint8(sb, &g)) return EINA_FALSE;
|
||||||
|
ty_sb_spaces_ltrim(sb);
|
||||||
|
if (!_parse_uint8(sb, &b)) return EINA_FALSE;
|
||||||
|
ty_sb_spaces_ltrim(sb);
|
||||||
|
if (!_parse_uint8(sb, &a)) return EINA_FALSE;
|
||||||
|
|
||||||
|
*rp = r;
|
||||||
|
*gp = g;
|
||||||
|
*bp = b;
|
||||||
|
*ap = a;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((const))
|
||||||
|
static Eina_Bool
|
||||||
|
_is_authorized_in_color_sharp(const Eina_Unicode g)
|
||||||
|
{
|
||||||
|
if (g == '#' ||
|
||||||
|
(g >= '0' && g <= '9') ||
|
||||||
|
(g >= 'A' && g <= 'F') ||
|
||||||
|
(g >= 'a' && g <= 'f'))
|
||||||
|
return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_sharp_color_find(Termpty *ty, int sc,
|
||||||
|
int *x1r, int *y1r, int *x2r, int *y2r,
|
||||||
|
uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
|
||||||
|
{
|
||||||
|
int x1 = *x1r, y1 = *y1r, x2 = *x2r, y2 = *y2r;
|
||||||
|
Eina_Bool goback = EINA_TRUE,
|
||||||
|
goforward = EINA_FALSE;
|
||||||
|
struct ty_sb sb = {.buf = NULL, .gap = 0, .len = 0, .alloc = 0};
|
||||||
|
int res;
|
||||||
|
char txt[8];
|
||||||
|
int txtlen = 0;
|
||||||
|
Eina_Bool found = EINA_FALSE;
|
||||||
|
int codepoint;
|
||||||
|
uint8_t r, g, b, a = 255;
|
||||||
|
|
||||||
|
res = _txt_at(ty, &x1, &y1, txt, &txtlen, &codepoint);
|
||||||
|
if ((res != 0) || (txtlen == 0))
|
||||||
|
goto end;
|
||||||
|
if (!_is_authorized_in_color_sharp(codepoint))
|
||||||
|
goto end;
|
||||||
|
res = ty_sb_add(&sb, txt, txtlen);
|
||||||
|
if (res < 0) goto end;
|
||||||
|
|
||||||
|
while (goback && sb.len <= 9)
|
||||||
|
{
|
||||||
|
int new_x1 = x1, new_y1 = y1;
|
||||||
|
|
||||||
|
res = _txt_prev_at(ty, &new_x1, &new_y1, txt, &txtlen, &codepoint);
|
||||||
|
if ((res != 0) || (txtlen == 0))
|
||||||
|
{
|
||||||
|
goback = EINA_FALSE;
|
||||||
|
goforward = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = ty_sb_prepend(&sb, txt, txtlen);
|
||||||
|
if (res < 0) goto end;
|
||||||
|
if (!_is_authorized_in_color_sharp(codepoint))
|
||||||
|
{
|
||||||
|
ty_sb_lskip(&sb, txtlen);
|
||||||
|
goback = EINA_FALSE;
|
||||||
|
goforward = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
x1 = new_x1;
|
||||||
|
y1 = new_y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (goforward && sb.len <= 9)
|
||||||
|
{
|
||||||
|
int new_x2 = x2, new_y2 = y2;
|
||||||
|
|
||||||
|
/* Check if the previous char is a delimiter */
|
||||||
|
res = _txt_next_at(ty, &new_x2, &new_y2, txt, &txtlen, &codepoint);
|
||||||
|
if ((res != 0) || (txtlen == 0))
|
||||||
|
{
|
||||||
|
goforward = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_is_authorized_in_color_sharp(codepoint))
|
||||||
|
{
|
||||||
|
goforward = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = ty_sb_add(&sb, txt, txtlen);
|
||||||
|
if (res < 0) goto end;
|
||||||
|
|
||||||
|
x2 = new_x2;
|
||||||
|
y2 = new_y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.buf[0] == '#')
|
||||||
|
{
|
||||||
|
if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
|
||||||
|
goto end;
|
||||||
|
found = EINA_TRUE;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
ty_sb_free(&sb);
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
if (rp) *rp = r;
|
||||||
|
if (gp) *gp = g;
|
||||||
|
if (bp) *bp = b;
|
||||||
|
if (ap) *ap = a;
|
||||||
|
if (x1r) *x1r = x1;
|
||||||
|
if (y1r) *y1r = y1 + sc;
|
||||||
|
if (x2r) *x2r = x2;
|
||||||
|
if (y2r) *y2r = y2 + sc;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Eina_Bool
|
Eina_Bool
|
||||||
termio_color_find(const Evas_Object *obj, int cx, int cy,
|
termio_color_find(const Evas_Object *obj, int cx, int cy,
|
||||||
int *x1r, int *y1r, int *x2r, int *y2r,
|
int *x1r, int *y1r, int *x2r, int *y2r,
|
||||||
uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
|
uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
|
||||||
{
|
{
|
||||||
int x1, x2, y1, y2, w = 0, h = 0, sc;
|
int x1, x2, y1, y2, w = 0, h = 0, sc;
|
||||||
//const char authorized[] = "#0123456789aAbBcCdDeEfFrghsoltun() ,+/";
|
|
||||||
Eina_Bool goback = EINA_TRUE,
|
Eina_Bool goback = EINA_TRUE,
|
||||||
goforward = EINA_FALSE;
|
goforward = EINA_FALSE;
|
||||||
struct ty_sb sb = {.buf = NULL, .gap = 0, .len = 0, .alloc = 0};
|
struct ty_sb sb = {.buf = NULL, .gap = 0, .len = 0, .alloc = 0};
|
||||||
|
@ -716,7 +961,6 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
|
||||||
int codepoint;
|
int codepoint;
|
||||||
uint8_t r, g, b, a = 255;
|
uint8_t r, g, b, a = 255;
|
||||||
|
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ty, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ty, EINA_FALSE);
|
||||||
|
|
||||||
x1 = x2 = cx;
|
x1 = x2 = cx;
|
||||||
|
@ -731,7 +975,11 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
|
||||||
y1 -= sc;
|
y1 -= sc;
|
||||||
y2 -= sc;
|
y2 -= sc;
|
||||||
|
|
||||||
/* TODO: boris */
|
found = _sharp_color_find(ty, sc, &x1, &y1, &x2, &y2,
|
||||||
|
&r, &g, &b, &a);
|
||||||
|
if (found)
|
||||||
|
goto end;
|
||||||
|
|
||||||
res = _txt_at(ty, &x1, &y1, txt, &txtlen, &codepoint);
|
res = _txt_at(ty, &x1, &y1, txt, &txtlen, &codepoint);
|
||||||
if ((res != 0) || (txtlen == 0))
|
if ((res != 0) || (txtlen == 0))
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -763,6 +1011,12 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
|
||||||
|
|
||||||
x1 = new_x1;
|
x1 = new_x1;
|
||||||
y1 = new_y1;
|
y1 = new_y1;
|
||||||
|
if (sbstartswith(&sb, "color"))
|
||||||
|
{
|
||||||
|
goback = EINA_FALSE;
|
||||||
|
goforward = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (goforward)
|
while (goforward)
|
||||||
|
@ -790,50 +1044,37 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
|
||||||
y2 = new_y2;
|
y2 = new_y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* colors do not span multiple lines (for the moment) */
|
||||||
|
if (y1 != y2)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/* Trim */
|
||||||
|
while (sb.len && (sb.buf[0] == ' ' || sb.buf[0] == '\t'))
|
||||||
|
{
|
||||||
|
sb.len--;
|
||||||
|
sb.buf++;
|
||||||
|
sb.gap++;
|
||||||
|
x1++;
|
||||||
|
}
|
||||||
|
while (sb.len && (sb.buf[sb.len-1] == ' ' || sb.buf[sb.len-1] == '\t'))
|
||||||
|
{
|
||||||
|
sb.len--;
|
||||||
|
x2--;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sb.len)
|
if (!sb.len)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (sb.buf[0] == '#')
|
if (sb.len > 6 && strncmp(sb.buf, "color", 5) == 0)
|
||||||
{
|
{
|
||||||
ty_sb_lskip(&sb, 1);
|
if (!_parse_edc_color(&sb, &r, &g, &b, &a))
|
||||||
switch (sb.len)
|
|
||||||
{
|
|
||||||
case 3:
|
|
||||||
if ((!_parse_hex(sb.buf[0], &r)) ||
|
|
||||||
(!_parse_hex(sb.buf[1], &g)) ||
|
|
||||||
(!_parse_hex(sb.buf[2], &b)))
|
|
||||||
goto end;
|
|
||||||
r <<= 4;
|
|
||||||
g <<= 4;
|
|
||||||
b <<= 4;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if ((!_parse_hex(sb.buf[0], &r)) ||
|
|
||||||
(!_parse_hex(sb.buf[1], &g)) ||
|
|
||||||
(!_parse_hex(sb.buf[2], &b)) ||
|
|
||||||
(!_parse_hex(sb.buf[3], &a)))
|
|
||||||
goto end;
|
|
||||||
r <<= 4;
|
|
||||||
g <<= 4;
|
|
||||||
b <<= 4;
|
|
||||||
a <<= 4;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
if ((!_parse_2hex(&sb.buf[0], &r)) ||
|
|
||||||
(!_parse_2hex(&sb.buf[2], &g)) ||
|
|
||||||
(!_parse_2hex(&sb.buf[4], &b)))
|
|
||||||
goto end;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if ((!_parse_2hex(&sb.buf[0], &r)) ||
|
|
||||||
(!_parse_2hex(&sb.buf[2], &g)) ||
|
|
||||||
(!_parse_2hex(&sb.buf[4], &b)) ||
|
|
||||||
(!_parse_2hex(&sb.buf[6], &a)))
|
|
||||||
goto end;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto end;
|
goto end;
|
||||||
|
found = EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
else if (sb.buf[0] == '#')
|
||||||
|
{
|
||||||
|
if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
|
||||||
|
goto end;
|
||||||
found = EINA_TRUE;
|
found = EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue