diff options
author | Youngbok Shin <youngb.shin@samsung.com> | 2018-08-20 07:21:53 -0400 |
---|---|---|
committer | Mike Blumenkrantz <zmike@samsung.com> | 2018-08-20 10:29:32 -0400 |
commit | 517018e00897f61136418861563a49144a5fe39a (patch) | |
tree | 694c299402631380a10a7ad6ddbebfbb774e7e91 | |
parent | 8da56ac873d5bb083b7cfe08aeefdaa2ad9a4b99 (diff) | |
download | efl-517018e00897f61136418861563a49144a5fe39a.tar.gz |
evas textblock: add/apply cursor cluster APIs based on grapheme cluster
Summary:
Add a feature for moving cursor over a grapheme cluster.
It is applied to edje_entry.c and elm_entry.c for improving
cursor handling just like other modern text editors. ex) gedit
The patch on Evas needs to update libunibreak library.
So, the patch will update libunibreak, too.
@feature
Test Plan:
1. Put "ഹലോ" in your entry.
2. Your cursor can reach at the end of text from the beginning
only in 2 right key event with this feature.
Reviewers: raster, cedric, jpeg, herdsman, zmike, devilhorns
Reviewed By: herdsman, zmike
Subscribers: #reviewers, #committers, zmike, bowonryu, woohyun
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D5490
26 files changed, 2295 insertions, 103 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 0699dde533..b09521cb72 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -193,7 +193,10 @@ static_libs/libunibreak/linebreak.h \ static_libs/libunibreak/linebreakdef.h \ static_libs/libunibreak/wordbreakdef.h \ static_libs/libunibreak/wordbreak.h \ -static_libs/libunibreak/wordbreakdata.c +static_libs/libunibreak/wordbreakdata.c \ +static_libs/libunibreak/graphemebreak.h \ +static_libs/libunibreak/graphemebreakdef.h \ +static_libs/libunibreak/graphemebreakdata.c # Linebreak lib_evas_libevas_la_SOURCES = \ @@ -202,7 +205,8 @@ static_libs/libunibreak/unibreakdef.c \ static_libs/libunibreak/linebreak.c \ static_libs/libunibreak/linebreakdata.c \ static_libs/libunibreak/linebreakdef.c \ -static_libs/libunibreak/wordbreak.c +static_libs/libunibreak/wordbreak.c \ +static_libs/libunibreak/graphemebreak.c # Main lib_evas_libevas_la_SOURCES += \ diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c index 6c1f8960ff..1ad3c30b65 100644 --- a/src/lib/edje/edje_entry.c +++ b/src/lib/edje/edje_entry.c @@ -536,7 +536,7 @@ _curs_jump_line(Evas_Textblock_Cursor *c, Evas_Object *o, Entry *en, int ln) if (!evas_object_textblock_line_number_geometry_get(o, ln, &lx, &ly, &lw, &lh)) return EINA_FALSE; - if (evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2))) + if (evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2))) return EINA_TRUE; evas_textblock_cursor_line_set(c, ln); if (cx < (lx + (lw / 2))) @@ -1607,24 +1607,33 @@ _delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos, ERR("Running very low on memory"); return; } - char *tmp = evas_textblock_cursor_content_get(c); + char *tmp = NULL; info->insert = EINA_FALSE; if (backspace) { info->change.del.start = pos - 1; info->change.del.end = pos; + tmp = evas_textblock_cursor_content_get(c); + evas_textblock_cursor_char_delete(c); } else { - info->change.del.start = pos + 1; + Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object); + evas_textblock_cursor_copy(c, cc); + evas_textblock_cursor_cluster_next(cc); + + info->change.del.start = evas_textblock_cursor_pos_get(cc); info->change.del.end = pos; + + tmp = evas_textblock_cursor_range_text_get(c, cc, EVAS_TEXTBLOCK_TEXT_MARKUP); + evas_textblock_cursor_range_delete(c, cc); + evas_textblock_cursor_free(cc); } info->change.del.content = eina_stringshare_add(tmp); if (tmp) free(tmp); - evas_textblock_cursor_char_delete(c); _edje_emit(ed, "entry,changed", en->rp->part->name); _edje_emit_full(ed, "entry,changed,user", en->rp->part->name, info, _free_entry_change_info); @@ -1855,7 +1864,7 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, } } } - if (evas_textblock_cursor_char_prev(en->cursor)) + if (evas_textblock_cursor_cluster_prev(en->cursor)) ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; #if defined(__APPLE__) && defined(__MACH__) if (altgr) evas_textblock_cursor_word_start(en->cursor); @@ -1903,7 +1912,7 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, #else if (control) evas_textblock_cursor_word_end(en->cursor); #endif - if (evas_textblock_cursor_char_next(en->cursor)) + if (evas_textblock_cursor_cluster_next(en->cursor)) ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; if (en->select_allow) { @@ -1921,7 +1930,7 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, // del to start of previous word _sel_start(en->cursor, rp->object, en); - evas_textblock_cursor_char_prev(en->cursor); + evas_textblock_cursor_cluster_prev(en->cursor); evas_textblock_cursor_word_start(en->cursor); _sel_preextend(ed, en->cursor, rp->object, en); @@ -1961,7 +1970,7 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, _sel_start(en->cursor, rp->object, en); evas_textblock_cursor_word_end(en->cursor); - evas_textblock_cursor_char_next(en->cursor); + evas_textblock_cursor_cluster_next(en->cursor); _sel_extend(ed, en->cursor, rp->object, en); @@ -2400,7 +2409,7 @@ _edje_key_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, v } static Evas_Textblock_Cursor * -_edje_cursor_char_coord_set(Edje_Real_Part *rp, Evas_Coord canvasx, Evas_Coord canvasy, Evas_Coord *cx, Evas_Coord *cy) +_edje_cursor_cluster_coord_set(Edje_Real_Part *rp, Evas_Coord canvasx, Evas_Coord canvasy, Evas_Coord *cx, Evas_Coord *cy) { Entry *en; Evas_Coord x, y, lh = 0, cly = 0; @@ -2432,7 +2441,7 @@ _edje_cursor_char_coord_set(Edje_Real_Part *rp, Evas_Coord canvasx, Evas_Coord c evas_textblock_cursor_free(line_cur); /* No need to check return value if not able to set the char coord Textblock * will take care */ - evas_textblock_cursor_char_coord_set(en->cursor, *cx, *cy); + evas_textblock_cursor_cluster_coord_set(en->cursor, *cx, *cy); return tc; } @@ -2530,7 +2539,7 @@ _edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_ else { evas_textblock_cursor_word_end(en->cursor); - evas_textblock_cursor_char_next(en->cursor); + evas_textblock_cursor_cluster_next(en->cursor); } _sel_extend(en->ed, en->cursor, rp->object, en); } @@ -2544,13 +2553,13 @@ _edje_part_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_ evas_textblock_cursor_word_start(en->cursor); _sel_start(en->cursor, rp->object, en); evas_textblock_cursor_word_end(en->cursor); - evas_textblock_cursor_char_next(en->cursor); + evas_textblock_cursor_cluster_next(en->cursor); _sel_extend(en->ed, en->cursor, rp->object, en); } goto end; } } - tc = _edje_cursor_char_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy); + tc = _edje_cursor_cluster_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy); if (dosel) { @@ -2670,7 +2679,7 @@ _edje_part_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UN #endif /* cx cy are unused but needed in mouse down, please bear with it */ - tc = _edje_cursor_char_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy); + tc = _edje_cursor_cluster_coord_set(rp, ev->canvas.x, ev->canvas.y, &cx, &cy); if (en->select_allow) { @@ -2748,7 +2757,7 @@ _edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_ evas_object_geometry_get(rp->object, &x, &y, &w, &h); cx = ev->cur.canvas.x - x; cy = ev->cur.canvas.y - y; - if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, cy)) + if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, cy)) { Evas_Coord lx, ly, lw, lh; @@ -2760,7 +2769,7 @@ _edje_part_mouse_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_ { evas_textblock_cursor_paragraph_first(en->cursor); evas_textblock_cursor_line_geometry_get(en->cursor, &lx, &ly, &lw, &lh); - if (!evas_textblock_cursor_char_coord_set(en->cursor, cx, ly + (lh / 2))) + if (!evas_textblock_cursor_cluster_coord_set(en->cursor, cx, ly + (lh / 2))) _curs_end(en->cursor, rp->object, en); } } @@ -4029,7 +4038,7 @@ _edje_text_cursor_next(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c) _edje_entry_imf_context_reset(rp); - if (!evas_textblock_cursor_char_next(c)) + if (!evas_textblock_cursor_cluster_next(c)) { return EINA_FALSE; } @@ -4062,7 +4071,7 @@ _edje_text_cursor_prev(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c) _edje_entry_imf_context_reset(rp); - if (!evas_textblock_cursor_char_prev(c)) + if (!evas_textblock_cursor_cluster_prev(c)) { if (evas_textblock_cursor_paragraph_prev(c)) goto ok; else return EINA_FALSE; @@ -4106,7 +4115,7 @@ _edje_text_cursor_up(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c) &lx, &ly, &lw, &lh)) return EINA_FALSE; evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch); - if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2))) + if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2))) evas_textblock_cursor_line_char_last(c); _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data); @@ -4145,7 +4154,7 @@ _edje_text_cursor_down(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c) &lx, &ly, &lw, &lh)) return EINA_FALSE; evas_textblock_cursor_char_geometry_get(c, &cx, &cy, &cw, &ch); - if (!evas_textblock_cursor_char_coord_set(c, cx, ly + (lh / 2))) + if (!evas_textblock_cursor_cluster_coord_set(c, cx, ly + (lh / 2))) evas_textblock_cursor_line_char_last(c); _sel_update(en->ed, c, rp->object, rp->typedata.text->entry_data); @@ -4347,7 +4356,7 @@ _edje_text_cursor_coord_set(Edje_Real_Part *rp, Efl_Text_Cursor_Cursor *c, _edje_emit(en->ed, "selection,changed", rp->part->name); } } - return evas_textblock_cursor_char_coord_set(c, x, y); + return evas_textblock_cursor_cluster_coord_set(c, x, y); } Eina_Bool diff --git a/src/lib/efl/interfaces/efl_text_cursor.eo b/src/lib/efl/interfaces/efl_text_cursor.eo index 973c7d85bd..b0e4c28b51 100644 --- a/src/lib/efl/interfaces/efl_text_cursor.eo +++ b/src/lib/efl/interfaces/efl_text_cursor.eo @@ -145,6 +145,20 @@ interface Efl.Text_Cursor { /* @inout */ cur: ptr(Efl.Text_Cursor_Cursor); [[Cursor object]] } } + cursor_cluster_next { + [[Advances to the next grapheme cluster]] + legacy: null; + params { + /* @inout */ cur: ptr(Efl.Text_Cursor_Cursor); [[Cursor object]] + } + } + cursor_cluster_prev { + [[Advances to the previous grapheme cluster]] + legacy: null; + params { + /* @inout */ cur: ptr(Efl.Text_Cursor_Cursor); [[Cursor object]] + } + } cursor_paragraph_char_first { [[Advances to the first character in this paragraph]] legacy: null; @@ -232,6 +246,17 @@ interface Efl.Text_Cursor { @in y: int; [[Y coord to set by.]] } } + cursor_cluster_coord_set { + [[Set cursor coordinates according to grapheme clusters. + It does not allow to put a cursor to the middle of a grapheme cluster. + ]] + legacy: null; + params { + /* @inout */ cur: ptr(Efl.Text_Cursor_Cursor); [[Cursor object]] + @in x: int; [[X coord to set by.]] + @in y: int; [[Y coord to set by.]] + } + } cursor_text_insert { [[Adds text to the current cursor position and set the cursor to *after* the start of the text just added. diff --git a/src/lib/evas/canvas/efl_canvas_text.eo b/src/lib/evas/canvas/efl_canvas_text.eo index b24139e34a..6c82adf82a 100644 --- a/src/lib/evas/canvas/efl_canvas_text.eo +++ b/src/lib/evas/canvas/efl_canvas_text.eo @@ -327,6 +327,8 @@ class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text_Cursor.cursor_copy; Efl.Text_Cursor.cursor_char_next; Efl.Text_Cursor.cursor_char_prev; + Efl.Text_Cursor.cursor_cluster_next; + Efl.Text_Cursor.cursor_cluster_prev; Efl.Text_Cursor.cursor_paragraph_char_first; Efl.Text_Cursor.cursor_paragraph_char_last; Efl.Text_Cursor.cursor_word_start; @@ -339,6 +341,7 @@ class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text_Cursor.cursor_paragraph_prev; Efl.Text_Cursor.cursor_line_jump_by; Efl.Text_Cursor.cursor_coord_set; + Efl.Text_Cursor.cursor_cluster_coord_set; Efl.Text_Cursor.cursor_text_insert; Efl.Text_Cursor.cursor_char_delete; Efl.Text_Annotate.annotation { set; get; } diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index f523f131e9..16f717ce41 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -77,6 +77,7 @@ #include "linebreak.h" #include "wordbreak.h" +#include "graphemebreak.h" #include "evas_filter.h" #include "efl_canvas_filter_internal.eo.h" @@ -9271,20 +9272,122 @@ _efl_canvas_text_efl_text_cursor_cursor_word_end(Eo *eo_obj, Efl_Canvas_Text_Dat efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); } -EAPI Eina_Bool -evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur) +static char * +_evas_textblock_grapheme_breaks_new(Evas_Object_Textblock_Item *it, size_t len) { - int ind; + char *grapheme_breaks = NULL; + const char *lang = (it->format->font.fdesc) ? it->format->font.fdesc->lang : ""; + + grapheme_breaks = malloc(len); + if (!grapheme_breaks) return NULL; + + set_graphemebreaks_utf32((const utf32_t *) + eina_ustrbuf_string_get( + it->text_node->unicode), + len, lang, grapheme_breaks); + + return grapheme_breaks; +} + +static size_t +_evas_textblock_cursor_cluster_pos_get(Evas_Textblock_Cursor *cur, Eina_Bool inc) +{ + Evas_Object_Textblock_Paragraph *par; + Efl_Canvas_Text_Data *o; + size_t cur_pos = cur->pos; + size_t ret = cur->pos; + + if (!inc) cur_pos--; + + if (!cur->node->par) + { + o = efl_data_scope_get(cur->obj, MY_CLASS); + if (o) _relayout_if_needed(cur->obj, o); + } + + par = cur->node->par; + + if (par) + { + Eina_List *l; + Evas_Object_Textblock_Item *it, *last_it = NULL; + EINA_LIST_FOREACH(par->logical_items, l, it) + { + if (it->text_pos > cur_pos) + { + if (!last_it) last_it = it; + break; + } + last_it = it; + } + + if (last_it) + { + it = last_it; + if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) + { + size_t len = eina_ustrbuf_length_get(it->text_node->unicode); + char *grapheme_breaks = _evas_textblock_grapheme_breaks_new(it, len); + + if (grapheme_breaks) + { + size_t grapheme_breaks_index = cur_pos; + + if (inc) + { + while ((grapheme_breaks_index < len) && + (grapheme_breaks[grapheme_breaks_index] != GRAPHEMEBREAK_BREAK)) + { + grapheme_breaks_index++; + } + + ret = grapheme_breaks_index + 1; + } + else + { + while ((grapheme_breaks_index > 0) && + (grapheme_breaks[grapheme_breaks_index - 1] != GRAPHEMEBREAK_BREAK)) + { + grapheme_breaks_index--; + } + + ret = grapheme_breaks_index; + } + + free(grapheme_breaks); + } + } + } + } + + return ret; +} + +static Eina_Bool +_evas_textblock_cursor_next(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster) +{ + Evas_Object_Protected_Data *obj; const Eina_Unicode *text; + int ind; if (!cur) return EINA_FALSE; - Evas_Object_Protected_Data *obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS); - evas_object_async_block(obj); TB_NULL_CHECK(cur->node, EINA_FALSE); + obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS); + evas_object_async_block(obj); + ind = cur->pos; text = eina_ustrbuf_string_get(cur->node->unicode); - if (text[ind]) ind++; + + if (text[ind]) + { + if (per_cluster) + ind = _evas_textblock_cursor_cluster_pos_get(cur, EINA_TRUE); + + if (ind <= (int)cur->pos) + ind = cur->pos + 1; + } + /* Only allow pointing a null if it's the last paragraph. * because we don't have a PS there. */ if (text[ind]) @@ -9311,23 +9414,30 @@ evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur) } } -EOLIAN static void -_efl_canvas_text_efl_text_cursor_cursor_char_next(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur) -{ - ASYNC_BLOCK; - evas_textblock_cursor_char_next(cur); - efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); -} - static Eina_Bool -_evas_textblock_cursor_char_prev(Efl_Text_Cursor_Cursor *cur) +_evas_textblock_cursor_prev(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster) { + Evas_Object_Protected_Data *obj; if (!cur) return EINA_FALSE; TB_NULL_CHECK(cur->node, EINA_FALSE); + obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS); + evas_object_async_block(obj); + if (cur->pos != 0) { + if (per_cluster) + { + size_t ret = _evas_textblock_cursor_cluster_pos_get(cur, EINA_FALSE); + + if (ret != cur->pos) + { + cur->pos = ret; + return EINA_TRUE; + } + } + cur->pos--; return EINA_TRUE; } @@ -9335,18 +9445,59 @@ _evas_textblock_cursor_char_prev(Efl_Text_Cursor_Cursor *cur) } EAPI Eina_Bool +evas_textblock_cursor_char_next(Efl_Text_Cursor_Cursor *cur) +{ + return _evas_textblock_cursor_next(cur, EINA_FALSE); +} + +EOLIAN static void +_efl_canvas_text_efl_text_cursor_cursor_char_next(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur) +{ + ASYNC_BLOCK; + if (_evas_textblock_cursor_next(cur, EINA_FALSE)) + efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); +} + +EAPI Eina_Bool evas_textblock_cursor_char_prev(Efl_Text_Cursor_Cursor *cur) { - if (!cur) return EINA_FALSE; - return _evas_textblock_cursor_char_prev(cur); + return _evas_textblock_cursor_prev(cur, EINA_FALSE); } EOLIAN static void _efl_canvas_text_efl_text_cursor_cursor_char_prev(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur) { ASYNC_BLOCK; - _evas_textblock_cursor_char_prev(cur); - efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); + if (_evas_textblock_cursor_prev(cur, EINA_FALSE)) + efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); +} + +EAPI Eina_Bool +evas_textblock_cursor_cluster_next(Efl_Text_Cursor_Cursor *cur) +{ + return _evas_textblock_cursor_next(cur, EINA_TRUE); +} + +EOLIAN static void +_efl_canvas_text_efl_text_cursor_cursor_cluster_next(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur) +{ + ASYNC_BLOCK; + if (_evas_textblock_cursor_next(cur, EINA_TRUE)) + efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); +} + +EAPI Eina_Bool +evas_textblock_cursor_cluster_prev(Efl_Text_Cursor_Cursor *cur) +{ + return _evas_textblock_cursor_prev(cur, EINA_TRUE); +} + +EOLIAN static void +_efl_canvas_text_efl_text_cursor_cursor_cluster_prev(Eo *eo_obj, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur) +{ + ASYNC_BLOCK; + if (_evas_textblock_cursor_prev(cur, EINA_TRUE)) + efl_event_callback_legacy_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CURSOR_CHANGED, NULL); } EAPI void @@ -12031,15 +12182,16 @@ _efl_canvas_text_visible_range_get(Eo *eo_obj EINA_UNUSED, return EINA_TRUE; } - -EAPI Eina_Bool -evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) +static Eina_Bool +_evas_textblock_cursor_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y, Eina_Bool per_cluster) { Evas_Object_Textblock_Paragraph *found_par; Evas_Object_Textblock_Line *ln; Evas_Object_Textblock_Item *it = NULL; Eina_Bool ret = EINA_FALSE; + if (!cur) return ret; + Evas_Object_Protected_Data *obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS); evas_object_async_block(obj); Efl_Canvas_Text_Data *o = efl_data_scope_get(cur->obj, MY_CLASS); @@ -12112,6 +12264,63 @@ evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, &cx, &cy, &cw, &ch); if (pos < 0) goto end; + + if ((pos > 0) && per_cluster) + { + size_t len = eina_ustrbuf_length_get(it->text_node->unicode); + char *grapheme_breaks = _evas_textblock_grapheme_breaks_new(it, len); + + /* If current position is not breakable, + * try to move cursor to a nearest breakable position. */ + if (grapheme_breaks && (grapheme_breaks[pos + it->text_pos - 1] != GRAPHEMEBREAK_BREAK)) + { + size_t left_index = pos + it->text_pos - 1; + size_t right_index = pos + it->text_pos - 1; + int lx, rx; + + /* To the left */ + while ((left_index > 0) && + (grapheme_breaks[left_index] != GRAPHEMEBREAK_BREAK)) + { + left_index--; + } + + ENFN->font_pen_coords_get(ENC, + ti->parent.format->font.font, + &ti->text_props, + left_index - it->text_pos + 1, + &lx, NULL, NULL, NULL); + + /* To the right */ + while ((right_index < len) && + (grapheme_breaks[right_index] != GRAPHEMEBREAK_BREAK)) + { + right_index++; + } + + ENFN->font_pen_coords_get(ENC, + ti->parent.format->font.font, + &ti->text_props, + right_index - it->text_pos + 1, + &rx, NULL, NULL, NULL); + + /* Decide a nearest position by checking its geometry. */ + if (((ti->text_props.bidi_dir != EVAS_BIDI_DIRECTION_RTL) && + ((ln->x + it->x + rx - x) >= (x - (lx + ln->x + it->x)))) || + ((ti->text_props.bidi_dir == EVAS_BIDI_DIRECTION_RTL) && + ((ln->x + it->x + lx - x) >= (x - (rx + ln->x + it->x))))) + { + pos = left_index - it->text_pos + 1; + } + else + { + pos = right_index - it->text_pos + 1; + } + } + + free(grapheme_breaks); + } + cur->pos = pos + it->text_pos; cur->node = it->text_node; ret = EINA_TRUE; @@ -12167,6 +12376,18 @@ end: return ret; } +EAPI Eina_Bool +evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) +{ + return _evas_textblock_cursor_coord_set(cur, x, y, EINA_FALSE); +} + +EAPI Eina_Bool +evas_textblock_cursor_cluster_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y) +{ + return _evas_textblock_cursor_coord_set(cur, x, y, EINA_TRUE); +} + EOLIAN static void _efl_canvas_text_efl_text_cursor_cursor_coord_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur EINA_UNUSED, Evas_Coord x, Evas_Coord y) @@ -12175,6 +12396,14 @@ _efl_canvas_text_efl_text_cursor_cursor_coord_set(Eo *eo_obj EINA_UNUSED, Efl_Ca evas_textblock_cursor_char_coord_set(cur, x, y); } +EOLIAN static void +_efl_canvas_text_efl_text_cursor_cursor_cluster_coord_set(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Text_Data *o EINA_UNUSED, Efl_Text_Cursor_Cursor *cur EINA_UNUSED, + Evas_Coord x, Evas_Coord y) +{ + ASYNC_BLOCK; + evas_textblock_cursor_cluster_coord_set(cur, x, y); +} + EAPI int evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) { @@ -13279,6 +13508,7 @@ evas_object_textblock_init(Evas_Object *eo_obj) linebreak_init = EINA_TRUE; init_linebreak(); init_wordbreak(); + init_graphemebreak(); } o = obj->private_data; @@ -15194,7 +15424,7 @@ _efl_canvas_text_efl_text_annotate_range_annotations_get(const Eo *eo_obj, Efl_C if (!it->start_node || !it->end_node) continue; _textblock_cursor_pos_at_fnode_set(eo_obj, &start2, it->start_node); _textblock_cursor_pos_at_fnode_set(eo_obj, &end2, it->end_node); - _evas_textblock_cursor_char_prev(&end2); + evas_textblock_cursor_char_prev(&end2); if (!((evas_textblock_cursor_compare(&start2, end) > 0) || (evas_textblock_cursor_compare(&end2, start) < 0))) { diff --git a/src/lib/evas/canvas/evas_textblock_legacy.h b/src/lib/evas/canvas/evas_textblock_legacy.h index 0d84075fa0..2c8ee05f57 100644 --- a/src/lib/evas/canvas/evas_textblock_legacy.h +++ b/src/lib/evas/canvas/evas_textblock_legacy.h @@ -605,6 +605,22 @@ EAPI Eina_Bool evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *obj); EAPI Eina_Bool evas_textblock_cursor_char_next(Evas_Textblock_Cursor *obj); /** + * @brief Advances the cursor one grapheme cluster backwards. + * + * @return @c true on success, @c false otherwise. + */ +EAPI Eina_Bool evas_textblock_cursor_cluster_prev(Evas_Textblock_Cursor *obj); + +/** + * @brief Advances the cursor one grapheme cluster forward. + * + * @return @c true on success, @c false otherwise. + * + * @ingroup Evas_Textblock_Cursor + */ +EAPI Eina_Bool evas_textblock_cursor_cluster_next(Evas_Textblock_Cursor *obj); + +/** * @brief Advances to the start of the next text node * * @return @c true if managed to advance, @c false otherwise @@ -860,6 +876,16 @@ EAPI Evas_Textblock_Cursor *evas_object_textblock_cursor_new(const Evas_Object * EAPI Eina_Bool evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *obj, Evas_Coord x, Evas_Coord y); /** + * @brief Sets the position of the cursor according to the X and Y coordinates and + * grapheme clusters of text. + * + * @param[in] y y coord to set by. + * + * @return @c true on success, @c false otherwise. + */ +EAPI Eina_Bool evas_textblock_cursor_cluster_coord_set(Evas_Textblock_Cursor *obj, Evas_Coord x, Evas_Coord y); + +/** * Free the cursor and unassociate it from the object. * @note do not use it to free unassociated cursors. * diff --git a/src/static_libs/libunibreak/ChangeLog b/src/static_libs/libunibreak/ChangeLog index cad33cfd26..8df529f0c9 100644 --- a/src/static_libs/libunibreak/ChangeLog +++ b/src/static_libs/libunibreak/ChangeLog @@ -1,3 +1,95 @@ +2016-12-15 Wu Yongwei <wuyongwei@gmail.com> + + * src/Makefile.am (include_HEADERS): Move graphemebreakdef.h to + EXTRA_DIST. + (EXTRA_DIST): Add graphemebreakdef.h and test_skips.h. + +2016-12-14 Wu Yongwei <wuyongwei@gmail.com> + + * src/linebreak.c: Adjust documentation comment. + * src/wordbreak.c: Ditto. + * src/graphemebreak.c: Ditto. + +2016-12-14 Wu Yongwei <wuyongwei@gmail.com> + + * Doxyfile (FULL_PATH_NAMES): Set to `NO'. + (DOT_IMAGE_FORMAT): Set to `svg'. + (SEARCHENGINE): Set to `YES'. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + Update for the libunibreak 4.0 release. + * NEWS: Add information about libunibreak 4.0. + * Doxyfile (PROJECT_NUMBER): Change to `4.0'. + * configure.ac (AC_INIT): Change the library version to `4.0'. + * src/Makefile.am (libunibreak_la_LDFLAGS): Set the version-info to + `4:0:1'. + * src/unibreakbase.h (UNIBREAK_VERSION): Set to 0x0400. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * src/Makefile.am (include_HEADERS): Add a missing file + graphemebreakdef.h. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * bootstrap: Add a missing `--copy' argument to glibtoolize. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * README.md: Update for grapheme break and links. + * LICENCE: Add Andreas Röver and update copyright information. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * Doxyfile (EXCLUDE): Add `src/tests.c'. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * src/wordbreak.c: Update Unicode version and link information. + * src/wordbreak.h: Ditto. + * src/wordbreakdef.h: Ditto. + * src/graphemebreak.c: Ditto. + * src/graphemebreak.h: Ditto. + * src/graphemebreakdef.h: Ditto. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * src/linebreak.c: Remove `@version' and update copyright header. + * src/linebreak.h: Ditto. + * src/linebreakdef.c: Ditto. + * src/linebreakdef.h: Ditto. + * src/wordbreak.c: Ditto. + * src/wordbreak.h: Ditto. + * src/wordbreakdef.h: Ditto. + * src/graphemebreak.c: Ditto. + * src/graphemebreak.h: Ditto. + * src/graphemebreakdef.h: Ditto. + * src/unibreakbase.c: Ditto. + * src/unibreakbase.h: Ditto. + * src/unibreakdef.c: Ditto. + * src/unibreakdef.h: Ditto. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * src/Makefile.msvc: Add graphemebreak.c. + * src/graphemebreak.c: Add a workaround of stdbool.h for MSVC + versions earlier than 2013. + * src/graphemebreak.h: Make include order consistent. + * src/linebreak.c (ends_with): Make the code compile under C89. + +2016-12-10 Wu Yongwei <wuyongwei@gmail.com> + + * src/Makefile.gcc (CFILES): Add graphemebreak.c. + (graphemebreakdata): New phony target. + (GraphemeBreakProperty.txt): New target. + (distclean): Add WordBreakProperty.txt and GraphemeBreakProperty.txt + as well. + +2016-12-05 Tom Hacohen <tom@stosb.com> + + * src/test_skips.h: New file. + 2016-12-04 Wu Yongwei <wuyongwei@gmail.com> Simpify implementation about RI pairing. diff --git a/src/static_libs/libunibreak/LICENCE b/src/static_libs/libunibreak/LICENCE index 3eda8d5061..3fba16ad53 100644 --- a/src/static_libs/libunibreak/LICENCE +++ b/src/static_libs/libunibreak/LICENCE @@ -1,6 +1,7 @@ -Copyright (C) 2008-2015 Wu Yongwei <wuyongwei at gmail dot com> -Copyright (C) 2012-2015 Tom Hacohen <tom at stosb dot com> +Copyright (C) 2008-2016 Wu Yongwei <wuyongwei at gmail dot com> +Copyright (C) 2012-2016 Tom Hacohen <tom at stosb dot com> Copyright (C) 2013 Petr Filipsky <philodej at gmail dot com> +Copyright (C) 2016 Andreas Röver <roever at users dot sf dot net> This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages diff --git a/src/static_libs/libunibreak/NEWS b/src/static_libs/libunibreak/NEWS index 7de7feba18..d217628da8 100644 --- a/src/static_libs/libunibreak/NEWS +++ b/src/static_libs/libunibreak/NEWS @@ -1,3 +1,10 @@ +New in libunibreak 4.0 + +- Update the code and data to conform to Unicode 9.0.0 +- Add grapheme breaking support +- Tested and enhanced according to the Unicode test suite +- Make bug fixes + New in libunibreak 3.0 - Update the code and data to conform to Unicode 7.0.0 diff --git a/src/static_libs/libunibreak/README.md b/src/static_libs/libunibreak/README.md index 52cd7388b5..f37fd902aa 100644 --- a/src/static_libs/libunibreak/README.md +++ b/src/static_libs/libunibreak/README.md @@ -9,8 +9,8 @@ breaking and word breaking algorithms as described in [Unicode Standard Annex 14] [1] and [Unicode Standard Annex 29] [2]. Check the project's [home page] [3] for up-to-date information. - [1]: http://www.unicode.org/reports/tr14/tr14-30.html - [2]: http://www.unicode.org/reports/tr29/tr29-21.html + [1]: http://www.unicode.org/reports/tr14/tr14-37.html + [2]: http://www.unicode.org/reports/tr29/tr29-29.html [3]: https://github.com/adah1972/libunibreak @@ -46,6 +46,8 @@ There are three ways to build the library: *LineBreak.txt*. - type `make wordbreakdata` to regenerate *wordbreakdata.c* from *WordBreakProperty.txt*. + - type `make graphemebreakdata` to regenerate *graphemebreakdata.c* + from *GraphemeBreakProperty.txt*. 2. On systems where GCC and Binutils are supported, one can type @@ -61,6 +63,8 @@ There are three ways to build the library: *LineBreak.txt*. - type `make wordbreakdata` to regenerate *wordbreakdata.c* from *WordBreakProperty.txt*. + - type `make graphemebreakdata` to regenerate *graphemebreakdata.c* + from *GraphemeBreakProperty.txt*. 3. On Windows, apart from using method 1 (Cygwin/MSYS) and method 2 (MinGW), MSVC can also be used. Type @@ -77,9 +81,9 @@ There are three ways to build the library: Documentation ------------- -Check the generated document *doc/html/linebreak\_8h.html* and -*doc/html/wordbreak\_8h.html* in the downloaded file for the public -interfaces exposed to applications. +Check the generated document *doc/html/linebreak\_8h.html*, +*doc/html/wordbreak\_8h.html*, and *doc/html/graphemebreak\_8h.html* in +the downloaded file for the public interfaces exposed to applications. <!-- diff --git a/src/static_libs/libunibreak/graphemebreak.c b/src/static_libs/libunibreak/graphemebreak.c new file mode 100644 index 0000000000..77c3d5f55c --- /dev/null +++ b/src/static_libs/libunibreak/graphemebreak.c @@ -0,0 +1,283 @@ +/* + * Grapheme breaking in a Unicode sequence. Designed to be used in a + * generic text renderer. + * + * Copyright (C) 2016 Andreas Röver <roever at users dot sf dot net> + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgement in the product + * documentation would be appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source + * distribution. + * + * The main reference is Unicode Standard Annex 29 (UAX #29): + * <URL:http://unicode.org/reports/tr29> + * + * When this library was designed, this annex was at Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> + * + * The Unicode Terms of Use are available at + * <URL:http://www.unicode.org/copyright.html> + */ + +/** + * @file graphemebreak.c + * + * Implementation of the grapheme breaking algorithm as described in Unicode + * Standard Annex 29. + * + * @author Andreas Roever + */ + +#if defined(_MSC_VER) && _MSC_VER < 1800 +typedef int bool; +#define false 0 +#define true 1 +#else +#include <stdbool.h> +#endif + +#include <string.h> +#include "graphemebreak.h" +#include "graphemebreakdata.c" +#include "unibreakdef.h" + +#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) + +/** + * Initializes the wordbreak internals. It currently does nothing, but + * it may in the future. + */ +void init_graphemebreak(void) +{ +} + +/** + * Gets the grapheme breaking class of a character. + * + * @param ch character to check + * @return the grapheme breaking class if found; \c GBP_Other otherwise + */ +static enum GraphemeBreakClass get_char_gb_class(utf32_t ch) +{ + int min = 0; + int max = ARRAY_LEN(gb_prop_default) - 1; + int mid; + + do + { + mid = (min + max) / 2; + + if (ch < gb_prop_default[mid].start) + max = mid - 1; + else if (ch > gb_prop_default[mid].end) + min = mid + 1; + else + return gb_prop_default[mid].prop; + } while (min <= max); + + return GBP_Other; +} + +/** + * Sets the grapheme breaking information for a generic input string. + * + * @param[in] s input string + * @param[in] len length of the input + * @param[out] brks pointer to the output breaking data, containing + * #GRAPHEMEBREAK_BREAK or #GRAPHEMEBREAK_NOBREAK + * @param[in] get_next_char function to get the next UTF-32 character + */ +static void set_graphemebreaks(const void *s, size_t len, char *brks, + get_next_char_t get_next_char) +{ + size_t posNext = 0; + bool rule10Left = false; // is the left side of rule 10 fulfilled? + bool evenRegionalIndicators = true; // is the number of preceeding + // GBP_RegionalIndicator characters + // even + + utf32_t ch = get_next_char(s, len, &posNext); + enum GraphemeBreakClass current_class = get_char_gb_class(ch); + + // initialize whole output to inside char + memset(brks, GRAPHEMEBREAK_INSIDEACHAR, len); + + while (true) + { + enum GraphemeBreakClass prev_class = current_class; + + // safe position if current character so that we can store the + // result there later on + size_t brksPos = posNext - 1; + + // get nect character + ch = get_next_char(s, len, &posNext); + + if (ch == EOS) + { + // done, place one final break after the last character as per + // algorithm rule GB1 + brks[brksPos] = GRAPHEMEBREAK_BREAK; + break; + } + + // get class of current character + current_class = get_char_gb_class(ch); + + // update some helper variables + if ((prev_class == GBP_E_Base) || (prev_class == GBP_E_Base_GAZ)) + { + rule10Left = true; + } + else if (prev_class != GBP_Extend) + { + rule10Left = false; + } + + if (prev_class == GBP_Regional_Indicator) + { + evenRegionalIndicators = !evenRegionalIndicators; + } + else + { + evenRegionalIndicators = true; + } + + // check all rules + if (prev_class == GBP_CR && current_class == GBP_LF) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB3 + } + else if ((prev_class == GBP_CR) || (prev_class == GBP_LF) || + (prev_class == GBP_Control) || (current_class == GBP_CR) || + (current_class == GBP_LF) || + (current_class == GBP_Control)) + { + brks[brksPos] = GRAPHEMEBREAK_BREAK; // Rule: GB4 + GB5 + } + else if ((prev_class == GBP_L) && + ((current_class == GBP_L) || (current_class == GBP_V) || + (current_class == GBP_LV) || (current_class == GBP_LVT))) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB6 + } + else if (((prev_class == GBP_LV) || (prev_class == GBP_V)) && + ((current_class == GBP_V) || (current_class == GBP_T))) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB7 + } + else if (((prev_class == GBP_LVT) || (prev_class == GBP_T)) && + (current_class == GBP_T)) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB8 + } + else if ((current_class == GBP_Extend) || + (current_class == GBP_ZWJ)) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB9 + } + else if (current_class == GBP_SpacingMark) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB9a + } + else if (prev_class == GBP_Prepend) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB9b + } + else if (rule10Left && (current_class == GBP_E_Modifier)) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB10 + } + else if ((prev_class == GBP_ZWJ) && + ((current_class == GBP_Glue_After_Zwj) || + (current_class == GBP_E_Base_GAZ))) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB11 + } + else if (!evenRegionalIndicators && + (current_class == GBP_Regional_Indicator)) + { + brks[brksPos] = GRAPHEMEBREAK_NOBREAK; // Rule: GB12 + GB13 + } + else + { + brks[brksPos] = GRAPHEMEBREAK_BREAK; // Rule: GB999 + } + } +} + +/** + * Sets the grapheme breaking information for a UTF-8 input string. + * + * @param[in] s input UTF-8 string + * @param[in] len length of the input + * @param[in] lang language of the input (reserved for future use) + * @param[out] brks pointer to the output breaking data, containing + * #GRAPHEMEBREAK_BREAK or #GRAPHEMEBREAK_NOBREAK. + * First element in output array is for the break behind + * the first character the pointer must point to an + * array with at least as many elements as there + * are characters in the string + */ +void set_graphemebreaks_utf8(const utf8_t *s, size_t len, const char *lang, + char *brks) +{ + (void)lang; + set_graphemebreaks(s, len, brks, + (get_next_char_t)ub_get_next_char_utf8); +} + +/** + * Sets the grapheme breaking information for a UTF-16 input string. + * + * @param[in] s input UTF-16 string + * @param[in] len length of the input + * @param[in] lang language of the input (reserved for future use) + * @param[out] brks pointer to the output breaking data, containing + * #GRAPHEMEBREAK_BREAK or #GRAPHEMEBREAK_NOBREAK. + * First element in output array is for the break behind + * the first character the pointer must point to an + * array with at least as many elements as there + * are characters in the string + */ +void set_graphemebreaks_utf16(const utf16_t *s, size_t len, + const char *lang, char *brks) +{ + (void)lang; + set_graphemebreaks(s, len, brks, + (get_next_char_t)ub_get_next_char_utf16); +} + +/** + * Sets the grapheme breaking information for a UTF-32 input string. + * + * @param[in] s input UTF-32 string + * @param[in] len length of the input + * @param[in] lang language of the input (reserved for future use) + * @param[out] brks pointer to the output breaking data, containing + * #GRAPHEMEBREAK_BREAK or #GRAPHEMEBREAK_NOBREAK. + * First element in output array is for the break behind + * the first character the pointer must point to an + * array with at least as many elements as there + * are characters in the string + */ +void set_graphemebreaks_utf32(const utf32_t *s, size_t len, + const char *lang, char *brks) +{ + (void)lang; + set_graphemebreaks(s, len, brks, + (get_next_char_t)ub_get_next_char_utf32); +} diff --git a/src/static_libs/libunibreak/graphemebreak.h b/src/static_libs/libunibreak/graphemebreak.h new file mode 100644 index 0000000000..c01768233a --- /dev/null +++ b/src/static_libs/libunibreak/graphemebreak.h @@ -0,0 +1,69 @@ +/* + * Grapheme breaking in a Unicode sequence. Designed to be used in a + * generic text renderer. + * + * Copyright (C) 2016 Andreas Röver <roever at users dot sf dot net> + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgement in the product + * documentation would be appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source + * distribution. + * + * The main reference is Unicode Standard Annex 29 (UAX #29): + * <URL:http://unicode.org/reports/tr29> + * + * When this library was designed, this annex was at Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> + * + * The Unicode Terms of Use are available at + * <URL:http://www.unicode.org/copyright.html> + */ + +/** + * @file graphemebreak.h + * + * Header file for the grapheme breaking algorithm. + * + * @author Andreas Röver + */ + +#ifndef GRAPHEMEBREAK_H +#define GRAPHEMEBREAK_H + +#include <stddef.h> +#include "unibreakbase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRAPHEMEBREAK_BREAK 0 /**< Between 2 graphemes */ +#define GRAPHEMEBREAK_NOBREAK 1 /**< Inside a grapheme */ +#define GRAPHEMEBREAK_INSIDEACHAR 2 /**< Inside a unicode character */ + +void init_graphemebreak(void); +void set_graphemebreaks_utf8(const utf8_t *s, size_t len, const char *lang, + char *brks); +void set_graphemebreaks_utf16(const utf16_t *s, size_t len, + const char *lang, char *brks); +void set_graphemebreaks_utf32(const utf32_t *s, size_t len, + const char *lang, char *brks); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/static_libs/libunibreak/graphemebreakdata.c b/src/static_libs/libunibreak/graphemebreakdata.c new file mode 100644 index 0000000000..cab9bebd80 --- /dev/null +++ b/src/static_libs/libunibreak/graphemebreakdata.c @@ -0,0 +1,1337 @@ +/* The content of this file is generated from: +# GraphemeBreakProperty-9.0.0.txt +# Date: 2016-06-03, 22:23:55 GMT +*/ + +#include "graphemebreakdef.h" + +static const struct GraphemeBreakProperties gb_prop_default[] = { + {0x0000, 0x0009, GBP_Control}, + {0x000A, 0x000A, GBP_LF}, + {0x000B, 0x000C, GBP_Control}, + {0x000D, 0x000D, GBP_CR}, + {0x000E, 0x001F, GBP_Control}, + {0x007F, 0x009F, GBP_Control}, + {0x00AD, 0x00AD, GBP_Control}, + {0x0300, 0x036F, GBP_Extend}, + {0x0483, 0x0487, GBP_Extend}, + {0x0488, 0x0489, GBP_Extend}, + {0x0591, 0x05BD, GBP_Extend}, + {0x05BF, 0x05BF, GBP_Extend}, + {0x05C1, 0x05C2, GBP_Extend}, + {0x05C4, 0x05C5, GBP_Extend}, + {0x05C7, 0x05C7, GBP_Extend}, + {0x0600, 0x0605, GBP_Prepend}, + {0x0610, 0x061A, GBP_Extend}, + {0x061C, 0x061C, GBP_Control}, + {0x064B, 0x065F, GBP_Extend}, + {0x0670, 0x0670, GBP_Extend}, + {0x06D6, 0x06DC, GBP_Extend}, + {0x06DD, 0x06DD, GBP_Prepend}, + {0x06DF, 0x06E4, GBP_Extend}, + {0x06E7, 0x06E8, GBP_Extend}, + {0x06EA, 0x06ED, GBP_Extend}, + {0x070F, 0x070F, GBP_Prepend}, + {0x0711, 0x0711, GBP_Extend}, + {0x0730, 0x074A, GBP_Extend}, + {0x07A6, 0x07B0, GBP_Extend}, + {0x07EB, 0x07F3, GBP_Extend}, + {0x0816, 0x0819, GBP_Extend}, + {0x081B, 0x0823, GBP_Extend}, + {0x0825, 0x0827, GBP_Extend}, + {0x0829, 0x082D, GBP_Extend}, + {0x0859, 0x085B, GBP_Extend}, + {0x08D4, 0x08E1, GBP_Extend}, + {0x08E2, 0x08E2, GBP_Prepend}, + {0x08E3, 0x0902, GBP_Extend}, + {0x0903, 0x0903, GBP_SpacingMark}, + {0x093A, 0x093A, GBP_Extend}, + {0x093B, 0x093B, GBP_SpacingMark}, + {0x093C, 0x093C, GBP_Extend}, + {0x093E, 0x0940, GBP_SpacingMark}, + {0x0941, 0x0948, GBP_Extend}, + {0x0949, 0x094C, GBP_SpacingMark}, + {0x094D, 0x094D, GBP_Extend}, + {0x094E, 0x094F, GBP_SpacingMark}, + {0x0951, 0x0957, GBP_Extend}, + {0x0962, 0x0963, GBP_Extend}, + {0x0981, 0x0981, GBP_Extend}, + {0x0982, 0x0983, GBP_SpacingMark}, + {0x09BC, 0x09BC, GBP_Extend}, + {0x09BE, 0x09BE, GBP_Extend}, + {0x09BF, 0x09C0, GBP_SpacingMark}, + {0x09C1, 0x09C4, GBP_Extend}, + {0x09C7, 0x09C8, GBP_SpacingMark}, + {0x09CB, 0x09CC, GBP_SpacingMark}, + {0x09CD, 0x09CD, GBP_Extend}, + {0x09D7, 0x09D7, GBP_Extend}, + {0x09E2, 0x09E3, GBP_Extend}, + {0x0A01, 0x0A02, GBP_Extend}, + {0x0A03, 0x0A03, GBP_SpacingMark}, + {0x0A3C, 0x0A3C, GBP_Extend}, + {0x0A3E, 0x0A40, GBP_SpacingMark}, + {0x0A41, 0x0A42, GBP_Extend}, + {0x0A47, 0x0A48, GBP_Extend}, + {0x0A4B, 0x0A4D, GBP_Extend}, + {0x0A51, 0x0A51, GBP_Extend}, + {0x0A70, 0x0A71, GBP_Extend}, + {0x0A75, 0x0A75, GBP_Extend}, + {0x0A81, 0x0A82, GBP_Extend}, + {0x0A83, 0x0A83, GBP_SpacingMark}, + {0x0ABC, 0x0ABC, GBP_Extend}, + {0x0ABE, 0x0AC0, GBP_SpacingMark}, + {0x0AC1, 0x0AC5, GBP_Extend}, + {0x0AC7, 0x0AC8, GBP_Extend}, + {0x0AC9, 0x0AC9, GBP_SpacingMark}, + {0x0ACB, 0x0ACC, GBP_SpacingMark}, + {0x0ACD, 0x0ACD, GBP_Extend}, + {0x0AE2, 0x0AE3, GBP_Extend}, + {0x0B01, 0x0B01, GBP_Extend}, + {0x0B02, 0x0B03, GBP_SpacingMark}, + {0x0B3C, 0x0B3C, GBP_Extend}, + {0x0B3E, 0x0B3E, GBP_Extend}, + {0x0B3F, 0x0B3F, GBP_Extend}, + {0x0B40, 0x0B40, GBP_SpacingMark}, + {0x0B41, 0x0B44, GBP_Extend}, + {0x0B47, 0x0B48, GBP_SpacingMark}, + {0x0B4B, 0x0B4C, GBP_SpacingMark}, + {0x0B4D, 0x0B4D, GBP_Extend}, + {0x0B56, 0x0B56, GBP_Extend}, + {0x0B57, 0x0B57, GBP_Extend}, + {0x0B62, 0x0B63, GBP_Extend}, + {0x0B82, 0x0B82, GBP_Extend}, + {0x0BBE, 0x0BBE, GBP_Extend}, + {0x0BBF, 0x0BBF, GBP_SpacingMark}, + {0x0BC0, 0x0BC0, GBP_Extend}, + {0x0BC1, 0x0BC2, GBP_SpacingMark}, + {0x0BC6, 0x0BC8, GBP_SpacingMark}, + {0x0BCA, 0x0BCC, GBP_SpacingMark}, + {0x0BCD, 0x0BCD, GBP_Extend}, + {0x0BD7, 0x0BD7, GBP_Extend}, + {0x0C00, 0x0C00, GBP_Extend}, + {0x0C01, 0x0C03, GBP_SpacingMark}, + {0x0C3E, 0x0C40, GBP_Extend}, + {0x0C41, 0x0C44, GBP_SpacingMark}, + {0x0C46, 0x0C48, GBP_Extend}, + {0x0C4A, 0x0C4D, GBP_Extend}, + {0x0C55, 0x0C56, GBP_Extend}, + {0x0C62, 0x0C63, GBP_Extend}, + {0x0C81, 0x0C81, GBP_Extend}, + {0x0C82, 0x0C83, GBP_SpacingMark}, + {0x0CBC, 0x0CBC, GBP_Extend}, + {0x0CBE, 0x0CBE, GBP_SpacingMark}, + {0x0CBF, 0x0CBF, GBP_Extend}, + {0x0CC0, 0x0CC1, GBP_SpacingMark}, + {0x0CC2, 0x0CC2, GBP_Extend}, + {0x0CC3, 0x0CC4, GBP_SpacingMark}, + {0x0CC6, 0x0CC6, GBP_Extend}, + {0x0CC7, 0x0CC8, GBP_SpacingMark}, + {0x0CCA, 0x0CCB, GBP_SpacingMark}, + {0x0CCC, 0x0CCD, GBP_Extend}, + {0x0CD5, 0x0CD6, GBP_Extend}, + {0x0CE2, 0x0CE3, GBP_Extend}, + {0x0D01, 0x0D01, GBP_Extend}, + {0x0D02, 0x0D03, GBP_SpacingMark}, + {0x0D3E, 0x0D3E, GBP_Extend}, + {0x0D3F, 0x0D40, GBP_SpacingMark}, + {0x0D41, 0x0D44, GBP_Extend}, + {0x0D46, 0x0D48, GBP_SpacingMark}, + {0x0D4A, 0x0D4C, GBP_SpacingMark}, + {0x0D4D, 0x0D4D, GBP_Extend}, + {0x0D4E, 0x0D4E, GBP_Prepend}, + {0x0D57, 0x0D57, GBP_Extend}, + {0x0D62, 0x0D63, GBP_Extend}, + {0x0D82, 0x0D83, GBP_SpacingMark}, + {0x0DCA, 0x0DCA, GBP_Extend}, + {0x0DCF, 0x0DCF, GBP_Extend}, + {0x0DD0, 0x0DD1, GBP_SpacingMark}, + {0x0DD2, 0x0DD4, GBP_Extend}, + {0x0DD6, 0x0DD6, GBP_Extend}, + {0x0DD8, 0x0DDE, GBP_SpacingMark}, + {0x0DDF, 0x0DDF, GBP_Extend}, + {0x0DF2, 0x0DF3, GBP_SpacingMark}, + {0x0E31, 0x0E31, GBP_Extend}, + {0x0E33, 0x0E33, GBP_SpacingMark}, + {0x0E34, 0x0E3A, GBP_Extend}, + {0x0E47, 0x0E4E, GBP_Extend}, + {0x0EB1, 0x0EB1, GBP_Extend}, + {0x0EB3, 0x0EB3, GBP_SpacingMark}, + {0x0EB4, 0x0EB9, GBP_Extend}, + {0x0EBB, 0x0EBC, GBP_Extend}, + {0x0EC8, 0x0ECD, GBP_Extend}, + {0x0F18, 0x0F19, GBP_Extend}, + {0x0F35, 0x0F35, GBP_Extend}, + {0x0F37, 0x0F37, GBP_Extend}, + {0x0F39, 0x0F39, GBP_Extend}, + {0x0F3E, 0x0F3F, GBP_SpacingMark}, + {0x0F71, 0x0F7E, GBP_Extend}, + {0x0F7F, 0x0F7F, GBP_SpacingMark}, + {0x0F80, 0x0F84, GBP_Extend}, + {0x0F86, 0x0F87, GBP_Extend}, + {0x0F8D, 0x0F97, GBP_Extend}, + {0x0F99, 0x0FBC, GBP_Extend}, + {0x0FC6, 0x0FC6, GBP_Extend}, + {0x102D, 0x1030, GBP_Extend}, + {0x1031, 0x1031, GBP_SpacingMark}, + {0x1032, 0x1037, GBP_Extend}, + {0x1039, 0x103A, GBP_Extend}, + {0x103B, 0x103C, GBP_SpacingMark}, + {0x103D, 0x103E, GBP_Extend}, + {0x1056, 0x1057, GBP_SpacingMark}, + {0x1058, 0x1059, GBP_Extend}, + {0x105E, 0x1060, GBP_Extend}, + {0x1071, 0x1074, GBP_Extend}, + {0x1082, 0x1082, GBP_Extend}, + {0x1084, 0x1084, GBP_SpacingMark}, + {0x1085, 0x1086, GBP_Extend}, + {0x108D, 0x108D, GBP_Extend}, + {0x109D, 0x109D, GBP_Extend}, + {0x1100, 0x115F, GBP_L}, + {0x1160, 0x11A7, GBP_V}, + {0x11A8, 0x11FF, GBP_T}, + {0x135D, 0x135F, GBP_Extend}, + {0x1712, 0x1714, GBP_Extend}, + {0x1732, 0x1734, GBP_Extend}, + {0x1752, 0x1753, GBP_Extend}, + {0x1772, 0x1773, GBP_Extend}, + {0x17B4, 0x17B5, GBP_Extend}, + {0x17B6, 0x17B6, GBP_SpacingMark}, + {0x17B7, 0x17BD, GBP_Extend}, + {0x17BE, 0x17C5, GBP_SpacingMark}, + {0x17C6, 0x17C6, GBP_Extend}, + {0x17C7, 0x17C8, GBP_SpacingMark}, + {0x17C9, 0x17D3, GBP_Extend}, + {0x17DD, 0x17DD, GBP_Extend}, + {0x180B, 0x180D, GBP_Extend}, + {0x180E, 0x180E, GBP_Control}, + {0x1885, 0x1886, GBP_Extend}, + {0x18A9, 0x18A9, GBP_Extend}, + {0x1920, 0x1922, GBP_Extend}, + {0x1923, 0x1926, GBP_SpacingMark}, + {0x1927, 0x1928, GBP_Extend}, + {0x1929, 0x192B, GBP_SpacingMark}, + {0x1930, 0x1931, GBP_SpacingMark}, + {0x1932, 0x1932, GBP_Extend}, + {0x1933, 0x1938, GBP_SpacingMark}, + {0x1939, 0x193B, GBP_Extend}, + {0x1A17, 0x1A18, GBP_Extend}, + {0x1A19, 0x1A1A, GBP_SpacingMark}, + {0x1A1B, 0x1A1B, GBP_Extend}, + {0x1A55, 0x1A55, GBP_SpacingMark}, + {0x1A56, 0x1A56, GBP_Extend}, + {0x1A57, 0x1A57, GBP_SpacingMark}, + {0x1A58, 0x1A5E, GBP_Extend}, + {0x1A60, 0x1A60, GBP_Extend}, + {0x1A62, 0x1A62, GBP_Extend}, + {0x1A65, 0x1A6C, GBP_Extend}, + {0x1A6D, 0x1A72, GBP_SpacingMark}, + {0x1A73, 0x1A7C, GBP_Extend}, + {0x1A7F, 0x1A7F, GBP_Extend}, + {0x1AB0, 0x1ABD, GBP_Extend}, + {0x1ABE, 0x1ABE, GBP_Extend}, + {0x1B00, 0x1B03, GBP_Extend}, + {0x1B04, 0x1B04, GBP_SpacingMark}, + {0x1B34, 0x1B34, GBP_Extend}, + {0x1B35, 0x1B35, GBP_SpacingMark}, + {0x1B36, 0x1B3A, GBP_Extend}, + {0x1B3B, 0x1B3B, GBP_SpacingMark}, + {0x1B3C, 0x1B3C, GBP_Extend}, + {0x1B3D, 0x1B41, GBP_SpacingMark}, + {0x1B42, 0x1B42, GBP_Extend}, + {0x1B43, 0x1B44, GBP_SpacingMark}, + {0x1B6B, 0x1B73, GBP_Extend}, + {0x1B80, 0x1B81, GBP_Extend}, + {0x1B82, 0x1B82, GBP_SpacingMark}, + {0x1BA1, 0x1BA1, GBP_SpacingMark}, + {0x1BA2, 0x1BA5, GBP_Extend}, + {0x1BA6, 0x1BA7, GBP_SpacingMark}, + {0x1BA8, 0x1BA9, GBP_Extend}, + {0x1BAA, 0x1BAA, GBP_SpacingMark}, + {0x1BAB, 0x1BAD, GBP_Extend}, + {0x1BE6, 0x1BE6, GBP_Extend}, + {0x1BE7, 0x1BE7, GBP_SpacingMark}, + {0x1BE8, 0x1BE9, GBP_Extend}, + {0x1BEA, 0x1BEC, GBP_SpacingMark}, + {0x1BED, 0x1BED, GBP_Extend}, + {0x1BEE, 0x1BEE, GBP_SpacingMark}, + {0x1BEF, 0x1BF1, GBP_Extend}, + {0x1BF2, 0x1BF3, GBP_SpacingMark}, + {0x1C24, 0x1C2B, GBP_SpacingMark}, + {0x1C2C, 0x1C33, GBP_Extend}, + {0x1C34, 0x1C35, GBP_SpacingMark}, + {0x1C36, 0x1C37, GBP_Extend}, + {0x1CD0, 0x1CD2, GBP_Extend}, + {0x1CD4, 0x1CE0, GBP_Extend}, + {0x1CE1, 0x1CE1, GBP_SpacingMark}, + {0x1CE2, 0x1CE8, GBP_Extend}, + {0x1CED, 0x1CED, GBP_Extend}, + {0x1CF2, 0x1CF3, GBP_SpacingMark}, + {0x1CF4, 0x1CF4, GBP_Extend}, + {0x1CF8, 0x1CF9, GBP_Extend}, + {0x1DC0, 0x1DF5, GBP_Extend}, + {0x1DFB, 0x1DFF, GBP_Extend}, + {0x200B, 0x200B, GBP_Control}, + {0x200C, 0x200C, GBP_Extend}, + {0x200D, 0x200D, GBP_ZWJ}, + {0x200E, 0x200F, GBP_Control}, + {0x2028, 0x2028, GBP_Control}, + {0x2029, 0x2029, GBP_Control}, + {0x202A, 0x202E, GBP_Control}, + {0x2060, 0x2064, GBP_Control}, + {0x2065, 0x2065, GBP_Control}, + {0x2066, 0x206F, GBP_Control}, + {0x20D0, 0x20DC, GBP_Extend}, + {0x20DD, 0x20E0, GBP_Extend}, + {0x20E1, 0x20E1, GBP_Extend}, + {0x20E2, 0x20E4, GBP_Extend}, + {0x20E5, 0x20F0, GBP_Extend}, + {0x261D, 0x261D, GBP_E_Base}, + {0x26F9, 0x26F9, GBP_E_Base}, + {0x270A, 0x270D, GBP_E_Base}, + {0x2764, 0x2764, GBP_Glue_After_Zwj}, + {0x2CEF, 0x2CF1, GBP_Extend}, + {0x2D7F, 0x2D7F, GBP_Extend}, + {0x2DE0, 0x2DFF, GBP_Extend}, + {0x302A, 0x302D, GBP_Extend}, + {0x302E, 0x302F, GBP_Extend}, + {0x3099, 0x309A, GBP_Extend}, + {0xA66F, 0xA66F, GBP_Extend}, + {0xA670, 0xA672, GBP_Extend}, + {0xA674, 0xA67D, GBP_Extend}, + {0xA69E, 0xA69F, GBP_Extend}, + {0xA6F0, 0xA6F1, GBP_Extend}, + {0xA802, 0xA802, GBP_Extend}, + {0xA806, 0xA806, GBP_Extend}, + {0xA80B, 0xA80B, GBP_Extend}, + {0xA823, 0xA824, GBP_SpacingMark}, + {0xA825, 0xA826, GBP_Extend}, + {0xA827, 0xA827, GBP_SpacingMark}, + {0xA880, 0xA881, GBP_SpacingMark}, + {0xA8B4, 0xA8C3, GBP_SpacingMark}, + {0xA8C4, 0xA8C5, GBP_Extend}, + {0xA8E0, 0xA8F1, GBP_Extend}, + {0xA926, 0xA92D, GBP_Extend}, + {0xA947, 0xA951, GBP_Extend}, + {0xA952, 0xA953, GBP_SpacingMark}, + {0xA960, 0xA97C, GBP_L}, + {0xA980, 0xA982, GBP_Extend}, + {0xA983, 0xA983, GBP_SpacingMark}, + {0xA9B3, 0xA9B3, GBP_Extend}, + {0xA9B4, 0xA9B5, GBP_SpacingMark}, + {0xA9B6, 0xA9B9, GBP_Extend}, + {0xA9BA, 0xA9BB, GBP_SpacingMark}, + {0xA9BC, 0xA9BC, GBP_Extend}, + {0xA9BD, 0xA9C0, GBP_SpacingMark}, + {0xA9E5, 0xA9E5, GBP_Extend}, + {0xAA29, 0xAA2E, GBP_Extend}, + {0xAA2F, 0xAA30, GBP_SpacingMark}, + {0xAA31, 0xAA32, GBP_Extend}, + {0xAA33, 0xAA34, GBP_SpacingMark}, + {0xAA35, 0xAA36, GBP_Extend}, + {0xAA43, 0xAA43, GBP_Extend}, + {0xAA4C, 0xAA4C, GBP_Extend}, + {0xAA4D, 0xAA4D, GBP_SpacingMark}, + {0xAA7C, 0xAA7C, GBP_Extend}, + {0xAAB0, 0xAAB0, GBP_Extend}, + {0xAAB2, 0xAAB4, GBP_Extend}, + {0xAAB7, 0xAAB8, GBP_Extend}, + {0xAABE, 0xAABF, GBP_Extend}, + {0xAAC1, 0xAAC1, GBP_Extend}, + {0xAAEB, 0xAAEB, GBP_SpacingMark}, + {0xAAEC, 0xAAED, GBP_Extend}, + {0xAAEE, 0xAAEF, GBP_SpacingMark}, + {0xAAF5, 0xAAF5, GBP_SpacingMark}, + {0xAAF6, 0xAAF6, GBP_Extend}, + {0xABE3, 0xABE4, GBP_SpacingMark}, + {0xABE5, 0xABE5, GBP_Extend}, + {0xABE6, 0xABE7, GBP_SpacingMark}, + {0xABE8, 0xABE8, GBP_Extend}, + {0xABE9, 0xABEA, GBP_SpacingMark}, + {0xABEC, 0xABEC, GBP_SpacingMark}, + {0xABED, 0xABED, GBP_Extend}, + {0xAC00, 0xAC00, GBP_LV}, + {0xAC01, 0xAC1B, GBP_LVT}, + {0xAC1C, 0xAC1C, GBP_LV}, + {0xAC1D, 0xAC37, GBP_LVT}, + {0xAC38, 0xAC38, GBP_LV}, + {0xAC39, 0xAC53, GBP_LVT}, + {0xAC54, 0xAC54, GBP_LV}, + {0xAC55, 0xAC6F, GBP_LVT}, + {0xAC70, 0xAC70, GBP_LV}, + {0xAC71, 0xAC8B, GBP_LVT}, + {0xAC8C, 0xAC8C, GBP_LV}, + {0xAC8D, 0xACA7, GBP_LVT}, + {0xACA8, 0xACA8, GBP_LV}, + {0xACA9, 0xACC3, GBP_LVT}, + {0xACC4, 0xACC4, GBP_LV}, + {0xACC5, 0xACDF, GBP_LVT}, + {0xACE0, 0xACE0, GBP_LV}, + {0xACE1, 0xACFB, GBP_LVT}, + {0xACFC, 0xACFC, GBP_LV}, + {0xACFD, 0xAD17, GBP_LVT}, + {0xAD18, 0xAD18, GBP_LV}, + {0xAD19, 0xAD33, GBP_LVT}, + {0xAD34, 0xAD34, GBP_LV}, + {0xAD35, 0xAD4F, GBP_LVT}, + {0xAD50, 0xAD50, GBP_LV}, + {0xAD51, 0xAD6B, GBP_LVT}, + {0xAD6C, 0xAD6C, GBP_LV}, + {0xAD6D, 0xAD87, GBP_LVT}, + {0xAD88, 0xAD88, GBP_LV}, + {0xAD89, 0xADA3, GBP_LVT}, + {0xADA4, 0xADA4, GBP_LV}, + {0xADA5, 0xADBF, GBP_LVT}, + {0xADC0, 0xADC0, GBP_LV}, + {0xADC1, 0xADDB, GBP_LVT}, + {0xADDC, 0xADDC, GBP_LV}, + {0xADDD, 0xADF7, GBP_LVT}, + {0xADF8, 0xADF8, GBP_LV}, + {0xADF9, 0xAE13, GBP_LVT}, + {0xAE14, 0xAE14, GBP_LV}, + {0xAE15, 0xAE2F, GBP_LVT}, + {0xAE30, 0xAE30, GBP_LV}, + {0xAE31, 0xAE4B, GBP_LVT}, + {0xAE4C, 0xAE4C, GBP_LV}, + {0xAE4D, 0xAE67, GBP_LVT}, + {0xAE68, 0xAE68, GBP_LV}, + {0xAE69, 0xAE83, GBP_LVT}, + {0xAE84, 0xAE84, GBP_LV}, + {0xAE85, 0xAE9F, GBP_LVT}, + {0xAEA0, 0xAEA0, GBP_LV}, + {0xAEA1, 0xAEBB, GBP_LVT}, + {0xAEBC, 0xAEBC, GBP_LV}, + {0xAEBD, 0xAED7, GBP_LVT}, + {0xAED8, 0xAED8, GBP_LV}, + {0xAED9, 0xAEF3, GBP_LVT}, + {0xAEF4, 0xAEF4, GBP_LV}, + {0xAEF5, 0xAF0F, GBP_LVT}, + {0xAF10, 0xAF10, GBP_LV}, + {0xAF11, 0xAF2B, GBP_LVT}, + {0xAF2C, 0xAF2C, GBP_LV}, + {0xAF2D, 0xAF47, GBP_LVT}, + {0xAF48, 0xAF48, GBP_LV}, + {0xAF49, 0xAF63, GBP_LVT}, + {0xAF64, 0xAF64, GBP_LV}, + {0xAF65, 0xAF7F, GBP_LVT}, + {0xAF80, 0xAF80, GBP_LV}, + {0xAF81, 0xAF9B, GBP_LVT}, + {0xAF9C, 0xAF9C, GBP_LV}, + {0xAF9D, 0xAFB7, GBP_LVT}, + {0xAFB8, 0xAFB8, GBP_LV}, + {0xAFB9, 0xAFD3, GBP_LVT}, + {0xAFD4, 0xAFD4, GBP_LV}, + {0xAFD5, 0xAFEF, GBP_LVT}, + {0xAFF0, 0xAFF0, GBP_LV}, + {0xAFF1, 0xB00B, GBP_LVT}, + {0xB00C, 0xB00C, GBP_LV}, + {0xB00D, 0xB027, GBP_LVT}, + {0xB028, 0xB028, GBP_LV}, + {0xB029, 0xB043, GBP_LVT}, + {0xB044, 0xB044, GBP_LV}, + {0xB045, 0xB05F, GBP_LVT}, + {0xB060, 0xB060, GBP_LV}, + {0xB061, 0xB07B, GBP_LVT}, + {0xB07C, 0xB07C, GBP_LV}, + {0xB07D, 0xB097, GBP_LVT}, + {0xB098, 0xB098, GBP_LV}, + {0xB099, 0xB0B3, GBP_LVT}, + {0xB0B4, 0xB0B4, GBP_LV}, + {0xB0B5, 0xB0CF, GBP_LVT}, + {0xB0D0, 0xB0D0, GBP_LV}, + {0xB0D1, 0xB0EB, GBP_LVT}, + {0xB0EC, 0xB0EC, GBP_LV}, + {0xB0ED, 0xB107, GBP_LVT}, + {0xB108, 0xB108, GBP_LV}, + {0xB109, 0xB123, GBP_LVT}, + {0xB124, 0xB124, GBP_LV}, + {0xB125, 0xB13F, GBP_LVT}, + {0xB140, 0xB140, GBP_LV}, + {0xB141, 0xB15B, GBP_LVT}, + {0xB15C, 0xB15C, GBP_LV}, + {0xB15D, 0xB177, GBP_LVT}, + {0xB178, 0xB178, GBP_LV}, + {0xB179, 0xB193, GBP_LVT}, + {0xB194, 0xB194, GBP_LV}, + {0xB195, 0xB1AF, GBP_LVT}, + {0xB1B0, 0xB1B0, GBP_LV}, + {0xB1B1, 0xB1CB, GBP_LVT}, + {0xB1CC, 0xB1CC, GBP_LV}, + {0xB1CD, 0xB1E7, GBP_LVT}, + {0xB1E8, 0xB1E8, GBP_LV}, + {0xB1E9, 0xB203, GBP_LVT}, + {0xB204, 0xB204, GBP_LV}, + {0xB205, 0xB21F, GBP_LVT}, + {0xB220, 0xB220, GBP_LV}, + {0xB221, 0xB23B, GBP_LVT}, + {0xB23C, 0xB23C, GBP_LV}, + {0xB23D, 0xB257, GBP_LVT}, + {0xB258, 0xB258, GBP_LV}, + {0xB259, 0xB273, GBP_LVT}, + {0xB274, 0xB274, GBP_LV}, + {0xB275, 0xB28F, GBP_LVT}, + {0xB290, 0xB290, GBP_LV}, + {0xB291, 0xB2AB, GBP_LVT}, + {0xB2AC, 0xB2AC, GBP_LV}, + {0xB2AD, 0xB2C7, GBP_LVT}, + {0xB2C8, 0xB2C8, GBP_LV}, + {0xB2C9, 0xB2E3, GBP_LVT}, + {0xB2E4, 0xB2E4, GBP_LV}, + {0xB2E5, 0xB2FF, GBP_LVT}, + {0xB300, 0xB300, GBP_LV}, + {0xB301, 0xB31B, GBP_LVT}, + {0xB31C, 0xB31C, GBP_LV}, + {0xB31D, 0xB337, GBP_LVT}, + {0xB338, 0xB338, GBP_LV}, + {0xB339, 0xB353, GBP_LVT}, + {0xB354, 0xB354, GBP_LV}, + {0xB355, 0xB36F, GBP_LVT}, + {0xB370, 0xB370, GBP_LV}, + {0xB371, 0xB38B, GBP_LVT}, + {0xB38C, 0xB38C, GBP_LV}, + {0xB38D, 0xB3A7, GBP_LVT}, + {0xB3A8, 0xB3A8, GBP_LV}, + {0xB3A9, 0xB3C3, GBP_LVT}, + {0xB3C4, 0xB3C4, GBP_LV}, + {0xB3C5, 0xB3DF, GBP_LVT}, + {0xB3E0, 0xB3E0, GBP_LV}, + {0xB3E1, 0xB3FB, GBP_LVT}, + {0xB3FC, 0xB3FC, GBP_LV}, + {0xB3FD, 0xB417, GBP_LVT}, + {0xB418, 0xB418, GBP_LV}, + {0xB419, 0xB433, GBP_LVT}, + {0xB434, 0xB434, GBP_LV}, + {0xB435, 0xB44F, GBP_LVT}, + {0xB450, 0xB450, GBP_LV}, + {0xB451, 0xB46B, GBP_LVT}, + {0xB46C, 0xB46C, GBP_LV}, + {0xB46D, 0xB487, GBP_LVT}, + {0xB488, 0xB488, GBP_LV}, + {0xB489, 0xB4A3, GBP_LVT}, + {0xB4A4, 0xB4A4, GBP_LV}, + {0xB4A5, 0xB4BF, GBP_LVT}, + {0xB4C0, 0xB4C0, GBP_LV}, + {0xB4C1, 0xB4DB, GBP_LVT}, + {0xB4DC, 0xB4DC, GBP_LV}, + {0xB4DD, 0xB4F7, GBP_LVT}, + {0xB4F8, 0xB4F8, GBP_LV}, + {0xB4F9, 0xB513, GBP_LVT}, + {0xB514, 0xB514, GBP_LV}, + {0xB515, 0xB52F, GBP_LVT}, + {0xB530, 0xB530, GBP_LV}, + {0xB531, 0xB54B, GBP_LVT}, + {0xB54C, 0xB54C, GBP_LV}, + {0xB54D, 0xB567, GBP_LVT}, + {0xB568, 0xB568, GBP_LV}, + {0xB569, 0xB583, GBP_LVT}, + {0xB584, 0xB584, GBP_LV}, + {0xB585, 0xB59F, GBP_LVT}, + {0xB5A0, 0xB5A0, GBP_LV}, + {0xB5A1, 0xB5BB, GBP_LVT}, + {0xB5BC, 0xB5BC, GBP_LV}, + {0xB5BD, 0xB5D7, GBP_LVT}, + {0xB5D8, 0xB5D8, GBP_LV}, + {0xB5D9, 0xB5F3, GBP_LVT}, + {0xB5F4, 0xB5F4, GBP_LV}, + {0xB5F5, 0xB60F, GBP_LVT}, + {0xB610, 0xB610, GBP_LV}, + {0xB611, 0xB62B, GBP_LVT}, + {0xB62C, 0xB62C, GBP_LV}, + {0xB62D, 0xB647, GBP_LVT}, + {0xB648, 0xB648, GBP_LV}, + {0xB649, 0xB663, GBP_LVT}, + {0xB664, 0xB664, GBP_LV}, + {0xB665, 0xB67F, GBP_LVT}, + {0xB680, 0xB680, GBP_LV}, + {0xB681, 0xB69B, GBP_LVT}, + {0xB69C, 0xB69C, GBP_LV}, + {0xB69D, 0xB6B7, GBP_LVT}, + {0xB6B8, 0xB6B8, GBP_LV}, + {0xB6B9, 0xB6D3, GBP_LVT}, + {0xB6D4, 0xB6D4, GBP_LV}, + {0xB6D5, 0xB6EF, GBP_LVT}, + {0xB6F0, 0xB6F0, GBP_LV}, + {0xB6F1, 0xB70B, GBP_LVT}, + {0xB70C, 0xB70C, GBP_LV}, + {0xB70D, 0xB727, GBP_LVT}, + {0xB728, 0xB728, GBP_LV}, + {0xB729, 0xB743, GBP_LVT}, + {0xB744, 0xB744, GBP_LV}, + {0xB745, 0xB75F, GBP_LVT}, + {0xB760, 0xB760, GBP_LV}, + {0xB761, 0xB77B, GBP_LVT}, + {0xB77C, 0xB77C, GBP_LV}, + {0xB77D, 0xB797, GBP_LVT}, + {0xB798, 0xB798, GBP_LV}, + {0xB799, 0xB7B3, GBP_LVT}, + {0xB7B4, 0xB7B4, GBP_LV}, + {0xB7B5, 0xB7CF, GBP_LVT}, + {0xB7D0, 0xB7D0, GBP_LV}, + {0xB7D1, 0xB7EB, GBP_LVT}, + {0xB7EC, 0xB7EC, GBP_LV}, + {0xB7ED, 0xB807, GBP_LVT}, + {0xB808, 0xB808, GBP_LV}, + {0xB809, 0xB823, GBP_LVT}, + {0xB824, 0xB824, GBP_LV}, + {0xB825, 0xB83F, GBP_LVT}, + {0xB840, 0xB840, GBP_LV}, + {0xB841, 0xB85B, GBP_LVT}, + {0xB85C, 0xB85C, GBP_LV}, + {0xB85D, 0xB877, GBP_LVT}, + {0xB878, 0xB878, GBP_LV}, + {0xB879, 0xB893, GBP_LVT}, + {0xB894, 0xB894, GBP_LV}, + {0xB895, 0xB8AF, GBP_LVT}, + {0xB8B0, 0xB8B0, GBP_LV}, + {0xB8B1, 0xB8CB, GBP_LVT}, + {0xB8CC, 0xB8CC, GBP_LV}, + {0xB8CD, 0xB8E7, GBP_LVT}, + {0xB8E8, 0xB8E8, GBP_LV}, + {0xB8E9, 0xB903, GBP_LVT}, + {0xB904, 0xB904, GBP_LV}, + {0xB905, 0xB91F, GBP_LVT}, + {0xB920, 0xB920, GBP_LV}, + {0xB921, 0xB93B, GBP_LVT}, + {0xB93C, 0xB93C, GBP_LV}, + {0xB93D, 0xB957, GBP_LVT}, + {0xB958, 0xB958, GBP_LV}, + {0xB959, 0xB973, GBP_LVT}, + {0xB974, 0xB974, GBP_LV}, + {0xB975, 0xB98F, GBP_LVT}, + {0xB990, 0xB990, GBP_LV}, + {0xB991, 0xB9AB, GBP_LVT}, + {0xB9AC, 0xB9AC, GBP_LV}, + {0xB9AD, 0xB9C7, GBP_LVT}, + {0xB9C8, 0xB9C8, GBP_LV}, + {0xB9C9, 0xB9E3, GBP_LVT}, + {0xB9E4, 0xB9E4, GBP_LV}, + {0xB9E5, 0xB9FF, GBP_LVT}, + {0xBA00, 0xBA00, GBP_LV}, + {0xBA01, 0xBA1B, GBP_LVT}, + {0xBA1C, 0xBA1C, GBP_LV}, + {0xBA1D, 0xBA37, GBP_LVT}, + {0xBA38, 0xBA38, GBP_LV}, + {0xBA39, 0xBA53, GBP_LVT}, + {0xBA54, 0xBA54, GBP_LV}, + {0xBA55, 0xBA6F, GBP_LVT}, + {0xBA70, 0xBA70, GBP_LV}, + {0xBA71, 0xBA8B, GBP_LVT}, + {0xBA8C, 0xBA8C, GBP_LV}, + {0xBA8D, 0xBAA7, GBP_LVT}, + {0xBAA8, 0xBAA8, GBP_LV}, + {0xBAA9, 0xBAC3, GBP_LVT}, + {0xBAC4, 0xBAC4, GBP_LV}, + {0xBAC5, 0xBADF, GBP_LVT}, + {0xBAE0, 0xBAE0, GBP_LV}, + {0xBAE1, 0xBAFB, GBP_LVT}, + {0xBAFC, 0xBAFC, GBP_LV}, + {0xBAFD, 0xBB17, GBP_LVT}, + {0xBB18, 0xBB18, GBP_LV}, + {0xBB19, 0xBB33, GBP_LVT}, + {0xBB34, 0xBB34, GBP_LV}, + {0xBB35, 0xBB4F, GBP_LVT}, + {0xBB50, 0xBB50, GBP_LV}, + {0xBB51, 0xBB6B, GBP_LVT}, + {0xBB6C, 0xBB6C, GBP_LV}, + {0xBB6D, 0xBB87, GBP_LVT}, + {0xBB88, 0xBB88, GBP_LV}, + {0xBB89, 0xBBA3, GBP_LVT}, + {0xBBA4, 0xBBA4, GBP_LV}, + {0xBBA5, 0xBBBF, GBP_LVT}, + {0xBBC0, 0xBBC0, GBP_LV}, + {0xBBC1, 0xBBDB, GBP_LVT}, + {0xBBDC, 0xBBDC, GBP_LV}, + {0xBBDD, 0xBBF7, GBP_LVT}, + {0xBBF8, 0xBBF8, GBP_LV}, + {0xBBF9, 0xBC13, GBP_LVT}, + {0xBC14, 0xBC14, GBP_LV}, + {0xBC15, 0xBC2F, GBP_LVT}, + {0xBC30, 0xBC30, GBP_LV}, + {0xBC31, 0xBC4B, GBP_LVT}, + {0xBC4C, 0xBC4C, GBP_LV}, + {0xBC4D, 0xBC67, GBP_LVT}, + {0xBC68, 0xBC68, GBP_LV}, + {0xBC69, 0xBC83, GBP_LVT}, + {0xBC84, 0xBC84, GBP_LV}, + {0xBC85, 0xBC9F, GBP_LVT}, + {0xBCA0, 0xBCA0, GBP_LV}, + {0xBCA1, 0xBCBB, GBP_LVT}, + {0xBCBC, 0xBCBC, GBP_LV}, + {0xBCBD, 0xBCD7, GBP_LVT}, + {0xBCD8, 0xBCD8, GBP_LV}, + {0xBCD9, 0xBCF3, GBP_LVT}, + {0xBCF4, 0xBCF4, GBP_LV}, + {0xBCF5, 0xBD0F, GBP_LVT}, + {0xBD10, 0xBD10, GBP_LV}, + {0xBD11, 0xBD2B, GBP_LVT}, + {0xBD2C, 0xBD2C, GBP_LV}, + {0xBD2D, 0xBD47, GBP_LVT}, + {0xBD48, 0xBD48, GBP_LV}, + {0xBD49, 0xBD63, GBP_LVT}, + {0xBD64, 0xBD64, GBP_LV}, + {0xBD65, 0xBD7F, GBP_LVT}, + {0xBD80, 0xBD80, GBP_LV}, + {0xBD81, 0xBD9B, GBP_LVT}, + {0xBD9C, 0xBD9C, GBP_LV}, + {0xBD9D, 0xBDB7, GBP_LVT}, + {0xBDB8, 0xBDB8, GBP_LV}, + {0xBDB9, 0xBDD3, GBP_LVT}, + {0xBDD4, 0xBDD4, GBP_LV}, + {0xBDD5, 0xBDEF, GBP_LVT}, + {0xBDF0, 0xBDF0, GBP_LV}, + {0xBDF1, 0xBE0B, GBP_LVT}, + {0xBE0C, 0xBE0C, GBP_LV}, + {0xBE0D, 0xBE27, GBP_LVT}, + {0xBE28, 0xBE28, GBP_LV}, + {0xBE29, 0xBE43, GBP_LVT}, + {0xBE44, 0xBE44, GBP_LV}, + {0xBE45, 0xBE5F, GBP_LVT}, + {0xBE60, 0xBE60, GBP_LV}, + {0xBE61, 0xBE7B, GBP_LVT}, + {0xBE7C, 0xBE7C, GBP_LV}, + {0xBE7D, 0xBE97, GBP_LVT}, + {0xBE98, 0xBE98, GBP_LV}, + {0xBE99, 0xBEB3, GBP_LVT}, + {0xBEB4, 0xBEB4, GBP_LV}, + {0xBEB5, 0xBECF, GBP_LVT}, + {0xBED0, 0xBED0, GBP_LV}, + {0xBED1, 0xBEEB, GBP_LVT}, + {0xBEEC, 0xBEEC, GBP_LV}, + {0xBEED, 0xBF07, GBP_LVT}, + {0xBF08, 0xBF08, GBP_LV}, + {0xBF09, 0xBF23, GBP_LVT}, + {0xBF24, 0xBF24, GBP_LV}, + {0xBF25, 0xBF3F, GBP_LVT}, + {0xBF40, 0xBF40, GBP_LV}, + {0xBF41, 0xBF5B, GBP_LVT}, + {0xBF5C, 0xBF5C, GBP_LV}, + {0xBF5D, 0xBF77, GBP_LVT}, + {0xBF78, 0xBF78, GBP_LV}, + {0xBF79, 0xBF93, GBP_LVT}, + {0xBF94, 0xBF94, GBP_LV}, + {0xBF95, 0xBFAF, GBP_LVT}, + {0xBFB0, 0xBFB0, GBP_LV}, + {0xBFB1, 0xBFCB, GBP_LVT}, + {0xBFCC, 0xBFCC, GBP_LV}, + {0xBFCD, 0xBFE7, GBP_LVT}, + {0xBFE8, 0xBFE8, GBP_LV}, + {0xBFE9, 0xC003, GBP_LVT}, + {0xC004, 0xC004, GBP_LV}, + {0xC005, 0xC01F, GBP_LVT}, + {0xC020, 0xC020, GBP_LV}, + {0xC021, 0xC03B, GBP_LVT}, + {0xC03C, 0xC03C, GBP_LV}, + {0xC03D, 0xC057, GBP_LVT}, + {0xC058, 0xC058, GBP_LV}, + {0xC059, 0xC073, GBP_LVT}, + {0xC074, 0xC074, GBP_LV}, + {0xC075, 0xC08F, GBP_LVT}, + {0xC090, 0xC090, GBP_LV}, + {0xC091, 0xC0AB, GBP_LVT}, + {0xC0AC, 0xC0AC, GBP_LV}, + {0xC0AD, 0xC0C7, GBP_LVT}, + {0xC0C8, 0xC0C8, GBP_LV}, + {0xC0C9, 0xC0E3, GBP_LVT}, + {0xC0E4, 0xC0E4, GBP_LV}, + {0xC0E5, 0xC0FF, GBP_LVT}, + {0xC100, 0xC100, GBP_LV}, + {0xC101, 0xC11B, GBP_LVT}, + {0xC11C, 0xC11C, GBP_LV}, + {0xC11D, 0xC137, GBP_LVT}, + {0xC138, 0xC138, GBP_LV}, + {0xC139, 0xC153, GBP_LVT}, + {0xC154, 0xC154, GBP_LV}, + {0xC155, 0xC16F, GBP_LVT}, + {0xC170, 0xC170, GBP_LV}, + {0xC171, 0xC18B, GBP_LVT}, + {0xC18C, 0xC18C, GBP_LV}, + {0xC18D, 0xC1A7, GBP_LVT}, + {0xC1A8, 0xC1A8, GBP_LV}, + {0xC1A9, 0xC1C3, GBP_LVT}, + {0xC1C4, 0xC1C4, GBP_LV}, + {0xC1C5, 0xC1DF, GBP_LVT}, + {0xC1E0, 0xC1E0, GBP_LV}, + {0xC1E1, 0xC1FB, GBP_LVT}, + {0xC1FC, 0xC1FC, GBP_LV}, + {0xC1FD, 0xC217, GBP_LVT}, + {0xC218, 0xC218, GBP_LV}, + {0xC219, 0xC233, GBP_LVT}, + {0xC234, 0xC234, GBP_LV}, + {0xC235, 0xC24F, GBP_LVT}, + {0xC250, 0xC250, GBP_LV}, + {0xC251, 0xC26B, GBP_LVT}, + {0xC26C, 0xC26C, GBP_LV}, + {0xC26D, 0xC287, GBP_LVT}, + {0xC288, 0xC288, GBP_LV}, + {0xC289, 0xC2A3, GBP_LVT}, + {0xC2A4, 0xC2A4, GBP_LV}, + {0xC2A5, 0xC2BF, GBP_LVT}, + {0xC2C0, 0xC2C0, GBP_LV}, + {0xC2C1, 0xC2DB, GBP_LVT}, + {0xC2DC, 0xC2DC, GBP_LV}, + {0xC2DD, 0xC2F7, GBP_LVT}, + {0xC2F8, 0xC2F8, GBP_LV}, + {0xC2F9, 0xC313, GBP_LVT}, + {0xC314, 0xC314, GBP_LV}, + {0xC315, 0xC32F, GBP_LVT}, + {0xC330, 0xC330, GBP_LV}, + {0xC331, 0xC34B, GBP_LVT}, + {0xC34C, 0xC34C, GBP_LV}, + {0xC34D, 0xC367, GBP_LVT}, + {0xC368, 0xC368, GBP_LV}, + {0xC369, 0xC383, GBP_LVT}, + {0xC384, 0xC384, GBP_LV}, + {0xC385, 0xC39F, GBP_LVT}, + {0xC3A0, 0xC3A0, GBP_LV}, + {0xC3A1, 0xC3BB, GBP_LVT}, + {0xC3BC, 0xC3BC, GBP_LV}, + {0xC3BD, 0xC3D7, GBP_LVT}, + {0xC3D8, 0xC3D8, GBP_LV}, + {0xC3D9, 0xC3F3, GBP_LVT}, + {0xC3F4, 0xC3F4, GBP_LV}, + {0xC3F5, 0xC40F, GBP_LVT}, + {0xC410, 0xC410, GBP_LV}, + {0xC411, 0xC42B, GBP_LVT}, + {0xC42C, 0xC42C, GBP_LV}, + {0xC42D, 0xC447, GBP_LVT}, + {0xC448, 0xC448, GBP_LV}, + {0xC449, 0xC463, GBP_LVT}, + {0xC464, 0xC464, GBP_LV}, + {0xC465, 0xC47F, GBP_LVT}, + {0xC480, 0xC480, GBP_LV}, + {0xC481, 0xC49B, GBP_LVT}, + {0xC49C, 0xC49C, GBP_LV}, + {0xC49D, 0xC4B7, GBP_LVT}, + {0xC4B8, 0xC4B8, GBP_LV}, + {0xC4B9, 0xC4D3, GBP_LVT}, + {0xC4D4, 0xC4D4, GBP_LV}, + {0xC4D5, 0xC4EF, GBP_LVT}, + {0xC4F0, 0xC4F0, GBP_LV}, + {0xC4F1, 0xC50B, GBP_LVT}, + {0xC50C, 0xC50C, GBP_LV}, + {0xC50D, 0xC527, GBP_LVT}, + {0xC528, 0xC528, GBP_LV}, + {0xC529, 0xC543, GBP_LVT}, + {0xC544, 0xC544, GBP_LV}, + {0xC545, 0xC55F, GBP_LVT}, + {0xC560, 0xC560, GBP_LV}, + {0xC561, 0xC57B, GBP_LVT}, + {0xC57C, 0xC57C, GBP_LV}, + {0xC57D, 0xC597, GBP_LVT}, + {0xC598, 0xC598, GBP_LV}, + {0xC599, 0xC5B3, GBP_LVT}, + {0xC5B4, 0xC5B4, GBP_LV}, + {0xC5B5, 0xC5CF, GBP_LVT}, + {0xC5D0, 0xC5D0, GBP_LV}, + {0xC5D1, 0xC5EB, GBP_LVT}, + {0xC5EC, 0xC5EC, GBP_LV}, + {0xC5ED, 0xC607, GBP_LVT}, + {0xC608, 0xC608, GBP_LV}, + {0xC609, 0xC623, GBP_LVT}, + {0xC624, 0xC624, GBP_LV}, + {0xC625, 0xC63F, GBP_LVT}, + {0xC640, 0xC640, GBP_LV}, + {0xC641, 0xC65B, GBP_LVT}, + {0xC65C, 0xC65C, GBP_LV}, + {0xC65D, 0xC677, GBP_LVT}, + {0xC678, 0xC678, GBP_LV}, + {0xC679, 0xC693, GBP_LVT}, + {0xC694, 0xC694, GBP_LV}, + {0xC695, 0xC6AF, GBP_LVT}, + {0xC6B0, 0xC6B0, GBP_LV}, + {0xC6B1, 0xC6CB, GBP_LVT}, + {0xC6CC, 0xC6CC, GBP_LV}, + {0xC6CD, 0xC6E7, GBP_LVT}, + {0xC6E8, 0xC6E8, GBP_LV}, + {0xC6E9, 0xC703, GBP_LVT}, + {0xC704, 0xC704, GBP_LV}, + {0xC705, 0xC71F, GBP_LVT}, + {0xC720, 0xC720, GBP_LV}, + {0xC721, 0xC73B, GBP_LVT}, + {0xC73C, 0xC73C, GBP_LV}, + {0xC73D, 0xC757, GBP_LVT}, + {0xC758, 0xC758, GBP_LV}, + {0xC759, 0xC773, GBP_LVT}, + {0xC774, 0xC774, GBP_LV}, + {0xC775, 0xC78F, GBP_LVT}, + {0xC790, 0xC790, GBP_LV}, + {0xC791, 0xC7AB, GBP_LVT}, + {0xC7AC, 0xC7AC, GBP_LV}, + {0xC7AD, 0xC7C7, GBP_LVT}, + {0xC7C8, 0xC7C8, GBP_LV}, + {0xC7C9, 0xC7E3, GBP_LVT}, + {0xC7E4, 0xC7E4, GBP_LV}, + {0xC7E5, 0xC7FF, GBP_LVT}, + {0xC800, 0xC800, GBP_LV}, + {0xC801, 0xC81B, GBP_LVT}, + {0xC81C, 0xC81C, GBP_LV}, + {0xC81D, 0xC837, GBP_LVT}, + {0xC838, 0xC838, GBP_LV}, + {0xC839, 0xC853, GBP_LVT}, + {0xC854, 0xC854, GBP_LV}, + {0xC855, 0xC86F, GBP_LVT}, + {0xC870, 0xC870, GBP_LV}, + {0xC871, 0xC88B, GBP_LVT}, + {0xC88C, 0xC88C, GBP_LV}, + {0xC88D, 0xC8A7, GBP_LVT}, + {0xC8A8, 0xC8A8, GBP_LV}, + {0xC8A9, 0xC8C3, GBP_LVT}, + {0xC8C4, 0xC8C4, GBP_LV}, + {0xC8C5, 0xC8DF, GBP_LVT}, + {0xC8E0, 0xC8E0, GBP_LV}, + {0xC8E1, 0xC8FB, GBP_LVT}, + {0xC8FC, 0xC8FC, GBP_LV}, + {0xC8FD, 0xC917, GBP_LVT}, + {0xC918, 0xC918, GBP_LV}, + {0xC919, 0xC933, GBP_LVT}, + {0xC934, 0xC934, GBP_LV}, + {0xC935, 0xC94F, GBP_LVT}, + {0xC950, 0xC950, GBP_LV}, + {0xC951, 0xC96B, GBP_LVT}, + {0xC96C, 0xC96C, GBP_LV}, + {0xC96D, 0xC987, GBP_LVT}, + {0xC988, 0xC988, GBP_LV}, + {0xC989, 0xC9A3, GBP_LVT}, + {0xC9A4, 0xC9A4, GBP_LV}, + {0xC9A5, 0xC9BF, GBP_LVT}, + {0xC9C0, 0xC9C0, GBP_LV}, + {0xC9C1, 0xC9DB, GBP_LVT}, + {0xC9DC, 0xC9DC, GBP_LV}, + {0xC9DD, 0xC9F7, GBP_LVT}, + {0xC9F8, 0xC9F8, GBP_LV}, + {0xC9F9, 0xCA13, GBP_LVT}, + {0xCA14, 0xCA14, GBP_LV}, + {0xCA15, 0xCA2F, GBP_LVT}, + {0xCA30, 0xCA30, GBP_LV}, + {0xCA31, 0xCA4B, GBP_LVT}, + {0xCA4C, 0xCA4C, GBP_LV}, + {0xCA4D, 0xCA67, GBP_LVT}, + {0xCA68, 0xCA68, GBP_LV}, + {0xCA69, 0xCA83, GBP_LVT}, + {0xCA84, 0xCA84, GBP_LV}, + {0xCA85, 0xCA9F, GBP_LVT}, + {0xCAA0, 0xCAA0, GBP_LV}, + {0xCAA1, 0xCABB, GBP_LVT}, + {0xCABC, 0xCABC, GBP_LV}, + {0xCABD, 0xCAD7, GBP_LVT}, + {0xCAD8, 0xCAD8, GBP_LV}, + {0xCAD9, 0xCAF3, GBP_LVT}, + {0xCAF4, 0xCAF4, GBP_LV}, + {0xCAF5, 0xCB0F, GBP_LVT}, + {0xCB10, 0xCB10, GBP_LV}, + {0xCB11, 0xCB2B, GBP_LVT}, + {0xCB2C, 0xCB2C, GBP_LV}, + {0xCB2D, 0xCB47, GBP_LVT}, + {0xCB48, 0xCB48, GBP_LV}, + {0xCB49, 0xCB63, GBP_LVT}, + {0xCB64, 0xCB64, GBP_LV}, + {0xCB65, 0xCB7F, GBP_LVT}, + {0xCB80, 0xCB80, GBP_LV}, + {0xCB81, 0xCB9B, GBP_LVT}, + {0xCB9C, 0xCB9C, GBP_LV}, + {0xCB9D, 0xCBB7, GBP_LVT}, + {0xCBB8, 0xCBB8, GBP_LV}, + {0xCBB9, 0xCBD3, GBP_LVT}, + {0xCBD4, 0xCBD4, GBP_LV}, + {0xCBD5, 0xCBEF, GBP_LVT}, + {0xCBF0, 0xCBF0, GBP_LV}, + {0xCBF1, 0xCC0B, GBP_LVT}, + {0xCC0C, 0xCC0C, GBP_LV}, + {0xCC0D, 0xCC27, GBP_LVT}, + {0xCC28, 0xCC28, GBP_LV}, + {0xCC29, 0xCC43, GBP_LVT}, + {0xCC44, 0xCC44, GBP_LV}, + {0xCC45, 0xCC5F, GBP_LVT}, + {0xCC60, 0xCC60, GBP_LV}, + {0xCC61, 0xCC7B, GBP_LVT}, + {0xCC7C, 0xCC7C, GBP_LV}, + {0xCC7D, 0xCC97, GBP_LVT}, + {0xCC98, 0xCC98, GBP_LV}, + {0xCC99, 0xCCB3, GBP_LVT}, + {0xCCB4, 0xCCB4, GBP_LV}, + {0xCCB5, 0xCCCF, GBP_LVT}, + {0xCCD0, 0xCCD0, GBP_LV}, + {0xCCD1, 0xCCEB, GBP_LVT}, + {0xCCEC, 0xCCEC, GBP_LV}, + {0xCCED, 0xCD07, GBP_LVT}, + {0xCD08, 0xCD08, GBP_LV}, + {0xCD09, 0xCD23, GBP_LVT}, + {0xCD24, 0xCD24, GBP_LV}, + {0xCD25, 0xCD3F, GBP_LVT}, + {0xCD40, 0xCD40, GBP_LV}, + {0xCD41, 0xCD5B, GBP_LVT}, + {0xCD5C, 0xCD5C, GBP_LV}, + {0xCD5D, 0xCD77, GBP_LVT}, + {0xCD78, 0xCD78, GBP_LV}, + {0xCD79, 0xCD93, GBP_LVT}, + {0xCD94, 0xCD94, GBP_LV}, + {0xCD95, 0xCDAF, GBP_LVT}, + {0xCDB0, 0xCDB0, GBP_LV}, + {0xCDB1, 0xCDCB, GBP_LVT}, + {0xCDCC, 0xCDCC, GBP_LV}, + {0xCDCD, 0xCDE7, GBP_LVT}, + {0xCDE8, 0xCDE8, GBP_LV}, + {0xCDE9, 0xCE03, GBP_LVT}, + {0xCE04, 0xCE04, GBP_LV}, + {0xCE05, 0xCE1F, GBP_LVT}, + {0xCE20, 0xCE20, GBP_LV}, + {0xCE21, 0xCE3B, GBP_LVT}, + {0xCE3C, 0xCE3C, GBP_LV}, + {0xCE3D, 0xCE57, GBP_LVT}, + {0xCE58, 0xCE58, GBP_LV}, + {0xCE59, 0xCE73, GBP_LVT}, + {0xCE74, 0xCE74, GBP_LV}, + {0xCE75, 0xCE8F, GBP_LVT}, + {0xCE90, 0xCE90, GBP_LV}, + {0xCE91, 0xCEAB, GBP_LVT}, + {0xCEAC, 0xCEAC, GBP_LV}, + {0xCEAD, 0xCEC7, GBP_LVT}, + {0xCEC8, 0xCEC8, GBP_LV}, + {0xCEC9, 0xCEE3, GBP_LVT}, + {0xCEE4, 0xCEE4, GBP_LV}, + {0xCEE5, 0xCEFF, GBP_LVT}, + {0xCF00, 0xCF00, GBP_LV}, + {0xCF01, 0xCF1B, GBP_LVT}, + {0xCF1C, 0xCF1C, GBP_LV}, + {0xCF1D, 0xCF37, GBP_LVT}, + {0xCF38, 0xCF38, GBP_LV}, + {0xCF39, 0xCF53, GBP_LVT}, + {0xCF54, 0xCF54, GBP_LV}, + {0xCF55, 0xCF6F, GBP_LVT}, + {0xCF70, 0xCF70, GBP_LV}, + {0xCF71, 0xCF8B, GBP_LVT}, + {0xCF8C, 0xCF8C, GBP_LV}, + {0xCF8D, 0xCFA7, GBP_LVT}, + {0xCFA8, 0xCFA8, GBP_LV}, + {0xCFA9, 0xCFC3, GBP_LVT}, + {0xCFC4, 0xCFC4, GBP_LV}, + {0xCFC5, 0xCFDF, GBP_LVT}, + {0xCFE0, 0xCFE0, GBP_LV}, + {0xCFE1, 0xCFFB, GBP_LVT}, + {0xCFFC, 0xCFFC, GBP_LV}, + {0xCFFD, 0xD017, GBP_LVT}, + {0xD018, 0xD018, GBP_LV}, + {0xD019, 0xD033, GBP_LVT}, + {0xD034, 0xD034, GBP_LV}, + {0xD035, 0xD04F, GBP_LVT}, + {0xD050, 0xD050, GBP_LV}, + {0xD051, 0xD06B, GBP_LVT}, + {0xD06C, 0xD06C, GBP_LV}, + {0xD06D, 0xD087, GBP_LVT}, + {0xD088, 0xD088, GBP_LV}, + {0xD089, 0xD0A3, GBP_LVT}, + {0xD0A4, 0xD0A4, GBP_LV}, + {0xD0A5, 0xD0BF, GBP_LVT}, + {0xD0C0, 0xD0C0, GBP_LV}, + {0xD0C1, 0xD0DB, GBP_LVT}, + {0xD0DC, 0xD0DC, GBP_LV}, + {0xD0DD, 0xD0F7, GBP_LVT}, + {0xD0F8, 0xD0F8, GBP_LV}, + {0xD0F9, 0xD113, GBP_LVT}, + {0xD114, 0xD114, GBP_LV}, + {0xD115, 0xD12F, GBP_LVT}, + {0xD130, 0xD130, GBP_LV}, + {0xD131, 0xD14B, GBP_LVT}, + {0xD14C, 0xD14C, GBP_LV}, + {0xD14D, 0xD167, GBP_LVT}, + {0xD168, 0xD168, GBP_LV}, + {0xD169, 0xD183, GBP_LVT}, + {0xD184, 0xD184, GBP_LV}, + {0xD185, 0xD19F, GBP_LVT}, + {0xD1A0, 0xD1A0, GBP_LV}, + {0xD1A1, 0xD1BB, GBP_LVT}, + {0xD1BC, 0xD1BC, GBP_LV}, + {0xD1BD, 0xD1D7, GBP_LVT}, + {0xD1D8, 0xD1D8, GBP_LV}, + {0xD1D9, 0xD1F3, GBP_LVT}, + {0xD1F4, 0xD1F4, GBP_LV}, + {0xD1F5, 0xD20F, GBP_LVT}, + {0xD210, 0xD210, GBP_LV}, + {0xD211, 0xD22B, GBP_LVT}, + {0xD22C, 0xD22C, GBP_LV}, + {0xD22D, 0xD247, GBP_LVT}, + {0xD248, 0xD248, GBP_LV}, + {0xD249, 0xD263, GBP_LVT}, + {0xD264, 0xD264, GBP_LV}, + {0xD265, 0xD27F, GBP_LVT}, + {0xD280, 0xD280, GBP_LV}, + {0xD281, 0xD29B, GBP_LVT}, + {0xD29C, 0xD29C, GBP_LV}, + {0xD29D, 0xD2B7, GBP_LVT}, + {0xD2B8, 0xD2B8, GBP_LV}, + {0xD2B9, 0xD2D3, GBP_LVT}, + {0xD2D4, 0xD2D4, GBP_LV}, + {0xD2D5, 0xD2EF, GBP_LVT}, + {0xD2F0, 0xD2F0, GBP_LV}, + {0xD2F1, 0xD30B, GBP_LVT}, + {0xD30C, 0xD30C, GBP_LV}, + {0xD30D, 0xD327, GBP_LVT}, + {0xD328, 0xD328, GBP_LV}, + {0xD329, 0xD343, GBP_LVT}, + {0xD344, 0xD344, GBP_LV}, + {0xD345, 0xD35F, GBP_LVT}, + {0xD360, 0xD360, GBP_LV}, + {0xD361, 0xD37B, GBP_LVT}, + {0xD37C, 0xD37C, GBP_LV}, + {0xD37D, 0xD397, GBP_LVT}, + {0xD398, 0xD398, GBP_LV}, + {0xD399, 0xD3B3, GBP_LVT}, + {0xD3B4, 0xD3B4, GBP_LV}, + {0xD3B5, 0xD3CF, GBP_LVT}, + {0xD3D0, 0xD3D0, GBP_LV}, + {0xD3D1, 0xD3EB, GBP_LVT}, + {0xD3EC, 0xD3EC, GBP_LV}, + {0xD3ED, 0xD407, GBP_LVT}, + {0xD408, 0xD408, GBP_LV}, + {0xD409, 0xD423, GBP_LVT}, + {0xD424, 0xD424, GBP_LV}, + {0xD425, 0xD43F, GBP_LVT}, + {0xD440, 0xD440, GBP_LV}, + {0xD441, 0xD45B, GBP_LVT}, + {0xD45C, 0xD45C, GBP_LV}, + {0xD45D, 0xD477, GBP_LVT}, + {0xD478, 0xD478, GBP_LV}, + {0xD479, 0xD493, GBP_LVT}, + {0xD494, 0xD494, GBP_LV}, + {0xD495, 0xD4AF, GBP_LVT}, + {0xD4B0, 0xD4B0, GBP_LV}, + {0xD4B1, 0xD4CB, GBP_LVT}, + {0xD4CC, 0xD4CC, GBP_LV}, + {0xD4CD, 0xD4E7, GBP_LVT}, + {0xD4E8, 0xD4E8, GBP_LV}, + {0xD4E9, 0xD503, GBP_LVT}, + {0xD504, 0xD504, GBP_LV}, + {0xD505, 0xD51F, GBP_LVT}, + {0xD520, 0xD520, GBP_LV}, + {0xD521, 0xD53B, GBP_LVT}, + {0xD53C, 0xD53C, GBP_LV}, + {0xD53D, 0xD557, GBP_LVT}, + {0xD558, 0xD558, GBP_LV}, + {0xD559, 0xD573, GBP_LVT}, + {0xD574, 0xD574, GBP_LV}, + {0xD575, 0xD58F, GBP_LVT}, + {0xD590, 0xD590, GBP_LV}, + {0xD591, 0xD5AB, GBP_LVT}, + {0xD5AC, 0xD5AC, GBP_LV}, + {0xD5AD, 0xD5C7, GBP_LVT}, + {0xD5C8, 0xD5C8, GBP_LV}, + {0xD5C9, 0xD5E3, GBP_LVT}, + {0xD5E4, 0xD5E4, GBP_LV}, + {0xD5E5, 0xD5FF, GBP_LVT}, + {0xD600, 0xD600, GBP_LV}, + {0xD601, 0xD61B, GBP_LVT}, + {0xD61C, 0xD61C, GBP_LV}, + {0xD61D, 0xD637, GBP_LVT}, + {0xD638, 0xD638, GBP_LV}, + {0xD639, 0xD653, GBP_LVT}, + {0xD654, 0xD654, GBP_LV}, + {0xD655, 0xD66F, GBP_LVT}, + {0xD670, 0xD670, GBP_LV}, + {0xD671, 0xD68B, GBP_LVT}, + {0xD68C, 0xD68C, GBP_LV}, + {0xD68D, 0xD6A7, GBP_LVT}, + {0xD6A8, 0xD6A8, GBP_LV}, + {0xD6A9, 0xD6C3, GBP_LVT}, + {0xD6C4, 0xD6C4, GBP_LV}, + {0xD6C5, 0xD6DF, GBP_LVT}, + {0xD6E0, 0xD6E0, GBP_LV}, + {0xD6E1, 0xD6FB, GBP_LVT}, + {0xD6FC, 0xD6FC, GBP_LV}, + {0xD6FD, 0xD717, GBP_LVT}, + {0xD718, 0xD718, GBP_LV}, + {0xD719, 0xD733, GBP_LVT}, + {0xD734, 0xD734, GBP_LV}, + {0xD735, 0xD74F, GBP_LVT}, + {0xD750, 0xD750, GBP_LV}, + {0xD751, 0xD76B, GBP_LVT}, + {0xD76C, 0xD76C, GBP_LV}, + {0xD76D, 0xD787, GBP_LVT}, + {0xD788, 0xD788, GBP_LV}, + {0xD789, 0xD7A3, GBP_LVT}, + {0xD7B0, 0xD7C6, GBP_V}, + {0xD7CB, 0xD7FB, GBP_T}, + {0xD800, 0xDFFF, GBP_Control}, + {0xFB1E, 0xFB1E, GBP_Extend}, + {0xFE00, 0xFE0F, GBP_Extend}, + {0xFE20, 0xFE2F, GBP_Extend}, + {0xFEFF, 0xFEFF, GBP_Control}, + {0xFF9E, 0xFF9F, GBP_Extend}, + {0xFFF0, 0xFFF8, GBP_Control}, + {0xFFF9, 0xFFFB, GBP_Control}, + {0x101FD, 0x101FD, GBP_Extend}, + {0x102E0, 0x102E0, GBP_Extend}, + {0x10376, 0x1037A, GBP_Extend}, + {0x10A01, 0x10A03, GBP_Extend}, + {0x10A05, 0x10A06, GBP_Extend}, + {0x10A0C, 0x10A0F, GBP_Extend}, + {0x10A38, 0x10A3A, GBP_Extend}, + {0x10A3F, 0x10A3F, GBP_Extend}, + {0x10AE5, 0x10AE6, GBP_Extend}, + {0x11000, 0x11000, GBP_SpacingMark}, + {0x11001, 0x11001, GBP_Extend}, + {0x11002, 0x11002, GBP_SpacingMark}, + {0x11038, 0x11046, GBP_Extend}, + {0x1107F, 0x11081, GBP_Extend}, + {0x11082, 0x11082, GBP_SpacingMark}, + {0x110B0, 0x110B2, GBP_SpacingMark}, + {0x110B3, 0x110B6, GBP_Extend}, + {0x110B7, 0x110B8, GBP_SpacingMark}, + {0x110B9, 0x110BA, GBP_Extend}, + {0x110BD, 0x110BD, GBP_Prepend}, + {0x11100, 0x11102, GBP_Extend}, + {0x11127, 0x1112B, GBP_Extend}, + {0x1112C, 0x1112C, GBP_SpacingMark}, + {0x1112D, 0x11134, GBP_Extend}, + {0x11173, 0x11173, GBP_Extend}, + {0x11180, 0x11181, GBP_Extend}, + {0x11182, 0x11182, GBP_SpacingMark}, + {0x111B3, 0x111B5, GBP_SpacingMark}, + {0x111B6, 0x111BE, GBP_Extend}, + {0x111BF, 0x111C0, GBP_SpacingMark}, + {0x111C2, 0x111C3, GBP_Prepend}, + {0x111CA, 0x111CC, GBP_Extend}, + {0x1122C, 0x1122E, GBP_SpacingMark}, + {0x1122F, 0x11231, GBP_Extend}, + {0x11232, 0x11233, GBP_SpacingMark}, + {0x11234, 0x11234, GBP_Extend}, + {0x11235, 0x11235, GBP_SpacingMark}, + {0x11236, 0x11237, GBP_Extend}, + {0x1123E, 0x1123E, GBP_Extend}, + {0x112DF, 0x112DF, GBP_Extend}, + {0x112E0, 0x112E2, GBP_SpacingMark}, + {0x112E3, 0x112EA, GBP_Extend}, + {0x11300, 0x11301, GBP_Extend}, + {0x11302, 0x11303, GBP_SpacingMark}, + {0x1133C, 0x1133C, GBP_Extend}, + {0x1133E, 0x1133E, GBP_Extend}, + {0x1133F, 0x1133F, GBP_SpacingMark}, + {0x11340, 0x11340, GBP_Extend}, + {0x11341, 0x11344, GBP_SpacingMark}, + {0x11347, 0x11348, GBP_SpacingMark}, + {0x1134B, 0x1134D, GBP_SpacingMark}, + {0x11357, 0x11357, GBP_Extend}, + {0x11362, 0x11363, GBP_SpacingMark}, + {0x11366, 0x1136C, GBP_Extend}, + {0x11370, 0x11374, GBP_Extend}, + {0x11435, 0x11437, GBP_SpacingMark}, + {0x11438, 0x1143F, GBP_Extend}, + {0x11440, 0x11441, GBP_SpacingMark}, + {0x11442, 0x11444, GBP_Extend}, + {0x11445, 0x11445, GBP_SpacingMark}, + {0x11446, 0x11446, GBP_Extend}, + {0x114B0, 0x114B0, GBP_Extend}, + {0x114B1, 0x114B2, GBP_SpacingMark}, + {0x114B3, 0x114B8, GBP_Extend}, + {0x114B9, 0x114B9, GBP_SpacingMark}, + {0x114BA, 0x114BA, GBP_Extend}, + {0x114BB, 0x114BC, GBP_SpacingMark}, + {0x114BD, 0x114BD, GBP_Extend}, + {0x114BE, 0x114BE, GBP_SpacingMark}, + {0x114BF, 0x114C0, GBP_Extend}, + {0x114C1, 0x114C1, GBP_SpacingMark}, + {0x114C2, 0x114C3, GBP_Extend}, + {0x115AF, 0x115AF, GBP_Extend}, + {0x115B0, 0x115B1, GBP_SpacingMark}, + {0x115B2, 0x115B5, GBP_Extend}, + {0x115B8, 0x115BB, GBP_SpacingMark}, + {0x115BC, 0x115BD, GBP_Extend}, + {0x115BE, 0x115BE, GBP_SpacingMark}, + {0x115BF, 0x115C0, GBP_Extend}, + {0x115DC, 0x115DD, GBP_Extend}, + {0x11630, 0x11632, GBP_SpacingMark}, + {0x11633, 0x1163A, GBP_Extend}, + {0x1163B, 0x1163C, GBP_SpacingMark}, + {0x1163D, 0x1163D, GBP_Extend}, + {0x1163E, 0x1163E, GBP_SpacingMark}, + {0x1163F, 0x11640, GBP_Extend}, + {0x116AB, 0x116AB, GBP_Extend}, + {0x116AC, 0x116AC, GBP_SpacingMark}, + {0x116AD, 0x116AD, GBP_Extend}, + {0x116AE, 0x116AF, GBP_SpacingMark}, + {0x116B0, 0x116B5, GBP_Extend}, + {0x116B6, 0x116B6, GBP_SpacingMark}, + {0x116B7, 0x116B7, GBP_Extend}, + {0x1171D, 0x1171F, GBP_Extend}, + {0x11720, 0x11721, GBP_SpacingMark}, + {0x11722, 0x11725, GBP_Extend}, + {0x11726, 0x11726, GBP_SpacingMark}, + {0x11727, 0x1172B, GBP_Extend}, + {0x11C2F, 0x11C2F, GBP_SpacingMark}, + {0x11C30, 0x11C36, GBP_Extend}, + {0x11C38, 0x11C3D, GBP_Extend}, + {0x11C3E, 0x11C3E, GBP_SpacingMark}, + {0x11C3F, 0x11C3F, GBP_Extend}, + {0x11C92, 0x11CA7, GBP_Extend}, + {0x11CA9, 0x11CA9, GBP_SpacingMark}, + {0x11CAA, 0x11CB0, GBP_Extend}, + {0x11CB1, 0x11CB1, GBP_SpacingMark}, + {0x11CB2, 0x11CB3, GBP_Extend}, + {0x11CB4, 0x11CB4, GBP_SpacingMark}, + {0x11CB5, 0x11CB6, GBP_Extend}, + {0x16AF0, 0x16AF4, GBP_Extend}, + {0x16B30, 0x16B36, GBP_Extend}, + {0x16F51, 0x16F7E, GBP_SpacingMark}, + {0x16F8F, 0x16F92, GBP_Extend}, + {0x1BC9D, 0x1BC9E, GBP_Extend}, + {0x1BCA0, 0x1BCA3, GBP_Control}, + {0x1D165, 0x1D165, GBP_Extend}, + {0x1D166, 0x1D166, GBP_SpacingMark}, + {0x1D167, 0x1D169, GBP_Extend}, + {0x1D16D, 0x1D16D, GBP_SpacingMark}, + {0x1D16E, 0x1D172, GBP_Extend}, + {0x1D173, 0x1D17A, GBP_Control}, + {0x1D17B, 0x1D182, GBP_Extend}, + {0x1D185, 0x1D18B, GBP_Extend}, + {0x1D1AA, 0x1D1AD, GBP_Extend}, + {0x1D242, 0x1D244, GBP_Extend}, + {0x1DA00, 0x1DA36, GBP_Extend}, + {0x1DA3B, 0x1DA6C, GBP_Extend}, + {0x1DA75, 0x1DA75, GBP_Extend}, + {0x1DA84, 0x1DA84, GBP_Extend}, + {0x1DA9B, 0x1DA9F, GBP_Extend}, + {0x1DAA1, 0x1DAAF, GBP_Extend}, + {0x1E000, 0x1E006, GBP_Extend}, + {0x1E008, 0x1E018, GBP_Extend}, + {0x1E01B, 0x1E021, GBP_Extend}, + {0x1E023, 0x1E024, GBP_Extend}, + {0x1E026, 0x1E02A, GBP_Extend}, + {0x1E8D0, 0x1E8D6, GBP_Extend}, + {0x1E944, 0x1E94A, GBP_Extend}, + {0x1F1E6, 0x1F1FF, GBP_Regional_Indicator}, + {0x1F385, 0x1F385, GBP_E_Base}, + {0x1F3C3, 0x1F3C4, GBP_E_Base}, + {0x1F3CA, 0x1F3CB, GBP_E_Base}, + {0x1F3FB, 0x1F3FF, GBP_E_Modifier}, + {0x1F442, 0x1F443, GBP_E_Base}, + {0x1F446, 0x1F450, GBP_E_Base}, + {0x1F466, 0x1F469, GBP_E_Base_GAZ}, + {0x1F46E, 0x1F46E, GBP_E_Base}, + {0x1F470, 0x1F478, GBP_E_Base}, + {0x1F47C, 0x1F47C, GBP_E_Base}, + {0x1F481, 0x1F483, GBP_E_Base}, + {0x1F485, 0x1F487, GBP_E_Base}, + {0x1F48B, 0x1F48B, GBP_Glue_After_Zwj}, + {0x1F4AA, 0x1F4AA, GBP_E_Base}, + {0x1F575, 0x1F575, GBP_E_Base}, + {0x1F57A, 0x1F57A, GBP_E_Base}, + {0x1F590, 0x1F590, GBP_E_Base}, + {0x1F595, 0x1F596, GBP_E_Base}, + {0x1F5E8, 0x1F5E8, GBP_Glue_After_Zwj}, + {0x1F645, 0x1F647, GBP_E_Base}, + {0x1F64B, 0x1F64F, GBP_E_Base}, + {0x1F6A3, 0x1F6A3, GBP_E_Base}, + {0x1F6B4, 0x1F6B6, GBP_E_Base}, + {0x1F6C0, 0x1F6C0, GBP_E_Base}, + {0x1F918, 0x1F91E, GBP_E_Base}, + {0x1F926, 0x1F926, GBP_E_Base}, + {0x1F930, 0x1F930, GBP_E_Base}, + {0x1F933, 0x1F939, GBP_E_Base}, + {0x1F93C, 0x1F93E, GBP_E_Base}, + {0xE0000, 0xE0000, GBP_Control}, + {0xE0001, 0xE0001, GBP_Control}, + {0xE0002, 0xE001F, GBP_Control}, + {0xE0020, 0xE007F, GBP_Extend}, + {0xE0080, 0xE00FF, GBP_Control}, + {0xE0100, 0xE01EF, GBP_Extend}, + {0xE01F0, 0xE0FFF, GBP_Control}, + {0xFFFFFFFF, 0xFFFFFFFF, GBP_Undefined} +}; diff --git a/src/static_libs/libunibreak/graphemebreakdef.h b/src/static_libs/libunibreak/graphemebreakdef.h new file mode 100644 index 0000000000..0de1f3d623 --- /dev/null +++ b/src/static_libs/libunibreak/graphemebreakdef.h @@ -0,0 +1,82 @@ +/* + * Grapheme breaking in a Unicode sequence. Designed to be used in a + * generic text renderer. + * + * Copyright (C) 2016 Andreas Röver <roever at users dot sf dot net> + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgement in the product + * documentation would be appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source + * distribution. + * + * The main reference is Unicode Standard Annex 29 (UAX #29): + * <URL:http://unicode.org/reports/tr29> + * + * When this library was designed, this annex was at Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> + * + * The Unicode Terms of Use are available at + * <URL:http://www.unicode.org/copyright.html> + */ + +/** + * @file graphemebreakdef.h + * + * Definitions of internal data structures, declarations of global + * variables, and function prototypes for the grapheme breaking algorithm. + * + * @author Andreas Röver + */ + +#include "unibreakdef.h" + +/** + * Word break classes. This is a direct mapping of Table 2 of Unicode + * Standard Annex 29 + */ +enum GraphemeBreakClass +{ + GBP_CR, + GBP_LF, + GBP_Control, + GBP_Extend, + GBP_ZWJ, + GBP_Regional_Indicator, + GBP_Prepend, + GBP_SpacingMark, + GBP_L, + GBP_V, + GBP_T, + GBP_LV, + GBP_LVT, + GBP_E_Base, + GBP_E_Modifier, + GBP_Glue_After_Zwj, + GBP_E_Base_GAZ, + GBP_Other, + GBP_Undefined +}; + +/** + * Struct for entries of grapheme break properties. The array of the + * entries \e must be sorted. + */ +struct GraphemeBreakProperties +{ + utf32_t start; /**< Starting coding point */ + utf32_t end; /**< End coding point, including */ + enum GraphemeBreakClass prop; /**< The grapheme breaking property */ +}; diff --git a/src/static_libs/libunibreak/linebreak.c b/src/static_libs/libunibreak/linebreak.c index 3d87a0413d..41f23c1c08 100644 --- a/src/static_libs/libunibreak/linebreak.c +++ b/src/static_libs/libunibreak/linebreak.c @@ -45,7 +45,6 @@ * Implementation of the line breaking algorithm as described in Unicode * Standard Annex 14. * - * @version 3.2, 2016/12/04 * @author Wu Yongwei * @author Petr Filipsky */ @@ -68,7 +67,7 @@ /** * Enumeration of break actions. They are used in the break action - * pair table below. + * pair table #baTable. */ enum BreakAction { @@ -81,7 +80,7 @@ enum BreakAction /** * Break action pair table. This is a direct mapping of Table 2 of - * Unicode Standard Annex 14, Revision 37. + * Unicode Standard Annex 14, Revision 37, except the "CB" part. */ static enum BreakAction baTable[LBP_CB][LBP_CB] = { { /* OP */ @@ -313,11 +312,12 @@ static struct LineBreakPropertiesIndex lb_prop_index[LINEBREAK_INDEX_SIZE] = static __inline int ends_with(const char *str, const char *suffix, unsigned suffixLen) { + unsigned len; if (str == NULL) { return 0; } - unsigned len = strlen(str); + len = strlen(str); if (len >= suffixLen && memcmp(str + len - suffixLen, suffix, suffixLen) == 0) { @@ -706,6 +706,23 @@ int lb_process_next_char( /** * Sets the line breaking information for a generic input string. * + * Currently, this implementation has customization for the following + * ISO 639-1 language codes (for \a lang): + * + * - de (German) + * - en (English) + * - es (Spanish) + * - fr (French) + * - ja (Japanese) + * - ko (Korean) + * - ru (Russian) + * - zh (Chinese) + * + * In addition, a suffix <code>"-strict"</code> may be added to indicate + * strict (as versus normal) line-breaking behaviour. See the <a + * href="http://www.unicode.org/reports/tr14/#CJ">Conditional Japanese + * Starter section of UAX #14</a> for more details. + * * @param[in] s input string * @param[in] len length of the input * @param[in] lang language of the input @@ -766,6 +783,7 @@ void set_linebreaks( * @param[out] brks pointer to the output breaking data, containing * #LINEBREAK_MUSTBREAK, #LINEBREAK_ALLOWBREAK, * #LINEBREAK_NOBREAK, or #LINEBREAK_INSIDEACHAR + * @see #set_linebreaks for a note about \a lang. */ void set_linebreaks_utf8( const utf8_t *s, @@ -786,6 +804,7 @@ void set_linebreaks_utf8( * @param[out] brks pointer to the output breaking data, containing * #LINEBREAK_MUSTBREAK, #LINEBREAK_ALLOWBREAK, * #LINEBREAK_NOBREAK, or #LINEBREAK_INSIDEACHAR + * @see #set_linebreaks for a note about \a lang. */ void set_linebreaks_utf16( const utf16_t *s, @@ -806,6 +825,7 @@ void set_linebreaks_utf16( * @param[out] brks pointer to the output breaking data, containing * #LINEBREAK_MUSTBREAK, #LINEBREAK_ALLOWBREAK, * #LINEBREAK_NOBREAK, or #LINEBREAK_INSIDEACHAR + * @see #set_linebreaks for a note about \a lang. */ void set_linebreaks_utf32( const utf32_t *s, diff --git a/src/static_libs/libunibreak/linebreak.h b/src/static_libs/libunibreak/linebreak.h index 7753b3d83b..fd7351191b 100644 --- a/src/static_libs/libunibreak/linebreak.h +++ b/src/static_libs/libunibreak/linebreak.h @@ -43,7 +43,6 @@ * * Header file for the line breaking algorithm. * - * @version 3.1, 2016/09/10 * @author Wu Yongwei */ diff --git a/src/static_libs/libunibreak/linebreakdef.c b/src/static_libs/libunibreak/linebreakdef.c index 04c3db3487..6b485cecbd 100644 --- a/src/static_libs/libunibreak/linebreakdef.c +++ b/src/static_libs/libunibreak/linebreakdef.c @@ -43,7 +43,6 @@ * * Definition of language-specific data. * - * @version 3.1, 2016/09/10 * @author Wu Yongwei */ diff --git a/src/static_libs/libunibreak/linebreakdef.h b/src/static_libs/libunibreak/linebreakdef.h index 9432ed3326..37ec7b546e 100644 --- a/src/static_libs/libunibreak/linebreakdef.h +++ b/src/static_libs/libunibreak/linebreakdef.h @@ -45,7 +45,6 @@ * Definitions of internal data structures, declarations of global * variables, and function prototypes for the line breaking algorithm. * - * @version 3.2, 2016/12/03 * @author Wu Yongwei * @author Petr Filipsky */ diff --git a/src/static_libs/libunibreak/unibreakbase.c b/src/static_libs/libunibreak/unibreakbase.c index b0d8f3b729..686852a990 100644 --- a/src/static_libs/libunibreak/unibreakbase.c +++ b/src/static_libs/libunibreak/unibreakbase.c @@ -4,7 +4,7 @@ * Break processing in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2015 Wu Yongwei <wuyongwei at gmail dot com> + * Copyright (C) 2015-2016 Wu Yongwei <wuyongwei at gmail dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -29,7 +29,6 @@ * * Definition of basic libunibreak information. * - * @version 3.0, 2015/05/10 * @author Wu Yongwei */ diff --git a/src/static_libs/libunibreak/unibreakbase.h b/src/static_libs/libunibreak/unibreakbase.h index 08c012737c..ff9a6ce8a9 100644 --- a/src/static_libs/libunibreak/unibreakbase.h +++ b/src/static_libs/libunibreak/unibreakbase.h @@ -4,7 +4,7 @@ * Break processing in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2015 Wu Yongwei <wuyongwei at gmail dot com> + * Copyright (C) 2015-2016 Wu Yongwei <wuyongwei at gmail dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -29,7 +29,6 @@ * * Header file for common definitions in the libunibreak library. * - * @version 3.0, 2015/05/10 * @author Wu Yongwei */ @@ -40,7 +39,7 @@ extern "C" { #endif -#define UNIBREAK_VERSION 0x0300 /**< Version of the library linebreak */ +#define UNIBREAK_VERSION 0x0400 /**< Version of the library linebreak */ extern const int unibreak_version; #ifndef UNIBREAK_UTF_TYPES_DEFINED diff --git a/src/static_libs/libunibreak/unibreakdef.c b/src/static_libs/libunibreak/unibreakdef.c index 20ce2b3484..4d4f2b2863 100644 --- a/src/static_libs/libunibreak/unibreakdef.c +++ b/src/static_libs/libunibreak/unibreakdef.c @@ -4,7 +4,7 @@ * Break processing in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2015 Wu Yongwei <wuyongwei at gmail dot com> + * Copyright (C) 2015-2016 Wu Yongwei <wuyongwei at gmail dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -29,7 +29,6 @@ * * Definition of utility functions used by the libunibreak library. * - * @version 3.0, 2015/05/10 * @author Wu Yongwei */ diff --git a/src/static_libs/libunibreak/unibreakdef.h b/src/static_libs/libunibreak/unibreakdef.h index f5d5744990..e13016d8cd 100644 --- a/src/static_libs/libunibreak/unibreakdef.h +++ b/src/static_libs/libunibreak/unibreakdef.h @@ -4,7 +4,7 @@ * Break processing in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2015 Wu Yongwei <wuyongwei at gmail dot com> + * Copyright (C) 2015-2016 Wu Yongwei <wuyongwei at gmail dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -29,7 +29,6 @@ * * Header file for private definitions in the libunibreak library. * - * @version 3.0, 2015/05/10 * @author Wu Yongwei */ diff --git a/src/static_libs/libunibreak/wordbreak.c b/src/static_libs/libunibreak/wordbreak.c index d90d77b799..aece4b3c45 100644 --- a/src/static_libs/libunibreak/wordbreak.c +++ b/src/static_libs/libunibreak/wordbreak.c @@ -4,7 +4,7 @@ * Word breaking in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2013-2015 Tom Hacohen <tom at stosb dot com> + * Copyright (C) 2013-2016 Tom Hacohen <tom at stosb dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -30,9 +30,9 @@ * Unicode 6.0.0: * <URL:http://www.unicode.org/reports/tr29/tr29-17.html> * - * This library has been updated according to Revision 27, for - * Unicode 8.0.0: - * <URL:http://www.unicode.org/reports/tr29/tr29-27.html> + * This library has been updated according to Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> * * The Unicode Terms of Use are available at * <URL:http://www.unicode.org/copyright.html> @@ -44,7 +44,6 @@ * Implementation of the word breaking algorithm as described in Unicode * Standard Annex 29. * - * @version 3.1, 2015/05/18 * @author Tom Hacohen */ @@ -149,7 +148,7 @@ static void set_brks_to( * * @param[in] s input string * @param[in] len length of the input - * @param[in] lang language of the input + * @param[in] lang language of the input (reserved for future use) * @param[out] brks pointer to the output breaking data, containing * #WORDBREAK_BREAK, #WORDBREAK_NOBREAK, or * #WORDBREAK_INSIDEACHAR @@ -210,13 +209,7 @@ static void set_wordbreaks( posLast = posCur; break; } -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif -#if __has_attribute(fallthrough) - __attribute__((fallthrough)); -#endif - /* Fall off */ + /* Fall off */ case WBP_Newline: /* WB3a,3b */ @@ -329,13 +322,7 @@ static void set_wordbreaks( wbcSeqStart = wbcCur; posLast = posCur; } -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif -#if __has_attribute(fallthrough) - __attribute__((fallthrough)); -#endif - /* No break on purpose */ + /* No break on purpose */ case WBP_MidNumLet: if (((wbcLast == WBP_ALetter) || (wbcLast == WBP_Hebrew_Letter)) || /* WB6,7 */ @@ -511,7 +498,7 @@ static void set_wordbreaks( * * @param[in] s input UTF-8 string * @param[in] len length of the input - * @param[in] lang language of the input + * @param[in] lang language of the input (reserved for future use) * @param[out] brks pointer to the output breaking data, containing * #WORDBREAK_BREAK, #WORDBREAK_NOBREAK, or * #WORDBREAK_INSIDEACHAR @@ -531,7 +518,7 @@ void set_wordbreaks_utf8( * * @param[in] s input UTF-16 string * @param[in] len length of the input - * @param[in] lang language of the input + * @param[in] lang language of the input (reserved for future use) * @param[out] brks pointer to the output breaking data, containing * #WORDBREAK_BREAK, #WORDBREAK_NOBREAK, or * #WORDBREAK_INSIDEACHAR @@ -551,7 +538,7 @@ void set_wordbreaks_utf16( * * @param[in] s input UTF-32 string * @param[in] len length of the input - * @param[in] lang language of the input + * @param[in] lang language of the input (reserved for future use) * @param[out] brks pointer to the output breaking data, containing * #WORDBREAK_BREAK, #WORDBREAK_NOBREAK, or * #WORDBREAK_INSIDEACHAR diff --git a/src/static_libs/libunibreak/wordbreak.h b/src/static_libs/libunibreak/wordbreak.h index b9124d7b52..1040c13280 100644 --- a/src/static_libs/libunibreak/wordbreak.h +++ b/src/static_libs/libunibreak/wordbreak.h @@ -4,7 +4,7 @@ * Word breaking in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2013-2015 Tom Hacohen <tom at stosb dot com> + * Copyright (C) 2013-2016 Tom Hacohen <tom at stosb dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -30,9 +30,9 @@ * Unicode 6.0.0: * <URL:http://www.unicode.org/reports/tr29/tr29-17.html> * - * This library has been updated according to Revision 25, for - * Unicode 7.0.0: - * <URL:http://www.unicode.org/reports/tr29/tr29-25.html> + * This library has been updated according to Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> * * The Unicode Terms of Use are available at * <URL:http://www.unicode.org/copyright.html> @@ -43,7 +43,6 @@ * * Header file for the word breaking (segmentation) algorithm. * - * @version 3.0, 2015/05/10 * @author Tom Hacohen */ diff --git a/src/static_libs/libunibreak/wordbreakdef.h b/src/static_libs/libunibreak/wordbreakdef.h index b00aff33e9..82cd98e7c3 100644 --- a/src/static_libs/libunibreak/wordbreakdef.h +++ b/src/static_libs/libunibreak/wordbreakdef.h @@ -4,7 +4,7 @@ * Word breaking in a Unicode sequence. Designed to be used in a * generic text renderer. * - * Copyright (C) 2013-15 Tom Hacohen <tom at stosb dot com> + * Copyright (C) 2013-16 Tom Hacohen <tom at stosb dot com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages @@ -30,9 +30,9 @@ * Unicode 6.0.0: * <URL:http://www.unicode.org/reports/tr29/tr29-17.html> * - * This library has been updated according to Revision 25, for - * Unicode 7.0.0: - * <URL:http://www.unicode.org/reports/tr29/tr29-25.html> + * This library has been updated according to Revision 29, for + * Unicode 9.0.0: + * <URL:http://www.unicode.org/reports/tr29/tr29-29.html> * * The Unicode Terms of Use are available at * <URL:http://www.unicode.org/copyright.html> @@ -44,7 +44,6 @@ * Definitions of internal data structures, declarations of global * variables, and function prototypes for the word breaking algorithm. * - * @version 3.0, 2015/05/10 * @author Tom Hacohen */ diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c index 1f6cb139b2..49f7577374 100644 --- a/src/tests/evas/evas_test_textblock.c +++ b/src/tests/evas/evas_test_textblock.c @@ -105,8 +105,9 @@ while (0) EFL_START_TEST(evas_textblock_cursor) { START_TB_TEST(); + Evas_Textblock_Cursor *cur2; Evas_Coord x, y, w, h; - size_t i, len; + size_t i, j, len; Evas_Coord nw, nh; Evas_BiDi_Direction dir; const char *buf = "This is a<br/> test.<ps/>Lets see if this works.<ps/>עוד פסקה."; @@ -973,6 +974,27 @@ EFL_START_TEST(evas_textblock_cursor) } evas_textblock_cursor_free(cur2); } + + /* Testing for grapheme cluster */ + cur2 = evas_object_textblock_cursor_new(tb); + evas_object_textblock_text_markup_set(tb, "ഹലോ"); + evas_textblock_cursor_pos_set(cur, 0); + evas_textblock_cursor_pos_set(cur2, 0); + + i = j = 0; + while (evas_textblock_cursor_cluster_next(cur)) i++; + ck_assert_int_eq(i, 2); + + while (evas_textblock_cursor_char_next(cur2)) j++; + ck_assert_int_eq(j, 4); + + i = j = 0; + while (evas_textblock_cursor_cluster_prev(cur)) i++; + ck_assert_int_eq(i, 2); + + while (evas_textblock_cursor_char_prev(cur2)) j++; + ck_assert_int_eq(j, 4); + END_TB_TEST(); } EFL_END_TEST |