syntax_color: apply syntax_color on only visible text region.

it's really faster than before while editing large text.
This commit is contained in:
ChunEon Park 2014-05-26 23:35:57 +09:00
parent 20685840ce
commit 6104c3cd7f
6 changed files with 140 additions and 48 deletions

View File

@ -4,7 +4,9 @@
//FIXME: Make flexible //FIXME: Make flexible
const int MAX_LINE_DIGIT_CNT = 10; const int MAX_LINE_DIGIT_CNT = 10;
const double SYNTAX_COLOR_TIME = 0.25; const int SYNTAX_COLOR_SPARE_LINES = 25;
const double SYNTAX_COLOR_DEFAULT_TIME = 0.25;
const double SYNTAX_COLOR_SHORT_TIME = 0.025;
struct editor_s struct editor_s
{ {
@ -19,6 +21,7 @@ struct editor_s
int cur_line; int cur_line;
int line_max; int line_max;
Evas_Coord scroller_h;
Ecore_Timer *syntax_color_timer; Ecore_Timer *syntax_color_timer;
@ -79,24 +82,53 @@ line_decrease(edit_data *ed, int cnt)
if (ed->line_max < 1) line_init(ed); if (ed->line_max < 1) line_init(ed);
} }
static void
current_visible_text_region_get(edit_data *ed, int *from_line, int *to_line)
{
Evas_Coord region_y, region_h;
Evas_Coord cursor_h;
elm_scroller_region_get(ed->scroller, NULL, &region_y, NULL, &region_h);
elm_entry_cursor_geometry_get(ed->en_edit, NULL, NULL, NULL, &cursor_h);
int from = (region_y / cursor_h) - SYNTAX_COLOR_SPARE_LINES;
int to = from + (region_h / cursor_h) + SYNTAX_COLOR_SPARE_LINES;
from -= SYNTAX_COLOR_SPARE_LINES;
to += SYNTAX_COLOR_SPARE_LINES;
if (from < 1) from = 1;
if (to > ed->line_max) to = ed->line_max;
*from_line = from;
*to_line = to;
}
static void static void
syntax_color_apply(edit_data *ed) syntax_color_apply(edit_data *ed)
{ {
//FIXME: Optimize here by applying color syntax for only changed lines Evas_Object *tb = elm_entry_textblock_get(ed->en_edit);
char *text = (char *) elm_entry_entry_get(ed->en_edit); char *text = (char *) evas_object_textblock_text_markup_get(tb);
int pos = elm_entry_cursor_pos_get(ed->en_edit); int pos = elm_entry_cursor_pos_get(ed->en_edit);
int from_line, to_line;
current_visible_text_region_get(ed, &from_line, &to_line);
char *from, *to;
char *utf8 = (char *) color_cancel(syntax_color_data_get(ed->sh), text, char *utf8 = (char *) color_cancel(syntax_color_data_get(ed->sh), text,
strlen(text)); strlen(text), from_line, to_line, &from,
&to);
if (!utf8) return; if (!utf8) return;
const char *translated = color_apply(syntax_color_data_get(ed->sh), utf8, const char *translated = color_apply(syntax_color_data_get(ed->sh), utf8,
strlen(utf8)); strlen(utf8), from, to);
if (!translated) return;
/* I'm not sure this will be problem. /* I'm not sure this will be problem.
But it can avoid entry_object_text_escaped_set() in Edje. But it can avoid entry_object_text_escaped_set() in Edje.
Logically that's unnecessary in this case. */ Logically that's unnecessary in this case. */
Evas_Object *tb = elm_entry_textblock_get(ed->en_edit);
evas_object_textblock_text_markup_set(tb, translated); evas_object_textblock_text_markup_set(tb, translated);
elm_entry_calc_force(ed->en_edit); elm_entry_calc_force(ed->en_edit);
elm_entry_cursor_pos_set(ed->en_edit, 0);
elm_entry_cursor_pos_set(ed->en_edit, pos); elm_entry_cursor_pos_set(ed->en_edit, pos);
//FIXME: Need to recover selection area. //FIXME: Need to recover selection area.
} }
@ -112,11 +144,10 @@ syntax_color_timer_cb(void *data)
} }
static void static void
syntax_color_timer_update(edit_data *ed) syntax_color_timer_update(edit_data *ed, double time)
{ {
ecore_timer_del(ed->syntax_color_timer); ecore_timer_del(ed->syntax_color_timer);
ed->syntax_color_timer = ecore_timer_add(SYNTAX_COLOR_TIME, ed->syntax_color_timer = ecore_timer_add(time, syntax_color_timer_cb, ed);
syntax_color_timer_cb, ed);
} }
static void static void
@ -164,7 +195,7 @@ edit_changed_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
right after applying syntax color. This workaround makes avoid to not right after applying syntax color. This workaround makes avoid to not
applying syntax color while entry has the selected text. */ applying syntax color while entry has the selected text. */
if (elm_entry_selection_get(ed->en_edit)) return; if (elm_entry_selection_get(ed->en_edit)) return;
syntax_color_timer_update(ed); syntax_color_timer_update(ed, SYNTAX_COLOR_DEFAULT_TIME);
} }
static void static void
@ -317,7 +348,7 @@ edit_template_insert(edit_data *ed)
elm_entry_cursor_pos_set(ed->en_edit, cursor_pos); elm_entry_cursor_pos_set(ed->en_edit, cursor_pos);
syntax_color_timer_update(ed); syntax_color_timer_update(ed, 0);
snprintf(buf, sizeof(buf), "Template code inserted. (%s)", buf2); snprintf(buf, sizeof(buf), "Template code inserted. (%s)", buf2);
stats_info_msg_update(buf); stats_info_msg_update(buf);
} }
@ -397,7 +428,7 @@ edit_template_part_insert(edit_data *ed, Edje_Part_Type type)
elm_entry_cursor_pos_set(ed->en_edit, cursor_pos); elm_entry_cursor_pos_set(ed->en_edit, cursor_pos);
syntax_color_timer_update(ed); syntax_color_timer_update(ed, SYNTAX_COLOR_SHORT_TIME);
snprintf(buf, sizeof(buf), "Template code inserted. (%s Part)", part); snprintf(buf, sizeof(buf), "Template code inserted. (%s Part)", part);
stats_info_msg_update(buf); stats_info_msg_update(buf);
} }
@ -741,6 +772,25 @@ key_up_cb(void *data, int type EINA_UNUSED, void *ev)
return ECORE_CALLBACK_PASS_ON; return ECORE_CALLBACK_PASS_ON;
} }
static void
scroller_scroll_cb(void *data, Evas_Object *obj, void *event_info)
{
edit_data *ed = data;
syntax_color_timer_update(ed, SYNTAX_COLOR_SHORT_TIME);
}
static void
scroller_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
edit_data *ed = data;
Evas_Coord h;
evas_object_geometry_get(obj, NULL, NULL, NULL, &h);
if (h == ed->scroller_h) return;
syntax_color_timer_update(ed, SYNTAX_COLOR_SHORT_TIME);
ed->scroller_h = h;
}
edit_data * edit_data *
edit_init(Evas_Object *parent) edit_init(Evas_Object *parent)
{ {
@ -759,6 +809,12 @@ edit_init(Evas_Object *parent)
elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_AUTO, elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_AUTO,
ELM_SCROLLER_POLICY_AUTO); ELM_SCROLLER_POLICY_AUTO);
elm_object_focus_allow_set(scroller, EINA_FALSE); elm_object_focus_allow_set(scroller, EINA_FALSE);
evas_object_smart_callback_add(scroller, "scroll,up", scroller_scroll_cb,
ed);
evas_object_smart_callback_add(scroller, "scroll,down", scroller_scroll_cb,
ed);
evas_object_event_callback_add(scroller, EVAS_CALLBACK_RESIZE,
scroller_resize_cb, ed);
evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND,
EVAS_HINT_EXPAND); EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(scroller, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_align_set(scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
@ -811,7 +867,7 @@ edit_init(Evas_Object *parent)
ed->cur_line = -1; ed->cur_line = -1;
edit_line_number_toggle(ed); edit_line_number_toggle(ed);
edit_font_size_update(ed, EINA_FALSE); edit_font_size_update(ed, EINA_FALSE, EINA_FALSE);
return ed; return ed;
} }
@ -960,7 +1016,7 @@ edit_new(edit_data *ed)
} }
void void
edit_font_size_update(edit_data *ed, Eina_Bool msg) edit_font_size_update(edit_data *ed, Eina_Bool msg, Eina_Bool update)
{ {
elm_object_scale_set(ed->layout, config_font_size_get()); elm_object_scale_set(ed->layout, config_font_size_get());
@ -969,6 +1025,8 @@ edit_font_size_update(edit_data *ed, Eina_Bool msg)
char buf[128]; char buf[128];
snprintf(buf, sizeof(buf), "Font Size: %1.1fx", config_font_size_get()); snprintf(buf, sizeof(buf), "Font Size: %1.1fx", config_font_size_get());
stats_info_msg_update(buf); stats_info_msg_update(buf);
if (update) syntax_color_timer_update(ed, 0);
} }
void void

View File

@ -305,12 +305,12 @@ main_mouse_wheel_cb(void *data, int type EINA_UNUSED, void *ev)
if (event->z < 0) if (event->z < 0)
{ {
config_font_size_set(config_font_size_get() + 0.1f); config_font_size_set(config_font_size_get() + 0.1f);
edit_font_size_update(ad->ed, EINA_TRUE); edit_font_size_update(ad->ed, EINA_TRUE, EINA_TRUE);
} }
else else
{ {
config_font_size_set(config_font_size_get() - 0.1f); config_font_size_set(config_font_size_get() - 0.1f);
edit_font_size_update(ad->ed, EINA_TRUE); edit_font_size_update(ad->ed, EINA_TRUE, EINA_TRUE);
} }
return ECORE_CALLBACK_PASS_ON; return ECORE_CALLBACK_PASS_ON;
@ -365,7 +365,7 @@ config_update_cb(void *data)
app_data *ad = data; app_data *ad = data;
build_cmd_set(); build_cmd_set();
edit_line_number_toggle(ad->ed); edit_line_number_toggle(ad->ed);
edit_font_size_update(ad->ed, EINA_FALSE); edit_font_size_update(ad->ed, EINA_FALSE, EINA_TRUE);
base_tools_toggle(EINA_FALSE); base_tools_toggle(EINA_FALSE);
base_statusbar_toggle(EINA_FALSE); base_statusbar_toggle(EINA_FALSE);

View File

@ -281,10 +281,9 @@ static int
tab_skip(Eina_Strbuf *strbuf, const char **src, int length, char **cur, tab_skip(Eina_Strbuf *strbuf, const char **src, int length, char **cur,
char **prev) char **prev)
{ {
int cmp_size = 6; //strlen("<tab/>"); if (strncmp(*cur, TAB, TAB_LEN)) return 0;
if (strncmp(*cur, "<tab/>", cmp_size)) return 0; eina_strbuf_append_length(strbuf, *prev, (*cur - *prev + TAB_LEN));
eina_strbuf_append_length(strbuf, *prev, (*cur - *prev + cmp_size)); *cur += TAB_LEN;
*cur += cmp_size;
if (*cur > (*src + length)) return -1; if (*cur > (*src + length)) return -1;
*prev = *cur; *prev = *cur;
@ -532,7 +531,8 @@ nospace:
} }
const char * const char *
color_cancel(color_data *cd, const char *src, int length) color_cancel(color_data *cd, const char *src, int length, int from_pos,
int to_pos, char **from, char **to)
{ {
if (!src || length < 1) return NULL; if (!src || length < 1) return NULL;
Eina_Strbuf *strbuf = cd->strbuf; Eina_Strbuf *strbuf = cd->strbuf;
@ -541,14 +541,31 @@ color_cancel(color_data *cd, const char *src, int length)
const char *str = NULL; const char *str = NULL;
char *prev = (char *) src; char *prev = (char *) src;
char *cur = (char *) src; char *cur = (char *) src;
int line = 1;
Eina_Bool find_from = EINA_TRUE;
Eina_Bool find_to = EINA_TRUE;
while (cur && (cur <= (src + length))) while (cur && (cur <= (src + length)))
{ {
if (find_from && (line == from_pos))
{
from_pos = eina_strbuf_length_get(strbuf);
find_from = EINA_FALSE;
}
if (find_to && (line == to_pos))
{
to_pos = eina_strbuf_length_get(strbuf);
find_to = EINA_FALSE;
}
//escape EOL: <br/> //escape EOL: <br/>
if (br_skip(strbuf, &src, length, &cur, &prev) == 1) if (br_skip(strbuf, &src, length, &cur, &prev) == 1)
{
line++;
continue; continue;
}
//escape EOL: <tab/> //escape TAB: <tab/>
if (tab_skip(strbuf, &src, length, &cur, &prev) == 1) if (tab_skip(strbuf, &src, length, &cur, &prev) == 1)
continue; continue;
@ -569,6 +586,14 @@ color_cancel(color_data *cd, const char *src, int length)
if (prev + 1 < cur) eina_strbuf_append(strbuf, prev); if (prev + 1 < cur) eina_strbuf_append(strbuf, prev);
str = eina_strbuf_string_get(strbuf); str = eina_strbuf_string_get(strbuf);
} }
//Exceptional Handling
if (find_from) from_pos = 0;
if (find_to) to_pos = eina_strbuf_length_get(strbuf);
*from = ((char *) str) + from_pos;
*to = ((char *) str) + to_pos;
return str; return str;
} }
@ -659,17 +684,14 @@ color_markup_insert(Eina_Strbuf *strbuf, const char **src, int length, char **cu
return 0; return 0;
} }
/*
OPTIMIZATION POINT
1. Apply Color only changed line.
*/
const char * const char *
color_apply(color_data *cd, const char *src, int length) color_apply(color_data *cd, const char *src, int length, char *from, char *to)
{ {
Eina_Bool inside_string = EINA_FALSE; Eina_Bool inside_string = EINA_FALSE;
Eina_Bool inside_comment = EINA_FALSE; Eina_Bool inside_comment = EINA_FALSE;
if (!src || (length < 1)) return NULL; if (!src || (length < 1)) return NULL;
if (from == to) return NULL;
Eina_Strbuf *strbuf = cd->cachebuf; Eina_Strbuf *strbuf = cd->cachebuf;
eina_strbuf_reset(strbuf); eina_strbuf_reset(strbuf);
@ -682,6 +704,8 @@ color_apply(color_data *cd, const char *src, int length)
while (cur && (cur <= (src + length))) while (cur && (cur <= (src + length)))
{ {
//escape empty string //escape empty string
if (cur >= from)
{
if (cur[0] == ' ') if (cur[0] == ' ')
{ {
if (cur > prev) if (cur > prev)
@ -692,6 +716,7 @@ color_apply(color_data *cd, const char *src, int length)
prev = cur; prev = cur;
continue; continue;
} }
}
//handle comment: /* ~ */ //handle comment: /* ~ */
ret = comment_apply(strbuf, &src, length, &cur, &prev, cd->col_comment, ret = comment_apply(strbuf, &src, length, &cur, &prev, cd->col_comment,
@ -700,10 +725,13 @@ color_apply(color_data *cd, const char *src, int length)
else if (ret == -1) goto finished; else if (ret == -1) goto finished;
//handle comment: // //handle comment: //
ret = comment2_apply(strbuf, &src, length, &cur, &prev, cd->col_comment, if (cur >= from)
&inside_comment); {
ret = comment2_apply(strbuf, &src, length, &cur, &prev,
cd->col_comment, &inside_comment);
if (ret == 1) continue; if (ret == 1) continue;
else if (ret == -1) goto finished; else if (ret == -1) goto finished;
}
//escape string: " ~ " //escape string: " ~ "
ret = string_apply(strbuf, &cur, &prev, cd->col_string, inside_string); ret = string_apply(strbuf, &cur, &prev, cd->col_string, inside_string);
@ -724,11 +752,15 @@ color_apply(color_data *cd, const char *src, int length)
if (ret == 1) continue; if (ret == 1) continue;
//apply color markup //apply color markup
if (cur >= from)
{
ret = color_markup_insert(strbuf, &src, length, &cur, &prev, cd); ret = color_markup_insert(strbuf, &src, length, &cur, &prev, cd);
if (ret == 1) continue; if (ret == 1) continue;
else if (ret == -1) goto finished; else if (ret == -1) goto finished;
}
cur++; cur++;
if (cur > to) goto finished;
} }
//Same with origin source. //Same with origin source.
@ -739,7 +771,7 @@ color_apply(color_data *cd, const char *src, int length)
{ {
finished: finished:
//append leftovers. //append leftovers.
if (prev + 1 < cur) eina_strbuf_append(strbuf, prev); if (prev < cur) eina_strbuf_append(strbuf, prev);
str = eina_strbuf_string_get(strbuf); str = eina_strbuf_string_get(strbuf);
} }

View File

@ -11,7 +11,7 @@ Eina_Bool edit_save(edit_data *ed);
void edit_new(edit_data* ed); void edit_new(edit_data* ed);
void edit_view_sync_cb_set(edit_data *ed, void (*cb)(void *data, Eina_Stringshare *part_name, Eina_Stringshare *group_name), void *data); void edit_view_sync_cb_set(edit_data *ed, void (*cb)(void *data, Eina_Stringshare *part_name, Eina_Stringshare *group_name), void *data);
void edit_view_sync(edit_data *ed); void edit_view_sync(edit_data *ed);
void edit_font_size_update(edit_data *ed, Eina_Bool msg); void edit_font_size_update(edit_data *ed, Eina_Bool msg, Eina_Bool update);
void edit_template_insert(edit_data *ed); void edit_template_insert(edit_data *ed);
void edit_template_part_insert(edit_data *ed, Edje_Part_Type type); void edit_template_part_insert(edit_data *ed, Edje_Part_Type type);
void edit_part_highlight_toggle(edit_data *ed, Eina_Bool msg); void edit_part_highlight_toggle(edit_data *ed, Eina_Bool msg);

View File

@ -3,6 +3,8 @@
#define QUOT_LEN 1 #define QUOT_LEN 1
#define EOL "<br/>" #define EOL "<br/>"
#define EOL_LEN 5 #define EOL_LEN 5
#define TAB "<tab/>"
#define TAB_LEN 6
parser_data *parser_init(); parser_data *parser_init();
void parser_term(parser_data *pd); void parser_term(parser_data *pd);

View File

@ -1,6 +1,6 @@
color_data *color_init(Eina_Strbuf *strbuf); color_data *color_init(Eina_Strbuf *strbuf);
void color_term(color_data *cd); void color_term(color_data *cd);
const char *color_cancel(color_data *cd, const char *str, int length); const char *color_cancel(color_data *cd, const char *str, int length, int from_pos, int to_pos, char **from, char **to);
const char *color_apply(color_data *cd, const char *str, int length); const char *color_apply(color_data *cd, const char *str, int length, char *from, char *to);
Eina_Bool color_ready(color_data *cd); Eina_Bool color_ready(color_data *cd);