forked from enlightenment/efl
Evas textblock: Improved the implementation of *_text_markup_to_utf8.
Also support passing NULL instead of a real textblock object. Added appropriate tests + improved previous tests. SVN revision: 66254
This commit is contained in:
parent
633a51f3d0
commit
0e0a275762
|
@ -8151,12 +8151,12 @@ EAPI const char *evas_textblock_escape_string_range_get(const c
|
||||||
* version of the text. i.e: <br> and <\n> will be replaced with \n, &...; with
|
* version of the text. i.e: <br> and <\n> will be replaced with \n, &...; with
|
||||||
* the actual char and etc.
|
* the actual char and etc.
|
||||||
*
|
*
|
||||||
* @param obj the textblock object to work with.
|
* @param obj the textblock object to work with. (if NULL, tries the default)
|
||||||
* @param text the markup text (if NULL, return NULL)
|
* @param text the markup text (if NULL, return NULL)
|
||||||
* @return an allocated plain text version of the markup
|
* @return an allocated plain text version of the markup
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
EAPI char *evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text) EINA_WARN_UNUSED_RESULT EINA_MALLOC EINA_ARG_NONNULL(1);
|
EAPI char *evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text) EINA_WARN_UNUSED_RESULT EINA_MALLOC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the markup version of the plain text.
|
* Return the markup version of the plain text.
|
||||||
|
|
|
@ -585,7 +585,7 @@ _style_clear(Evas_Textblock_Style *ts)
|
||||||
* @return The replacement string found.
|
* @return The replacement string found.
|
||||||
*/
|
*/
|
||||||
static inline const char *
|
static inline const char *
|
||||||
_style_match_tag(Evas_Textblock_Style *ts, const char *s, size_t tag_len, size_t *replace_len)
|
_style_match_tag(const Evas_Textblock_Style *ts, const char *s, size_t tag_len, size_t *replace_len)
|
||||||
{
|
{
|
||||||
Evas_Object_Style_Tag *tag;
|
Evas_Object_Style_Tag *tag;
|
||||||
|
|
||||||
|
@ -3043,8 +3043,16 @@ _format_finalize(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
|
||||||
* Returns true if the item is a paragraph separator, false otherwise
|
* Returns true if the item is a paragraph separator, false otherwise
|
||||||
* @def _IS_PARAGRAPH_SEPARATOR(item)
|
* @def _IS_PARAGRAPH_SEPARATOR(item)
|
||||||
*/
|
*/
|
||||||
|
#define _IS_PARAGRAPH_SEPARATOR_SIMPLE(item) \
|
||||||
|
(!strcmp(item, "ps"))
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* Returns true if the item is a paragraph separator, false otherwise
|
||||||
|
* takes legacy mode into account.
|
||||||
|
* @def _IS_PARAGRAPH_SEPARATOR(item)
|
||||||
|
*/
|
||||||
#define _IS_PARAGRAPH_SEPARATOR(o, item) \
|
#define _IS_PARAGRAPH_SEPARATOR(o, item) \
|
||||||
(!strcmp(item, "ps") || \
|
(_IS_PARAGRAPH_SEPARATOR_SIMPLE(item) || \
|
||||||
(o->legacy_newline && _IS_LINE_SEPARATOR(item))) /* Paragraph separator */
|
(o->legacy_newline && _IS_LINE_SEPARATOR(item))) /* Paragraph separator */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5123,32 +5131,136 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj)
|
||||||
EAPI char *
|
EAPI char *
|
||||||
evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text)
|
evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text)
|
||||||
{
|
{
|
||||||
|
/* FIXME: Redundant and awful, should be merged with markup_prepend */
|
||||||
|
Eina_Strbuf *sbuf;
|
||||||
|
char *s, *p, *ret;
|
||||||
|
char *tag_start, *tag_end, *esc_start, *esc_end;
|
||||||
|
|
||||||
if (!text) return NULL;
|
if (!text) return NULL;
|
||||||
|
|
||||||
/* FIXME: Can be done better, this is the least redundant way of doing it,
|
|
||||||
* but by far the slowest, when the time comes, this should be
|
|
||||||
* re-implemented. */
|
|
||||||
char *ret;
|
|
||||||
Evas_Object *obj2;
|
|
||||||
Evas_Textblock_Cursor *cur1, *cur2;
|
|
||||||
obj2 = evas_object_textblock_add(evas_object_evas_get(obj));
|
|
||||||
/* Shouldn't have been const, casting is ok, or at least conforms
|
|
||||||
* with the rest of the ugliness in this func*/
|
|
||||||
evas_object_textblock_style_set(obj2,
|
|
||||||
(Evas_Textblock_Style *) evas_object_textblock_style_get(obj));
|
|
||||||
evas_object_textblock_legacy_newline_set(obj2,
|
|
||||||
evas_object_textblock_legacy_newline_get(obj));
|
|
||||||
|
|
||||||
evas_object_textblock_text_markup_set(obj2, text);
|
tag_start = tag_end = esc_start = esc_end = NULL;
|
||||||
cur1 = evas_object_textblock_cursor_get(obj2);
|
sbuf = eina_strbuf_new();
|
||||||
cur2 = evas_object_textblock_cursor_new(obj2);
|
p = (char *)text;
|
||||||
evas_textblock_cursor_paragraph_first(cur1);
|
s = p;
|
||||||
evas_textblock_cursor_paragraph_last(cur2);
|
/* This loop goes through all of the mark up text until it finds format
|
||||||
ret = evas_textblock_cursor_range_text_get(cur1, cur2,
|
* tags, escape sequences or the terminating NULL. When it finds either
|
||||||
EVAS_TEXTBLOCK_TEXT_PLAIN);
|
* of those, it appends the text found up until that point to the textblock
|
||||||
evas_textblock_cursor_free(cur2);
|
* proccesses whatever found. It repeats itself until the termainating
|
||||||
evas_object_del(obj2);
|
* 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 '/' */
|
||||||
|
|
||||||
|
ttag_len = tag_end - tag_start;
|
||||||
|
|
||||||
|
ttag = malloc(ttag_len + 1);
|
||||||
|
if (ttag)
|
||||||
|
{
|
||||||
|
const char *match = NULL;
|
||||||
|
size_t replace_len;
|
||||||
|
memcpy(ttag, tag_start, ttag_len);
|
||||||
|
ttag[ttag_len] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (obj)
|
||||||
|
{
|
||||||
|
match = _style_match_tag(
|
||||||
|
evas_object_textblock_style_get(obj),
|
||||||
|
ttag, ttag_len, &replace_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) match = ttag;
|
||||||
|
|
||||||
|
if (_IS_PARAGRAPH_SEPARATOR_SIMPLE(match))
|
||||||
|
eina_strbuf_append(sbuf, "\xE2\x80\xA9");
|
||||||
|
else if (_IS_LINE_SEPARATOR(match))
|
||||||
|
eina_strbuf_append(sbuf, "\n");
|
||||||
|
else if (_IS_TAB(match))
|
||||||
|
eina_strbuf_append(sbuf, "\t");
|
||||||
|
else if (!strncmp(match, "item", 4))
|
||||||
|
eina_strbuf_append(sbuf, "\xEF\xBF\xBC");
|
||||||
|
|
||||||
|
free(ttag);
|
||||||
|
}
|
||||||
|
tag_start = tag_end = NULL;
|
||||||
|
}
|
||||||
|
else if (esc_end)
|
||||||
|
{
|
||||||
|
const char *escape;
|
||||||
|
|
||||||
|
escape = _escaped_char_get(esc_start, esc_end + 1);
|
||||||
|
eina_strbuf_append(sbuf, escape);
|
||||||
|
esc_start = esc_end = NULL;
|
||||||
|
}
|
||||||
|
else if (*p == 0)
|
||||||
|
{
|
||||||
|
eina_strbuf_append_length(sbuf, s, p - s);
|
||||||
|
s = NULL;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
eina_strbuf_append_length(sbuf, s, p - s);
|
||||||
|
s = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
eina_strbuf_append_length(sbuf, s, p - s);
|
||||||
|
s = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7125,7 +7237,7 @@ _evas_textblock_node_format_new(Evas_Object_Textblock *o, const char *_format)
|
||||||
/* Just use as is, it's a special format. */
|
/* Just use as is, it's a special format. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *tmp = format;;
|
const char *tmp = format;
|
||||||
if (format[0] != '-')
|
if (format[0] != '-')
|
||||||
{
|
{
|
||||||
n->opener = EINA_TRUE;
|
n->opener = EINA_TRUE;
|
||||||
|
|
|
@ -21,9 +21,7 @@ _evas_textblock_format_offset_get(const Evas_Object_Textblock_Node_Format *n);
|
||||||
|
|
||||||
static const char *style_buf =
|
static const char *style_buf =
|
||||||
"DEFAULT='font=Sans font_size=10 color=#000 text_class=entry'"
|
"DEFAULT='font=Sans font_size=10 color=#000 text_class=entry'"
|
||||||
"br='\n'"
|
"newline='br'"
|
||||||
"ps='ps'"
|
|
||||||
"tab='\t'"
|
|
||||||
"b='+ font=Sans:style=bold'";
|
"b='+ font=Sans:style=bold'";
|
||||||
|
|
||||||
#define START_TB_TEST() \
|
#define START_TB_TEST() \
|
||||||
|
@ -1518,18 +1516,94 @@ START_TEST(evas_textblock_text_getters)
|
||||||
fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
|
fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
|
||||||
EVAS_TEXTBLOCK_TEXT_MARKUP), "aaa"));
|
EVAS_TEXTBLOCK_TEXT_MARKUP), "aaa"));
|
||||||
|
|
||||||
/* Markup to plain */
|
/* Markup to plain and vice versa */
|
||||||
{
|
{
|
||||||
char *tmp = evas_textblock_text_markup_to_utf8(tb, "<br/>aa<\n/>bb<\t/>");
|
char *tmp, *tmp2;
|
||||||
|
|
||||||
|
/* Real textblock object */
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(tb, "<br/>aa<\n/>bb<\t/>");
|
||||||
fail_if(strcmp(tmp, "\naa\nbb\t"));
|
fail_if(strcmp(tmp, "\naa\nbb\t"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "<br/>aa<br/>bb<tab/>"));
|
||||||
|
free(tmp2);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
tmp = evas_textblock_text_markup_to_utf8(tb, "a<item></item>");
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a<item></item>");
|
||||||
fail_if(strcmp(tmp, "a\xEF\xBF\xBC"));
|
fail_if(strcmp(tmp, "a\xEF\xBF\xBC"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a"));
|
||||||
|
free(tmp2);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
tmp = evas_textblock_text_markup_to_utf8(tb, "a ");
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a ");
|
||||||
fail_if(strcmp(tmp, "a\xC2\xA0"));
|
fail_if(strcmp(tmp, "a\xC2\xA0"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a\xC2\xA0"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a<b>b</b><more></>a");
|
||||||
|
fail_if(strcmp(tmp, "aba"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "aba"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a&a");
|
||||||
|
fail_if(strcmp(tmp, "a&a"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a&a"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a<newline/>a");
|
||||||
|
fail_if(strcmp(tmp, "a\na"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a<br/>a"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
/* NULL textblock object */
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(NULL, "<br/>aa<\n/>bb<\t/>");
|
||||||
|
fail_if(strcmp(tmp, "\naa\nbb\t"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "<br/>aa<br/>bb<tab/>"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(NULL, "a<item></item>");
|
||||||
|
fail_if(strcmp(tmp, "a\xEF\xBF\xBC"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(NULL, "a ");
|
||||||
|
fail_if(strcmp(tmp, "a\xC2\xA0"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a\xC2\xA0"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(NULL, "a<b>b</b><more></>a");
|
||||||
|
fail_if(strcmp(tmp, "aba"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "aba"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(tb, "a&a");
|
||||||
|
fail_if(strcmp(tmp, "a&a"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "a&a"));
|
||||||
|
free(tmp2);
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
tmp = evas_textblock_text_markup_to_utf8(NULL, "a<newline/>a");
|
||||||
|
fail_if(strcmp(tmp, "aa"));
|
||||||
|
tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
|
||||||
|
fail_if(strcmp(tmp2, "aa"));
|
||||||
|
free(tmp2);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue