From 58d76412fe37bc01e7bd41183a0291bef29497f9 Mon Sep 17 00:00:00 2001 From: tasn Date: Thu, 8 Dec 2011 12:05:47 +0000 Subject: [PATCH] Evas textblock: Improve internal handling of formats. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@66022 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/canvas/evas_object_textblock.c | 223 ++++++++++++++++----------------- 1 file changed, 111 insertions(+), 112 deletions(-) diff --git a/src/lib/canvas/evas_object_textblock.c b/src/lib/canvas/evas_object_textblock.c index 11e1a10..205ad93 100644 --- a/src/lib/canvas/evas_object_textblock.c +++ b/src/lib/canvas/evas_object_textblock.c @@ -194,10 +194,10 @@ typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format; * Returns true if closer is the closer of base. */ #define _FORMAT_IS_CLOSER_OF(base, closer, closer_len) \ - (!strncmp(base + 1, closer, closer_len) && \ - (!base[closer_len + 1] || \ - (base[closer_len + 1] == '=') || \ - _is_white(base[closer_len + 1]))) + (!strncmp(base, closer, closer_len) && \ + (!base[closer_len] || \ + (base[closer_len] == '=') || \ + _is_white(base[closer_len]))) /*FIXME: document the structs and struct items. */ struct _Evas_Object_Style_Tag @@ -228,6 +228,8 @@ struct _Evas_Object_Textblock_Node_Format Evas_Object_Textblock_Node_Text *text_node; size_t offset; unsigned char anchor : 2; + Eina_Bool opener : 1; + Eina_Bool own_closer : 1; Eina_Bool visible : 1; Eina_Bool format_change : 1; Eina_Bool is_new : 1; @@ -1688,8 +1690,8 @@ _format_fill(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *st s = str; - /* get rid of anything +s or -s off the start of the string */ - while ((*s == ' ') || (*s == '+') || (*s == '-')) s++; + /* get rid of any spaces at the start of the string */ + while (*s == ' ') s++; while ((item = _format_parse(&s))) { @@ -2130,7 +2132,6 @@ _layout_format_pop(Ctxt *c, const char *format) if ((c->format_stack) && (c->format_stack->next)) { Eina_List *redo_nodes = NULL; - format++; /* Skip the '-' */ /* Generic pop, should just pop. */ if (((format[0] == ' ') && !format[1]) || @@ -3040,7 +3041,7 @@ _layout_do_format(const Evas_Object *obj __UNUSED__, Ctxt *c, int handled = 0; s = n->format; - if (!strncmp(s, "+ item ", 7)) + if (!strncmp(s, "item ", 5)) { // one of: // item size=20x10 href=name @@ -3132,16 +3133,14 @@ _layout_do_format(const Evas_Object *obj __UNUSED__, Ctxt *c, if (!handled) { Eina_Bool push_fmt = EINA_FALSE; - if (s[0] == '+') + if (n->opener && !n->own_closer) { fmt = _layout_format_push(c, fmt, n); - s++; push_fmt = EINA_TRUE; } - else if (s[0] == '-') + else if (!n->opener) { fmt = _layout_format_pop(c, n->orig_format); - s++; } while ((item = _format_parse(&s))) { @@ -3845,18 +3844,16 @@ _format_changes_invalidate_text_nodes(Ctxt *c) const char *fstr = fnode->orig_format; /* balance < 0 means we gave up and everything should be * invalidated */ - if (*fstr == '+') + if (fnode->opener && !fnode->own_closer) { balance++; if (!fstack) start_n = fnode->text_node; fstack = eina_list_prepend(fstack, fnode); } - else if (*fstr == '-') + else if (!fnode->opener) { size_t fstr_len; - /* Skip the '-' */ - fstr++; fstr_len = strlen(fstr); /* Generic popper, just pop */ if (((fstr[0] == ' ') && !fstr[1]) || !fstr[0]) @@ -4980,18 +4977,16 @@ evas_object_textblock_text_markup_prepend(Evas_Textblock_Cursor *cur, const char * @param fnode the format node to process. */ static void -_markup_get_format_append(Evas_Object_Textblock *o __UNUSED__, Eina_Strbuf *txt, Evas_Object_Textblock_Node_Format *fnode) +_markup_get_format_append(Eina_Strbuf *txt, Evas_Object_Textblock_Node_Format *fnode) { eina_strbuf_append_char(txt, '<'); { const char *s; - int pop = 0; // FIXME: need to escape s = fnode->orig_format; - if (*s == '-') pop = 1; - while ((*s == ' ') || (*s == '+') || (*s == '-')) s++; - if (pop) eina_strbuf_append_char(txt, '/'); + if (!fnode->opener && !fnode->own_closer) + eina_strbuf_append_char(txt, '/'); eina_strbuf_append(txt, s); } eina_strbuf_append_char(txt, '>'); @@ -5062,7 +5057,7 @@ evas_object_textblock_text_markup_get(const Evas_Object *obj) tmp_ch = text[off]; text[off] = 0; /* Null terminate the part of the string */ _markup_get_text_append(txt, text); - _markup_get_format_append(o, txt, fnode); + _markup_get_format_append(txt, fnode); text[off] = tmp_ch; /* Restore the char */ text += off; if (fnode->visible) @@ -5454,15 +5449,13 @@ evas_textblock_node_format_remove_pair(Evas_Object *obj, { const char *fstr = fmt->orig_format; - if (fstr && (*fstr == '+')) + if (fmt->opener && !fmt->own_closer) { fstack = eina_list_prepend(fstack, fmt); } - else if (fstr && (*fstr == '-')) + else if (fstr && !fmt->opener) { size_t fstr_len; - /* Skip the '-' */ - fstr++; fstr_len = strlen(fstr); /* Generic popper, just pop */ if (((fstr[0] == ' ') && !fstr[1]) || !fstr[0]) @@ -5888,10 +5881,9 @@ _evas_textblock_format_is_visible(Evas_Object_Textblock_Node_Format *fnode, fnode->anchor = ANCHOR_NONE; if (!s) return; - if (s[0] == '+' || s[0] == '-') + if (!fnode->own_closer) { - is_opener = (s[0] == '+'); - s++; + is_opener = fnode->opener; fnode->format_change = EINA_TRUE; } @@ -5987,16 +5979,14 @@ _evas_textblock_node_format_remove_matching(Evas_Object_Textblock *o, } - if (fstr && (*fstr == '+')) + if (fmt->opener && !fmt->own_closer) { formats = eina_list_prepend(formats, fmt); } - else if (fstr && (*fstr == '-')) + else if (fstr && !fmt->opener) { Evas_Object_Textblock_Node_Format *fnode; size_t fstr_len; - /* Skip the '-' */ - fstr++; fstr_len = strlen(fstr); /* Generic popper, just pop */ if (((fstr[0] == ' ') && !fstr[1]) || !fstr[0]) @@ -6856,6 +6846,7 @@ _evas_textblock_node_format_new(Evas_Object_Textblock *o, const char *_format) { Evas_Object_Textblock_Node_Format *n; const char *format = _format; + const char *pre_stripped_format = NULL; n = calloc(1, sizeof(Evas_Object_Textblock_Node_Format)); /* Create orig_format and format */ @@ -6873,56 +6864,66 @@ _evas_textblock_node_format_new(Evas_Object_Textblock *o, const char *_format) match = _style_match_tag(o->style, format, format_len, &replace_len); if (match) { - if ((match[0] == '+') || (match[0] == '-')) + if (match[0] != '-') { - char *norm_format; - norm_format = malloc(format_len + 2 + 1); - memcpy(norm_format, match, 2); - memcpy(norm_format + 2, format, format_len); - norm_format[format_len + 2] = '\0'; - n->orig_format = - eina_stringshare_add_length(norm_format, format_len + 2); - free(norm_format); - } - else - { - n->orig_format = - eina_stringshare_add_length(format, format_len); + n->opener = EINA_TRUE; + if (match[0] != '+') + { + n->own_closer = EINA_TRUE; + } } - n->format = eina_stringshare_add(match); + + pre_stripped_format = match; } else { - char *norm_format; - - norm_format = malloc(format_len + 2 + 1); - if (norm_format) + if (format[0] == '/') { - if (format[0] == '/') - { - memcpy(norm_format, "- ", 2); - memcpy(norm_format + 2, format + 1, format_len - 1); - norm_format[format_len + 2 - 1] = '\0'; - } - else - { - memcpy(norm_format, "+ ", 2); - memcpy(norm_format + 2, format, format_len); - norm_format[format_len + 2] = '\0'; - } - n->orig_format = eina_stringshare_add(norm_format); - free(norm_format); + format++; + format_len--; + } + else + { + n->opener = EINA_TRUE; } - n->format = eina_stringshare_ref(n->orig_format); } + + n->orig_format = eina_stringshare_add_length(format, format_len); + + if (!pre_stripped_format) + pre_stripped_format = n->orig_format; } /* Just use as is, it's a special format. */ else { - n->orig_format = eina_stringshare_add(format); - n->format = eina_stringshare_ref(n->orig_format); + const char *tmp = format;; + if (format[0] != '-') + { + n->opener = EINA_TRUE; + if (format[0] != '+') + { + n->own_closer = EINA_TRUE; + } + } + if ((*tmp == '+') || (*tmp == '-')) + { + tmp++; + while (*tmp == ' ') tmp++; + } + n->orig_format = eina_stringshare_add(tmp); + pre_stripped_format = n->orig_format; } + /* Strip format */ + { + const char *tmp = pre_stripped_format; + if ((*tmp == '+') || (*tmp == '-')) + { + tmp++; + while (*tmp == ' ') tmp++; + } + n->format = eina_stringshare_add(tmp); + } format = n->format; _evas_textblock_format_is_visible(n, format); @@ -7143,7 +7144,7 @@ evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur) should_merge = EINA_TRUE; } /* If a singnular, mark as invisible, so we'll delete it. */ - if (!format || ((*format != '+') && (*format != '-'))) + if (!format || last_fmt->own_closer) { last_fmt->visible = EINA_FALSE; } @@ -7272,60 +7273,40 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C EAPI char * evas_textblock_cursor_content_get(const Evas_Textblock_Cursor *cur) { - const Eina_Unicode *ustr; - Eina_Unicode buf[2]; - char *s; if (!cur || !cur->node) return NULL; if (evas_textblock_cursor_format_is_visible_get(cur)) { - size_t len; - const char *fstr; + Eina_Strbuf *buf; + Evas_Object_Textblock_Node_Format *fnode; char *ret; - int pop = 0; - fstr = evas_textblock_node_format_text_get( - _evas_textblock_node_visible_at_pos_get( - evas_textblock_cursor_format_get(cur))); - - if (!fstr) - return NULL; + fnode = _evas_textblock_node_visible_at_pos_get( + evas_textblock_cursor_format_get(cur)); - if (*fstr == '-') pop = 1; - while ((*fstr == ' ') || (*fstr == '+') || (*fstr == '-')) fstr++; - len = strlen(fstr); - - { - char *tmp; - if (pop) - { - ret = tmp = malloc(len + 3 + 1); /* and the null */ - memcpy(tmp, " and the null */ - *tmp = '<'; - tmp++; - } - memcpy(tmp, fstr, len); - memcpy(tmp + len, ">", 2); /* Including the null */ - } + buf = eina_strbuf_new(); + _markup_get_format_append(buf, fnode); + ret = eina_strbuf_string_steal(buf); + eina_strbuf_free(buf); return ret; } + else + { + const Eina_Unicode *ustr; + Eina_Unicode buf[2]; + char *s; - ustr = eina_ustrbuf_string_get(cur->node->unicode); - buf[0] = ustr[cur->pos]; - buf[1] = 0; - s = eina_unicode_unicode_to_utf8(buf, NULL); + ustr = eina_ustrbuf_string_get(cur->node->unicode); + buf[0] = ustr[cur->pos]; + buf[1] = 0; + s = eina_unicode_unicode_to_utf8(buf, NULL); - return s; + return s; + } } static char * _evas_textblock_cursor_range_text_markup_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *_cur2) { - Evas_Object_Textblock *o; Evas_Object_Textblock_Node_Text *tnode; Eina_Strbuf *buf; Evas_Textblock_Cursor *cur2; @@ -7334,7 +7315,6 @@ _evas_textblock_cursor_range_text_markup_get(const Evas_Textblock_Cursor *cur1, if (!cur1 || !cur1->node) return NULL; if (!_cur2 || !_cur2->node) return NULL; if (cur1->obj != _cur2->obj) return NULL; - o = (Evas_Object_Textblock *)(cur1->obj->object_data); if (evas_textblock_cursor_compare(cur1, _cur2) > 0) { const Evas_Textblock_Cursor *tc; @@ -7402,7 +7382,7 @@ _evas_textblock_cursor_range_text_markup_get(const Evas_Textblock_Cursor *cur1, tmp_ch = text[off]; text[off] = 0; /* Null terminate the part of the string */ _markup_get_text_append(buf, text); - _markup_get_format_append(o, buf, fnode); + _markup_get_format_append(buf, fnode); text[off] = tmp_ch; /* Restore the char */ text += off; if (fnode->visible) @@ -7624,8 +7604,27 @@ evas_textblock_cursor_format_get(const Evas_Textblock_Cursor *cur) EAPI const char * evas_textblock_node_format_text_get(const Evas_Object_Textblock_Node_Format *fmt) { + static char *ret = NULL; + char *tmp; + if (!fmt) return NULL; - return fmt->orig_format; + + if (ret) free(ret); + ret = malloc(strlen(fmt->orig_format) + 2 + 1); + tmp = ret; + + if (fmt->opener && !fmt->own_closer) + { + *(tmp++) = '+'; + *(tmp++) = ' '; + } + else if (!fmt->opener) + { + *(tmp++) = '-'; + *(tmp++) = ' '; + } + strcpy(tmp, fmt->orig_format); + return ret; } EAPI void -- 2.7.4