d868080107f6a34d3b4691205e376f8564f4a4cf
[framework/uifw/evas.git] / src / tests / evas_test_textblock.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <stdio.h>
6
7 #include <Eina.h>
8
9 #include "evas_suite.h"
10 #include "Evas.h"
11
12 #include "evas_tests_helpers.h"
13
14 /* Functions defined in evas_object_textblock.c */
15 EAPI Eina_Bool
16 _evas_textblock_check_item_node_link(Evas_Object *obj);
17 EAPI int
18 _evas_textblock_format_offset_get(const Evas_Object_Textblock_Node_Format *n);
19 /* end of functions defined in evas_object_textblock.c */
20
21
22 static const char *style_buf =
23    "DEFAULT='font=Sans font_size=10 color=#000 text_class=entry'"
24    "br='\n'"
25    "ps='ps'"
26    "tab='\t'"
27    "b='+ font=Sans:style=bold'";
28
29 #define START_TB_TEST() \
30    Evas *evas; \
31    Evas_Object *tb; \
32    Evas_Textblock_Style *st; \
33    Evas_Textblock_Cursor *cur; \
34    evas = EVAS_TEST_INIT_EVAS(); \
35    evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
36    tb = evas_object_textblock_add(evas); \
37    fail_if(!tb); \
38    evas_object_textblock_legacy_newline_set(tb, EINA_FALSE); \
39    st = evas_textblock_style_new(); \
40    fail_if(!st); \
41    evas_textblock_style_set(st, style_buf); \
42    fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \
43    evas_object_textblock_style_set(tb, st); \
44    cur = evas_object_textblock_cursor_new(tb); \
45 do \
46 { \
47 } \
48 while (0)
49
50 #define END_TB_TEST() \
51 do \
52 { \
53    evas_textblock_cursor_free(cur); \
54    evas_object_del(tb); \
55    evas_textblock_style_free(st); \
56    evas_free(evas); \
57    evas_shutdown(); \
58 } \
59 while (0)
60
61 START_TEST(evas_textblock_simple)
62 {
63    START_TB_TEST();
64    const char *buf = "Th<i>i</i>s is a <br> te<b>s</b>t.";
65    evas_object_textblock_text_markup_set(tb, buf);
66    fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
67    END_TB_TEST();
68 }
69 END_TEST
70
71 #define _CHECK_CURSOR_COORDS() \
72 do \
73 { \
74         Evas_Coord cx, cy, cw, ch; \
75         int ret; \
76         ret = evas_textblock_cursor_geometry_get(cur, &cx, &cy, &cw, &ch, \
77               NULL, EVAS_TEXTBLOCK_CURSOR_UNDER); \
78         fail_if(ret == -1); \
79         ret = evas_textblock_cursor_geometry_get(cur, &cx, &cy, &cw, &ch, \
80               NULL, EVAS_TEXTBLOCK_CURSOR_BEFORE); \
81         fail_if(ret == -1); \
82         ret = evas_textblock_cursor_char_geometry_get(cur, \
83               &cx, &cy, &cw, &ch); \
84         fail_if(ret == -1); \
85         ret = evas_textblock_cursor_pen_geometry_get(cur, &cx, &cy, &cw, &ch); \
86         fail_if(ret == -1); \
87         ret = evas_textblock_cursor_line_geometry_get(cur, \
88               &cx, &cy, &cw, &ch); \
89         fail_if(ret == -1); \
90 } \
91 while (0)
92 START_TEST(evas_textblock_cursor)
93 {
94    START_TB_TEST();
95    Evas_Coord x, y, w, h;
96    size_t i, len;
97    Evas_Coord nw, nh;
98    const char *buf = "This is a<br> test.<ps>Lets see if this works.<ps>עוד פסקה.";
99
100    /* Walk the textblock using cursor_char_next */
101    evas_object_textblock_text_markup_set(tb, buf);
102    fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
103    len = eina_unicode_utf8_get_len(buf) - 9; /* 9 because len(<br>) == 1 and len(<ps>) == 1 */
104    for (i = 0 ; i < len ; i++)
105      {
106         _CHECK_CURSOR_COORDS();
107
108         fail_if(evas_textblock_cursor_pos_get(cur) != (int) i);
109
110         fail_if(!evas_textblock_cursor_char_next(cur) && (i < len - 1));
111      }
112    fail_if(evas_textblock_cursor_char_next(cur));
113
114    /* Jump to positions all aronud the textblock */
115    evas_textblock_cursor_pos_set(cur, -1);
116    fail_if(evas_textblock_cursor_pos_get(cur) != 0);
117
118    evas_textblock_cursor_pos_set(cur, len + 5);
119    fail_if(evas_textblock_cursor_pos_get(cur) != (int) len);
120
121    for (i = 0 ; i < len ; i++)
122      {
123         evas_textblock_cursor_pos_set(cur, i);
124
125         _CHECK_CURSOR_COORDS();
126
127         fail_if(evas_textblock_cursor_pos_get(cur) != (int) i);
128      }
129
130    /* Create another cursor and insert text, making sure everything
131     * is in sync. */
132    evas_object_textblock_clear(tb);
133    Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
134    evas_textblock_cursor_copy(main_cur, cur);
135    fail_if(evas_textblock_cursor_pos_get(cur) !=
136          evas_textblock_cursor_pos_get(main_cur));
137
138    evas_textblock_cursor_text_prepend(main_cur, "a");
139    fail_if(evas_textblock_cursor_pos_get(cur) ==
140          evas_textblock_cursor_pos_get(main_cur));
141    evas_textblock_cursor_text_prepend(main_cur, "a");
142    fail_if(evas_textblock_cursor_pos_get(cur) ==
143          evas_textblock_cursor_pos_get(main_cur));
144
145    /* Insert text to a non-empty textblock */
146    evas_object_textblock_clear(tb);
147    evas_object_textblock_text_markup_set(tb, buf);
148    evas_textblock_cursor_copy(main_cur, cur);
149    fail_if(evas_textblock_cursor_pos_get(cur) !=
150          evas_textblock_cursor_pos_get(main_cur));
151
152    evas_textblock_cursor_text_prepend(main_cur, "a");
153    fail_if(evas_textblock_cursor_pos_get(cur) ==
154          evas_textblock_cursor_pos_get(main_cur));
155    evas_textblock_cursor_text_prepend(main_cur, "a");
156    fail_if(evas_textblock_cursor_pos_get(cur) ==
157          evas_textblock_cursor_pos_get(main_cur));
158
159    /* Make sure append works */
160    evas_textblock_cursor_copy(main_cur, cur);
161    fail_if(evas_textblock_cursor_pos_get(cur) !=
162          evas_textblock_cursor_pos_get(main_cur));
163    evas_textblock_cursor_text_append(main_cur, "a");
164    fail_if(evas_textblock_cursor_pos_get(cur) !=
165          evas_textblock_cursor_pos_get(main_cur));
166
167    /* Cursor comparison */
168    evas_textblock_cursor_pos_set(cur, 1);
169    evas_textblock_cursor_pos_set(main_cur, 2);
170    fail_if(evas_textblock_cursor_compare(cur, main_cur) != -1);
171
172    evas_textblock_cursor_pos_set(cur, 2);
173    evas_textblock_cursor_pos_set(main_cur, 2);
174    fail_if(evas_textblock_cursor_compare(cur, main_cur) != 0);
175
176    evas_textblock_cursor_pos_set(cur, 3);
177    evas_textblock_cursor_pos_set(main_cur, 2);
178    fail_if(evas_textblock_cursor_compare(cur, main_cur) != 1);
179
180    /* Paragraph first */
181    evas_object_textblock_text_markup_set(tb, buf);
182    for (i = 0 ; i < len ; i++)
183      {
184         evas_textblock_cursor_pos_set(cur, i);
185
186         evas_textblock_cursor_paragraph_first(cur);
187         fail_if(evas_textblock_cursor_pos_get(cur) != 0);
188      }
189
190    /* Paragraph last */
191    for (i = 0 ; i < len ; i++)
192      {
193         evas_textblock_cursor_pos_set(cur, i);
194
195         evas_textblock_cursor_paragraph_last(cur);
196         fail_if(evas_textblock_cursor_pos_get(cur) != (int) len);
197      }
198
199    /* Paragraph next */
200    evas_textblock_cursor_paragraph_last(cur);
201    fail_if(evas_textblock_cursor_paragraph_next(cur));
202
203    evas_textblock_cursor_paragraph_first(cur);
204    fail_if(!evas_textblock_cursor_paragraph_next(cur));
205    fail_if(!evas_textblock_cursor_paragraph_next(cur));
206
207    /* Paragraph prev */
208    evas_textblock_cursor_paragraph_first(cur);
209    fail_if(evas_textblock_cursor_paragraph_prev(cur));
210
211    evas_textblock_cursor_paragraph_last(cur);
212    fail_if(!evas_textblock_cursor_paragraph_prev(cur));
213    fail_if(!evas_textblock_cursor_paragraph_prev(cur));
214
215    /* Cher next */
216    evas_textblock_cursor_paragraph_last(cur);
217    fail_if(evas_textblock_cursor_char_next(cur));
218
219    evas_textblock_cursor_paragraph_first(cur);
220    fail_if(!evas_textblock_cursor_char_next(cur));
221    fail_if(!evas_textblock_cursor_paragraph_next(cur));
222    fail_if(!evas_textblock_cursor_char_next(cur));
223    fail_if(!evas_textblock_cursor_paragraph_next(cur));
224    fail_if(!evas_textblock_cursor_char_next(cur));
225
226    /* Cher prev */
227    evas_textblock_cursor_paragraph_first(cur);
228    fail_if(evas_textblock_cursor_char_prev(cur));
229
230    evas_textblock_cursor_paragraph_last(cur);
231    fail_if(!evas_textblock_cursor_char_prev(cur));
232    fail_if(!evas_textblock_cursor_paragraph_prev(cur));
233    fail_if(!evas_textblock_cursor_char_prev(cur));
234
235    /* Paragraph char first */
236    evas_textblock_cursor_paragraph_first(main_cur);
237    evas_textblock_cursor_paragraph_first(cur);
238    fail_if(!evas_textblock_cursor_char_next(cur));
239    evas_textblock_cursor_paragraph_char_first(cur);
240    fail_if(evas_textblock_cursor_compare(cur, main_cur));
241
242    /* Paragraph char last */
243    evas_textblock_cursor_paragraph_last(main_cur);
244    evas_textblock_cursor_paragraph_last(cur);
245    fail_if(!evas_textblock_cursor_char_prev(cur));
246    evas_textblock_cursor_paragraph_char_last(cur);
247    fail_if(evas_textblock_cursor_compare(cur, main_cur));
248
249    /* Line char first */
250    evas_textblock_cursor_paragraph_first(main_cur);
251    evas_textblock_cursor_paragraph_first(cur);
252    fail_if(!evas_textblock_cursor_char_next(cur));
253    evas_textblock_cursor_line_char_first(cur);
254    fail_if(evas_textblock_cursor_compare(cur, main_cur));
255
256    evas_textblock_cursor_pos_set(cur, 12);
257    evas_textblock_cursor_line_char_first(cur);
258    fail_if(evas_textblock_cursor_pos_get(cur) != 10);
259
260    /* Line char first */
261    evas_textblock_cursor_paragraph_last(main_cur);
262    evas_textblock_cursor_paragraph_last(cur);
263    fail_if(!evas_textblock_cursor_char_prev(cur));
264    evas_textblock_cursor_line_char_last(cur);
265    fail_if(evas_textblock_cursor_compare(cur, main_cur));
266
267    evas_textblock_cursor_pos_set(cur, 12);
268    evas_textblock_cursor_line_char_last(cur);
269    fail_if(evas_textblock_cursor_pos_get(cur) != 16);
270
271    /* Line set */
272    evas_textblock_cursor_paragraph_first(main_cur);
273    evas_textblock_cursor_paragraph_last(cur);
274
275    fail_if(!evas_textblock_cursor_line_set(cur, 0));
276    fail_if(evas_textblock_cursor_compare(cur, main_cur));
277    fail_if(!evas_textblock_cursor_line_set(cur, 1));
278    fail_if(!evas_textblock_cursor_line_set(cur, 2));
279    fail_if(!evas_textblock_cursor_line_set(cur, 3));
280
281    fail_if(evas_textblock_cursor_line_set(cur, -1));
282    fail_if(evas_textblock_cursor_line_set(cur, 99));
283
284    /* Paragraph text get */
285    evas_textblock_cursor_paragraph_first(cur);
286    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
287             "This is a<br> test."));
288    evas_textblock_cursor_paragraph_next(cur);
289    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
290             "Lets see if this works."));
291    evas_textblock_cursor_paragraph_next(cur);
292    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
293             "עוד פסקה."));
294
295    /* Paragraph length get */
296    evas_textblock_cursor_paragraph_first(cur);
297    /* -3 because len(<br>) == 1 */
298    fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
299             eina_unicode_utf8_get_len("This is a<br> test.") - 3);
300    evas_textblock_cursor_paragraph_next(cur);
301    fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
302             eina_unicode_utf8_get_len("Lets see if this works."));
303    evas_textblock_cursor_paragraph_next(cur);
304    fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
305             eina_unicode_utf8_get_len("עוד פסקה."));
306
307    /* Cursor content get */
308    evas_textblock_cursor_pos_set(cur, 0);
309    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "T"));
310    evas_textblock_cursor_pos_set(cur, 9);
311    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<br>"));
312    evas_textblock_cursor_pos_set(cur, 43);
313    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "ד"));
314
315    /* Eol get */
316    for (i = 0 ; i < len ; i++)
317      {
318         evas_textblock_cursor_pos_set(cur, i);
319         evas_textblock_cursor_copy(cur, main_cur);
320         evas_textblock_cursor_line_char_last(main_cur);
321
322         if (!evas_textblock_cursor_compare(cur, main_cur))
323           {
324              fail_if(!evas_textblock_cursor_eol_get(cur));
325           }
326         else
327           {
328              fail_if(evas_textblock_cursor_eol_get(cur));
329           }
330      }
331
332    /* Format positions */
333    const Evas_Object_Textblock_Node_Format *fnode;
334    fnode = evas_textblock_node_format_first_get(tb);
335    fail_if(!fnode);
336    evas_textblock_cursor_at_format_set(cur, fnode);
337    evas_textblock_cursor_copy(cur, main_cur);
338    fail_if(evas_textblock_cursor_pos_get(cur) != 9);
339    fail_if(evas_textblock_cursor_format_get(cur) != fnode);
340
341    fnode = evas_textblock_node_format_next_get(fnode);
342    fail_if(!fnode);
343    evas_textblock_cursor_at_format_set(cur, fnode);
344    fail_if(evas_textblock_cursor_pos_get(cur) != 16);
345    fail_if(evas_textblock_cursor_format_get(cur) != fnode);
346    evas_textblock_cursor_format_next(main_cur);
347    fail_if(evas_textblock_cursor_compare(main_cur, cur));
348
349    fnode = evas_textblock_node_format_prev_get(fnode);
350    fail_if(!fnode);
351    evas_textblock_cursor_at_format_set(cur, fnode);
352    fail_if(evas_textblock_cursor_pos_get(cur) != 9);
353    fail_if(evas_textblock_cursor_format_get(cur) != fnode);
354    evas_textblock_cursor_format_prev(main_cur);
355    fail_if(evas_textblock_cursor_compare(main_cur, cur));
356
357    evas_textblock_cursor_char_next(main_cur);
358    evas_textblock_cursor_format_prev(main_cur);
359    fail_if(evas_textblock_cursor_compare(main_cur, cur));
360
361
362    evas_object_textblock_text_markup_set(tb, buf);
363
364    /* Check that pen geometry and getting char at coord are in sync. */
365    do
366      {
367         int cur_pos;
368
369         /* Check if it's the last char, if it is, break, otherwise, go back
370          * to the current char because our test advanced the cursor. */
371         if (!evas_textblock_cursor_char_next(cur))
372            break;
373         else
374            evas_textblock_cursor_char_prev(cur);
375
376         cur_pos = evas_textblock_cursor_pos_get(cur);
377         evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
378         evas_textblock_cursor_char_coord_set(cur, x + (w / 2), y + (h / 2));
379         fail_if(cur_pos != evas_textblock_cursor_pos_get(cur));
380      }
381    while (evas_textblock_cursor_char_next(cur));
382
383    /* Try positions before the first paragraph, and after the last paragraph */
384    evas_object_textblock_text_markup_set(tb, buf);
385    evas_object_textblock_size_native_get(tb, &nw, &nh);
386    evas_object_resize(tb, nw, nh);
387    evas_textblock_cursor_pos_set(cur, 5);
388    evas_textblock_cursor_char_coord_set(cur, nw / 2,
389          -50);
390    evas_textblock_cursor_paragraph_first(main_cur);
391    fail_if(evas_textblock_cursor_compare(cur, main_cur));
392
393    evas_textblock_cursor_pos_set(cur, 5);
394    evas_textblock_cursor_char_coord_set(cur, nw / 2,
395          nh + 50);
396    evas_textblock_cursor_paragraph_last(main_cur);
397    fail_if(evas_textblock_cursor_compare(cur, main_cur));
398
399    /* Try positions beyond the left/right limits of lines. */
400    for (i = 0 ; i < 2 ; i++)
401      {
402         evas_textblock_cursor_line_set(cur, i);
403         evas_textblock_cursor_line_geometry_get(cur, &x, &y, &w, &h);
404
405         evas_textblock_cursor_pos_set(main_cur, 5);
406         evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
407         fail_if(evas_textblock_cursor_compare(main_cur, cur));
408
409         evas_textblock_cursor_line_char_last(cur);
410         evas_textblock_cursor_pos_set(main_cur, 5);
411         evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
412         fail_if(evas_textblock_cursor_compare(main_cur, cur));
413      }
414
415 #ifdef HAVE_FRIBIDI
416    evas_object_textblock_text_markup_set(tb,
417          "testנסיוןtestנסיון<ps>"
418          "נסיוןtestנסיוןtest<ps>"
419          "testנסיוןtest<ps>"
420          "נסיוןtestנסיון<ps>"
421          "testנסיון<br>נסיון<ps>"
422          "נסיוןtest<br>test"
423          );
424
425    for (i = 0 ; i < 8 ; i++)
426      {
427         evas_textblock_cursor_line_set(cur, i);
428         evas_textblock_cursor_line_geometry_get(cur, &x, &y, &w, &h);
429         switch (i)
430           {
431            case 0:
432            case 2:
433            case 4:
434            case 5:
435               /* Ltr paragraph */
436               evas_textblock_cursor_pos_set(main_cur, 7);
437               evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
438               fail_if(evas_textblock_cursor_compare(main_cur, cur));
439
440               evas_textblock_cursor_line_char_last(cur);
441               evas_textblock_cursor_pos_set(main_cur, 7);
442               evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
443               fail_if(evas_textblock_cursor_compare(main_cur, cur));
444               break;
445            case 1:
446            case 3:
447            case 6:
448            case 7:
449               /* Rtl paragraph */
450               evas_textblock_cursor_line_char_last(cur);
451               evas_textblock_cursor_pos_set(main_cur, 7);
452               evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
453               fail_if(evas_textblock_cursor_compare(main_cur, cur));
454
455               evas_textblock_cursor_line_char_first(cur);
456               evas_textblock_cursor_pos_set(main_cur, 7);
457               evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
458               fail_if(evas_textblock_cursor_compare(main_cur, cur));
459               break;
460           }
461      }
462 #endif
463
464    evas_object_textblock_text_markup_set(tb, buf);
465    /* Testing line geometry.*/
466      {
467         Evas_Coord lx, ly, lw, lh;
468         Evas_Coord plx, ply, plw, plh;
469         evas_textblock_cursor_line_set(cur, 0);
470         evas_textblock_cursor_copy(cur, main_cur);
471         evas_textblock_cursor_line_char_last(main_cur);
472         evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
473
474         while (evas_textblock_cursor_compare(cur, main_cur) <= 0)
475           {
476              evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
477              fail_if(0 != evas_textblock_cursor_line_geometry_get(
478                       cur, &lx, &ly, &lw, &lh));
479              fail_if((x < lx) || (x + w > lx + lw) ||
480                    (y < ly) || (y + h > ly + lh));
481              fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
482
483              plx = lx;
484              ply = ly;
485              plw = lw;
486              plh = lh;
487              evas_textblock_cursor_char_next(cur);
488           }
489
490         evas_textblock_cursor_line_set(cur, 1);
491         evas_textblock_cursor_copy(cur, main_cur);
492         evas_textblock_cursor_line_char_last(main_cur);
493         evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
494
495         while (evas_textblock_cursor_compare(cur, main_cur) <= 0)
496           {
497              evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
498              fail_if(1 != evas_textblock_cursor_line_geometry_get(
499                       cur, &lx, &ly, &lw, &lh));
500              fail_if((x < lx) || (x + w > lx + lw) ||
501                    (y < ly) || (y + h > ly + lh));
502              fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
503
504              plx = lx;
505              ply = ly;
506              plw = lw;
507              plh = lh;
508              evas_textblock_cursor_char_next(cur);
509           }
510
511         evas_textblock_cursor_paragraph_last(cur);
512         evas_textblock_cursor_line_set(cur, 0);
513         evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
514         evas_object_textblock_line_number_geometry_get(tb, 0,
515               &lx, &ly, &lw, &lh);
516         fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
517         fail_if(0 != evas_textblock_cursor_line_coord_set(cur, ly + (lh / 2)));
518
519         evas_textblock_cursor_line_set(cur, 1);
520         evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
521         evas_object_textblock_line_number_geometry_get(tb, 1,
522               &lx, &ly, &lw, &lh);
523         fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
524         fail_if(1 != evas_textblock_cursor_line_coord_set(cur, ly + (lh / 2)));
525
526         /* Before the start of the textblock */
527         fail_if(0 != evas_textblock_cursor_line_coord_set(cur, -50));
528         fail_if(3 != evas_textblock_cursor_line_coord_set(cur, 100000));
529
530         /* And now with a valigned textblock. */
531         evas_object_textblock_text_markup_set(tb, buf);
532         evas_object_textblock_size_native_get(tb, &nw, &nh);
533         evas_object_resize(tb, 2 * nw, 2 * nh);
534
535         evas_object_textblock_valign_set(tb, 0.5);
536         evas_textblock_cursor_paragraph_first(cur);
537         evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
538         fail_if(y <= 0);
539
540         evas_textblock_cursor_paragraph_last(main_cur);
541         evas_textblock_cursor_char_coord_set(main_cur, x + w, y / 2);
542         fail_if(evas_textblock_cursor_compare(main_cur, cur));
543
544         evas_textblock_cursor_paragraph_last(main_cur);
545         evas_textblock_cursor_line_coord_set(main_cur, y / 2);
546         fail_if(evas_textblock_cursor_compare(main_cur, cur));
547
548         /* Fail if they are equal, i.e if it for some reason thinks it should
549          * go to the end. */
550         evas_textblock_cursor_paragraph_first(main_cur);
551         evas_textblock_cursor_paragraph_last(cur);
552         evas_textblock_cursor_char_coord_set(main_cur, x + w, nh + 1);
553         fail_if(!evas_textblock_cursor_compare(main_cur, cur));
554
555         evas_textblock_cursor_paragraph_first(main_cur);
556         evas_textblock_cursor_paragraph_last(cur);
557         evas_textblock_cursor_line_coord_set(main_cur, nh + 1);
558         fail_if(!evas_textblock_cursor_compare(main_cur, cur));
559
560         /* Fail if it doesn't go to the end. */
561         evas_textblock_cursor_paragraph_last(cur);
562         evas_textblock_cursor_paragraph_first(main_cur);
563         evas_textblock_cursor_char_coord_set(main_cur, x + w, (2 * nh) - 1);
564         fail_if(evas_textblock_cursor_compare(main_cur, cur));
565
566         evas_textblock_cursor_paragraph_first(main_cur);
567         evas_textblock_cursor_line_coord_set(main_cur, (2 * nh) - 1);
568         fail_if(evas_textblock_cursor_compare(main_cur, cur));
569      }
570
571    END_TB_TEST();
572 }
573 END_TEST
574
575 START_TEST(evas_textblock_format_removal)
576 {
577    START_TB_TEST();
578    int i;
579    const char *buf = "Th<b>is a<a>tes</a>st</b>.";
580    const Evas_Object_Textblock_Node_Format *fnode;
581    Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
582    evas_object_textblock_text_markup_set(tb, buf);
583
584    /* Remove the "b" pair. */
585    fnode = evas_textblock_node_format_first_get(tb);
586    evas_textblock_node_format_remove_pair(tb,
587          (Evas_Object_Textblock_Node_Format *) fnode);
588
589    fnode = evas_textblock_node_format_first_get(tb);
590    fail_if (!fnode);
591    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
592             "+ a"));
593
594    fnode = evas_textblock_node_format_next_get(fnode);
595    fail_if (!fnode);
596    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
597             "- a"));
598
599    fnode = evas_textblock_node_format_next_get(fnode);
600    fail_if (fnode);
601
602    /* Now also remove the a pair */
603    fnode = evas_textblock_node_format_first_get(tb);
604    evas_textblock_node_format_remove_pair(tb,
605          (Evas_Object_Textblock_Node_Format *) fnode);
606    fnode = evas_textblock_node_format_first_get(tb);
607    fail_if (fnode);
608
609    /* Remove the "a" pair. */
610    evas_object_textblock_text_markup_set(tb, buf);
611
612    fnode = evas_textblock_node_format_first_get(tb);
613    fnode = evas_textblock_node_format_next_get(fnode);
614    evas_textblock_node_format_remove_pair(tb,
615          (Evas_Object_Textblock_Node_Format *) fnode);
616
617    fnode = evas_textblock_node_format_first_get(tb);
618    fail_if (!fnode);
619    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
620             "+ b"));
621
622    fnode = evas_textblock_node_format_next_get(fnode);
623    fail_if (!fnode);
624    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
625             "- b"));
626
627    fnode = evas_textblock_node_format_next_get(fnode);
628    fail_if (fnode);
629
630    /* Now also remove the b pair */
631    fnode = evas_textblock_node_format_first_get(tb);
632    evas_textblock_node_format_remove_pair(tb,
633          (Evas_Object_Textblock_Node_Format *) fnode);
634    fnode = evas_textblock_node_format_first_get(tb);
635    fail_if (fnode);
636
637    /* Now remove formats by removing text */
638    evas_object_textblock_text_markup_set(tb, buf);
639    evas_textblock_cursor_pos_set(cur, 6);
640    evas_textblock_cursor_char_delete(cur);
641    evas_textblock_cursor_char_delete(cur);
642    evas_textblock_cursor_char_delete(cur);
643    /* Only b formats should remain */
644    fnode = evas_textblock_node_format_first_get(tb);
645    fail_if (!fnode);
646    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
647             "+ b"));
648
649    fnode = evas_textblock_node_format_next_get(fnode);
650    fail_if (!fnode);
651    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
652             "- b"));
653
654    fnode = evas_textblock_node_format_next_get(fnode);
655    fail_if (fnode);
656
657    /* No formats should remain. */
658    evas_textblock_cursor_pos_set(cur, 2);
659    evas_textblock_cursor_char_delete(cur);
660    evas_textblock_cursor_char_delete(cur);
661    evas_textblock_cursor_char_delete(cur);
662    evas_textblock_cursor_char_delete(cur);
663    evas_textblock_cursor_char_delete(cur);
664    evas_textblock_cursor_char_delete(cur);
665    fnode = evas_textblock_node_format_first_get(tb);
666    fail_if (fnode);
667
668    /* Try to remove the formats in a way that shouldn't remove them */
669    evas_object_textblock_text_markup_set(tb, buf);
670    evas_textblock_cursor_pos_set(cur, 7);
671    evas_textblock_cursor_char_delete(cur);
672    evas_textblock_cursor_char_delete(cur);
673    evas_textblock_cursor_char_delete(cur);
674    evas_textblock_cursor_char_delete(cur);
675    fnode = evas_textblock_node_format_first_get(tb);
676    fail_if (!fnode);
677    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
678             "+ b"));
679
680    fnode = evas_textblock_node_format_next_get(fnode);
681    fail_if (!fnode);
682    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
683             "+ a"));
684
685    fnode = evas_textblock_node_format_next_get(fnode);
686    fail_if (!fnode);
687    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
688             "- a"));
689
690    fnode = evas_textblock_node_format_next_get(fnode);
691    fail_if (!fnode);
692    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
693             "- b"));
694
695    fnode = evas_textblock_node_format_next_get(fnode);
696    fail_if (fnode);
697
698    /* Try range deletion to delete a */
699    evas_object_textblock_text_markup_set(tb, buf);
700    evas_textblock_cursor_pos_set(cur, 6);
701    evas_textblock_cursor_pos_set(main_cur, 9);
702    evas_textblock_cursor_range_delete(cur, main_cur);
703    fnode = evas_textblock_node_format_first_get(tb);
704    fail_if (!fnode);
705    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
706             "+ b"));
707
708    fnode = evas_textblock_node_format_next_get(fnode);
709    fail_if (!fnode);
710    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
711             "- b"));
712
713    fnode = evas_textblock_node_format_next_get(fnode);
714    fail_if (fnode);
715
716    /* Range deletion to delete both */
717    evas_object_textblock_text_markup_set(tb, buf);
718    evas_textblock_cursor_pos_set(cur, 2);
719    evas_textblock_cursor_pos_set(main_cur, 11);
720    evas_textblock_cursor_range_delete(cur, main_cur);
721    fnode = evas_textblock_node_format_first_get(tb);
722    fail_if (fnode);
723
724    /* Range deletion across paragraphs */
725    evas_object_textblock_text_markup_set(tb,
726          "Th<b>is a<a>te<ps>"
727          "s</a>st</b>.");
728    evas_textblock_cursor_pos_set(cur, 6);
729    evas_textblock_cursor_pos_set(main_cur, 10);
730    evas_textblock_cursor_range_delete(cur, main_cur);
731    fnode = evas_textblock_node_format_first_get(tb);
732    fail_if (!fnode);
733    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
734             "+ b"));
735
736    fnode = evas_textblock_node_format_next_get(fnode);
737    fail_if (!fnode);
738    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
739             "- b"));
740
741    fnode = evas_textblock_node_format_next_get(fnode);
742    fail_if (fnode);
743
744    /* Two formats in the same place. */
745    evas_object_textblock_text_markup_set(tb, "a<b><a>b</a></b>b");
746    evas_textblock_cursor_pos_set(cur, 1);
747    evas_textblock_cursor_char_delete(cur);
748    fnode = evas_textblock_node_format_first_get(tb);
749    fail_if (fnode);
750
751    /* Two formats across different paragraphs with notihng in between. */
752    evas_object_textblock_text_markup_set(tb, "<b><ps></b>");
753    evas_textblock_cursor_pos_set(cur, 0);
754    evas_textblock_cursor_char_delete(cur);
755    fnode = evas_textblock_node_format_first_get(tb);
756    fail_if (fnode);
757
758    /* Try with range */
759    evas_object_textblock_text_markup_set(tb, "<b><ps></b>");
760    evas_textblock_cursor_pos_set(cur, 0);
761    evas_textblock_cursor_pos_set(main_cur, 1);
762    evas_textblock_cursor_range_delete(cur, main_cur);
763    fnode = evas_textblock_node_format_first_get(tb);
764    fail_if (fnode);
765
766    /* Verify fmt position and REP_CHAR positions are the same */
767    evas_object_textblock_text_markup_set(tb,
768          "This is<ps>an <item absize=93x152 vsize=ascent></>a.");
769    evas_textblock_cursor_pos_set(cur, 7);
770    evas_textblock_cursor_char_delete(cur);
771    fnode = evas_textblock_node_format_first_get(tb);
772    fail_if(_evas_textblock_format_offset_get(fnode) != 10);
773
774    /* Out of order <b><i></b></i> mixes. */
775    evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</i>e");
776    evas_textblock_cursor_pos_set(cur, 2);
777
778    for (i = 0 ; i < 2 ; i++)
779      {
780         fnode = evas_textblock_node_format_first_get(tb);
781         fail_if (!fnode);
782         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
783
784         fnode = evas_textblock_node_format_next_get(fnode);
785         fail_if (!fnode);
786         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
787
788         fnode = evas_textblock_node_format_next_get(fnode);
789         fail_if (!fnode);
790         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
791
792         fnode = evas_textblock_node_format_next_get(fnode);
793         fail_if (!fnode);
794         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
795
796         fnode = evas_textblock_node_format_next_get(fnode);
797         fail_if (fnode);
798
799         evas_textblock_cursor_char_delete(cur);
800      }
801    fnode = evas_textblock_node_format_first_get(tb);
802    fail_if (!fnode);
803    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
804
805    fnode = evas_textblock_node_format_next_get(fnode);
806    fail_if (!fnode);
807    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
808
809    fnode = evas_textblock_node_format_next_get(fnode);
810    fail_if (fnode);
811
812    /* This time with a generic closer */
813    evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</>e");
814    evas_textblock_cursor_pos_set(cur, 2);
815
816    for (i = 0 ; i < 2 ; i++)
817      {
818         fnode = evas_textblock_node_format_first_get(tb);
819         fail_if (!fnode);
820         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
821
822         fnode = evas_textblock_node_format_next_get(fnode);
823         fail_if (!fnode);
824         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
825
826         fnode = evas_textblock_node_format_next_get(fnode);
827         fail_if (!fnode);
828         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
829
830         fnode = evas_textblock_node_format_next_get(fnode);
831         fail_if (!fnode);
832         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
833
834         fnode = evas_textblock_node_format_next_get(fnode);
835         fail_if (fnode);
836
837         evas_textblock_cursor_char_delete(cur);
838      }
839    fnode = evas_textblock_node_format_first_get(tb);
840    fail_if (!fnode);
841    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
842
843    fnode = evas_textblock_node_format_next_get(fnode);
844    fail_if (!fnode);
845    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
846
847    fnode = evas_textblock_node_format_next_get(fnode);
848    fail_if (fnode);
849
850    /* And now with remove pair. */
851    evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</i>e");
852    evas_textblock_cursor_pos_set(cur, 2);
853    fnode = evas_textblock_node_format_first_get(tb);
854    evas_textblock_node_format_remove_pair(tb,
855          (Evas_Object_Textblock_Node_Format *) fnode);
856
857    fnode = evas_textblock_node_format_first_get(tb);
858    fail_if (!fnode);
859    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
860
861    fnode = evas_textblock_node_format_next_get(fnode);
862    fail_if (!fnode);
863    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
864
865    fnode = evas_textblock_node_format_next_get(fnode);
866    fail_if (fnode);
867
868    /* Remove the other pair */
869    evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</>d</i>e");
870    evas_textblock_cursor_pos_set(cur, 2);
871    fnode = evas_textblock_node_format_first_get(tb);
872    fnode = evas_textblock_node_format_next_get(fnode);
873    evas_textblock_node_format_remove_pair(tb,
874          (Evas_Object_Textblock_Node_Format *) fnode);
875
876    fnode = evas_textblock_node_format_first_get(tb);
877    fail_if (!fnode);
878    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
879
880    fnode = evas_textblock_node_format_next_get(fnode);
881    fail_if (!fnode);
882    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
883
884    fnode = evas_textblock_node_format_next_get(fnode);
885    fail_if (fnode);
886
887    /* Try to remove a format that doesn't have a pair (with a bad mkup) */
888    evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</>d</i>e");
889    evas_textblock_cursor_pos_set(cur, 2);
890    fnode = evas_textblock_node_format_first_get(tb);
891    evas_textblock_node_format_remove_pair(tb,
892          (Evas_Object_Textblock_Node_Format *) fnode);
893
894    fnode = evas_textblock_node_format_first_get(tb);
895    fail_if (!fnode);
896    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
897
898    fnode = evas_textblock_node_format_next_get(fnode);
899    fail_if (!fnode);
900    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
901
902    fnode = evas_textblock_node_format_next_get(fnode);
903    fail_if (!fnode);
904    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
905
906    fnode = evas_textblock_node_format_next_get(fnode);
907    fail_if (fnode);
908
909    END_TB_TEST();
910 }
911 END_TEST
912
913 /* Testing items */
914 START_TEST(evas_textblock_items)
915 {
916    Evas_Coord w, h, w2, h2, nw, nh, ih;
917    START_TB_TEST();
918    const char *buf = "This is an <item absize=93x152></>.";
919
920    /* Absolute item size */
921    buf = "This is an <item absize=93x152 vsize=full></>.";
922    evas_object_textblock_text_markup_set(tb, buf);
923    evas_object_textblock_size_formatted_get(tb, &w, &h);
924    fail_if((w < 93) || (h != 152));
925    evas_textblock_cursor_pos_set(cur, 11);
926    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
927    fail_if((w != 93) || (h != 152));
928
929    buf = "This is an <item absize=93x152 vsize=ascent></>.";
930    evas_object_textblock_text_markup_set(tb, buf);
931    evas_object_textblock_size_formatted_get(tb, &w, &h);
932    fail_if((w < 93) || (h <= 152));
933    evas_textblock_cursor_pos_set(cur, 11);
934    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
935    fail_if((w != 93) || (h != 152));
936
937    /* Size is the same as abssize, unless there's scaling applied. */
938    buf = "This is an <item size=93x152 vsize=full></>.";
939    evas_object_textblock_text_markup_set(tb, buf);
940    evas_object_textblock_size_formatted_get(tb, &w, &h);
941    fail_if((w < 93) || (h != 152));
942    evas_textblock_cursor_pos_set(cur, 11);
943    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
944    fail_if((w != 93) || (h != 152));
945
946    buf = "This is an <item size=93x152 vsize=ascent></>.";
947    evas_object_textblock_text_markup_set(tb, buf);
948    evas_object_textblock_size_formatted_get(tb, &w, &h);
949    fail_if((w < 93) || (h <= 152));
950    evas_textblock_cursor_pos_set(cur, 11);
951    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
952    fail_if((w != 93) || (h != 152));
953
954    evas_object_scale_set(tb, 2.0);
955    buf = "This is an <item size=93x152 vsize=full></>.";
956    evas_object_textblock_text_markup_set(tb, buf);
957    evas_object_textblock_size_formatted_get(tb, &w, &h);
958    fail_if((w < (2 * 93)) || (h != (2 * 152)));
959    evas_textblock_cursor_pos_set(cur, 11);
960    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
961    fail_if((w != (2 * 93)) || (h != (2 * 152)));
962    evas_textblock_cursor_pos_set(cur, 11);
963    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
964    fail_if((w != (2 * 93)) || (h != (2 * 152)));
965
966    buf = "This is an <item size=93x152 vsize=ascent></>.";
967    evas_object_textblock_text_markup_set(tb, buf);
968    evas_object_textblock_size_formatted_get(tb, &w, &h);
969    fail_if((w < (2 * 93)) || (h <= (2 * 152)));
970    evas_textblock_cursor_pos_set(cur, 11);
971    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
972    fail_if((w != (2 * 93)) || (h != (2 * 152)));
973
974    evas_object_scale_set(tb, 1.0);
975
976    /* Relsize */
977    /* relsize means it should adjust itself to the size of the line */
978    buf = "This is an <item relsize=93x152 vsize=full></>.";
979    evas_object_textblock_text_markup_set(tb, buf);
980    evas_object_textblock_size_formatted_get(tb, &w, &h);
981    fail_if((w >= 93) || (h >= 152));
982    evas_textblock_cursor_pos_set(cur, 11);
983    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &ih);
984    fail_if((w > 90) || (h != ih));
985
986    buf = "This is an <item relize=93x152 vsize=ascent></>.";
987    evas_object_textblock_text_markup_set(tb, buf);
988    evas_object_textblock_size_formatted_get(tb, &w, &h);
989    fail_if((w >= 93) || (h >= 152));
990    evas_textblock_cursor_pos_set(cur, 11);
991    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &ih);
992    fail_if((w > 90) || (h <= ih));
993
994    /* Relsize and abs size in the same line, all should be the same size */
995    buf = "<item relsize=64x64 vsize=ascent href=emoticon/knowing-grin></item><item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item><item relsize=64x64 vsize=ascent href=emoticon/knowing-grin></item>";
996    evas_object_textblock_text_markup_set(tb, buf);
997    evas_object_textblock_size_formatted_get(tb, &w, &h);
998    evas_object_textblock_size_native_get(tb, &nw, &nh);
999    fail_if((nw != w) || (nh != h));
1000    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
1001    evas_textblock_cursor_char_next(cur);
1002    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w2, &h2);
1003    fail_if((w != w2) || (h != h2));
1004    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
1005    evas_textblock_cursor_char_next(cur);
1006    evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w2, &h2);
1007    fail_if((w != w2) || (h != h2));
1008
1009    /* FIXME: Also verify x,y positions of the item. */
1010
1011    /* FIXME We need some item tests that involve line wrapping that make the
1012     * items move between lines that are in different sizes.
1013     * Also, tests that involve wrapping positions with relsized items. We
1014     * want to make sure the item gets a relsize on the correct time (before
1015     * the wrapping, and then is updated after the wrapping) and that
1016     * all the lines have the correct sizes afterwards. */
1017
1018    END_TB_TEST();
1019 }
1020 END_TEST
1021
1022 /* Wrapping tests */
1023 START_TEST(evas_textblock_wrapping)
1024 {
1025    Evas_Coord bw, bh, w, h, nw, nh;
1026    int i;
1027    START_TB_TEST();
1028    evas_object_textblock_text_markup_set(tb, "a");
1029    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1030
1031    /* Char wrap */
1032    evas_object_textblock_text_markup_set(tb, "aaaaaaa");
1033    evas_textblock_cursor_format_prepend(cur, "+ wrap=char");
1034    evas_object_resize(tb, bw, bh);
1035    evas_object_textblock_size_formatted_get(tb, &w, &h);
1036    /* Wrap to minimum */
1037    fail_if(w != bw);
1038    fail_if(h <= bh);
1039
1040    /* Mixed - fallback to char wrap */
1041    evas_object_textblock_text_markup_set(tb, "aaaaaaa");
1042    evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
1043    evas_object_resize(tb, bw, bh);
1044    evas_object_textblock_size_formatted_get(tb, &w, &h);
1045    /* Wrap to minimum */
1046    fail_if(w != bw);
1047    fail_if(h <= bh);
1048
1049    /* Basic Word wrap */
1050    evas_object_textblock_text_markup_set(tb, "aaaa");
1051    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1052
1053    evas_object_textblock_text_markup_set(tb, "aaaa aa");
1054    evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
1055    evas_object_resize(tb, bw, bh);
1056    evas_object_textblock_size_formatted_get(tb, &w, &h);
1057    /* Wrap to minimum */
1058    fail_if(w != bw);
1059    fail_if(h <= bh);
1060
1061    /* Mixed - fallback to word wrap */
1062    evas_object_textblock_text_markup_set(tb, "aaaa aa");
1063    evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
1064    evas_object_resize(tb, bw + 1, bh);
1065    evas_object_textblock_size_formatted_get(tb, &w, &h);
1066    /* Wrap to minimum */
1067    fail_if(w != bw);
1068    fail_if(h <= bh);
1069
1070    /* Wrap and then expand again. */
1071    evas_object_textblock_text_markup_set(tb, "aaaa aa");
1072    evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
1073    evas_object_resize(tb, bw, bh);
1074    evas_object_textblock_size_formatted_get(tb, &w, &h);
1075    evas_object_textblock_size_native_get(tb, &nw, &nh);
1076    evas_object_resize(tb, nw, nh);
1077    evas_object_textblock_size_formatted_get(tb, &w, &h);
1078    fail_if((w != nw) || (h != nh));
1079
1080    /* Reduce size until reaching the minimum, making sure we don't
1081     * get something wrong along the way */
1082    /* Char wrap */
1083    evas_object_textblock_text_markup_set(tb, "a");
1084    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1085    evas_object_textblock_text_markup_set(tb,
1086          "aaaa aaaa aaa aa aaa<ps>"
1087          "aaaa aaa aaa aaa aaa<ps>"
1088          "a aaaaa aaaaaaaaaaaaaa<br>aaaaa<ps>"
1089          "aaaaaa"
1090          );
1091    evas_textblock_cursor_format_prepend(cur, "+ wrap=char");
1092    evas_object_textblock_size_native_get(tb, &nw, &nh);
1093
1094    Evas_Coord iw;
1095    for (iw = nw ; iw >= bw ; iw--)
1096      {
1097         evas_object_resize(tb, iw, 1000);
1098         evas_object_textblock_size_formatted_get(tb, &w, &h);
1099         fail_if(w < bw);
1100         fail_if(w > iw);
1101      }
1102    fail_if(w != bw);
1103
1104    /* Word wrap */
1105    evas_object_textblock_text_markup_set(tb, "aaaaaa");
1106    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1107    evas_object_textblock_text_markup_set(tb,
1108          "aaaa aaaa aaa aa aaa<ps>"
1109          "aaaa aaa aaa aaa aaa<ps>"
1110          "a aaaaa aaaaaa<br>aaaaa<ps>"
1111          "aaaaa"
1112          );
1113    evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
1114    evas_object_textblock_size_native_get(tb, &nw, &nh);
1115
1116    for (iw = nw ; iw >= bw ; iw--)
1117      {
1118         evas_object_resize(tb, iw, 1000);
1119         evas_object_textblock_size_formatted_get(tb, &w, &h);
1120         fail_if(w < bw);
1121         fail_if(w > iw);
1122      }
1123    fail_if(w != bw);
1124
1125    /* Mixed wrap */
1126    evas_object_textblock_text_markup_set(tb, "a");
1127    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1128    evas_object_textblock_text_markup_set(tb,
1129          "aaaa aaaa aaa aa aaa<ps>"
1130          "aaaa aaa aaa aaa aaa<ps>"
1131          "a aaaaa aaaaaa<br>aaaaa<ps>"
1132          "aaaaa"
1133          );
1134    evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
1135    evas_object_textblock_size_native_get(tb, &nw, &nh);
1136
1137    for (iw = nw ; iw >= bw ; iw--)
1138      {
1139         evas_object_resize(tb, iw, 1000);
1140         evas_object_textblock_size_formatted_get(tb, &w, &h);
1141         fail_if(w < bw);
1142         fail_if(w > iw);
1143      }
1144    fail_if(w != bw);
1145
1146    /* Resize, making sure we keep going down in the minimum size. */
1147    char *wrap_style[] = { "+ wrap=word", "+ wrap=char", "+ wrap=mixed" };
1148    int wrap_items = sizeof(wrap_style) / sizeof(*wrap_style);
1149
1150    evas_object_textblock_text_markup_set(tb,
1151          "This is an entry widget in this window that<br>"
1152          "uses markup <b>like this</> for styling and<br>"
1153          "formatting <em>like this</>, as well as<br>"
1154          "<a href=X><link>links in the text</></a>, so enter text<br>"
1155          "in here to edit it. By the way, links are<br>"
1156          "called <a href=anc-02>Anchors</a> so you will need<br>"
1157          "to refer to them this way.<br>"
1158          "<br>"
1159
1160          "Also you can stick in items with (relsize + ascent): "
1161          "<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
1162          " (full) "
1163          "<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
1164          " (to the left)<br>"
1165
1166          "Also (size + ascent): "
1167          "<item size=16x16 vsize=ascent href=emoticon/haha></item>"
1168          " (full) "
1169          "<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
1170          " (before this)<br>"
1171
1172          "And as well (absize + ascent): "
1173          "<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
1174          " (full) "
1175          "<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
1176          " or even paths to image files on disk too like: "
1177          "<item absize=96x128 vsize=full href=file://%s/images/sky_01.jpg></item>"
1178          " ... end."
1179          );
1180
1181    /* Get minimum size */
1182    evas_object_textblock_size_native_get(tb, &nw, &nh);
1183
1184    for (i = 0 ; i < wrap_items ; i++)
1185      {
1186         evas_textblock_cursor_format_prepend(cur, wrap_style[i]);
1187         evas_object_resize(tb, 0, 0);
1188         evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1189
1190         for (iw = nw ; iw >= bw ; iw--)
1191           {
1192              evas_object_resize(tb, iw, 1000);
1193              evas_object_textblock_size_formatted_get(tb, &w, &h);
1194              fail_if(w < bw);
1195              fail_if(w > iw);
1196           }
1197         fail_if(w != bw);
1198      }
1199
1200
1201    /* Ellipsis */
1202    evas_object_textblock_text_markup_set(tb, "aaaaaaaaaa");
1203    evas_textblock_cursor_format_prepend(cur, "+ ellipsis=1.0");
1204    evas_object_textblock_size_native_get(tb, &nw, &nh);
1205    evas_object_resize(tb, nw / 2, nh);
1206    evas_object_textblock_size_formatted_get(tb, &w, &h);
1207    fail_if((w > (nw / 2)) || (h != nh));
1208
1209    END_TB_TEST();
1210 }
1211 END_TEST
1212
1213 /* Various textblock stuff */
1214 START_TEST(evas_textblock_various)
1215 {
1216    Evas_Coord w, h, bw, bh;
1217    START_TB_TEST();
1218    const char *buf = "This<ps>textblock<ps>has<ps>a<ps>lot<ps>of<ps>lines<ps>.";
1219    evas_object_textblock_text_markup_set(tb, buf);
1220    evas_object_textblock_size_formatted_get(tb, &w, &h);
1221    /* Move outside of the screen so it'll have to search for the correct
1222     * paragraph and etc. */
1223    evas_object_move(tb, -(w / 2), -(h / 2));
1224
1225    /* Replacement char */
1226    evas_object_textblock_text_markup_set(tb, "*");
1227    evas_object_textblock_size_formatted_get(tb, &bw, &bh);
1228    evas_object_textblock_replace_char_set(tb, "*");
1229    evas_object_textblock_text_markup_set(tb, "|");
1230    evas_object_textblock_size_formatted_get(tb, &w, &h);
1231    fail_if((w != bw) || (h != bh));
1232
1233    /* Items have correct text node information */
1234    evas_object_textblock_text_markup_set(tb, "");
1235    fail_if(!_evas_textblock_check_item_node_link(tb));
1236    evas_object_textblock_text_markup_set(tb, "<ps>");
1237    fail_if(!_evas_textblock_check_item_node_link(tb));
1238    evas_object_textblock_text_markup_set(tb, "a<ps>");
1239    fail_if(!_evas_textblock_check_item_node_link(tb));
1240    evas_object_textblock_text_markup_set(tb, "a<ps>a");
1241    fail_if(!_evas_textblock_check_item_node_link(tb));
1242    evas_object_textblock_text_markup_set(tb, "a<ps>a<ps>");
1243    fail_if(!_evas_textblock_check_item_node_link(tb));
1244    evas_object_textblock_text_markup_set(tb, "a<ps>a<ps>a");
1245    fail_if(!_evas_textblock_check_item_node_link(tb));
1246
1247    END_TB_TEST();
1248 }
1249 END_TEST
1250
1251 /* Various geometries. e.g. range geometry. */
1252 START_TEST(evas_textblock_geometries)
1253 {
1254    START_TB_TEST();
1255    const char *buf = "This is a <br> test.";
1256    evas_object_textblock_text_markup_set(tb, buf);
1257
1258    /* Single line range */
1259    Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
1260    evas_textblock_cursor_pos_set(cur, 0);
1261    evas_textblock_cursor_pos_set(main_cur, 6);
1262
1263    Eina_List *rects, *rects2;
1264    Evas_Textblock_Rectangle *tr, *tr2;
1265    rects = evas_textblock_cursor_range_geometry_get(cur, main_cur);
1266    fail_if(!rects);
1267    rects2 = evas_textblock_cursor_range_geometry_get(main_cur, cur);
1268    fail_if(!rects2);
1269
1270    fail_if(eina_list_count(rects) != 1);
1271    fail_if(eina_list_count(rects2) != 1);
1272
1273    tr = eina_list_data_get(rects);
1274    fail_if((tr->h <= 0) || (tr->w <= 0));
1275    tr2 = eina_list_data_get(rects2);
1276    fail_if((tr2->h <= 0) || (tr2->w <= 0));
1277
1278    fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
1279          (tr->h != tr2->h));
1280
1281    /* Multiline range */
1282    evas_textblock_cursor_pos_set(cur, 0);
1283    evas_textblock_cursor_pos_set(main_cur, 14);
1284
1285    rects = evas_textblock_cursor_range_geometry_get(cur, main_cur);
1286    fail_if(!rects);
1287    rects2 = evas_textblock_cursor_range_geometry_get(main_cur, cur);
1288    fail_if(!rects2);
1289
1290    fail_if(eina_list_count(rects) != 2);
1291    fail_if(eina_list_count(rects2) != 2);
1292
1293    tr = eina_list_data_get(rects);
1294    fail_if((tr->h <= 0) || (tr->w <= 0));
1295    tr2 = eina_list_data_get(rects2);
1296    fail_if((tr2->h <= 0) || (tr2->w <= 0));
1297
1298    fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
1299          (tr->h != tr2->h));
1300
1301    tr = eina_list_data_get(eina_list_next(rects));
1302    fail_if((tr->h <= 0) || (tr->w <= 0));
1303    tr2 = eina_list_data_get(eina_list_next(rects2));
1304    fail_if((tr2->h <= 0) || (tr2->w <= 0));
1305
1306    fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
1307          (tr->h != tr2->h));
1308
1309    /* Check that the second line is positioned below the first */
1310    tr = eina_list_data_get(rects);
1311    tr2 = eina_list_data_get(eina_list_next(rects));
1312    fail_if(tr->y >= tr2->y);
1313
1314    END_TB_TEST();
1315 }
1316 END_TEST
1317
1318 /* Should handle all the text editing. */
1319 START_TEST(evas_textblock_editing)
1320 {
1321    START_TB_TEST();
1322    const char *buf = "First par.<ps>Second par.";
1323    evas_object_textblock_text_markup_set(tb, buf);
1324    Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
1325
1326    /* Check deletion works */
1327    /* Try deleting after the end of the textblock */
1328      {
1329         char *content;
1330         evas_textblock_cursor_paragraph_last(cur);
1331         content = strdup(evas_object_textblock_text_markup_get(tb));
1332         evas_textblock_cursor_char_delete(cur);
1333         fail_if(strcmp(content, evas_object_textblock_text_markup_get(tb)));
1334         free(content);
1335      }
1336
1337    /* Delete the first char */
1338    evas_textblock_cursor_paragraph_first(cur);
1339    evas_textblock_cursor_char_delete(cur);
1340    fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
1341             "irst par.<ps>Second par."));
1342
1343    /* Delete some arbitrary char */
1344    evas_textblock_cursor_char_next(cur);
1345    evas_textblock_cursor_char_next(cur);
1346    evas_textblock_cursor_char_next(cur);
1347    evas_textblock_cursor_char_delete(cur);
1348    fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
1349             "irs par.<ps>Second par."));
1350
1351    /* Delete a range */
1352    evas_textblock_cursor_pos_set(main_cur, 1);
1353    evas_textblock_cursor_pos_set(cur, 6);
1354    evas_textblock_cursor_range_delete(cur, main_cur);
1355    fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
1356             "ir.<ps>Second par."));
1357    evas_textblock_cursor_paragraph_char_first(main_cur);
1358    evas_textblock_cursor_paragraph_char_last(cur);
1359    evas_textblock_cursor_char_next(cur);
1360    evas_textblock_cursor_range_delete(cur, main_cur);
1361    fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
1362             "Second par."));
1363
1364    evas_object_textblock_text_markup_set(tb, buf);
1365    evas_textblock_cursor_paragraph_last(main_cur);
1366    evas_object_textblock_text_markup_prepend(main_cur, "Test<b>bla</b>bla.");
1367    evas_textblock_cursor_paragraph_last(cur);
1368    evas_textblock_cursor_paragraph_char_first(main_cur);
1369    evas_textblock_cursor_range_delete(cur, main_cur);
1370    fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
1371             "First par.<ps>"));
1372
1373    /* Merging paragraphs */
1374    evas_object_textblock_text_markup_set(tb, buf);
1375    evas_textblock_cursor_paragraph_char_last(cur);
1376    evas_textblock_cursor_copy(cur, main_cur);
1377    evas_textblock_cursor_char_delete(cur);
1378
1379    evas_textblock_cursor_paragraph_first(cur);
1380    fail_if(evas_textblock_cursor_paragraph_next(cur));
1381
1382    /* Split paragraphs */
1383    evas_textblock_cursor_format_prepend(cur, "ps");
1384
1385    evas_textblock_cursor_paragraph_first(cur);
1386    fail_if(!evas_textblock_cursor_paragraph_next(cur));
1387    fail_if(evas_textblock_cursor_paragraph_next(cur));
1388
1389    /* Merge paragraphs using range deletion */
1390    evas_object_textblock_text_markup_set(tb, buf);
1391    evas_textblock_cursor_paragraph_first(cur);
1392    evas_textblock_cursor_paragraph_char_last(cur);
1393    evas_textblock_cursor_copy(cur, main_cur);
1394    evas_textblock_cursor_char_prev(cur);
1395    evas_textblock_cursor_char_next(main_cur);
1396
1397    evas_textblock_cursor_range_delete(cur, main_cur);
1398    evas_textblock_cursor_paragraph_first(cur);
1399    fail_if(evas_textblock_cursor_paragraph_next(cur));
1400
1401    /* FIXME: Also add text appending/prepending */
1402
1403    END_TB_TEST();
1404 }
1405 END_TEST
1406
1407 /* Text getters */
1408 START_TEST(evas_textblock_text_getters)
1409 {
1410    START_TB_TEST();
1411    const char *buf = "This is a <br> test.<ps>"
1412       "טקסט בעברית<ps>and now in english.";
1413    evas_object_textblock_text_markup_set(tb, buf);
1414    evas_textblock_cursor_paragraph_first(cur);
1415
1416    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
1417             "This is a <br> test."));
1418
1419    evas_textblock_cursor_paragraph_next(cur);
1420    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
1421             "טקסט בעברית"));
1422
1423    evas_textblock_cursor_paragraph_next(cur);
1424    fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
1425             "and now in english."));
1426
1427    /* Range get */
1428    Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
1429    evas_textblock_cursor_pos_set(main_cur, 2);
1430    evas_textblock_cursor_pos_set(cur, 2);
1431    fail_if(*evas_textblock_cursor_range_text_get(main_cur, cur,
1432             EVAS_TEXTBLOCK_TEXT_MARKUP));
1433
1434    evas_textblock_cursor_pos_set(main_cur, 2);
1435    evas_textblock_cursor_pos_set(cur, 6);
1436    fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
1437             EVAS_TEXTBLOCK_TEXT_MARKUP), "is i"));
1438
1439    evas_textblock_cursor_pos_set(main_cur, 5);
1440    evas_textblock_cursor_pos_set(cur, 14);
1441    fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
1442             EVAS_TEXTBLOCK_TEXT_MARKUP), "is a <br> te"));
1443
1444    evas_textblock_cursor_pos_set(main_cur, 14);
1445    evas_textblock_cursor_pos_set(cur, 20);
1446    fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
1447             EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps>טק"));
1448
1449    evas_textblock_cursor_pos_set(main_cur, 14);
1450    evas_textblock_cursor_pos_set(cur, 32);
1451    fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
1452             EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps>טקסט בעברית<ps>an"));
1453
1454    /* Backward range get */
1455    evas_textblock_cursor_pos_set(main_cur, 2);
1456    evas_textblock_cursor_pos_set(cur, 2);
1457    fail_if(*evas_textblock_cursor_range_text_get(cur, main_cur,
1458             EVAS_TEXTBLOCK_TEXT_MARKUP));
1459
1460    evas_textblock_cursor_pos_set(main_cur, 2);
1461    evas_textblock_cursor_pos_set(cur, 6);
1462    fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
1463             EVAS_TEXTBLOCK_TEXT_MARKUP), "is i"));
1464
1465    evas_textblock_cursor_pos_set(main_cur, 5);
1466    evas_textblock_cursor_pos_set(cur, 14);
1467    fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
1468             EVAS_TEXTBLOCK_TEXT_MARKUP), "is a <br> te"));
1469
1470    evas_textblock_cursor_pos_set(main_cur, 14);
1471    evas_textblock_cursor_pos_set(cur, 20);
1472    fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
1473             EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps>טק"));
1474
1475    evas_textblock_cursor_pos_set(main_cur, 14);
1476    evas_textblock_cursor_pos_set(cur, 32);
1477    fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
1478             EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps>טקסט בעברית<ps>an"));
1479
1480    /* Uninit cursors and other weird cases */
1481    evas_object_textblock_clear(tb);
1482    evas_textblock_cursor_copy(main_cur, cur);
1483    evas_textblock_cursor_text_prepend(main_cur, "aaa");
1484    fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
1485             EVAS_TEXTBLOCK_TEXT_MARKUP), "aaa"));
1486
1487    END_TB_TEST();
1488 }
1489 END_TEST
1490
1491 /* Formats */
1492 START_TEST(evas_textblock_formats)
1493 {
1494    START_TB_TEST();
1495    const char *buf = "Th<b>i<font_size=15 wrap=none>s i</font_size=13>s</> a <br> te<ps>st<item></>.";
1496    const Evas_Object_Textblock_Node_Format *fnode;
1497    evas_object_textblock_text_markup_set(tb, buf);
1498
1499    /* Walk from the start */
1500    fnode = evas_textblock_node_format_first_get(tb);
1501    fail_if(!fnode);
1502    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
1503
1504    fnode = evas_textblock_node_format_next_get(fnode);
1505    fail_if(!fnode);
1506    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
1507             "+ font_size=15 wrap=none"));
1508
1509    fnode = evas_textblock_node_format_next_get(fnode);
1510    fail_if(!fnode);
1511    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
1512             "- font_size=13"));
1513
1514    fnode = evas_textblock_node_format_next_get(fnode);
1515    fail_if(!fnode);
1516    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
1517
1518    fnode = evas_textblock_node_format_next_get(fnode);
1519    fail_if(!fnode);
1520    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "br"));
1521
1522    fnode = evas_textblock_node_format_next_get(fnode);
1523    fail_if(!fnode);
1524    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "ps"));
1525
1526    fnode = evas_textblock_node_format_next_get(fnode);
1527    fail_if(!fnode);
1528    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
1529
1530    fnode = evas_textblock_node_format_next_get(fnode);
1531    fail_if(!fnode);
1532    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
1533
1534    fnode = evas_textblock_node_format_next_get(fnode);
1535    fail_if(fnode);
1536
1537    /* Walk backwards */
1538    fnode = evas_textblock_node_format_last_get(tb);
1539    fail_if(!fnode);
1540    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
1541
1542    fnode = evas_textblock_node_format_prev_get(fnode);
1543    fail_if(!fnode);
1544    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
1545
1546    fnode = evas_textblock_node_format_prev_get(fnode);
1547    fail_if(!fnode);
1548    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "ps"));
1549
1550    fnode = evas_textblock_node_format_prev_get(fnode);
1551    fail_if(!fnode);
1552    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "br"));
1553
1554    fnode = evas_textblock_node_format_prev_get(fnode);
1555    fail_if(!fnode);
1556    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
1557
1558    fnode = evas_textblock_node_format_prev_get(fnode);
1559    fail_if(!fnode);
1560    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
1561             "- font_size=13"));
1562
1563    fnode = evas_textblock_node_format_prev_get(fnode);
1564    fail_if(!fnode);
1565    fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
1566             "+ font_size=15 wrap=none"));
1567
1568    fnode = evas_textblock_node_format_prev_get(fnode);
1569    fail_if(!fnode);
1570    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
1571
1572    fnode = evas_textblock_node_format_prev_get(fnode);
1573    fail_if(fnode);
1574
1575    /* Cursor and format detection */
1576    fnode = evas_textblock_node_format_first_get(tb);
1577    fail_if(!fnode);
1578    evas_textblock_cursor_at_format_set(cur, fnode);
1579    fail_if(evas_textblock_cursor_format_is_visible_get(cur));
1580
1581    fnode = evas_textblock_node_format_next_get(fnode);
1582    fail_if(!fnode);
1583    evas_textblock_cursor_at_format_set(cur, fnode);
1584    fail_if(evas_textblock_cursor_format_is_visible_get(cur));
1585
1586    fnode = evas_textblock_node_format_next_get(fnode);
1587    fail_if(!fnode);
1588    evas_textblock_cursor_at_format_set(cur, fnode);
1589    fail_if(evas_textblock_cursor_format_is_visible_get(cur));
1590
1591    fnode = evas_textblock_node_format_next_get(fnode);
1592    fail_if(!fnode);
1593    evas_textblock_cursor_at_format_set(cur, fnode);
1594    fail_if(evas_textblock_cursor_format_is_visible_get(cur));
1595
1596    fnode = evas_textblock_node_format_next_get(fnode);
1597    fail_if(!fnode);
1598    evas_textblock_cursor_at_format_set(cur, fnode);
1599    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1600
1601    fnode = evas_textblock_node_format_next_get(fnode);
1602    fail_if(!fnode);
1603    evas_textblock_cursor_at_format_set(cur, fnode);
1604    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1605
1606    size_t i = 0;
1607    evas_textblock_cursor_paragraph_first(cur);
1608    do
1609      {
1610         switch (i)
1611           {
1612            case 2:
1613            case 3:
1614            case 6:
1615            case 7:
1616            case 10:
1617            case 14:
1618            case 17:
1619            case 18:
1620               fail_if(!evas_textblock_cursor_is_format(cur));
1621               break;
1622            default:
1623               fail_if(evas_textblock_cursor_is_format(cur));
1624               fail_if(evas_textblock_cursor_format_is_visible_get(cur));
1625               break;
1626           }
1627         i++;
1628      }
1629    while (evas_textblock_cursor_char_next(cur));
1630
1631    /* Format text nodes invalidation */
1632      {
1633         Evas_Coord w, h, nw, nh;
1634         evas_object_textblock_text_markup_set(tb, "Test");
1635         evas_object_textblock_size_formatted_get(tb, &w, &h);
1636         evas_textblock_cursor_paragraph_first(cur);
1637         evas_textblock_cursor_format_prepend(cur, "+ font_size=40");
1638         evas_object_textblock_size_formatted_get(tb, &nw, &nh);
1639         fail_if((w >= nw) || (h >= nh));
1640      }
1641    /* FIXME: Should extend invalidation tests. */
1642
1643    /* Various formats, just verify there's no seg, we can't really
1644     * verify them visually, well, we can some of them. Possibly in the
1645     * future we will */
1646    evas_object_textblock_text_markup_set(tb,
1647          "<font_size=40>font_size=40</><ps>"
1648          "<color=#F210B3FF>color=#F210B3FF</><ps>"
1649          "<underline=single underline_color=#A2B3C4>underline=single underline_color=#A2B3C4</><ps>"
1650          "<underline=double underline_color=#F00 underline2_color=#00F>underline=double underline_color=#F00 underline2_color=#00F</><ps>"
1651          "<style=outline outline_color=#F0FA>style=outline outline_color=#F0FA</><ps>"
1652          "<style=shadow shadow_color=#F0F>style=shadow shadow_color=#F0F</><ps>"
1653          "<style=glow glow_color=#BBB>style=glow glow_color=#BBB</><ps>"
1654          "<style=glow glow2_color=#0F0>style=glow glow2_color=#0F0</><ps>"
1655          "<style=glow color=#fff glow2_color=#fe87 glow_color=#f214>style=glow color=#fff glow2_color=#fe87 glow_color=#f214</><ps>"
1656          "<backing=on backing_color=#00F>backing=on backing_color=#00F</><ps>"
1657          "<strikethrough=on strikethrough_color=#FF0>strikethrough=on strikethrough_color=#FF0</><ps>"
1658          "<align=right>align=right</><ps>"
1659          "<backing=on backing_color=#F008 valign=0.0>valign=0.0</><ps>"
1660          "<backing=on backing_color=#0F08 tabstops=50>tabstops=<\\t></>50</><ps>"
1661          "<backing=on backing_color=#00F8 linesize=40>linesize=40</><ps>"
1662          "<backing=on backing_color=#F0F8 linerelsize=200%>linerelsize=200%</><ps>"
1663          "<backing=on backing_color=#0FF8 linegap=20>linegap=20</><ps>"
1664          "<backing=on backing_color=#FF08 linerelgap=100%>linerelgap=100%</><ps>");
1665
1666    /* Force a relayout */
1667    evas_object_textblock_size_formatted_get(tb, NULL, NULL);
1668
1669    /* Removing paired formats. */
1670    evas_object_textblock_text_markup_set(tb, "<a>aa<b>bb</b>cc</a>");
1671    fnode = evas_textblock_node_format_first_get(tb);
1672    evas_textblock_node_format_remove_pair(tb, (Evas_Object_Textblock_Node_Format *) fnode);
1673    fnode = evas_textblock_node_format_first_get(tb);
1674    fail_if(!fnode);
1675    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
1676    fnode = evas_textblock_node_format_next_get(fnode);
1677    fail_if(!fnode);
1678    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
1679
1680    evas_object_textblock_text_markup_set(tb, "<a>aa<b>bb</b>cc</a>");
1681    fnode = evas_textblock_node_format_first_get(tb);
1682    fnode = evas_textblock_node_format_next_get(fnode);
1683    evas_textblock_node_format_remove_pair(tb, (Evas_Object_Textblock_Node_Format *) fnode);
1684    fnode = evas_textblock_node_format_first_get(tb);
1685    fail_if(!fnode);
1686    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ a"));
1687    fnode = evas_textblock_node_format_next_get(fnode);
1688    fail_if(!fnode);
1689    fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- a"));
1690
1691    /* Format list get */
1692    evas_object_textblock_text_markup_set(tb, "<a>a</>a<item>b</>"
1693          "b<item>b</>c<a>c</>");
1694    const Eina_List *flist = evas_textblock_node_format_list_get(tb, "a");
1695    const Eina_List *itr;
1696    EINA_LIST_FOREACH(flist, itr, fnode)
1697      {
1698         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ a"));
1699      }
1700
1701    flist = evas_textblock_node_format_list_get(tb, "item");
1702    EINA_LIST_FOREACH(flist, itr, fnode)
1703      {
1704         fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
1705      }
1706
1707    /* Make sure we get all the types of visible formats correctly. */
1708    evas_object_textblock_text_markup_set(tb, "<ps>a<br>a<tab>a<item></>");
1709    fail_if(strcmp(evas_textblock_node_format_text_get(
1710                evas_textblock_cursor_format_get(cur)), "ps"));
1711    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<ps>"));
1712    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1713    fail_if(!evas_textblock_cursor_char_next(cur));
1714    fail_if(!evas_textblock_cursor_char_next(cur));
1715    fail_if(strcmp(evas_textblock_node_format_text_get(
1716                evas_textblock_cursor_format_get(cur)), "br"));
1717    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<br>"));
1718    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1719    fail_if(!evas_textblock_cursor_char_next(cur));
1720    fail_if(!evas_textblock_cursor_char_next(cur));
1721    fail_if(strcmp(evas_textblock_node_format_text_get(
1722                evas_textblock_cursor_format_get(cur)), "tab"));
1723    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<tab>"));
1724    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1725    fail_if(!evas_textblock_cursor_char_next(cur));
1726    fail_if(!evas_textblock_cursor_char_next(cur));
1727    fail_if(strcmp(evas_textblock_node_format_text_get(
1728                evas_textblock_cursor_format_get(cur)), "+ item"));
1729    fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<item>"));
1730    fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
1731
1732    END_TB_TEST();
1733 }
1734 END_TEST
1735
1736 /* Different text styles, for example, shadow. */
1737 START_TEST(evas_textblock_style)
1738 {
1739    Evas_Coord w, h, nw, nh;
1740    Evas_Coord l, r, t, b;
1741    START_TB_TEST();
1742    Evas_Textblock_Style *newst;
1743    const char *buf = "Test<ps>Test2<ps>נסיון";
1744    evas_object_textblock_text_markup_set(tb, buf);
1745    fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
1746
1747    evas_object_textblock_size_formatted_get(tb, &w, &h);
1748    newst = evas_textblock_style_new();
1749    fail_if(!newst);
1750    evas_textblock_style_set(newst,
1751          "DEFAULT='font=Sans font_size=20 color=#000 text_class=entry'"
1752          "br='\n'"
1753          "ps='ps'"
1754          "tab='\t'");
1755    evas_object_textblock_style_set(tb, newst);
1756    evas_object_textblock_size_formatted_get(tb, &nw, &nh);
1757    fail_if((w >= nw) || (h >= nh));
1758
1759    /* Style padding. */
1760    evas_object_textblock_text_markup_set(tb, "Test");
1761    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1762    fail_if((l != 0) || (r != 0) || (t != 0) || (b != 0));
1763
1764    evas_object_textblock_text_markup_set(tb, "<style=shadow>Test</>");
1765    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1766    fail_if((l != 0) || (r != 1) || (t != 0) || (b != 1));
1767
1768    evas_object_textblock_text_markup_set(tb, "<style=outline>Test</>");
1769    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1770    fail_if((l != 1) || (r != 1) || (t != 1) || (b != 1));
1771
1772    evas_object_textblock_text_markup_set(tb, "<style=soft_outline>Test</>");
1773    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1774    fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
1775
1776    evas_object_textblock_text_markup_set(tb, "<style=glow>Test</>");
1777    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1778    fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
1779
1780    evas_object_textblock_text_markup_set(tb, "<style=outline_shadow>Test</>");
1781    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1782    fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
1783
1784    evas_object_textblock_text_markup_set(tb, "<style=far_shadow>Test</>");
1785    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1786    fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
1787
1788    evas_object_textblock_text_markup_set(tb, "<style=outline_soft_shadow>Test</>");
1789    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1790    fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
1791
1792    evas_object_textblock_text_markup_set(tb, "<style=soft_shadow>Test</>");
1793    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1794    fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
1795
1796    evas_object_textblock_text_markup_set(tb, "<style=far_soft_shadow>Test</>");
1797    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1798    fail_if((l != 0) || (r != 4) || (t != 0) || (b != 4));
1799
1800    /* Mixed style padding */
1801    evas_object_textblock_text_markup_set(tb,
1802          "<style=far_shadow>Test</><style=far_soft_shadow>Test</>");
1803    evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
1804    fail_if((l != 1) || (r != 4) || (t != 1) || (b != 4));
1805
1806    END_TB_TEST();
1807 }
1808 END_TEST
1809
1810 /* Various setters and getters */
1811 START_TEST(evas_textblock_set_get)
1812 {
1813    START_TB_TEST();
1814    const char *buf = "";
1815    evas_object_textblock_text_markup_set(tb, buf);
1816    fail_if(strcmp(evas_textblock_style_get(st), style_buf));
1817    fail_if(evas_object_textblock_style_get(tb) != st);
1818    evas_object_textblock_replace_char_set(tb, "|");
1819    fail_if(strcmp(evas_object_textblock_replace_char_get(tb), "|"));
1820    evas_object_textblock_replace_char_set(tb, "ש");
1821    fail_if(strcmp(evas_object_textblock_replace_char_get(tb), "ש"));
1822
1823    evas_object_textblock_valign_set(tb, -1.0);
1824    fail_if(evas_object_textblock_valign_get(tb) != 0.0);
1825    evas_object_textblock_valign_set(tb, 0.0);
1826    fail_if(evas_object_textblock_valign_get(tb) != 0.0);
1827    evas_object_textblock_valign_set(tb, 0.432);
1828    fail_if(evas_object_textblock_valign_get(tb) != 0.432);
1829    evas_object_textblock_valign_set(tb, 1.0);
1830    fail_if(evas_object_textblock_valign_get(tb) != 1.0);
1831    evas_object_textblock_valign_set(tb, 1.5);
1832    fail_if(evas_object_textblock_valign_get(tb) != 1.0);
1833
1834    evas_object_textblock_bidi_delimiters_set(tb, ",.|");
1835    fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",.|"));
1836    evas_object_textblock_bidi_delimiters_set(tb, ",|");
1837    fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",|"));
1838    evas_object_textblock_bidi_delimiters_set(tb, NULL);
1839    fail_if(evas_object_textblock_bidi_delimiters_get(tb));
1840    evas_object_textblock_bidi_delimiters_set(tb, ",|");
1841    fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",|"));
1842
1843    /* Hinting */
1844    evas_object_textblock_text_markup_set(tb, "This is<ps>a test<br>bla");
1845    /* Force relayout */
1846    evas_object_textblock_size_formatted_get(tb, NULL, NULL);
1847    evas_font_hinting_set(evas, EVAS_FONT_HINTING_NONE);
1848    evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO);
1849    evas_font_hinting_set(evas, EVAS_FONT_HINTING_BYTECODE);
1850    END_TB_TEST();
1851 }
1852 END_TEST
1853
1854 /* Aux evas stuff, such as scale. */
1855 START_TEST(evas_textblock_evas)
1856 {
1857    Evas_Coord w, h, sw, sh;
1858    START_TB_TEST();
1859    const char *buf = "Test";
1860    evas_object_textblock_text_markup_set(tb, buf);
1861    evas_object_textblock_size_formatted_get(tb, &w, &h);
1862    evas_object_scale_set(tb, 3.0);
1863    evas_object_textblock_size_formatted_get(tb, &sw, &sh);
1864    fail_if((sw <= w) || (sh <= h));
1865
1866    evas_object_scale_set(tb, 0.5);
1867    evas_object_textblock_size_formatted_get(tb, &sw, &sh);
1868    fail_if((sw >= w) || (sh >= h));
1869
1870    END_TB_TEST();
1871 }
1872 END_TEST
1873
1874 /* All the string escaping stuff */
1875 START_TEST(evas_textblock_escaping)
1876 {
1877    int len;
1878    START_TB_TEST();
1879    fail_if(strcmp(evas_textblock_escape_string_get("&amp;"), "&"));
1880    fail_if(strcmp(evas_textblock_string_escape_get("&", &len), "&amp;"));
1881    fail_if(len != 1);
1882
1883    fail_if(strcmp(evas_textblock_escape_string_get("&middot;"), "\xc2\xb7"));
1884    fail_if(strcmp(evas_textblock_string_escape_get("\xc2\xb7", &len),
1885             "&middot;"));
1886    fail_if(len != 2);
1887
1888    fail_if(strcmp(evas_textblock_escape_string_get("&#x1f459;"),
1889             "\xF0\x9F\x91\x99"));
1890    fail_if(strcmp(evas_textblock_escape_string_get("&#128089;"),
1891             "\xF0\x9F\x91\x99"));
1892
1893    fail_if(evas_textblock_escape_string_get("&middot;aa"));
1894    const char *tmp = "&middot;aa";
1895    fail_if(strcmp(evas_textblock_escape_string_range_get(tmp, tmp + 8),
1896             "\xc2\xb7"));
1897    fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 9));
1898    fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 7));
1899    fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 5));
1900
1901    const char *buf = "This &middot; is";
1902    evas_object_textblock_text_markup_set(tb, buf);
1903    fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
1904
1905    buf = "This &nbsp; is";
1906    evas_object_textblock_text_markup_set(tb, buf);
1907    fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
1908
1909    END_TB_TEST();
1910 }
1911 END_TEST
1912
1913 START_TEST(evas_textblock_size)
1914 {
1915    START_TB_TEST();
1916    Evas_Coord w, h, h2, nw, nh;
1917    const char *buf = "This is a <br> test.<br>גם בעברית";
1918    /* When wrapping is off, native size should be the same as formatted
1919     * size */
1920
1921    evas_object_textblock_size_formatted_get(tb, &w, &h);
1922    evas_object_textblock_size_native_get(tb, &nw, &nh);
1923    fail_if((w != nw) || (h != nh));
1924    fail_if(w != 0);
1925
1926    evas_object_textblock_text_markup_set(tb, "a<br>a");
1927    evas_object_textblock_size_formatted_get(tb, &w, &h2);
1928    evas_object_textblock_size_native_get(tb, &nw, &nh);
1929    fail_if((w != nw) || (h2 != nh));
1930
1931    /* Two lines == double the height */
1932    fail_if(h * 2 != h2);
1933
1934    evas_object_textblock_text_markup_set(tb, buf);
1935
1936    evas_object_textblock_size_formatted_get(tb, &w, &h);
1937    evas_object_textblock_size_native_get(tb, &nw, &nh);
1938    fail_if((w != nw) || (h != nh));
1939    fail_if(w <= 0);
1940
1941    /* FIXME: There is a lot more to be done. */
1942    END_TB_TEST();
1943 }
1944 END_TEST
1945
1946 void evas_test_textblock(TCase *tc)
1947 {
1948    tcase_add_test(tc, evas_textblock_simple);
1949    tcase_add_test(tc, evas_textblock_cursor);
1950    tcase_add_test(tc, evas_textblock_size);
1951    tcase_add_test(tc, evas_textblock_editing);
1952    tcase_add_test(tc, evas_textblock_style);
1953    tcase_add_test(tc, evas_textblock_evas);
1954    tcase_add_test(tc, evas_textblock_text_getters);
1955    tcase_add_test(tc, evas_textblock_formats);
1956    tcase_add_test(tc, evas_textblock_format_removal);
1957    tcase_add_test(tc, evas_textblock_escaping);
1958    tcase_add_test(tc, evas_textblock_set_get);
1959    tcase_add_test(tc, evas_textblock_geometries);
1960    tcase_add_test(tc, evas_textblock_various);
1961    tcase_add_test(tc, evas_textblock_wrapping);
1962    tcase_add_test(tc, evas_textblock_items);
1963 }
1964