forked from enlightenment/efl
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
This commit is contained in:
parent
bc8b2857c1
commit
69d0646b33
|
@ -26,6 +26,8 @@ efl_eolian_files = \
|
||||||
lib/efl/interfaces/efl_text_format.eo \
|
lib/efl/interfaces/efl_text_format.eo \
|
||||||
lib/efl/interfaces/efl_text_cursor.eo \
|
lib/efl/interfaces/efl_text_cursor.eo \
|
||||||
lib/efl/interfaces/efl_text_annotate.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_text_properties.eo \
|
||||||
lib/efl/interfaces/efl_gfx_stack.eo \
|
lib/efl/interfaces/efl_gfx_stack.eo \
|
||||||
lib/efl/interfaces/efl_gfx_view.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_buffer.c \
|
||||||
lib/efl/interfaces/efl_io_queue.c \
|
lib/efl/interfaces/efl_io_queue.c \
|
||||||
lib/efl/interfaces/efl_observer.c \
|
lib/efl/interfaces/efl_observer.c \
|
||||||
|
lib/efl/interfaces/efl_text_markup_util.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl -I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@ -DEFL_GFX_FILTER_BETA
|
lib_efl_libefl_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl -I$(top_srcdir)/src/lib/efl @EFL_CFLAGS@ -DEFL_GFX_FILTER_BETA
|
||||||
|
|
|
@ -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_format.eo.h"
|
||||||
#include "interfaces/efl_text_cursor.eo.h"
|
#include "interfaces/efl_text_cursor.eo.h"
|
||||||
#include "interfaces/efl_text_annotate.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
|
#else
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "interfaces/efl_text_format.eo.c"
|
#include "interfaces/efl_text_format.eo.c"
|
||||||
#include "interfaces/efl_text_cursor.eo.c"
|
#include "interfaces/efl_text_cursor.eo.c"
|
||||||
#include "interfaces/efl_text_annotate.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.eo.c"
|
||||||
#include "interfaces/efl_gfx_buffer.eo.c"
|
#include "interfaces/efl_gfx_buffer.eo.c"
|
||||||
|
|
|
@ -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]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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, "<br/>");
|
||||||
|
else if (ch == _TAB)
|
||||||
|
eina_strbuf_append(sbuf, "<tab/>");
|
||||||
|
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, "<ps/>");
|
||||||
|
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"
|
|
@ -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]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@ import efl_text_types;
|
||||||
|
|
||||||
struct Efl.Canvas.Text.Style; [[EFL text style data structure]]
|
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,
|
class Efl.Canvas.Text (Efl.Canvas.Object, Efl.Text, Efl.Text.Properties,
|
||||||
Efl.Text.Font, Efl.Text.Style, Efl.Text.Format, Efl.Text.Cursor, Efl.Text.Annotate)
|
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]]
|
[[Efl canvas text class]]
|
||||||
legacy_prefix: evas_object_textblock;
|
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.annotation_positions_get;
|
||||||
Efl.Text.Annotate.cursor_object_item_annotation { get; }
|
Efl.Text.Annotate.cursor_object_item_annotation { get; }
|
||||||
Efl.Text.Annotate.cursor_object_item_insert;
|
Efl.Text.Annotate.cursor_object_item_insert;
|
||||||
|
Efl.Text.Markup.markup { set; get; }
|
||||||
|
Efl.Text.Markup.cursor_markup_insert;
|
||||||
}
|
}
|
||||||
events {
|
events {
|
||||||
cursor,changed; [[Called when cursor changed]]
|
cursor,changed; [[Called when cursor changed]]
|
||||||
|
|
|
@ -7454,12 +7454,12 @@ _prepend_escaped_char(Efl_Text_Cursor_Cursor *cur_obj, const char *s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EAPI void
|
static void
|
||||||
evas_object_textblock_text_markup_set(Eo *eo_obj, const char *text)
|
_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_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||||
evas_object_async_block(obj);
|
evas_object_async_block(obj);
|
||||||
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
|
|
||||||
if (text == o->markup_text)
|
if (text == o->markup_text)
|
||||||
{
|
{
|
||||||
/* Text is the same and already stringshared, do nothing */
|
/* 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
|
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;
|
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_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||||
evas_object_async_block(obj);
|
evas_object_async_block(obj);
|
||||||
TB_HEAD();
|
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);
|
_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
|
* @internal
|
||||||
|
@ -7711,15 +7742,14 @@ _markup_get_text_append(Eina_Strbuf *txt, const Eina_Unicode *text)
|
||||||
|
|
||||||
free(base);
|
free(base);
|
||||||
}
|
}
|
||||||
EAPI const char*
|
static const char*
|
||||||
evas_object_textblock_text_markup_get(Eo *eo_obj)
|
_evas_object_textblock_text_markup_get(Eo *eo_obj, Efl_Canvas_Text_Data *o)
|
||||||
{
|
{
|
||||||
Evas_Object_Textblock_Node_Text *n;
|
Evas_Object_Textblock_Node_Text *n;
|
||||||
Eina_Strbuf *txt = NULL;
|
Eina_Strbuf *txt = NULL;
|
||||||
|
|
||||||
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||||
evas_object_async_block(obj);
|
evas_object_async_block(obj);
|
||||||
Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
|
|
||||||
const char *markup;
|
const char *markup;
|
||||||
if (o->markup_text)
|
if (o->markup_text)
|
||||||
{
|
{
|
||||||
|
@ -7781,6 +7811,19 @@ evas_object_textblock_text_markup_get(Eo *eo_obj)
|
||||||
return markup;
|
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 *
|
EAPI char *
|
||||||
evas_textblock_text_markup_to_utf8(const Evas_Object *eo_obj, const char *text)
|
evas_textblock_text_markup_to_utf8(const Evas_Object *eo_obj, const char *text)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue