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); --