aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/canvas/evas_object_textblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/canvas/evas_object_textblock.c')
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_textblock.c180
1 files changed, 138 insertions, 42 deletions
diff --git a/libraries/evas/src/lib/canvas/evas_object_textblock.c b/libraries/evas/src/lib/canvas/evas_object_textblock.c
index 568911c..ee07e20 100644
--- a/libraries/evas/src/lib/canvas/evas_object_textblock.c
+++ b/libraries/evas/src/lib/canvas/evas_object_textblock.c
@@ -430,6 +430,7 @@ struct _Evas_Object_Textblock
430{ 430{
431 DATA32 magic; 431 DATA32 magic;
432 Evas_Textblock_Style *style; 432 Evas_Textblock_Style *style;
433 Evas_Textblock_Style *style_user;
433 Evas_Textblock_Cursor *cursor; 434 Evas_Textblock_Cursor *cursor;
434 Eina_List *cursors; 435 Eina_List *cursors;
435 Evas_Object_Textblock_Node_Text *text_nodes; 436 Evas_Object_Textblock_Node_Text *text_nodes;
@@ -4185,11 +4186,27 @@ _layout(const Evas_Object *obj, int w, int h, int *w_ret, int *h_ret)
4185 4186
4186 /* Start of logical layout creation */ 4187 /* Start of logical layout creation */
4187 /* setup default base style */ 4188 /* setup default base style */
4188 if ((c->o->style) && (c->o->style->default_tag))
4189 { 4189 {
4190 c->fmt = _layout_format_push(c, NULL, NULL); 4190 Eina_Bool finalize = EINA_FALSE;
4191 _format_fill(c->obj, c->fmt, c->o->style->default_tag); 4191 if ((c->o->style) && (c->o->style->default_tag))
4192 _format_finalize(c->obj, c->fmt); 4192 {
4193 c->fmt = _layout_format_push(c, NULL, NULL);
4194 _format_fill(c->obj, c->fmt, c->o->style->default_tag);
4195 finalize = EINA_TRUE;
4196 }
4197
4198 if ((c->o->style_user) && (c->o->style_user->default_tag))
4199 {
4200 if (!c->fmt)
4201 {
4202 c->fmt = _layout_format_push(c, NULL, NULL);
4203 }
4204 _format_fill(c->obj, c->fmt, c->o->style_user->default_tag);
4205 finalize = EINA_TRUE;
4206 }
4207
4208 if (finalize)
4209 _format_finalize(c->obj, c->fmt);
4193 } 4210 }
4194 if (!c->fmt) 4211 if (!c->fmt)
4195 { 4212 {
@@ -4485,9 +4502,9 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
4485 { 4502 {
4486 // format MUST be KEY='VALUE'[KEY='VALUE']... 4503 // format MUST be KEY='VALUE'[KEY='VALUE']...
4487 const char *p; 4504 const char *p;
4488 const char *key_start, *key_stop, *val_start, *val_stop; 4505 const char *key_start, *key_stop, *val_start;
4489 4506
4490 key_start = key_stop = val_start = val_stop = NULL; 4507 key_start = key_stop = val_start = NULL;
4491 p = ts->style_text; 4508 p = ts->style_text;
4492 while (*p) 4509 while (*p)
4493 { 4510 {
@@ -4504,19 +4521,54 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
4504 else if (!val_start) 4521 else if (!val_start)
4505 { 4522 {
4506 if (((*p) == '\'') && (*(p + 1))) 4523 if (((*p) == '\'') && (*(p + 1)))
4507 val_start = p + 1; 4524 {
4508 } 4525 val_start = ++p;
4509 else if (!val_stop) 4526 }
4510 {
4511 if (((*p) == '\'') && (p > ts->style_text) && (p[-1] != '\\'))
4512 val_stop = p;
4513 } 4527 }
4514 if ((key_start) && (key_stop) && (val_start) && (val_stop)) 4528 if ((key_start) && (key_stop) && (val_start))
4515 { 4529 {
4516 char *tags, *replaces; 4530 char *tags, *replaces = NULL;
4517 Evas_Object_Style_Tag *tag; 4531 Evas_Object_Style_Tag *tag;
4518 size_t tag_len = key_stop - key_start; 4532 const char *val_stop = NULL;
4519 size_t replace_len = val_stop - val_start; 4533 size_t tag_len;
4534 size_t replace_len;
4535
4536 {
4537 Eina_Strbuf *buf = eina_strbuf_new();
4538 val_stop = val_start;
4539 while(*p)
4540 {
4541 if (*p == '\'')
4542 {
4543 /* Break if we found the tag end */
4544 if (p[-1] != '\\')
4545 {
4546 eina_strbuf_append_length(buf, val_stop,
4547 p - val_stop);
4548 break;
4549 }
4550 else
4551 {
4552 eina_strbuf_append_length(buf, val_stop,
4553 p - val_stop - 1);
4554 eina_strbuf_append_char(buf, '\'');
4555 val_stop = p + 1;
4556 }
4557 }
4558 p++;
4559 }
4560 replaces = eina_strbuf_string_steal(buf);
4561 eina_strbuf_free(buf);
4562 }
4563 /* If we didn't find an end, just aboart. */
4564 if (!*p)
4565 {
4566 if (replaces) free(replaces);
4567 break;
4568 }
4569
4570 tag_len = key_stop - key_start;
4571 replace_len = val_stop - val_start;
4520 4572
4521 tags = malloc(tag_len + 1); 4573 tags = malloc(tag_len + 1);
4522 if (tags) 4574 if (tags)
@@ -4525,12 +4577,6 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
4525 tags[tag_len] = 0; 4577 tags[tag_len] = 0;
4526 } 4578 }
4527 4579
4528 replaces = malloc(replace_len + 1);
4529 if (replaces)
4530 {
4531 memcpy(replaces, val_start, replace_len);
4532 replaces[replace_len] = 0;
4533 }
4534 if ((tags) && (replaces)) 4580 if ((tags) && (replaces))
4535 { 4581 {
4536 if (!strcmp(tags, "DEFAULT")) 4582 if (!strcmp(tags, "DEFAULT"))
@@ -4561,7 +4607,7 @@ evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
4561 if (tags) free(tags); 4607 if (tags) free(tags);
4562 if (replaces) free(replaces); 4608 if (replaces) free(replaces);
4563 } 4609 }
4564 key_start = key_stop = val_start = val_stop = NULL; 4610 key_start = key_stop = val_start = NULL;
4565 } 4611 }
4566 p++; 4612 p++;
4567 } 4613 }
@@ -4576,13 +4622,15 @@ evas_textblock_style_get(const Evas_Textblock_Style *ts)
4576} 4622}
4577 4623
4578/* textblock styles */ 4624/* textblock styles */
4579EAPI void 4625
4580evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts) 4626static void
4627_textblock_style_generic_set(Evas_Object *obj, Evas_Textblock_Style *ts,
4628 Evas_Textblock_Style **obj_ts)
4581{ 4629{
4582 TB_HEAD(); 4630 TB_HEAD();
4583 if (ts == o->style) return; 4631 if (ts == *obj_ts) return;
4584 if ((ts) && (ts->delete_me)) return; 4632 if ((ts) && (ts->delete_me)) return;
4585 if (o->style) 4633 if (*obj_ts)
4586 { 4634 {
4587 Evas_Textblock_Style *old_ts; 4635 Evas_Textblock_Style *old_ts;
4588 if (o->markup_text) 4636 if (o->markup_text)
@@ -4591,7 +4639,7 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
4591 o->markup_text = NULL; 4639 o->markup_text = NULL;
4592 } 4640 }
4593 4641
4594 old_ts = o->style; 4642 old_ts = *obj_ts;
4595 old_ts->objects = eina_list_remove(old_ts->objects, obj); 4643 old_ts->objects = eina_list_remove(old_ts->objects, obj);
4596 if ((old_ts->delete_me) && (!old_ts->objects)) 4644 if ((old_ts->delete_me) && (!old_ts->objects))
4597 evas_textblock_style_free(old_ts); 4645 evas_textblock_style_free(old_ts);
@@ -4600,12 +4648,19 @@ evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
4600 { 4648 {
4601 ts->objects = eina_list_append(ts->objects, obj); 4649 ts->objects = eina_list_append(ts->objects, obj);
4602 } 4650 }
4603 o->style = ts; 4651 *obj_ts = ts;
4604 4652
4605 _evas_textblock_invalidate_all(o); 4653 _evas_textblock_invalidate_all(o);
4606 _evas_textblock_changed(o, obj); 4654 _evas_textblock_changed(o, obj);
4607} 4655}
4608 4656
4657EAPI void
4658evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
4659{
4660 TB_HEAD();
4661 _textblock_style_generic_set(obj, ts, &(o->style));
4662}
4663
4609EAPI const Evas_Textblock_Style * 4664EAPI const Evas_Textblock_Style *
4610evas_object_textblock_style_get(const Evas_Object *obj) 4665evas_object_textblock_style_get(const Evas_Object *obj)
4611{ 4666{
@@ -4614,6 +4669,27 @@ evas_object_textblock_style_get(const Evas_Object *obj)
4614} 4669}
4615 4670
4616EAPI void 4671EAPI void
4672evas_object_textblock_style_user_push(Evas_Object *obj, Evas_Textblock_Style *ts)
4673{
4674 TB_HEAD();
4675 _textblock_style_generic_set(obj, ts, &(o->style_user));
4676}
4677
4678EAPI const Evas_Textblock_Style *
4679evas_object_textblock_style_user_peek(const Evas_Object *obj)
4680{
4681 TB_HEAD_RETURN(NULL);
4682 return o->style_user;
4683}
4684
4685EAPI void
4686evas_object_textblock_style_user_pop(Evas_Object *obj)
4687{
4688 TB_HEAD();
4689 _textblock_style_generic_set(obj, NULL, &(o->style_user));
4690}
4691
4692EAPI void
4617evas_object_textblock_replace_char_set(Evas_Object *obj, const char *ch) 4693evas_object_textblock_replace_char_set(Evas_Object *obj, const char *ch)
4618{ 4694{
4619 TB_HEAD(); 4695 TB_HEAD();
@@ -4902,7 +4978,7 @@ evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text)
4902 o->markup_text = NULL; 4978 o->markup_text = NULL;
4903 } 4979 }
4904 _nodes_clear(obj); 4980 _nodes_clear(obj);
4905 if (!o->style) 4981 if (!o->style && !o->style_user)
4906 { 4982 {
4907 if (text != o->markup_text) 4983 if (text != o->markup_text)
4908 { 4984 {
@@ -5244,7 +5320,7 @@ evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text)
5244 const char *escape; 5320 const char *escape;
5245 5321
5246 escape = _escaped_char_get(esc_start, esc_end + 1); 5322 escape = _escaped_char_get(esc_start, esc_end + 1);
5247 eina_strbuf_append(sbuf, escape); 5323 if (escape) eina_strbuf_append(sbuf, escape);
5248 esc_start = esc_end = NULL; 5324 esc_start = esc_end = NULL;
5249 } 5325 }
5250 else if (*p == 0) 5326 else if (*p == 0)
@@ -5650,7 +5726,6 @@ EAPI Eina_Bool
5650evas_textblock_cursor_is_format(const Evas_Textblock_Cursor *cur) 5726evas_textblock_cursor_is_format(const Evas_Textblock_Cursor *cur)
5651{ 5727{
5652 if (!cur || !cur->node) return EINA_FALSE; 5728 if (!cur || !cur->node) return EINA_FALSE;
5653 if (evas_textblock_cursor_format_is_visible_get(cur)) return EINA_TRUE;
5654 return (_evas_textblock_cursor_node_format_at_pos_get(cur)) ? 5729 return (_evas_textblock_cursor_node_format_at_pos_get(cur)) ?
5655 EINA_TRUE : EINA_FALSE; 5730 EINA_TRUE : EINA_FALSE;
5656} 5731}
@@ -5977,9 +6052,9 @@ evas_textblock_cursor_format_prev(Evas_Textblock_Cursor *cur)
5977#else 6052#else
5978 6053
5979#define BREAK_AFTER(i) \ 6054#define BREAK_AFTER(i) \
5980 ((!str[i + 1]) || \ 6055 ((!text[i + 1]) || \
5981 (_is_white(str[i]) && !_is_white(str[i + 1])) || \ 6056 (_is_white(text[i]) && !_is_white(text[i + 1])) || \
5982 (!_is_white(str[i]) && _is_white(str[i + 1]))) 6057 (!_is_white(text[i]) && _is_white(text[i + 1])))
5983 6058
5984#endif 6059#endif
5985 6060
@@ -7241,7 +7316,13 @@ _evas_textblock_node_format_new(Evas_Object_Textblock *o, const char *_format)
7241 } 7316 }
7242 } 7317 }
7243 7318
7244 match = _style_match_tag(o->style, format, format_len, &replace_len); 7319 if (!o->style_user || !(match = _style_match_tag(o->style_user, format,
7320 format_len, &replace_len)))
7321 {
7322 match = _style_match_tag(o->style, format, format_len,
7323 &replace_len);
7324 }
7325
7245 if (match) 7326 if (match)
7246 { 7327 {
7247 if (match[0] != '-') 7328 if (match[0] != '-')
@@ -7633,6 +7714,7 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
7633 } 7714 }
7634 fnode = _evas_textblock_cursor_node_format_at_pos_get(cur1); 7715 fnode = _evas_textblock_cursor_node_format_at_pos_get(cur1);
7635 7716
7717 n1->dirty = n2->dirty = EINA_TRUE;
7636 if (should_merge) 7718 if (should_merge)
7637 { 7719 {
7638 /* We call this function instead of the cursor one because we already 7720 /* We call this function instead of the cursor one because we already
@@ -7646,7 +7728,6 @@ evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_C
7646 evas_textblock_cursor_copy(cur1, o->cursor); 7728 evas_textblock_cursor_copy(cur1, o->cursor);
7647 7729
7648 _evas_textblock_changed(o, cur1->obj); 7730 _evas_textblock_changed(o, cur1->obj);
7649 n1->dirty = n2->dirty = EINA_TRUE;
7650} 7731}
7651 7732
7652 7733
@@ -8022,6 +8103,7 @@ evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur)
8022 8103
8023 if (!cur) return EINA_FALSE; 8104 if (!cur) return EINA_FALSE;
8024 if (!cur->node) return EINA_FALSE; 8105 if (!cur->node) return EINA_FALSE;
8106 if (!evas_textblock_cursor_is_format(cur)) return EINA_FALSE;
8025 text = eina_ustrbuf_string_get(cur->node->unicode); 8107 text = eina_ustrbuf_string_get(cur->node->unicode);
8026 return EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(text[cur->pos]); 8108 return EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(text[cur->pos]);
8027} 8109}
@@ -9016,12 +9098,22 @@ _size_native_calc_line_finalize(const Evas_Object *obj, Eina_List *items,
9016 Eina_List *i; 9098 Eina_List *i;
9017 9099
9018 it = eina_list_data_get(items); 9100 it = eina_list_data_get(items);
9019 /* If there are no text items yet, calc ascent/descent
9020 * according to the current format. */
9021 if (it && (*ascent + *descent == 0))
9022 _layout_format_ascent_descent_adjust(obj, ascent, descent, it->format);
9023
9024 *w = 0; 9101 *w = 0;
9102
9103 if (it)
9104 {
9105 /* If there are no text items yet, calc ascent/descent
9106 * according to the current format. */
9107 if (*ascent + *descent == 0)
9108 _layout_format_ascent_descent_adjust(obj, ascent, descent,
9109 it->format);
9110
9111 /* Add margins. */
9112 if (it->format)
9113 *w = it->format->margin.l + it->format->margin.r;
9114 }
9115
9116
9025 /* Adjust all the item sizes according to the final line size, 9117 /* Adjust all the item sizes according to the final line size,
9026 * and update the x positions of all the items of the line. */ 9118 * and update the x positions of all the items of the line. */
9027 EINA_LIST_FOREACH(items, i, it) 9119 EINA_LIST_FOREACH(items, i, it)
@@ -9226,6 +9318,10 @@ evas_object_textblock_free(Evas_Object *obj)
9226 9318
9227 evas_object_textblock_clear(obj); 9319 evas_object_textblock_clear(obj);
9228 evas_object_textblock_style_set(obj, NULL); 9320 evas_object_textblock_style_set(obj, NULL);
9321 while (evas_object_textblock_style_user_peek(obj))
9322 {
9323 evas_object_textblock_style_user_pop(obj);
9324 }
9229 o = (Evas_Object_Textblock *)(obj->object_data); 9325 o = (Evas_Object_Textblock *)(obj->object_data);
9230 free(o->cursor); 9326 free(o->cursor);
9231 while (o->cursors) 9327 while (o->cursors)