billiob pushed a commit to branch master.

http://git.enlightenment.org/apps/terminology.git/commit/?id=10c720aa004022bce1bb9edbd8daba35543799cd

commit 10c720aa004022bce1bb9edbd8daba35543799cd
Author: Boris Faure <[email protected]>
Date:   Sun May 24 19:37:58 2020 +0200

    termiolink: rework color finder
---
 src/bin/sb.h         |   4 +
 src/bin/termiolink.c | 377 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 313 insertions(+), 68 deletions(-)

diff --git a/src/bin/sb.h b/src/bin/sb.h
index a52be74..4cdc8e1 100644
--- a/src/bin/sb.h
+++ b/src/bin/sb.h
@@ -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_free(struct ty_sb *sb);
 
+#define sbstartswith(SB, ConstRef) \
+     (((SB)->len >= sizeof(ConstRef) -1) \
+        && (!strncmp((SB)->buf, ConstRef, sizeof(ConstRef) - 1)))
+
 #endif
diff --git a/src/bin/termiolink.c b/src/bin/termiolink.c
index 89ea480..11e9702 100644
--- a/src/bin/termiolink.c
+++ b/src/bin/termiolink.c
@@ -1,5 +1,6 @@
 #include "private.h"
 #include <Elementary.h>
+#include <assert.h>
 #include "termpty.h"
 #include "backlog.h"
 #include "termiolink.h"
@@ -626,35 +627,64 @@ end:
    return s;
 }
 
+__attribute__((const))
 static Eina_Bool
 _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;
-      case '0': EINA_FALLTHROUGH;
-      case '1': EINA_FALLTHROUGH;
-      case '2': EINA_FALLTHROUGH;
-      case '3': EINA_FALLTHROUGH;
-      case '4': EINA_FALLTHROUGH;
-      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;
+        size_t imid = (imin + imax) / 2;
+
+        if (authorized[imid] == codepoint) return EINA_TRUE;
+        else if (authorized[imid] < codepoint) imin = imid + 1;
+        else imax = imid - 1;
+        if (imax > imaxmax) break;
      }
    return EINA_FALSE;
 }
@@ -698,13 +728,228 @@ _parse_2hex(const char *s, uint8_t *v)
    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
 termio_color_find(const Evas_Object *obj, int cx, int cy,
                   int *x1r, int *y1r, int *x2r, int *y2r,
                   uint8_t *rp, uint8_t *gp, uint8_t *bp, uint8_t *ap)
 {
    int x1, x2, y1, y2, w = 0, h = 0, sc;
-   //const char authorized[] = "#0123456789aAbBcCdDeEfFrghsoltun() ,+/";
    Eina_Bool goback = EINA_TRUE,
              goforward = EINA_FALSE;
    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;
    uint8_t r, g, b, a = 255;
 
-
    EINA_SAFETY_ON_NULL_RETURN_VAL(ty, EINA_FALSE);
 
    x1 = x2 = cx;
@@ -731,7 +975,11 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
    y1 -= 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);
    if ((res != 0) || (txtlen == 0))
      goto end;
@@ -763,6 +1011,12 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
 
         x1 = new_x1;
         y1 = new_y1;
+        if (sbstartswith(&sb, "color"))
+          {
+             goback = EINA_FALSE;
+             goforward = EINA_TRUE;
+             break;
+          }
      }
 
    while (goforward)
@@ -790,50 +1044,37 @@ termio_color_find(const Evas_Object *obj, int cx, int cy,
         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)
      goto end;
 
-   if (sb.buf[0] == '#')
+   if (sb.len > 6 && strncmp(sb.buf, "color", 5) == 0)
      {
-        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)))
-                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;
-          }
+        if (!_parse_edc_color(&sb, &r, &g, &b, &a))
+          goto end;
+        found = EINA_TRUE;
+     }
+   else if (sb.buf[0] == '#')
+     {
+        if (!_parse_sharp_color(&sb, &r, &g, &b, &a))
+          goto end;
         found = EINA_TRUE;
      }
 

-- 


Reply via email to