hermet pushed a commit to branch master.

http://git.enlightenment.org/tools/enventor.git/commit/?id=ed7e655add622be20a2300b5166810bf28a550ce

commit ed7e655add622be20a2300b5166810bf28a550ce
Author: taehyub <taehyub....@samsung.com>
Date:   Wed Jan 27 13:01:53 2016 +0900

    edc_editor: add pair of bracket highlighting feature
    
    Summary: when mouse cursor on bracket which are '{', '}', the bracket is 
highlighted with its pair.
    
    Reviewers: Jaehyun_Cho, Hermet
    
    Reviewed By: Hermet
    
    Subscribers: herb, NikaWhite, Jaehyun_Cho
    
    Differential Revision: https://phab.enlightenment.org/D3588
---
 src/lib/edc_editor.c       |  72 ++++++++++++
 src/lib/edc_parser.c       | 282 ++++++++++++++++++++++++++++++++++++++++++++-
 src/lib/enventor_private.h |  12 +-
 3 files changed, 364 insertions(+), 2 deletions(-)

diff --git a/src/lib/edc_editor.c b/src/lib/edc_editor.c
index c9f9d88..1f3b9af 100644
--- a/src/lib/edc_editor.c
+++ b/src/lib/edc_editor.c
@@ -175,6 +175,28 @@ error_highlight(edit_data *ed, Evas_Object *tb)
      }
    evas_textblock_cursor_free(cur1);
 }
+
+static void
+bracket_highlight(edit_data *ed, Evas_Object *tb)
+{
+   Evas_Textblock_Cursor *cur1 = evas_object_textblock_cursor_new(tb);
+
+   int left_bracket = parser_left_bracket_pos_get(ed->pd);
+   int right_bracket = parser_right_bracket_pos_get(ed->pd);
+
+   evas_textblock_cursor_pos_set(cur1, left_bracket);
+   evas_object_textblock_text_markup_prepend(cur1, 
"<hilight><color=#B1B1B1FF>");
+   evas_textblock_cursor_pos_set(cur1, left_bracket+1);
+   evas_object_textblock_text_markup_prepend(cur1, "</color></hilight>");
+
+   evas_textblock_cursor_pos_set(cur1, right_bracket);
+   evas_object_textblock_text_markup_prepend(cur1, 
"<hilight><color=#B1B1B1FF>");
+   evas_textblock_cursor_pos_set(cur1, right_bracket+1);
+   evas_object_textblock_text_markup_prepend(cur1, "</color></hilight>");
+
+   evas_textblock_cursor_free(cur1);
+}
+
 static void
 syntax_color_apply(edit_data *ed, Eina_Bool partial)
 {
@@ -202,6 +224,7 @@ syntax_color_apply(edit_data *ed, Eina_Bool partial)
       Logically that's unnecessary in this case. */
    evas_object_textblock_text_markup_set(tb, translated);
    error_highlight(ed, tb);
+   bracket_highlight(ed, tb);
    entry_recover(ed, pos);
 }
 
@@ -269,6 +292,50 @@ syntax_color_thread_cancel_cb(void *data, Ecore_Thread 
*thread EINA_UNUSED)
    free(td);
 }
 
+void
+bracket_changed_cb(void *data)
+{
+   edit_data *ed = data;
+   syntax_color_partial_update(ed, SYNTAX_COLOR_SHORT_TIME);
+}
+
+static void
+bracket_update(edit_data *ed)
+{
+   int pos = elm_entry_cursor_pos_get(ed->en_edit);
+   if (pos == 0) return;
+
+   Evas_Object *tb = elm_entry_textblock_get(ed->en_edit);
+   Evas_Textblock_Cursor *cur1 = evas_object_textblock_cursor_get(tb);
+
+   char ch1, ch2;
+   ch1 = -1;
+   ch2 = -1;
+
+   ch1 = evas_textblock_cursor_content_get(cur1)[0];
+   Eina_Bool is_exist = evas_textblock_cursor_char_prev(cur1);
+   if (is_exist)
+     ch2 = evas_textblock_cursor_content_get(cur1)[0];
+   evas_textblock_cursor_char_next(cur1);
+
+   if (ch1 != '{' && ch1 != '}' && ch2 != '{' && ch2 != '}')
+     {
+        int prev_left_bracket = parser_prev_left_bracket_pos_get(ed->pd);
+        int prev_right_bracket = parser_prev_right_bracket_pos_get(ed->pd);
+        if (prev_left_bracket != -1 && prev_right_bracket != -1)
+          {
+             parser_left_bracket_pos_set(ed->pd, -1);
+             parser_right_bracket_pos_set(ed->pd, -1);
+             parser_prev_left_bracket_pos_set(ed->pd, -1);
+             parser_prev_right_bracket_pos_set(ed->pd, -1);
+             syntax_color_partial_update(ed, SYNTAX_COLOR_SHORT_TIME);
+          }
+        return;
+     }
+
+   parser_bracket_pair_find(ed->pd, ed->en_edit, bracket_changed_cb, ed);
+}
+
 static void
 edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
 {
@@ -324,8 +391,11 @@ edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, 
void *event_info)
         if (info->change.del.content[0] == ' ') return;
      }
 
+
    if (!syntax_color) return;
    syntax_color_partial_update(ed, SYNTAX_COLOR_DEFAULT_TIME);
+
+   parser_bracket_pair_cancel(ed->pd);
 }
 
 static void
@@ -730,6 +800,8 @@ edit_cursor_changed_cb(void *data, Evas_Object *obj 
EINA_UNUSED,
    edit_data *ed = data;
    cur_line_pos_set(ed, EINA_FALSE);
    edit_view_sync(ed);
+
+   bracket_update(ed);
 }
 
 static void
diff --git a/src/lib/edc_parser.c b/src/lib/edc_parser.c
index f326aad..6820e30 100644
--- a/src/lib/edc_parser.c
+++ b/src/lib/edc_parser.c
@@ -52,6 +52,22 @@ typedef struct type_init_thread_data_s
    parser_data *pd;
 } type_init_td;
 
+typedef struct bracket_data_s
+{
+   int left;
+   int right;
+   int prev_left;
+   int prev_right;
+} bracket;
+
+typedef struct bracket_thread_data_s
+{
+   int pos;
+   const char *text;
+   Bracket_Update_Cb update_cb;
+   void *data;
+} bracket_data_td;
+
 struct parser_s
 {
    Eina_Inarray *attrs;
@@ -59,10 +75,15 @@ struct parser_s
    type_init_td *titd;
    Eina_List *macro_list;
 
+   bracket_data_td *bracket_td;
+   Ecore_Thread *bracket_thread;
+   bracket bracket_pos;
+
+   Eina_Bool is_bracket_thread_req: 1;
+
    Eina_Bool macro_update : 1;
 };
 
-
 /*****************************************************************************/
 /* Internal method implementation                                            */
 /*****************************************************************************/
@@ -1857,6 +1878,8 @@ parser_init(void)
 
    td->pd = pd;
    pd->titd = td;
+   pd->bracket_pos.left = -1;
+   pd->bracket_pos.right = -1;
    td->thread = ecore_thread_run(type_init_thread_blocking,
                                  type_init_thread_end,
                                  type_init_thread_cancel, td);
@@ -1949,3 +1972,260 @@ parser_macro_update(parser_data *pd, Eina_Bool 
macro_update)
 {
    pd->macro_update = macro_update;
 }
+
+static Eina_Bool
+bracket_pair_parse(int pos, const char *text, int *left, int *right)
+{
+   int left_bracket = -1;
+   int right_bracket = -1;
+
+   int cur_pos = pos;
+   int depth = 0;
+
+   if (cur_pos == 0)
+     return EINA_FALSE;
+
+   const char *utf8 = text;
+   int length = strlen(utf8);
+
+   // left,  {
+   if (utf8[cur_pos] == '{')
+     {
+        left_bracket = cur_pos;
+        cur_pos++;
+        while (cur_pos < length)
+          {
+             if (utf8[cur_pos] == '{') depth++;
+             else if (utf8[cur_pos] == '}')
+               {
+                  if (depth) depth--;
+                  else
+                    {
+                       right_bracket = cur_pos;
+                       break;
+                    }
+               }
+             cur_pos++;
+          }
+     }
+   // left,  }
+   else if(utf8[cur_pos] == '}')
+     {
+        right_bracket = cur_pos;
+        cur_pos--;
+        while (cur_pos)
+          {
+             if (utf8[cur_pos] == '}') depth++;
+             else if(utf8[cur_pos] == '{')
+               {
+                  if(depth) depth--;
+                  else
+                    {
+                       left_bracket = cur_pos;
+                       break;
+                    }
+               }
+             cur_pos--;
+          }
+     }
+   // right, {
+   else if(utf8[cur_pos - 1] == '{')
+     {
+        left_bracket = cur_pos - 1;
+        while (cur_pos < length)
+          {
+             if (utf8[cur_pos] == '{') depth++;
+             else if (utf8[cur_pos] == '}')
+               {
+                  if (depth) depth--;
+                  else
+                    {
+                       right_bracket = cur_pos;
+                       break;
+                    }
+               }
+             cur_pos++;
+          }
+     }
+   // right, }
+   else if(utf8[cur_pos - 1] == '}')
+     {
+        right_bracket = cur_pos - 1;
+        cur_pos -= 2;
+        while (cur_pos)
+          {
+             if (utf8[cur_pos] == '}') depth++;
+             else if (utf8[cur_pos] == '{')
+               {
+                  if(depth) depth--;
+                  else
+                    {
+                       left_bracket = cur_pos;
+                       break;
+                    }
+               }
+             cur_pos--;
+          }
+     }
+
+   if (left_bracket == -1 || right_bracket == -1)
+     {
+        left_bracket = -1;
+           right_bracket = -1;
+        }
+
+   *left = left_bracket;
+   *right = right_bracket;
+
+  return EINA_TRUE;
+}
+
+static void bracket_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED);
+static void bracket_thread_end_cb(void *data, Ecore_Thread *thread 
EINA_UNUSED);
+static void bracket_thread_cancel_cb(void *data, Ecore_Thread *thread 
EINA_UNUSED);
+
+static void
+bracket_thread_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
+{
+   parser_data *pd = data;
+
+   if (bracket_pair_parse(pd->bracket_td->pos, pd->bracket_td->text,
+                          &(pd->bracket_pos.left),
+                          &(pd->bracket_pos.right)) == EINA_FALSE)
+     return;
+
+   if (pd->bracket_pos.left != -1 && pd->bracket_pos.right != -1)
+     {
+        if (pd->bracket_pos.prev_left != pd->bracket_pos.left
+            && pd->bracket_pos.prev_right != pd->bracket_pos.right)
+          {
+             pd->bracket_td->update_cb(pd->bracket_td->data);
+             pd->bracket_pos.prev_left = pd->bracket_pos.left;
+             pd->bracket_pos.prev_right = pd->bracket_pos.right;
+          }
+     }
+   else if(pd->bracket_pos.prev_left != -1 && pd->bracket_pos.prev_right != -1)
+     {
+        pd->bracket_td->update_cb(pd->bracket_td->data);
+        pd->bracket_pos.prev_left = -1;
+        pd->bracket_pos.prev_right = -1;
+     }
+}
+
+static void
+bracket_thread_end_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
+{
+   parser_data *pd = data;
+
+   if (pd->is_bracket_thread_req == EINA_TRUE)
+     {
+        pd->is_bracket_thread_req = EINA_FALSE;
+        pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
+                                              bracket_thread_end_cb,
+                                              bracket_thread_cancel_cb,
+                                              pd);
+     }
+   else
+    {
+        free(pd->bracket_td);
+        pd->bracket_td = NULL;
+        pd->bracket_thread = NULL;
+    }
+}
+
+static void
+bracket_thread_cancel_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
+{
+   parser_data *pd = data;
+
+   if (pd->is_bracket_thread_req == EINA_TRUE)
+     {
+        pd->is_bracket_thread_req = EINA_FALSE;
+        pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
+                                              bracket_thread_end_cb,
+                                              bracket_thread_cancel_cb,
+                                              pd);
+     }
+   else
+     {
+        free(pd->bracket_td);
+        pd->bracket_td = NULL;
+        pd->bracket_thread = NULL;
+     }
+}
+
+void
+parser_bracket_pair_find(parser_data *pd, Evas_Object *entry,
+                         Bracket_Update_Cb func, void *data)
+{
+
+   ecore_thread_cancel(pd->bracket_thread);
+
+   if (pd->bracket_td == NULL)
+     pd->bracket_td = calloc(1, sizeof(bracket_data_td));
+
+   const char *text = elm_entry_entry_get(entry);
+   char *utf8 = elm_entry_markup_to_utf8(text);
+   int pos = elm_entry_cursor_pos_get(entry);
+
+   pd->bracket_td->pos = pos;
+   pd->bracket_td->text = utf8;
+   pd->bracket_td->update_cb = func;
+   pd->bracket_td->data = data;
+
+   if (pd->bracket_thread == NULL)
+     {
+        pd->is_bracket_thread_req = EINA_FALSE;
+        pd->bracket_thread = ecore_thread_run(bracket_thread_cb,
+                                              bracket_thread_end_cb,
+                                              bracket_thread_cancel_cb,
+                                              pd);
+     }
+   else
+     pd->is_bracket_thread_req = EINA_TRUE;
+}
+
+void parser_bracket_pair_cancel(parser_data *pd)
+{
+   ecore_thread_cancel(pd->bracket_thread);
+}
+
+void parser_left_bracket_pos_set(parser_data *pd, int pos)
+{
+   pd->bracket_pos.left = pos;
+}
+
+void parser_right_bracket_pos_set(parser_data *pd, int pos)
+{
+   pd->bracket_pos.right = pos;
+}
+
+void parser_prev_left_bracket_pos_set(parser_data *pd, int pos)
+{
+   pd->bracket_pos.prev_left = pos;
+}
+
+void parser_prev_right_bracket_pos_set(parser_data *pd, int pos)
+{
+   pd->bracket_pos.prev_right = pos;
+}
+
+int parser_left_bracket_pos_get(parser_data *pd)
+{
+   return pd->bracket_pos.left;
+}
+
+int parser_right_bracket_pos_get(parser_data *pd)
+{
+   return pd->bracket_pos.right;
+}
+
+int parser_prev_left_bracket_pos_get(parser_data *pd)
+{
+   return pd->bracket_pos.prev_left;
+}
+
+int parser_prev_right_bracket_pos_get(parser_data *pd)
+{
+   return pd->bracket_pos.prev_right;
+}
diff --git a/src/lib/enventor_private.h b/src/lib/enventor_private.h
index 1d85a68..b7e835b 100644
--- a/src/lib/enventor_private.h
+++ b/src/lib/enventor_private.h
@@ -139,7 +139,17 @@ Eina_Bool parser_state_info_get(Evas_Object *entry, 
state_info *info);
 void parser_macro_list_set(parser_data *pd, const char *text);
 Eina_List *parser_macro_list_get(parser_data *pd);
 void parser_macro_update(parser_data *pd, Eina_Bool macro_update);
-
+typedef void (*Bracket_Update_Cb)(void *data);
+void parser_bracket_pair_find(parser_data *pd, Evas_Object *entry, 
Bracket_Update_Cb func, void *data);
+void parser_bracket_pair_cancel(parser_data *pd);
+void parser_left_bracket_pos_set(parser_data *pd, int pos);
+void parser_right_bracket_pos_set(parser_data *pd, int pos);
+void parser_prev_left_bracket_pos_set(parser_data *pd, int pos);
+void parser_prev_right_bracket_pos_set(parser_data *pd, int pos);
+int parser_left_bracket_pos_get(parser_data *pd);
+int parser_right_bracket_pos_get(parser_data *pd);
+int parser_prev_left_bracket_pos_get(parser_data *pd);
+int parser_prev_right_bracket_pos_get(parser_data *pd);
 
 /* syntax helper */
 syntax_helper *syntax_init(void);

-- 


Reply via email to