From 69d0646b33f932194a59f1f3499c45591b92be96 Mon Sep 17 00:00:00 2001 From: Daniel Hirt Date: Mon, 25 Sep 2017 19:21:21 +0300 Subject: [PATCH] Efl text: add Efl.Text.Markup interface Adds basic markup operations for text objects, and implements it in Efl.Canvas.Text. Also, this adds the Efl.Text.Markup_Util class. This utility class allows basic text-markup conversions. @feature --- src/Makefile_Efl.am | 3 + src/lib/efl/Efl.h | 2 + src/lib/efl/interfaces/efl_interfaces_main.c | 1 + src/lib/efl/interfaces/efl_text_markup.eo | 21 + src/lib/efl/interfaces/efl_text_markup_util.c | 500 ++++++++++++++++++ .../efl/interfaces/efl_text_markup_util.eo | 30 ++ src/lib/evas/canvas/efl_canvas_text.eo | 7 +- src/lib/evas/canvas/evas_object_textblock.c | 59 ++- 8 files changed, 613 insertions(+), 10 deletions(-) create mode 100644 src/lib/efl/interfaces/efl_text_markup.eo create mode 100644 src/lib/efl/interfaces/efl_text_markup_util.c create mode 100644 src/lib/efl/interfaces/efl_text_markup_util.eo diff --git a/src/Makefile_Efl.am b/src/Makefile_Efl.am index 25dde93a7c..83e861fb88 100644 --- a/src/Makefile_Efl.am +++ b/src/Makefile_Efl.am @@ -26,6 +26,8 @@ efl_eolian_files = \ lib/efl/interfaces/efl_text_format.eo \ lib/efl/interfaces/efl_text_cursor.eo \ lib/efl/interfaces/efl_text_annotate.eo \ + lib/efl/interfaces/efl_text_markup.eo \ + lib/efl/interfaces/efl_text_markup_util.eo \ lib/efl/interfaces/efl_text_properties.eo \ lib/efl/interfaces/efl_gfx_stack.eo \ lib/efl/interfaces/efl_gfx_view.eo \ @@ -125,6 +127,7 @@ lib/efl/interfaces/efl_io_writer.c \ lib/efl/interfaces/efl_io_buffer.c \ lib/efl/interfaces/efl_io_queue.c \ lib/efl/interfaces/efl_observer.c \ +lib/efl/interfaces/efl_text_markup_util.c \ $(NULL) lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl -I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@ -DEFL_GFX_FILTER_BETA diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index 82a1e3d460..1b5a9bcfe7 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -163,6 +163,8 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command; #include "interfaces/efl_text_format.eo.h" #include "interfaces/efl_text_cursor.eo.h" #include "interfaces/efl_text_annotate.eo.h" +#include "interfaces/efl_text_markup.eo.h" +#include "interfaces/efl_text_markup_util.eo.h" #else diff --git a/src/lib/efl/interfaces/efl_interfaces_main.c b/src/lib/efl/interfaces/efl_interfaces_main.c index ded13b6ece..fc80036fb4 100644 --- a/src/lib/efl/interfaces/efl_interfaces_main.c +++ b/src/lib/efl/interfaces/efl_interfaces_main.c @@ -19,6 +19,7 @@ #include "interfaces/efl_text_format.eo.c" #include "interfaces/efl_text_cursor.eo.c" #include "interfaces/efl_text_annotate.eo.c" +#include "interfaces/efl_text_markup.eo.c" #include "interfaces/efl_gfx.eo.c" #include "interfaces/efl_gfx_buffer.eo.c" diff --git a/src/lib/efl/interfaces/efl_text_markup.eo b/src/lib/efl/interfaces/efl_text_markup.eo new file mode 100644 index 0000000000..99ea34b4ba --- /dev/null +++ b/src/lib/efl/interfaces/efl_text_markup.eo @@ -0,0 +1,21 @@ +interface Efl.Text.Markup(Efl.Text.Cursor) { + [[Markup data that populates the text object's style and format + + @since 1.21 + ]] + methods { + @property markup { + values { + markup: string; [[The markup-text representation set to this text.]] + } + } + cursor_markup_insert { + [[Inserts a markup text to the text object in a given cursor position]] + params { + cur: ptr(Efl.Text.Cursor.Cursor); [[Cursor position to insert markup]] + @in markup: string; [[The markup text to insert]] + } + } + } +} + diff --git a/src/lib/efl/interfaces/efl_text_markup_util.c b/src/lib/efl/interfaces/efl_text_markup_util.c new file mode 100644 index 0000000000..9c8a9cf55d --- /dev/null +++ b/src/lib/efl/interfaces/efl_text_markup_util.c @@ -0,0 +1,500 @@ +#include "config.h" +#include "Efl.h" + +#define MY_CLASS EFL_TEXT_MARKUP_UTIL_CLASS + +#define ERR(...) EINA_LOG_DOM_ERR(EINA_LOG_DOMAIN_DEFAULT, __VA_ARGS__) + +#define _REPLACEMENT_CHAR 0xFFFC +#define _PARAGRAPH_SEPARATOR 0x2029 +#define _NEWLINE '\n' +#define _TAB '\t' + +#define _REPLACEMENT_CHAR_UTF8 "\xEF\xBF\xBC" +#define _PARAGRAPH_SEPARATOR_UTF8 "\xE2\x80\xA9" +#define _NEWLINE_UTF8 "\n" +#define _TAB_UTF8 "\t" +#define EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(ch) \ + (((ch) == _REPLACEMENT_CHAR) || \ + ((ch) == _NEWLINE) || \ + ((ch) == _TAB) || \ + ((ch) == _PARAGRAPH_SEPARATOR)) + +#define _IS_TAB(item) \ + (!strcmp(item, "tab") || !strcmp(item, "\t") || !strcmp(item, "\\t")) + +#define _IS_LINE_SEPARATOR(item) \ + (!strcmp(item, "br") || !strcmp(item, "\n") || !strcmp(item, "\\n")) + +#define _IS_PARAGRAPH_SEPARATOR_SIMPLE(item) \ + (!strcmp(item, "ps")) + +#define _IS_PARAGRAPH_SEPARATOR(o, item) \ + (_IS_PARAGRAPH_SEPARATOR_SIMPLE(item) || \ + (o->legacy_newline && _IS_LINE_SEPARATOR(item))) /* Paragraph separator */ + +static void +_markup_get_text_utf8_append(Eina_Strbuf *sbuf, const char *text) +{ + int ch, pos = 0, pos2 = 0; + + for (;;) + { + pos = pos2; + ch = eina_unicode_utf8_next_get(text, &pos2); + if ((ch <= 0) || (pos2 <= 0)) break; + + if (ch == _NEWLINE) + eina_strbuf_append(sbuf, "
"); + else if (ch == _TAB) + eina_strbuf_append(sbuf, ""); + else if (ch == '<') + eina_strbuf_append(sbuf, "<"); + else if (ch == '>') + eina_strbuf_append(sbuf, ">"); + else if (ch == '&') + eina_strbuf_append(sbuf, "&"); + else if (ch == '"') + eina_strbuf_append(sbuf, """); + else if (ch == _PARAGRAPH_SEPARATOR) + eina_strbuf_append(sbuf, ""); + else if (ch == _REPLACEMENT_CHAR) + eina_strbuf_append(sbuf, ""); + else if (ch != '\r') + { + eina_strbuf_append_length(sbuf, text + pos, pos2 - pos); + } + } +} + +EOLIAN static char* +_efl_text_markup_util_text_to_markup(Eo *class EINA_UNUSED, + void *_pd EINA_UNUSED, const char *text) +{ + Eina_Strbuf *sbuf; + char *str = NULL; + + if (!text) return NULL; + + sbuf = eina_strbuf_new(); + + _markup_get_text_utf8_append(sbuf, text); + + str = eina_strbuf_string_steal(sbuf); + eina_strbuf_free(sbuf); + return str; +} + +/* table of html escapes (that i can find) this should be ordered with the + * most common first as it's a linear search to match - no hash for this. + * + * these are stored as one large string and one additional array that + * contains the offsets to the tokens for space efficiency. + */ +/** + * @internal + * @var escape_strings[] + * This string consists of NULL terminated pairs of strings, the first of + * every pair is an escape and the second is the value of the escape. + */ +static const char escape_strings[] = +/* most common escaped stuff */ +""\0" "\x22\0" +"&\0" "\x26\0" +"'\0" "\x27\0" +"<\0" "\x3c\0" +">\0" "\x3e\0" +/* all the rest */ +" \0" "\xc2\xa0\0" +"¡\0" "\xc2\xa1\0" +"¢\0" "\xc2\xa2\0" +"£\0" "\xc2\xa3\0" +"¤\0" "\xc2\xa4\0" +"¥\0" "\xc2\xa5\0" +"¦\0" "\xc2\xa6\0" +"§\0" "\xc2\xa7\0" +"¨\0" "\xc2\xa8\0" +"©\0" "\xc2\xa9\0" +"ª\0" "\xc2\xaa\0" +"«\0" "\xc2\xab\0" +"¬\0" "\xc2\xac\0" +"­\0" "\xc2\xad\0" +"®\0" "\xc2\xae\0" +"¯\0" "\xc2\xaf\0" +"°\0" "\xc2\xb0\0" +"±\0" "\xc2\xb1\0" +"²\0" "\xc2\xb2\0" +"³\0" "\xc2\xb3\0" +"´\0" "\xc2\xb4\0" +"µ\0" "\xc2\xb5\0" +"¶\0" "\xc2\xb6\0" +"·\0" "\xc2\xb7\0" +"¸\0" "\xc2\xb8\0" +"¹\0" "\xc2\xb9\0" +"º\0" "\xc2\xba\0" +"»\0" "\xc2\xbb\0" +"¼\0" "\xc2\xbc\0" +"½\0" "\xc2\xbd\0" +"¾\0" "\xc2\xbe\0" +"¿\0" "\xc2\xbf\0" +"À\0" "\xc3\x80\0" +"Á\0" "\xc3\x81\0" +"Â\0" "\xc3\x82\0" +"Ã\0" "\xc3\x83\0" +"Ä\0" "\xc3\x84\0" +"Å\0" "\xc3\x85\0" +"&Aelig;\0" "\xc3\x86\0" +"Ç\0" "\xc3\x87\0" +"È\0" "\xc3\x88\0" +"É\0" "\xc3\x89\0" +"Ê\0" "\xc3\x8a\0" +"Ë\0" "\xc3\x8b\0" +"Ì\0" "\xc3\x8c\0" +"Í\0" "\xc3\x8d\0" +"Î\0" "\xc3\x8e\0" +"Ï\0" "\xc3\x8f\0" +"&Eth;\0" "\xc3\x90\0" +"Ñ\0" "\xc3\x91\0" +"Ò\0" "\xc3\x92\0" +"Ó\0" "\xc3\x93\0" +"Ô\0" "\xc3\x94\0" +"Õ\0" "\xc3\x95\0" +"Ö\0" "\xc3\x96\0" +"×\0" "\xc3\x97\0" +"Ø\0" "\xc3\x98\0" +"Ù\0" "\xc3\x99\0" +"Ú\0" "\xc3\x9a\0" +"Û\0" "\xc3\x9b\0" +"Ý\0" "\xc3\x9d\0" +"&Thorn;\0" "\xc3\x9e\0" +"ß\0" "\xc3\x9f\0" +"à\0" "\xc3\xa0\0" +"á\0" "\xc3\xa1\0" +"â\0" "\xc3\xa2\0" +"ã\0" "\xc3\xa3\0" +"ä\0" "\xc3\xa4\0" +"å\0" "\xc3\xa5\0" +"æ\0" "\xc3\xa6\0" +"ç\0" "\xc3\xa7\0" +"è\0" "\xc3\xa8\0" +"é\0" "\xc3\xa9\0" +"ê\0" "\xc3\xaa\0" +"ë\0" "\xc3\xab\0" +"ì\0" "\xc3\xac\0" +"í\0" "\xc3\xad\0" +"î\0" "\xc3\xae\0" +"ï\0" "\xc3\xaf\0" +"ð\0" "\xc3\xb0\0" +"ñ\0" "\xc3\xb1\0" +"ò\0" "\xc3\xb2\0" +"ó\0" "\xc3\xb3\0" +"ô\0" "\xc3\xb4\0" +"õ\0" "\xc3\xb5\0" +"ö\0" "\xc3\xb6\0" +"÷\0" "\xc3\xb7\0" +"ø\0" "\xc3\xb8\0" +"ù\0" "\xc3\xb9\0" +"ú\0" "\xc3\xba\0" +"û\0" "\xc3\xbb\0" +"ü\0" "\xc3\xbc\0" +"ý\0" "\xc3\xbd\0" +"þ\0" "\xc3\xbe\0" +"ÿ\0" "\xc3\xbf\0" +"α\0" "\xce\x91\0" +"β\0" "\xce\x92\0" +"γ\0" "\xce\x93\0" +"δ\0" "\xce\x94\0" +"ε\0" "\xce\x95\0" +"ζ\0" "\xce\x96\0" +"η\0" "\xce\x97\0" +"θ\0" "\xce\x98\0" +"ι\0" "\xce\x99\0" +"κ\0" "\xce\x9a\0" +"λ\0" "\xce\x9b\0" +"μ\0" "\xce\x9c\0" +"ν\0" "\xce\x9d\0" +"ξ\0" "\xce\x9e\0" +"ο\0" "\xce\x9f\0" +"π\0" "\xce\xa0\0" +"ρ\0" "\xce\xa1\0" +"σ\0" "\xce\xa3\0" +"τ\0" "\xce\xa4\0" +"υ\0" "\xce\xa5\0" +"φ\0" "\xce\xa6\0" +"χ\0" "\xce\xa7\0" +"ψ\0" "\xce\xa8\0" +"ω\0" "\xce\xa9\0" +"…\0" "\xe2\x80\xa6\0" +"€\0" "\xe2\x82\xac\0" +"←\0" "\xe2\x86\x90\0" +"↑\0" "\xe2\x86\x91\0" +"→\0" "\xe2\x86\x92\0" +"↓\0" "\xe2\x86\x93\0" +"↔\0" "\xe2\x86\x94\0" +"←\0" "\xe2\x87\x90\0" +"→\0" "\xe2\x87\x92\0" +"∀\0" "\xe2\x88\x80\0" +"∃\0" "\xe2\x88\x83\0" +"∇\0" "\xe2\x88\x87\0" +"∏\0" "\xe2\x88\x8f\0" +"∑\0" "\xe2\x88\x91\0" +"∧\0" "\xe2\x88\xa7\0" +"∨\0" "\xe2\x88\xa8\0" +"∫\0" "\xe2\x88\xab\0" +"≠\0" "\xe2\x89\xa0\0" +"≡\0" "\xe2\x89\xa1\0" +"⊕\0" "\xe2\x8a\x95\0" +"⊥\0" "\xe2\x8a\xa5\0" +"†\0" "\xe2\x80\xa0\0" +"‡\0" "\xe2\x80\xa1\0" +"•\0" "\xe2\x80\xa2\0" +"‌\0" "\xe2\x80\x8c\0" +"‍\0" "\xe2\x80\x8d\0" +"‎\0" "\xe2\x80\x8e\0" +"‏\0" "\xe2\x80\x8f\0" +; + +static inline void +_escaped_advance_after_end_of_string(const char **p_buf) +{ + while (**p_buf != 0) (*p_buf)++; + (*p_buf)++; +} + +static inline int +_escaped_is_eq_and_advance(const char *s, const char *s_end, + const char **p_m, const char *m_end) +{ + Eina_Bool reached_end; + for (;((s < s_end) && (*p_m < m_end)); s++, (*p_m)++) + { + if (*s != **p_m) + { + _escaped_advance_after_end_of_string(p_m); + return 0; + } + } + + reached_end = !**p_m; + if (*p_m < m_end) + _escaped_advance_after_end_of_string(p_m); + + return ((s == s_end) && reached_end); +} + +static inline const char * +_escaped_char_get(const char *s, const char *s_end) +{ + /* Handle numeric escape codes. */ + if (s[1] == '#') + { + static char utf8_escape[7]; /* Support up to 6 bytes utf8 */ + char ustr[10]; + Eina_Unicode uchar[2] = { 0, 0 }; + char *utf8_char; + size_t len = 0; + int base = 10; + s += 2; /* Skip "&#" */ + + if ((*s == 'x') && (*s == 'X')) + { + s++; + base = 16; + } + + len = s_end - s; + if (len > sizeof(ustr)) + len = sizeof(ustr); + + memcpy(ustr, s, len); + ustr[len - 1] = '\0'; + uchar[0] = strtol(ustr, NULL, base); + + if (uchar[0] == 0) + return NULL; + + utf8_char = eina_unicode_unicode_to_utf8(uchar, NULL); + // eina_unicode_unicode_to_utf8() always creates a string that + // is nul terminated - guaranteed + if (utf8_char) + { + strcpy(utf8_escape, utf8_char); + free(utf8_char); + } + + return utf8_escape; + } + else + { + const char *map_itr, *map_end; + + map_itr = escape_strings; + map_end = map_itr + sizeof(escape_strings); + + while (map_itr < map_end) + { + if (_escaped_is_eq_and_advance(s, s_end, &map_itr, map_end)) + return map_itr; + if (map_itr < map_end) + _escaped_advance_after_end_of_string(&map_itr); + } + } + + return NULL; +} + +static char * +_text_util_markup_to_text(const char *text) +{ + Eina_Strbuf *sbuf; + char *s, *p, *ret; + char *tag_start, *tag_end, *esc_start, *esc_end; + + if (!text) return NULL; + + tag_start = tag_end = esc_start = esc_end = NULL; + sbuf = eina_strbuf_new(); + p = (char *)text; + s = p; + /* This loop goes through all of the mark up text until it finds format + * tags, escape sequences or the terminating NULL. When it finds either + * of those, it appends the text found up until that point to the textblock + * proccesses whatever found. It repeats itself until the termainating + * NULL is reached. */ + for (;;) + { + /* If we got to the end of string or just finished/started tag + * or escape sequence handling. */ + if ((*p == 0) || + (tag_end) || (esc_end) || + (tag_start) || (esc_start)) + { + if (tag_end) + { + /* If we reached to a tag ending, analyze the tag */ + char *ttag; + size_t ttag_len; + + tag_start++; /* Skip the < */ + tag_end--; /* Skip the > */ + if ((tag_end > tag_start) && (*(tag_end - 1) == '/')) + { + tag_end --; /* Skip the terminating '/' */ + while (*(tag_end - 1) == ' ') + tag_end--; /* skip trailing ' ' */ + } + + ttag_len = tag_end - tag_start; + + ttag = malloc(ttag_len + 1); + if (ttag) + { + memcpy(ttag, tag_start, ttag_len); + ttag[ttag_len] = 0; + + if (_IS_PARAGRAPH_SEPARATOR_SIMPLE(ttag)) + eina_strbuf_append(sbuf, _PARAGRAPH_SEPARATOR_UTF8); + else if (_IS_LINE_SEPARATOR(ttag)) + eina_strbuf_append(sbuf, _NEWLINE_UTF8); + else if (_IS_TAB(ttag)) + eina_strbuf_append(sbuf, _TAB_UTF8); + else if (!strncmp(ttag, "item", 4)) + eina_strbuf_append(sbuf, _REPLACEMENT_CHAR_UTF8); + + free(ttag); + } + tag_start = tag_end = NULL; + } + else if (esc_end) + { + const char *escape; + + escape = _escaped_char_get(esc_start, esc_end + 1); + if (escape) eina_strbuf_append(sbuf, escape); + esc_start = esc_end = NULL; + } + else if (*p == 0) + { + if (s) + { + eina_strbuf_append_length(sbuf, s, p - s); + s = NULL; + } + else + { + ERR("There is a invalid markup tag at positoin '%u'. Please check the text.", (unsigned int) (p - text)); + } + } + if (*p == 0) + break; + } + if (*p == '<') + { + if (!esc_start) + { + /* Append the text prior to this to the textblock and + * mark the start of the tag */ + tag_start = p; + tag_end = NULL; + if (s) + { + eina_strbuf_append_length(sbuf, s, p - s); + s = NULL; + } + else + { + ERR("There is a invalid markup tag at positoin '%u'. Please check the text.", (unsigned int) (p - text)); + } + } + } + else if (*p == '>') + { + if (tag_start) + { + tag_end = p + 1; + s = p + 1; + } + } + else if (*p == '&') + { + if (!tag_start) + { + /* Append the text prior to this to the textblock and mark + * the start of the escape sequence */ + esc_start = p; + esc_end = NULL; + if (s) + { + eina_strbuf_append_length(sbuf, s, p - s); + s = NULL; + } + else + { + ERR("There is a invalid markup tag at positoin '%u'. Please check the text.", (unsigned int) (p - text)); + } + } + } + else if (*p == ';') + { + if (esc_start) + { + esc_end = p; + s = p + 1; + } + } + p++; + } + + ret = eina_strbuf_string_steal(sbuf); + eina_strbuf_free(sbuf); + return ret; +} + +static EOLIAN char* +_efl_text_markup_util_markup_to_text(Eo *class EINA_UNUSED, + void *_pd EINA_UNUSED, const char *text) +{ + return _text_util_markup_to_text(text); +} + +#include "interfaces/efl_text_markup_util.eo.c" diff --git a/src/lib/efl/interfaces/efl_text_markup_util.eo b/src/lib/efl/interfaces/efl_text_markup_util.eo new file mode 100644 index 0000000000..304b2cacf9 --- /dev/null +++ b/src/lib/efl/interfaces/efl_text_markup_util.eo @@ -0,0 +1,30 @@ +class Efl.Text.Markup_Util () { + [[Utility class for markup, such as conversions + + @since 1.21. + ]] + data: null; + methods { + text_to_markup @class { + [[Converts a given (UTF-8) text to a markup-compatible string. + This is used mainly to set a plain text with the $.markup_set + property. + ]] + params { + @in text: string; [[The text (UTF-8) to convert to markup]] + } + return: mstring @owned; [[The markup representation of given text]] + } + markup_to_text @class { + [[Converts a given (UTF-8) text to a markup-compatible string. + This is used mainly to set a plain text with the $.markup_set + property. + ]] + params { + @in text: string; [[The markup-text to convert to text (UTF-8)]] + } + return: mstring @owned; [[The text representation of given format]] + } + } +} + diff --git a/src/lib/evas/canvas/efl_canvas_text.eo b/src/lib/evas/canvas/efl_canvas_text.eo index 22b8e9dd0d..00a05653df 100644 --- a/src/lib/evas/canvas/efl_canvas_text.eo +++ b/src/lib/evas/canvas/efl_canvas_text.eo @@ -2,8 +2,9 @@ import efl_text_types; struct Efl.Canvas.Text.Style; [[EFL text style data structure]] -class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text.Properties, Efl.Canvas.Filter.Internal, -Efl.Text.Font, Efl.Text.Style, Efl.Text.Format, Efl.Text.Cursor, Efl.Text.Annotate) +class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text.Properties, +Efl.Canvas.Filter.Internal, Efl.Text.Font, Efl.Text.Style, Efl.Text.Format, +Efl.Text.Cursor, Efl.Text.Annotate, Efl.Text.Markup) { [[Efl canvas text class]] legacy_prefix: evas_object_textblock; @@ -346,6 +347,8 @@ Efl.Text.Font, Efl.Text.Style, Efl.Text.Format, Efl.Text.Cursor, Efl.Text.Annota Efl.Text.Annotate.annotation_positions_get; Efl.Text.Annotate.cursor_object_item_annotation { get; } Efl.Text.Annotate.cursor_object_item_insert; + Efl.Text.Markup.markup { set; get; } + Efl.Text.Markup.cursor_markup_insert; } events { cursor,changed; [[Called when cursor changed]] diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index eabc0b18bc..f4e63c897c 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -7454,12 +7454,12 @@ _prepend_escaped_char(Efl_Text_Cursor_Cursor *cur_obj, const char *s, } -EAPI void -evas_object_textblock_text_markup_set(Eo *eo_obj, const char *text) +static void +_evas_object_textblock_text_markup_set(Eo *eo_obj, Efl_Canvas_Text_Data *o, + const char *text) { Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); evas_object_async_block(obj); - Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); if (text == o->markup_text) { /* Text is the same and already stringshared, do nothing */ @@ -7507,10 +7507,26 @@ evas_object_textblock_text_markup_set(Eo *eo_obj, const char *text) } EAPI void -evas_object_textblock_text_markup_prepend(Efl_Text_Cursor_Cursor *cur, const char *text) +evas_object_textblock_text_markup_set(Eo *eo_obj, const char *text) +{ + Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); + _evas_object_textblock_text_markup_set(eo_obj, o, text); +} + +EOLIAN void +_efl_canvas_text_efl_text_markup_markup_set(Eo *eo_obj, Efl_Canvas_Text_Data *o, + const char *text) +{ + ASYNC_BLOCK; + _evas_object_textblock_text_markup_set(eo_obj, o, text); + //efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL); +} + +static void +_evas_object_textblock_text_markup_prepend(Eo *eo_obj, + Efl_Text_Cursor_Cursor *cur, const char *text) { if (!cur) return; - Evas_Object *eo_obj = cur->obj; Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); evas_object_async_block(obj); TB_HEAD(); @@ -7631,6 +7647,21 @@ evas_object_textblock_text_markup_prepend(Efl_Text_Cursor_Cursor *cur, const cha _evas_textblock_changed(o, eo_obj); } +EAPI void +evas_object_textblock_text_markup_prepend(Efl_Text_Cursor_Cursor *cur, const char *text) +{ + _evas_object_textblock_text_markup_prepend(cur->obj, cur, text); +} + +EOLIAN static void +_efl_canvas_text_efl_text_markup_cursor_markup_insert(Eo *eo_obj, + Efl_Canvas_Text_Data *o EINA_UNUSED, + Efl_Text_Cursor_Cursor *cur, const char *markup) +{ + ASYNC_BLOCK; + _evas_object_textblock_text_markup_prepend(eo_obj, cur, markup); + //efl_event_callback_call(eo_obj, EFL_CANVAS_TEXT_EVENT_CHANGED, NULL); +} /** * @internal @@ -7711,15 +7742,14 @@ _markup_get_text_append(Eina_Strbuf *txt, const Eina_Unicode *text) free(base); } -EAPI const char* -evas_object_textblock_text_markup_get(Eo *eo_obj) +static const char* +_evas_object_textblock_text_markup_get(Eo *eo_obj, Efl_Canvas_Text_Data *o) { Evas_Object_Textblock_Node_Text *n; Eina_Strbuf *txt = NULL; Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); evas_object_async_block(obj); - Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); const char *markup; if (o->markup_text) { @@ -7781,6 +7811,19 @@ evas_object_textblock_text_markup_get(Eo *eo_obj) return markup; } +EAPI const char* +evas_object_textblock_text_markup_get(Eo *eo_obj) +{ + Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS); + return _evas_object_textblock_text_markup_get(eo_obj, o); +} + +EOLIAN const char* +_efl_canvas_text_efl_text_markup_markup_get(Eo *eo_obj, Efl_Canvas_Text_Data *o) +{ + return _evas_object_textblock_text_markup_get(eo_obj, o); +} + EAPI char * evas_textblock_text_markup_to_utf8(const Evas_Object *eo_obj, const char *text) {