more fixed to textblock plus an addition - reverse the markup.
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 15 Oct 2008 09:58:17 +0000 (09:58 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 15 Oct 2008 09:58:17 +0000 (09:58 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@36664 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Evas.h
src/lib/canvas/evas_object_textblock.c

index 38a2a76..76b8089 100644 (file)
@@ -619,7 +619,8 @@ extern "C" {
    typedef enum _Evas_Textblock_Text_Type
      {
        EVAS_TEXTBLOCK_TEXT_RAW,
-       EVAS_TEXTBLOCK_TEXT_PLAIN
+       EVAS_TEXTBLOCK_TEXT_PLAIN,
+       EVAS_TEXTBLOCK_TEXT_MARKUP
      } Evas_Textblock_Text_Type;
    
    EAPI Evas_Object                 *evas_object_textblock_add(Evas *e);
@@ -668,6 +669,7 @@ extern "C" {
    EAPI const char                  *evas_textblock_cursor_node_text_get(const Evas_Textblock_Cursor *cur);
    EAPI int                          evas_textblock_cursor_node_text_length_get(const Evas_Textblock_Cursor *cur);
    EAPI const char                  *evas_textblock_cursor_node_format_get(const Evas_Textblock_Cursor *cur);
+   EAPI Evas_Bool                    evas_textblock_cursor_node_format_is_visible_get(const Evas_Textblock_Cursor *cur);
    EAPI char                        *evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2, Evas_Textblock_Text_Type format);
        
    EAPI int                          evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch);
index e7c2c4c..59e4ef3 100644 (file)
@@ -219,8 +219,6 @@ _style_clear(Evas_Textblock_Style *ts)
    ts->tags = NULL;
 }
 
-/* setting a textblock via markup */
-/*
 static char *
 _style_match_replace(Evas_Textblock_Style *ts, char *s)
 {
@@ -235,7 +233,6 @@ _style_match_replace(Evas_Textblock_Style *ts, char *s)
      }
    return NULL;
 }
-*/
 
 static char *
 _style_match_tag(Evas_Textblock_Style *ts, char *s)
@@ -458,6 +455,71 @@ _lines_clear(const Evas_Object *obj, Evas_Object_Textblock_Line *lines)
      }
 }
 
+static void
+_nodes_adjacent_merge(const Evas_Object *obj, Evas_Object_Textblock_Node *n1)
+{
+   Evas_Object_Textblock *o;
+   Evas_Object_Textblock_Node *n0, *n2;
+   Evas_List *l;
+   int plen;
+   
+   if (n1->type != NODE_TEXT) return;
+   o = (Evas_Object_Textblock *)(obj->object_data);
+   n0 = (Evas_Object_Textblock_Node *)((Evas_Object_List *)n1)->prev;
+   n2 = (Evas_Object_Textblock_Node *)((Evas_Object_List *)n1)->next;
+   if ((n0) && (n0->type == NODE_TEXT))
+     {
+       plen = n0->len;
+       n0->text = _strbuf_append(n0->text, n1->text, &(n0->len), &(n0->alloc));
+       ((Evas_Object_List *)n0)->next = (Evas_Object_List *)n2;
+       if (n2) ((Evas_Object_List *)n2)->prev = (Evas_Object_List *)n0;
+       // fix any cursors in n1
+       if (n1 == o->cursor->node)
+         {
+            o->cursor->node = n0;
+            o->cursor->pos += plen;
+         }
+        for (l = o->cursors; l; l = l->next)
+         {
+            if (n1 == ((Evas_Textblock_Cursor *)l->data)->node)
+              {
+                 ((Evas_Textblock_Cursor *)l->data)->node = n0;
+                 ((Evas_Textblock_Cursor *)l->data)->pos += plen;
+              }
+         }
+       if (n1->text) free(n1->text);
+       free(n1);
+       n1 = n0;
+     }
+   if ((n2) && (n2->type == NODE_TEXT))
+     {
+       n0 = n1;
+       n1 = n2;
+       n2 = (Evas_Object_Textblock_Node *)((Evas_Object_List *)n1)->next;
+       plen = n0->len;
+       n0->text = _strbuf_append(n0->text, n1->text, &(n0->len), &(n0->alloc));
+       ((Evas_Object_List *)n0)->next = (Evas_Object_List *)n2;
+       if (n2) ((Evas_Object_List *)n2)->prev = (Evas_Object_List *)n0;
+       // fix any cursors in n1
+       if (n1 == o->cursor->node)
+         {
+            o->cursor->node = n0;
+            o->cursor->pos += plen;
+         }
+        for (l = o->cursors; l; l = l->next)
+         {
+            if (n1 == ((Evas_Textblock_Cursor *)l->data)->node)
+              {
+                 ((Evas_Textblock_Cursor *)l->data)->node = n0;
+                 ((Evas_Textblock_Cursor *)l->data)->pos += plen;
+              }
+         }
+       if (n1->text) free(n1->text);
+       free(n1);
+       n1 = n0;
+     }
+}
+
 /* table of html escapes (that i can find) this should be ordered with the
  * most common first as it's a linear search to match - no hash for this.
  *
@@ -2312,9 +2374,25 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
    Evas_List *l;
    
    if (!ts) return;
+
+   for (l = ts->objects; l; l = l->next)
+     {
+       Evas_Object *obj;
+       Evas_Object_Textblock *o;
+       
+       obj = l->data;
+       o = (Evas_Object_Textblock *)(obj->object_data);
+       if (o->markup_text)
+         {
+            free(o->markup_text);
+            o->markup_text = NULL;
+            evas_object_textblock_text_markup_get(obj);
+         }
+     }
+   
    _style_clear(ts);
    if (text) ts->style_text = strdup(text);
-
+   
    if (ts->style_text)
      {
        // format MUST be KEY='VALUE'[KEY='VALUE']...
@@ -2436,6 +2514,12 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
    TB_HEAD();
    if (ts == o->style) return;
    if ((ts) && (ts->delete_me)) return;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+       evas_object_textblock_text_markup_get(obj);
+     }
    if (o->style)
      {
        Evas_Textblock_Style *old_ts;
@@ -2646,6 +2730,11 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text)
               }
             p++;
          }
+     }
+   evas_textblock_cursor_node_last(o->cursor);
+   evas_textblock_cursor_format_append(o->cursor, "\n");
+   if (text)
+     {
        if (text != o->markup_text)
          o->markup_text = strdup(text);
      }
@@ -2666,7 +2755,72 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text)
 EAPI const char *
 evas_object_textblock_text_markup_get(const Evas_Object *obj)
 {
+   Evas_Object_List *l;
+   char *txt = NULL;
+   int txt_len = 0, txt_alloc = 0;
+   
    TB_HEAD_RETURN(NULL);
+   if (o->markup_text) return(o->markup_text);
+   for (l = (Evas_Object_List *)o->nodes; l; l = l->next)
+     {
+       Evas_Object_Textblock_Node *n;
+       
+       n = (Evas_Object_Textblock_Node *)l;
+        if ((n->type == NODE_FORMAT) && (n->text))
+         {
+            char *tag = _style_match_replace(o->style, n->text);
+            txt = _strbuf_append(txt, "<", &txt_len, &txt_alloc);
+            if (tag)
+              {
+                 // FIXME: need to escape
+                 txt = _strbuf_append(txt, tag, &txt_len, &txt_alloc);
+              }
+            else
+              {
+                 char *s;
+                 int push = 0;
+                 int pop = 0;
+                 
+                 // FIXME: need to escape      
+                 s = n->text;
+                 if (*s == '+') push = 1;
+                 if (*s == '-') pop = 1;
+                 while ((*s == ' ') || (*s == '+') || (*s == '-')) s++;
+                 if (pop) txt = _strbuf_append(txt, "/", &txt_len, &txt_alloc);
+                 txt = _strbuf_append(txt, s, &txt_len, &txt_alloc);
+              }
+            txt = _strbuf_append(txt, ">", &txt_len, &txt_alloc);
+         }
+       else if ((n->type == NODE_TEXT) && (n->text))
+         {
+            if (strchr(n->text, '<') || strchr(n->text, '>') ||
+                strchr(n->text, '&'))
+              {
+                 char *p;
+                 
+                 p = n->text;
+                 while (*p)
+                   {
+                      char s[2];
+                      
+                      s[0] = *p;
+                      s[1] = 0;
+                      if (s[0] == '<')
+                        txt = _strbuf_append(txt, "&lt;", &txt_len, &txt_alloc);
+                      else if (s[0] == '>')
+                        txt = _strbuf_append(txt, "&gt;", &txt_len, &txt_alloc);
+                      else if (s[0] == '&')
+                        txt = _strbuf_append(txt, "&amp;", &txt_len, &txt_alloc);
+                      else
+                        txt = _strbuf_append(txt, s, &txt_len, &txt_alloc);
+                      p++;
+                   }
+              }
+            else
+              txt = _strbuf_append(txt, n->text, &txt_len, &txt_alloc);
+         }
+     }
+   o->markup_text = txt;
    return o->markup_text;
 }
 
@@ -3107,7 +3261,7 @@ EAPI void
 evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n;
+   Evas_Object_Textblock_Node *n, *nrel;
    int index, ch;
    
    if (!cur) return;
@@ -3138,9 +3292,13 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text)
    n = cur->node;
    if ((!n) || (n->type == NODE_FORMAT))
      {
+       nrel = n;
        n = calloc(1, sizeof(Evas_Object_Textblock_Node));
        n->type = NODE_TEXT;
-       o->nodes = evas_object_list_append(o->nodes, n);
+       if (nrel)
+         o->nodes = evas_object_list_append_relative(o->nodes, n, nrel);
+       else
+         o->nodes = evas_object_list_append(o->nodes, n);
      }
    cur->node = n;
    index = cur->pos;
@@ -3158,6 +3316,11 @@ evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text)
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3171,7 +3334,7 @@ EAPI void
 evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text)
 {
    Evas_Object_Textblock *o;
-   Evas_Object_Textblock_Node *n;
+   Evas_Object_Textblock_Node *n, *nrel;
    int index;
    
    if (!cur) return;
@@ -3206,9 +3369,13 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text)
    n = cur->node;
    if ((!n) || (n->type == NODE_FORMAT))
      {
+       nrel = n;
        n = calloc(1, sizeof(Evas_Object_Textblock_Node));
        n->type = NODE_TEXT;
-       o->nodes = evas_object_list_append(o->nodes, n);
+       if (nrel)
+         o->nodes = evas_object_list_prepend_relative(o->nodes, n, nrel);
+       else
+         o->nodes = evas_object_list_prepend(o->nodes, n);
      }
    cur->node = n;
    index = cur->pos;
@@ -3220,6 +3387,11 @@ evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text)
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3286,6 +3458,11 @@ evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *form
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3347,6 +3524,11 @@ evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *for
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3364,6 +3546,8 @@ evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur)
    if (!cur) return;
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    n = cur->node;
+   if ((n->text) && (!strcmp(n->text, "\n")) && 
+       (!((Evas_Object_List *)n)->next)) return;
    n2 = (Evas_Object_Textblock_Node *)(((Evas_Object_List *)n)->next);
    if (n2)
      {
@@ -3406,9 +3590,16 @@ evas_textblock_cursor_node_delete(Evas_Textblock_Cursor *cur)
    if (n->text) free(n->text);
    free(n);
    
+   if (n2) _nodes_adjacent_merge(cur->obj, n2);
+   
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3484,6 +3675,11 @@ evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur)
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur->obj);
 }
 
@@ -3699,6 +3895,11 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(cur1->obj);
 }
 
@@ -3755,6 +3956,54 @@ evas_textblock_cursor_node_format_get(const Evas_Textblock_Cursor *cur)
 
 /*
  * to be documented.
+ * @param cur to be documented.
+ * @return to be documented.
+ */
+EAPI Evas_Bool
+evas_textblock_cursor_node_format_is_visible_get(const Evas_Textblock_Cursor *cur)
+{
+   Evas_Object_Textblock_Node *n;
+   
+   if (!cur) return NULL;
+   n = cur->node;
+   if (!n) return NULL;
+   if (n->type != NODE_FORMAT) return 0;
+   if (!n->text) return;
+     {
+       char *s;
+       char *item;
+       int push = 0;
+       int pop = 0;
+       int visible = 0;
+       
+       s = n->text;
+       if (s[0] == '+')
+         {
+            push = 1;
+            s++;
+         }
+       else if (s[0] == '-')
+         {
+            pop = 1;
+            s++;
+         }
+       while ((item = _format_parse(&s)))
+         {
+            char tmp_delim = *s;
+            *s = '\0';
+            if ((!strcmp(item, "\n")) || (!strcmp(item, "\\n")))
+              visible = 1;
+            else if ((!strcmp(item, "\t")) || (!strcmp(item, "\\t")))
+              visible = 1;
+            *s = tmp_delim;
+            if (visible) return 1;
+         }
+     }
+   return 0;
+}
+
+/*
+ * to be documented.
  * @param cur1 to be documented.
  * @param cur2 to be documented.
  * @param format to be documented.
@@ -3851,14 +4100,24 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
    int pos, ret;
    
    if (!cur) return -1;
-   if (!cur->node) return -1;
+   if (!cur->node)
+     {
+       return -1;
+     }
    o = (Evas_Object_Textblock *)(cur->obj->object_data);
    if (!o->formatted.valid) _relayout(cur->obj);
    if (cur->node->type == NODE_FORMAT)
-     _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+     {
+       _find_layout_format_item_line_match(cur->obj, cur->node, &ln, &fi);
+     }
    else
-     _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
-   if (!ln) return -1;
+     {
+       _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
+     }
+   if (!ln)
+     {
+       return -1;
+     }
    if (it)
      {
        pos = cur->pos - it->source_pos;
@@ -3893,7 +4152,10 @@ evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_C
        w = fi->w;
        h = ln->h;
      }
-   else return -1;
+   else
+     {
+       return -1;
+     }
    if (cx) *cx = x;
    if (cy) *cy = y;
    if (cw) *cw = w;
@@ -4196,11 +4458,6 @@ evas_object_textblock_clear(Evas_Object *obj)
        cur->node = NULL;
        cur->pos = 0;
      }
-   if (o->markup_text)
-     {
-       free(o->markup_text);
-       o->markup_text = NULL;
-     }
    if (o->lines)
      {
        _lines_clear(obj, o->lines);
@@ -4209,6 +4466,11 @@ evas_object_textblock_clear(Evas_Object *obj)
    o->formatted.valid = 0;
    o->native.valid = 0;
    o->changed = 1;
+   if (o->markup_text)
+     {
+       free(o->markup_text);
+       o->markup_text = NULL;
+     }
    evas_object_change(obj);
    /* FIXME: adjust cursors that are affected by the change */
 }