Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / text / FGrp_TextTextComposite.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /*
19  * @file        FGrp_TextTextComposite.cpp
20  * @brief       This is the implementation file for TextComposite class.
21  */
22
23 // Includes
24 #include <new>
25 #include <FBaseSysLog.h>
26 #include <FApp_AppInfo.h>
27 #include "FGrp_TextCommon.h"
28 #include "FGrp_TextTextElement.h"
29 #include "FGrp_TextTextSimple.h"
30 #include "FGrp_TextTextCutLink.h"
31 #include "FGrp_TextTextLine.h"
32 #include "FGrp_TextTextColumn.h"
33 #include "FGrp_TextTextCutLinkListInfo.h"
34 #include "FGrp_TextTextComposite.h"
35 #include "FGrp_TextTextUtility.h"
36 #include "FGrp_CanvasImpl.h"
37 #include "FGrp_TextTextWidthManager.h"
38 #include "../FGrp_Canvas.h"
39
40 using namespace Tizen::Base;
41 using namespace Tizen::Base::Utility;
42 using namespace Tizen::Base::Collection;
43
44 #define Release(x) \
45         if (x) \
46         { \
47                 delete x; \
48                 x = null; \
49         }
50
51 namespace Tizen { namespace Graphics
52 {
53
54 namespace _Text
55 {
56
57 struct NoneWrapComposeInfo
58 {
59         int prevTextOffset;
60         int prevTextLength;
61         int prevWidth;
62         int prevHeight;
63         int prevEndType;
64 };
65
66 TextComposite::TextComposite(TextElement* pTextElement)
67 {
68         __pTextElementList = new (std::nothrow) LinkedList;
69         SysTryReturn(NID_GRP
70                         , __pTextElementList
71                         , , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
72
73         __wrap = TEXT_OBJECT_WRAP_TYPE_WORD;
74         __workStart = 0;
75         __workLength = 0;
76         __workWidth = 0;
77         __length = 0;
78         __displayBlock = false;
79         __defaultBlockColor = Color(183, 212, 247);
80         __cursorIndex = -1;
81
82         __ignoreRearBlank = true;
83         __ignoreFrontBlank = false;
84
85         __rearSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_ONE;
86         __frontSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_ONE;
87
88         __lineSpacing = 0;
89         __elementVertialAlignment = TEXT_OBJECT_ALIGNMENT_BOTTOM;
90         __pCurrentTextColumn = null;
91         __pCutLinkListInfo = new (std::nothrow)TextCutLinkListInfo;
92
93         {
94                 wchar_t abbrevText[2];
95                 abbrevText[0] = TEXT_ABBREV_CHARACTER;
96                 abbrevText[1] = 0;
97
98                 __pAbbrevTextElement = new (std::nothrow)TextSimple(abbrevText, 1, TEXT_ELEMENT_SOURCE_TYPE_INTERNAL, null,
99                                 Color::GetColor(COLOR_ID_BLACK), Color::GetColor(COLOR_ID_WHITE), Color::GetColor(COLOR_ID_WHITE));
100         }
101
102         if (pTextElement != null)
103         {
104                 AppendElement(*pTextElement);
105         }
106         __drawAbbrevText = false;
107         __drawTextEllipsis = false;
108         __TextObjectEllipsisType = TEXT_OBJECT_ELLIPSIS_TYPE_TAIL;
109
110         __partialComposingModeEnabled = false;
111         __lineIndexCompositeDone = 0;
112         __totalComposedHeight = 0;
113         __composePartialLimitHeight = 0;
114
115         __headEllipsisTextLength = 0;
116         __headEllipsisWidth = 0;
117         __middleEllipsisHeadWidth = 0;
118         __middleEllipsisTextLengthInHead = 0;
119         __middleEllipsisTextLengthInTail = 0;
120         __middleEllipsisWidth = 0;
121         __isChanged = false;
122         __pTextWidthManager = null;
123         __widthManagerEnabled = false;
124
125         __pSweepInfo = null;
126 }
127
128 TextComposite::~TextComposite(void)
129 {
130         if (__pCutLinkListInfo)
131         {
132                 delete __pCutLinkListInfo;
133                 __pCutLinkListInfo = null;
134         }
135
136         if (__pTextElementList)
137         {
138                 RemoveAllElements(true);
139                 delete __pTextElementList;
140                 __pTextElementList = null;
141         }
142
143         if (__pAbbrevTextElement)
144         {
145                 delete __pAbbrevTextElement;
146                 __pAbbrevTextElement = null;
147         }
148 }
149
150 int
151 TextComposite::ForwardAnalyze(int startTextIndex, int textLength, int maxWidth, TextObjectWrapType wrap, int& actualLength,
152                                                            int& width, int& height)
153 {
154         SysTryReturn(NID_GRP
155                         , 0 <= startTextIndex && startTextIndex < __length
156                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. startTextIndex(%d)", startTextIndex);
157
158         SysTryReturn(NID_GRP
159                         , textLength <= __length
160                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. textLength(%d)", textLength);
161
162         result r = E_SUCCESS;
163
164         Dimension textSize;
165         int elementTextOffset = 0;
166         int elementIndex = 0;
167         int textIndexFromElementOffset = 0;
168         int remainingWidth = 0;
169         int remainingLength = 0;
170         int textCount = 0;
171         int currentLength = 0;
172         int ret = TEXT_RETBY_NORMAL;
173
174         IEnumerator* pEnum = null;
175         TextElement* pTextElement = null;
176
177         bool isFirstWord = true;
178         Dimension tempTextSize;
179         int tempTextCount = 0;
180         actualLength = 0;
181         width = 0;
182         height = 0;
183
184         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
185                                                                                          textIndexFromElementOffset);
186         SysTryReturn(NID_GRP
187                 , pTextElement
188                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
189
190         textCount = 0;
191         remainingWidth = maxWidth;
192         remainingLength = textLength;
193         currentLength = Math::Min(remainingLength, currentLength);
194
195         pEnum = __pTextElementList->GetEnumeratorN();
196         for (int i = 0; i <= elementIndex; i++)
197         {
198                 r = pEnum->MoveNext();
199                 SysTryCatch(NID_GRP
200                                 , r == E_SUCCESS
201                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
202         }
203
204         while ((remainingWidth != 0) && (remainingLength != 0))
205         {
206                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
207                                                                                          __wrap, textCount, textSize.width, textSize.height);
208
209                 textSize.height += __lineSpacing;
210
211                 remainingWidth -= textSize.width;
212                 remainingLength -= textCount;
213                 currentLength -= textCount;
214
215                 if (textCount != 0)
216                 {
217                         actualLength += textCount;
218                         width += textSize.width;
219                         height = Math::Max(textSize.height, height);
220                 }
221
222                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
223                 {
224                         tempTextCount = actualLength;
225                         tempTextSize.width = width;
226                         tempTextSize.height = height;
227                 }
228
229                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
230                 {
231                         break;
232                 }
233
234                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
235                 {
236                         if (ret == TEXT_RETBY_LIMITWIDTH)
237                         {
238                                 if (isFirstWord == false)
239                                 {
240                                         actualLength = tempTextCount;
241                                         width = tempTextSize.width;
242                                         height = tempTextSize.height;
243
244                                         ret = TEXT_RETBY_NORMAL;
245                                 }
246                                 break;
247                         }
248
249                         isFirstWord = false;
250
251                         if (0 < currentLength)
252                         {
253                                 textIndexFromElementOffset += textCount;
254                                 continue;
255                         }
256                 }
257                 else
258                 {
259                         if (ret == TEXT_RETBY_LIMITWIDTH)
260                         {
261                                 break;
262                         }
263                 }
264
265                 if (pEnum->MoveNext() != E_SUCCESS)
266                 {
267                         break;
268                 }
269
270                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
271                 if (pTextElement == null)
272                 {
273                         break;
274                 }
275
276                 isFirstWord = true;
277                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
278                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
279         }
280
281         if (ret == TEXT_RETBY_LIMITLENGTH)
282         {
283                 ret = TEXT_RETBY_NORMAL;
284         }
285
286         SetLastResult(E_SUCCESS);
287         Release(pEnum);
288         return ret;
289
290 CATCH:
291         Release(pEnum);
292         return -1;
293 }
294
295 int
296 TextComposite::ForwardAnalyzeWithBaseline(int startTextIndex, int textLength, int maxWidth, TextObjectWrapType wrap, int& actualLength,
297                                                            int& width, int& height, int& baseline)
298 {
299         SysTryReturn(NID_GRP
300                         , 0 <= startTextIndex && startTextIndex < __length
301                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. startTextIndex(%d)", startTextIndex);
302
303         SysTryReturn(NID_GRP
304                         , textLength <= __length
305                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. textLength(%d)", textLength);
306
307         result r = E_SUCCESS;
308
309         Dimension textSize;
310         int elementTextOffset = 0;
311         int elementIndex = 0;
312         int textIndexFromElementOffset = 0;
313         int remainingWidth = 0;
314         int remainingLength = 0;
315         int textCount = 0;
316         int currentLength = 0;
317         int ret = TEXT_RETBY_NORMAL;
318         bool isMaxHeightImage = false;
319
320         IEnumerator* pEnum = null;
321         TextElement* pTextElement = null;
322
323         bool isFirstWord = true;
324         Dimension tempTextSize;
325         int tempTextCount = 0;
326         actualLength = 0;
327         width = 0;
328         height = 0;
329
330         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
331                                                                                          textIndexFromElementOffset);
332         SysTryReturn(NID_GRP
333                 , pTextElement
334                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
335
336         textCount = 0;
337         remainingWidth = maxWidth;
338         remainingLength = textLength;
339         currentLength = Math::Min(remainingLength, currentLength);
340         baseline = pTextElement->GetBaseline();
341
342         pEnum = __pTextElementList->GetEnumeratorN();
343         for (int i = 0; i <= elementIndex; i++)
344         {
345                 r = pEnum->MoveNext();
346                 SysTryCatch(NID_GRP
347                                 , r == E_SUCCESS
348                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
349         }
350
351         while (remainingLength != 0)
352         {
353                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
354                                                                                          __wrap, textCount, textSize.width, textSize.height);
355
356                 textSize.height += __lineSpacing;
357                 remainingWidth -= textSize.width;
358                 remainingLength -= textCount;
359                 currentLength -= textCount;
360
361                 if (textCount != 0)
362                 {
363                         actualLength += textCount;
364                         width += textSize.width;
365                         baseline = Math::Max(pTextElement->GetBaseline(), baseline);
366
367                         // height = Math::Max(textSize.height, height);
368                         if (height < textSize.height)
369                         {
370                                 height = textSize.height;
371
372                                 (pTextElement->GetType() == TEXT_ELEMENT_TYPE_IMAGE) ? isMaxHeightImage = true : isMaxHeightImage = false;
373                         }
374                 }
375
376                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
377                 {
378                         tempTextCount = actualLength;
379                         tempTextSize.width = width;
380                         tempTextSize.height = height;
381                 }
382
383                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
384                 {
385                         break;
386                 }
387
388                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
389                 {
390                         if (ret == TEXT_RETBY_LIMITWIDTH)
391                         {
392                                 if (isFirstWord == false)
393                                 {
394                                         actualLength = tempTextCount;
395                                         width = tempTextSize.width;
396                                         height = tempTextSize.height;
397
398                                         ret = TEXT_RETBY_NORMAL;
399                                 }
400                                 break;
401                         }
402
403                         isFirstWord = false;
404
405                         if (0 < currentLength)
406                         {
407                                 textIndexFromElementOffset += textCount;
408                                 continue;
409                         }
410                 }
411                 else
412                 {
413                         if (ret == TEXT_RETBY_LIMITWIDTH)
414                         {
415                                 break;
416                         }
417                 }
418
419                 if (pEnum->MoveNext() != E_SUCCESS)
420                 {
421                         break;
422                 }
423
424                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
425                 if (pTextElement == null)
426                 {
427                         break;
428                 }
429
430                 isFirstWord = true;
431                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
432                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
433         }
434
435         if (ret == TEXT_RETBY_LIMITLENGTH)
436         {
437                 ret = TEXT_RETBY_NORMAL;
438         }
439
440         if (isMaxHeightImage)
441         {
442                 height += baseline;
443         }
444
445         SetLastResult(E_SUCCESS);
446         Release(pEnum);
447         return ret;
448
449 CATCH:
450         Release(pEnum);
451         return -1;
452 }
453
454 result
455 TextComposite::GetRegion(int textIndex, int textLength, int& width, int& height) const
456 {
457         SysTryReturn(NID_GRP
458                         , 0 <= textIndex && textIndex < __length
459                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. textIndex(%d) __length(%d)"
460                         , textIndex, __length);
461
462         SysTryReturn(NID_GRP
463                         , textLength <= __length
464                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid. textIndex(%d) __length(%d)"
465                         , textIndex, __length);
466
467         result r = E_SUCCESS;
468         IEnumerator* pEnum = null;
469         TextElement* pTextElement = null;
470         Dimension textSize;
471         int currentLength = 0;
472         int elementTextOffset = 0;
473         int elementIndex = 0;
474         int textIndexFromElementOffset = 0;
475
476         width = 0;
477         height = 0;
478
479         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
480                                                                                          textIndexFromElementOffset);
481         SysTryReturn(NID_GRP
482                 , pTextElement
483                 , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
484
485         pEnum = __pTextElementList->GetEnumeratorN();
486         for (int i = 0; i <= elementIndex; i++)
487         {
488                 r = pEnum->MoveNext();
489                 SysTryCatch(NID_GRP
490                                 , r == E_SUCCESS
491                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
492         }
493
494         currentLength = Math::Min(currentLength, textLength);
495
496         while (textLength != 0)
497         {
498                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
499
500                 width += textSize.width;
501                 height = Math::Max(height, textSize.height);
502                 textLength -= currentLength;
503
504                 if (pEnum->MoveNext() != E_SUCCESS)
505                 {
506                         break;
507                 }
508
509                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
510                 if (pTextElement == null)
511                 {
512                         break;
513                 }
514
515                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
516                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
517         }
518
519         Release(pEnum);
520         return r;
521
522 CATCH:
523         width = 0;
524         height = 0;
525
526         Release(pEnum);
527         return r;
528 }
529
530 int
531 TextComposite::GetHeight(int textIndex) const
532 {
533         if (__length == 0)
534         {
535                 return 0;
536         }
537
538         SysTryReturn(NID_GRP
539                         , 0 <= textIndex && textIndex < __length
540                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
541
542         TextElement* pTextElement = null;
543         int currentLength = 0;
544         int elementTextOffset = 0;
545         int elementIndex = 0;
546         int textIndexFromElementOffset = 0;
547
548         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
549                                                                                          textIndexFromElementOffset);
550         SysTryCatch(NID_GRP
551                 , pTextElement
552                 , , E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
553
554         return pTextElement->GetHeight();
555
556 CATCH:
557         return -1;
558 }
559
560 result
561 TextComposite::Draw(_CanvasImpl& canvasImpl, Rectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
562                                          const TextObjectActionType action)
563 {
564         if (textLength == 0)
565         {
566                 return E_SUCCESS;
567         }
568
569         SysTryReturn(NID_GRP
570                         , 0 <= startTextIndex && startTextIndex < __length
571                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
572
573         SysTryReturn(NID_GRP
574                         , textLength <= __length
575                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
576
577         result r = E_SUCCESS;
578         IEnumerator* pEnum = null;
579         TextElement* pTextElement = null;
580
581         Dimension textSize;
582         Dimension spaceCharDim;
583         Dimension abbrevTextDim;
584         Rectangle adjustedRect = displayRect;
585         int currentLength = 0;
586         int elementTextOffset = 0;
587         int elementIndex = 0;
588         int textIndexFromElementOffset = 0;
589         int blockStartTextIndex = 0;
590         int blockEndTextIndex = 0;
591         bool drawAbbrevText = false;
592         bool isAlternateLookEnabled = false;
593
594         _Canvas* pCanvas = _Canvas::GetInstance(canvasImpl);
595         SysTryReturn(NID_GRP
596                         , pCanvas
597                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native canvas instance.");
598
599         pTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength,
600                                                                                          textIndexFromElementOffset);
601
602         if (pTextElement && __ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
603         {
604                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
605                 if (pSimpleText != null)
606                 {
607                         int length = startTextIndex + textLength - elementTextOffset - 1;
608                         const wchar_t* pText = pSimpleText->GetText();
609                         SysTryReturn(NID_GRP
610                                 , pText
611                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
612
613                         SysTryReturn(NID_GRP
614                                 , length >= 0 && length < pSimpleText->GetTextLength()
615                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE
616                                 , "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
617
618                         if (pText[length] == (wchar_t)L' ')
619                         {
620                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
621                                 textLength--;
622                         }
623                 }
624         }
625
626         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
627                                                                                                          textIndexFromElementOffset);
628         SysTryCatch(NID_GRP
629                         , pTextElement
630                         , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
631
632         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
633         {
634                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
635                 if (pSimpleText != null)
636                 {
637                         int index = startTextIndex - elementTextOffset;
638                         const wchar_t* pText = pSimpleText->GetText();
639                         SysTryReturn(NID_GRP
640                                 , pText
641                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
642
643                         SysTryReturn(NID_GRP
644                                 , index >= 0 && index < pSimpleText->GetTextLength()
645                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE
646                                 , "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
647
648                         if (pText[index] == (wchar_t)L' ')
649                         {
650                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
651                                 textLength--;
652                                 currentLength--;
653                                 startTextIndex++;
654                                 textIndexFromElementOffset++;
655                         }
656                 }
657         }
658
659         switch (alignment & TEXT_ALIGNMASK_HORIZ)
660         {
661         case TEXT_OBJECT_ALIGNMENT_LEFT:
662                 // fall through
663         default:
664                 break;
665
666         case TEXT_OBJECT_ALIGNMENT_CENTER:
667                 GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
668                 if (textSize.width < adjustedRect.width)
669                 {
670                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
671                 }
672                 break;
673
674         case TEXT_OBJECT_ALIGNMENT_RIGHT:
675                 GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
676                 if (textSize.width < adjustedRect.width)
677                 {
678                         adjustedRect.x += adjustedRect.width - textSize.width;
679                 }
680                 break;
681         }
682
683         pEnum = __pTextElementList->GetEnumeratorN();
684         for (int i = 0; i <= elementIndex; i++)
685         {
686                 r = pEnum->MoveNext();
687                 SysTryCatch(NID_GRP
688                                 , r == E_SUCCESS
689                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
690         }
691
692         currentLength = Math::Min(textLength, currentLength);
693
694         while (textLength > 0)
695         {
696                 textLength -= currentLength;
697
698                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
699
700                 if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV && (pTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT))
701                 {
702                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
703                         SysTryCatch(NID_GRP
704                                         , pSimpleText
705                                         , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
706
707                         SetAbbrevObjectFontInfo(pSimpleText);
708
709                         int textCount = 0;
710                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
711
712                         if (adjustedRect.width < textSize.width + abbrevTextDim.width || textLength <= 0)
713                         {
714                                 int endType = TEXT_RETBY_NORMAL;
715
716                                 if (adjustedRect.width > abbrevTextDim.width)
717                                 {
718                                         int remainingLength = pSimpleText->GetTextLength() - textIndexFromElementOffset;
719                                         endType = pSimpleText->ForwardAnalyze(textIndexFromElementOffset, remainingLength, adjustedRect.width - abbrevTextDim.width,
720                                                                                                                                  TEXT_OBJECT_WRAP_TYPE_NONE, textCount, textSize.width, textSize.height);
721
722                                         if (endType == TEXT_RETBY_OVERWIDTH)
723                                         {
724                                                 textSize.width = 0;
725                                                 textSize.height = 0;
726                                                 textCount = 0;
727                                         }
728                                 }
729                                 else
730                                 {
731                                         textSize.width = 0;
732                                         textCount = 0;
733                                         textSize.height = pSimpleText->GetHeight();
734                                 }
735
736                                 currentLength = textCount;
737                                 drawAbbrevText = true;
738
739                                 switch (alignment & TEXT_ALIGNMASK_HORIZ)
740                                 {
741                                         case TEXT_OBJECT_ALIGNMENT_CENTER:
742                                                 if (textSize.width + abbrevTextDim.width < adjustedRect.width)
743                                                 {
744                                                         adjustedRect.x = displayRect.x + (adjustedRect.width - (textSize.width + abbrevTextDim.width)) / 2;
745                                                 }
746                                                 break;
747
748                                         case TEXT_OBJECT_ALIGNMENT_RIGHT:
749                                                 if (textSize.width + abbrevTextDim.width < adjustedRect.width)
750                                                 {
751                                                         adjustedRect.x = displayRect.x + adjustedRect.width - (textSize.width + abbrevTextDim.width);
752                                                 }
753                                                 break;
754
755                                         case TEXT_OBJECT_ALIGNMENT_LEFT:
756                                                 // fall through
757                                         default:
758                                                 break;
759                                  }
760                         }
761                 }
762
763                 switch (alignment & TEXT_ALIGNMASK_VERT)
764                 {
765                 case TEXT_OBJECT_ALIGNMENT_TOP:
766                         // fall through
767                 default:
768                         adjustedRect.y = displayRect.y;
769                         break;
770
771                 case TEXT_OBJECT_ALIGNMENT_MIDDLE:
772                         adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
773                         break;
774
775                 case TEXT_OBJECT_ALIGNMENT_BOTTOM:
776                         adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
777                         break;
778                 }
779
780                 if (pTextElement->IsBackGroundDrawingModeEnable())
781                 {
782                         Dimension blockSize;
783                         r = pTextElement->GetRegion(textIndexFromElementOffset, currentLength, blockSize.width, blockSize.height);
784                         SysTryReturn(NID_GRP
785                                 , r == E_SUCCESS
786                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
787
788                         r = pCanvas->FillRectangle(pTextElement->GetBackgroundColor(), Rectangle(adjustedRect.x, displayRect.y, blockSize.width, displayRect.height));
789                         SysTryReturn(NID_GRP
790                                 , r == E_SUCCESS
791                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
792                 }
793
794                 isAlternateLookEnabled = (bool)pTextElement->GetValue(SET_ALTERNATE_LOOK);
795                 if (__displayBlock && isAlternateLookEnabled == false)
796                 {
797                         Dimension tempTextSize;
798                         int adjustedX = 0;
799
800                         blockStartTextIndex = Math::Max(__workStart, startTextIndex);
801                         blockEndTextIndex = Math::Min(__workStart + __workLength, startTextIndex + currentLength);
802
803                         if (blockStartTextIndex < blockEndTextIndex)
804                         {
805                                 blockStartTextIndex = textIndexFromElementOffset + (blockStartTextIndex - startTextIndex);
806                                 blockEndTextIndex = textIndexFromElementOffset + (blockEndTextIndex - startTextIndex);
807                                 adjustedX = adjustedRect.x;
808
809                                 if (textIndexFromElementOffset < blockStartTextIndex)
810                                 {
811                                         //[TODO] yunji19.park : to change api -> _Font::GetPosition()
812                                         pTextElement->GetRegion(textIndexFromElementOffset, blockStartTextIndex - textIndexFromElementOffset, tempTextSize.width, tempTextSize.height);
813                                         adjustedX += tempTextSize.width;
814                                 }
815
816                                 Rectangle blockRect = adjustedRect;
817                                 blockRect.x = adjustedX;
818
819                                 Dimension blockSize;
820                                 int blockLength = blockEndTextIndex - blockStartTextIndex;
821                                 r = pTextElement->GetBlockRegion(blockStartTextIndex, blockLength, blockSize.width, blockSize.height);
822                                 SysTryReturn(NID_GRP
823                                         , r == E_SUCCESS
824                                         , r, r, "[%s] Propagating.", GetErrorMessage(r));
825
826                                 r = pCanvas->FillRectangle(__defaultBlockColor, Rectangle(blockRect.x, displayRect.y, blockSize.width, displayRect.height));
827                                 SysTryReturn(NID_GRP
828                                         , r == E_SUCCESS
829                                         , r, r, "[%s] Propagating.", GetErrorMessage(r));
830                         }
831                 }
832
833                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
834
835                 adjustedRect.x += textSize.width;
836                 adjustedRect.width -= textSize.width;
837
838                 if (drawAbbrevText)
839                 {
840                         if (pTextElement->IsBackGroundDrawingModeEnable())
841                         {
842                                 r = pCanvas->FillRectangle(pTextElement->GetBackgroundColor(), Rectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
843                                 SysTryReturn(NID_GRP
844                                         , r == E_SUCCESS
845                                         , r, r, "[%s] Propagating.", GetErrorMessage(r));
846                         }
847
848                         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
849
850                         adjustedRect.x += abbrevTextDim.width;
851                         adjustedRect.width -= abbrevTextDim.width;
852
853                         break;
854                 }
855
856                 if (!textLength || adjustedRect.width <= 0)
857                 {
858                         break;
859                 }
860
861                 startTextIndex += currentLength;
862
863                 if (pEnum->MoveNext() != E_SUCCESS)
864                 {
865                         break;
866                 }
867
868                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
869                 if (pTextElement == null)
870                 {
871                         break;
872                 }
873
874                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
875                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
876
877                 if (currentLength == 0)
878                 {
879                         break;
880                 }
881         }
882
883         Release(pEnum);
884         return E_SUCCESS;
885
886 CATCH:
887         Release(pEnum);
888         return r;
889 }
890
891 result
892 TextComposite::DrawWithBaseline(_CanvasImpl& canvasImpl, Rectangle& displayRect, int startTextIndex, int textLength, const TextObjectAlignment alignment,
893                                          const TextObjectActionType action, int baseline)
894 {
895         if (textLength == 0)
896         {
897                 return E_SUCCESS;
898         }
899
900         SysTryReturn(NID_GRP
901                         , 0 <= startTextIndex && startTextIndex < __length
902                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
903
904         SysTryReturn(NID_GRP
905                         , textLength <= __length
906                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
907
908         result r = E_SUCCESS;
909         IEnumerator* pEnum = null;
910         TextElement* pTextElement = null;
911
912         Dimension textSize;
913         Dimension spaceCharDim;
914         Dimension abbrevTextDim;
915         Rectangle adjustedRect = displayRect;
916         int currentLength = 0;
917         int elementTextOffset = 0;
918         int elementIndex = 0;
919         int textIndexFromElementOffset = 0;
920         int blockStartTextIndex = 0;
921         int blockEndTextIndex = 0;
922         bool drawAbbrevText = false;
923         bool isAlternateLookEnabled = false;
924
925         _Canvas* pCanvas = _Canvas::GetInstance(canvasImpl);
926         SysTryReturn(NID_GRP
927                         , pCanvas
928                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native canvas instance.");
929
930         pTextElement = GetElementAtTextIndex(startTextIndex + textLength - 1, elementTextOffset, elementIndex, currentLength,
931                                                                                          textIndexFromElementOffset);
932
933         if (pTextElement && __ignoreRearBlank && __rearSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
934         {
935                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
936                 if (pSimpleText != null)
937                 {
938                         int length = startTextIndex + textLength - elementTextOffset - 1;
939                         const wchar_t* pText = pSimpleText->GetText();
940                         SysTryReturn(NID_GRP
941                                 , pText
942                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
943
944                         SysTryReturn(NID_GRP
945                                 , length >= 0 && length < pSimpleText->GetTextLength()
946                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",length, pSimpleText->GetTextLength());
947
948                         if (pText[length] == (wchar_t)L' ')
949                         {
950                                 GetRegion(length + elementTextOffset, 1, spaceCharDim.width, spaceCharDim.height);
951                                 textLength--;
952                         }
953                 }
954         }
955
956         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
957                                                                                                          textIndexFromElementOffset);
958         SysTryCatch(NID_GRP
959                         , pTextElement
960                         , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
961
962         if (__ignoreFrontBlank && __frontSpaceHideMode == TEXT_OBJECT_SPACE_HIDE_TYPE_ONE)
963         {
964                 const TextSimple* pSimpleText = dynamic_cast <const TextSimple*>(pTextElement);
965                 if (pSimpleText != null)
966                 {
967                         int index = startTextIndex - elementTextOffset;
968                         const wchar_t* pText = pSimpleText->GetText();
969                         SysTryReturn(NID_GRP
970                                 , pText
971                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text.");
972
973                         SysTryReturn(NID_GRP
974                                 , index >= 0 && index < pSimpleText->GetTextLength()
975                                 , E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] text index(%d) must greater than 0 and must be less than total string length(%d)",index, pSimpleText->GetTextLength());
976
977                         if (pText[index] == (wchar_t)L' ')
978                         {
979                                 GetRegion(textIndexFromElementOffset, 1, spaceCharDim.width, spaceCharDim.height);
980                                 textLength--;
981                                 startTextIndex++;
982                                 textIndexFromElementOffset++;
983                         }
984                 }
985         }
986
987         switch (alignment & TEXT_ALIGNMASK_HORIZ)
988         {
989         case TEXT_OBJECT_ALIGNMENT_LEFT:
990                 // fall through
991         default:
992                 break;
993
994         case TEXT_OBJECT_ALIGNMENT_CENTER:
995                 GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
996                 if (textSize.width < adjustedRect.width)
997                 {
998                         adjustedRect.x += (adjustedRect.width - textSize.width) / 2;
999                 }
1000                 break;
1001
1002         case TEXT_OBJECT_ALIGNMENT_RIGHT:
1003                 GetRegion(startTextIndex, textLength, textSize.width, textSize.height);
1004                 if (textSize.width < adjustedRect.width)
1005                 {
1006                         adjustedRect.x += adjustedRect.width - textSize.width;
1007                 }
1008                 break;
1009         }
1010
1011         pEnum = __pTextElementList->GetEnumeratorN();
1012         for (int i = 0; i <= elementIndex; i++)
1013         {
1014                 r = pEnum->MoveNext();
1015                 SysTryCatch(NID_GRP
1016                                 , r == E_SUCCESS
1017                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
1018         }
1019
1020         adjustedRect.y = displayRect.y + displayRect.height - baseline;
1021         canvasImpl.SetTextOrigin(TEXT_ORIGIN_BASELINE);
1022
1023         currentLength = Math::Min(textLength, currentLength);
1024
1025         while (textLength > 0)
1026         {
1027                 textLength -= currentLength;
1028
1029                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
1030
1031                 if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV && (pTextElement->GetType() == TEXT_ELEMENT_TYPE_TEXT))
1032                 {
1033                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
1034                         SysTryCatch(NID_GRP
1035                                         , pSimpleText
1036                                         , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to cast text element.");
1037
1038                         SetAbbrevObjectFontInfo(pSimpleText);
1039
1040                         int textCount = 0;
1041                         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
1042
1043                         if (adjustedRect.width < textSize.width + abbrevTextDim.width || textLength <= 0)
1044                         {
1045                                 int endType = TEXT_RETBY_NORMAL;
1046
1047                                 if (adjustedRect.width > abbrevTextDim.width)
1048                                 {
1049                                         int remainingLength = pSimpleText->GetTextLength() - textIndexFromElementOffset;
1050                                         endType = pSimpleText->ForwardAnalyze(textIndexFromElementOffset, remainingLength, adjustedRect.width - abbrevTextDim.width,
1051                                                                                                                                  TEXT_OBJECT_WRAP_TYPE_NONE, textCount, textSize.width, textSize.height);
1052
1053                                         if (endType == TEXT_RETBY_OVERWIDTH)
1054                                         {
1055                                                 textSize.width = 0;
1056                                                 textSize.height = 0;
1057                                                 textCount = 0;
1058                                         }
1059                                 }
1060                                 else
1061                                 {
1062                                         textSize.width = 0;
1063                                         textCount = 0;
1064                                         textSize.height = pSimpleText->GetHeight();
1065                                 }
1066
1067                                 currentLength = textCount;
1068                                 drawAbbrevText = true;
1069
1070                                 switch (alignment & TEXT_ALIGNMASK_HORIZ)
1071                                 {
1072                                         case TEXT_OBJECT_ALIGNMENT_CENTER:
1073                                                 if (textSize.width + abbrevTextDim.width < adjustedRect.width)
1074                                                 {
1075                                                         adjustedRect.x = displayRect.x + (adjustedRect.width - (textSize.width + abbrevTextDim.width)) / 2;
1076                                                 }
1077                                                 break;
1078
1079                                         case TEXT_OBJECT_ALIGNMENT_RIGHT:
1080                                                 if (textSize.width + abbrevTextDim.width < adjustedRect.width)
1081                                                 {
1082                                                         adjustedRect.x = displayRect.x + adjustedRect.width - (textSize.width + abbrevTextDim.width);
1083                                                 }
1084                                                 break;
1085
1086                                         case TEXT_OBJECT_ALIGNMENT_LEFT:
1087                                                 // fall through
1088                                         default:
1089                                                 break;
1090                                  }
1091                         }
1092                 }
1093
1094                 if (pTextElement->IsBackGroundDrawingModeEnable())
1095                 {
1096                         Dimension blockSize;
1097                         r = pTextElement->GetRegion(textIndexFromElementOffset, currentLength, blockSize.width, blockSize.height);
1098                         SysTryReturn(NID_GRP
1099                                 , r == E_SUCCESS
1100                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
1101
1102                         r = pCanvas->FillRectangle(pTextElement->GetBackgroundColor(), Rectangle(adjustedRect.x, displayRect.y, blockSize.width, displayRect.height));
1103                         SysTryReturn(NID_GRP
1104                                 , r == E_SUCCESS
1105                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
1106                 }
1107
1108                 isAlternateLookEnabled = (bool)pTextElement->GetValue(SET_ALTERNATE_LOOK);
1109                 if (__displayBlock && isAlternateLookEnabled == false)
1110                 {
1111                         Dimension tempTextSize;
1112                         int adjustedX = 0;
1113
1114                         blockStartTextIndex = Math::Max(__workStart, startTextIndex);
1115                         blockEndTextIndex = Math::Min(__workStart + __workLength, startTextIndex + currentLength);
1116                         if (blockStartTextIndex < blockEndTextIndex)
1117                         {
1118                                 blockStartTextIndex = textIndexFromElementOffset + (blockStartTextIndex - startTextIndex);
1119                                 blockEndTextIndex = textIndexFromElementOffset + (blockEndTextIndex - startTextIndex);
1120                                 adjustedX = adjustedRect.x;
1121
1122                                 if (textIndexFromElementOffset < blockStartTextIndex)
1123                                 {
1124                                         pTextElement->GetRegion(textIndexFromElementOffset, blockStartTextIndex - textIndexFromElementOffset, tempTextSize.width, tempTextSize.height);
1125                                         adjustedX += tempTextSize.width;
1126                                 }
1127
1128                                 Rectangle block_rect = adjustedRect;
1129                                 block_rect.x = adjustedX;
1130                         }
1131                 }
1132
1133                 Rectangle imageRect = adjustedRect;
1134                 imageRect.y -= textSize.height;
1135                 TextElementType objectType = pTextElement->GetType();
1136                 if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1137                 {
1138                         pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, alignment, action);
1139                 }
1140                 else
1141                 {
1142                         pTextElement->Draw(canvasImpl, imageRect, textIndexFromElementOffset, currentLength, alignment, action);
1143                 }
1144
1145                 adjustedRect.x += textSize.width;
1146                 adjustedRect.width -= textSize.width;
1147
1148                 if (drawAbbrevText)
1149                 {
1150                         if (pTextElement->IsBackGroundDrawingModeEnable())
1151                         {
1152                                 r = pCanvas->FillRectangle(pTextElement->GetBackgroundColor(), Rectangle(adjustedRect.x, displayRect.y, abbrevTextDim.width, displayRect.height));
1153                                 SysTryReturn(NID_GRP
1154                                         , r == E_SUCCESS
1155                                         , r, r, "[%s] Propagating.", GetErrorMessage(r));
1156                         }
1157
1158                         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), action);
1159
1160                         adjustedRect.x += abbrevTextDim.width;
1161                         adjustedRect.width -= abbrevTextDim.width;
1162
1163                         break;
1164                 }
1165
1166                 if (!textLength || adjustedRect.width <= 0)
1167                 {
1168                         break;
1169                 }
1170
1171                 startTextIndex += currentLength;
1172
1173                 if (pEnum->MoveNext() != E_SUCCESS)
1174                 {
1175                         break;
1176                 }
1177
1178                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1179                 if (pTextElement == null)
1180                 {
1181                         break;
1182                 }
1183
1184                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
1185                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
1186
1187                 if (currentLength == 0)
1188                 {
1189                         break;
1190                 }
1191         }
1192
1193         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1194
1195         Release(pEnum);
1196         return E_SUCCESS;
1197
1198 CATCH:
1199         canvasImpl.SetTextOrigin(TEXT_ORIGIN_LEFT_TOP);
1200
1201         Release(pEnum);
1202         return r;
1203 }
1204
1205 result
1206 TextComposite::DrawLine(_CanvasImpl& canvasImpl, TextLine* pTextLine, const Rectangle& displayRect,
1207                 const TextObjectAlignment align, const TextObjectActionType action)
1208 {
1209         SysTryReturn(NID_GRP
1210                 , pTextLine
1211                 , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1212
1213         int lineOffset = 0;
1214         int lineLength = 0;
1215
1216         Rectangle adjustedRect;
1217         Rectangle lineBounds;
1218         Dimension lineTextSize;
1219
1220         lineLength = pTextLine->GetTextLength();
1221         lineOffset = pTextLine->GetTextOffset();
1222
1223         lineBounds = pTextLine->GetBounds();
1224         pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
1225
1226         adjustedRect = displayRect;
1227         adjustedRect.width = lineBounds.width;
1228         adjustedRect.height = lineBounds.height;
1229
1230         if (__elementVertialAlignment & TEXT_OBJECT_ALIGNMENT_BASELINE)
1231         {
1232                 return DrawWithBaseline(canvasImpl, adjustedRect, lineOffset, lineLength, (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | TEXT_OBJECT_ALIGNMENT_BASELINE), action, pTextLine->GetBaseline());
1233         }
1234         else
1235         {
1236                 return Draw(canvasImpl, adjustedRect, lineOffset, lineLength, (TextObjectAlignment)((TEXT_ALIGNMASK_HORIZ & align) | __elementVertialAlignment), action);
1237         }
1238 }
1239
1240 result
1241 TextComposite::GetValue(TextElement* pTextElement, TextComponentInfoValueType type, unsigned int* value) const
1242 {
1243         SysTryReturn(NID_GRP
1244                         , pTextElement
1245                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1246
1247         TextElementType objectType = TextUtility::GetObjectTypeFromValueType(type);
1248
1249         SysTryReturn(NID_GRP
1250                         , pTextElement->GetType() == objectType
1251                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get type.");
1252
1253         *value = pTextElement->GetValue(type);
1254
1255         return E_SUCCESS;
1256 }
1257
1258 result
1259 TextComposite::InsertElementAt(TextElement& textElement, int textIndex)
1260 {
1261         SysTryReturn(NID_GRP
1262                         , 0 <= textIndex && textIndex <= __length
1263                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1264
1265         result r = E_SUCCESS;
1266
1267         TextElement* pCurrentTextElement = null;
1268         TextElement* pNewTextElement = null;
1269
1270         int currentLength = 0;
1271         int elementTextOffset = 0;
1272         int elementIndex = 0;
1273         int textIndexFromElementOffset = 0;
1274
1275         pCurrentTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex,
1276                         currentLength, textIndexFromElementOffset);
1277
1278         if (pCurrentTextElement != null)
1279         {
1280                 if (textIndex == elementTextOffset)
1281                 {
1282                         r = __pTextElementList->InsertAt(textElement, elementIndex);
1283                         SysTryReturn(NID_GRP
1284                                 , r == E_SUCCESS
1285                                 , r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1286                 }
1287                 else
1288                 {
1289                         pCurrentTextElement->SetTextLength(pCurrentTextElement->GetTextLength() - currentLength);
1290
1291                         r = __pTextElementList->InsertAt(textElement, ++elementIndex);
1292                         SysTryReturn(NID_GRP
1293                                 , r == E_SUCCESS
1294                                 , r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1295
1296                         pNewTextElement = pCurrentTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
1297                         SysTryReturn(NID_GRP
1298                                 , pNewTextElement
1299                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
1300
1301                         pNewTextElement->SetTextLength(currentLength);
1302
1303                         if (textIndexFromElementOffset != 0)
1304                         {
1305                                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
1306                         }
1307
1308                         r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
1309                         SysTryReturn(NID_GRP
1310                                 , r == E_SUCCESS
1311                                 , r, r, "[%s] Fail to insert element.", GetErrorMessage(r));
1312                 }
1313         }
1314         else
1315         {
1316                 if (textIndex == __length)
1317                 {
1318                         r = __pTextElementList->Add(textElement);
1319                         SysTryReturn(NID_GRP
1320                                 , r == E_SUCCESS
1321                                 , r, r, "[%s] Fail to add element.", GetErrorMessage(r));
1322                 }
1323                 else
1324                 {
1325                         return E_SYSTEM;
1326                 }
1327         }
1328
1329         int elementTextLength = textElement.GetTextLength();
1330
1331         __workStart = textIndex;
1332         __workLength = elementTextLength;
1333         __length += elementTextLength;
1334         __isChanged = true;
1335
1336         TextElementType objectType = textElement.GetType();
1337         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK)
1338         {
1339                 TextCutLink* pLinkElement = dynamic_cast < TextCutLink* >(&textElement);
1340                 __pCutLinkListInfo->InsertCutLinkElementInfo(textIndex, *pLinkElement, elementTextLength);
1341         }
1342         else
1343         {
1344                 __pCutLinkListInfo->InsertText(textIndex, elementTextLength);
1345         }
1346
1347         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1348         {
1349                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(&textElement);
1350                 if (pSimpleText != null)
1351                 {
1352                         pSimpleText->SetUserWrap(__wrap);
1353                 }
1354         }
1355
1356         return r;
1357 }
1358
1359 result
1360 TextComposite::AppendElement(TextElement& textElement)
1361 {
1362         result r = E_SUCCESS;
1363         int elementTextLength = textElement.GetTextLength();
1364
1365         r = __pTextElementList->Add(textElement);
1366         SysTryReturn(NID_GRP
1367                 , r == E_SUCCESS
1368                 , r, r, "[%s] Fail to add element.", GetErrorMessage(r));
1369
1370         __workStart = __length;
1371         __workLength = elementTextLength;
1372         __length += elementTextLength;
1373         __isChanged = true;
1374
1375         TextElementType objectType = textElement.GetType();
1376         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK)
1377         {
1378                 TextCutLink* pLinkElement = dynamic_cast < TextCutLink* >(&textElement);
1379                 __pCutLinkListInfo->InsertCutLinkElementInfo(__workStart, *pLinkElement, elementTextLength);
1380         }
1381         else
1382         {
1383                 __pCutLinkListInfo->InsertText(__workStart, elementTextLength);
1384         }
1385
1386         if (objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT)
1387         {
1388                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(&textElement);
1389                 if (pSimpleText != null)
1390                 {
1391                         pSimpleText->SetUserWrap(__wrap);
1392                 }
1393         }
1394
1395         return r;
1396 }
1397
1398 result
1399 TextComposite::RemoveElementAt(int elementIndex, bool deallocate)
1400 {
1401         SysTryReturn(NID_GRP
1402                         , elementIndex >= 0 && elementIndex < __pTextElementList->GetCount()
1403                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1404
1405         result r = E_SUCCESS;
1406         TextElement* pTextElement = null;
1407
1408         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex));
1409         if (pTextElement != null)
1410         {
1411                 int elementTextLength = pTextElement->GetTextLength();
1412                 int elementTextOffset = GetFirstTextIndexAt(elementIndex);
1413
1414                 r = __pTextElementList->RemoveAt(elementIndex);
1415                 SysTryReturn(NID_GRP
1416                         , r == E_SUCCESS
1417                         , r, r, "[%s] Fail to remove element.", GetErrorMessage(r));
1418
1419                 if (pTextElement->GetType() == TEXT_ELEMENT_TYPE_CUTLINK)
1420                 {
1421                         __pCutLinkListInfo->RemoveCutLinkElementInfo(dynamic_cast < TextCutLink* >(pTextElement));
1422                 }
1423                 else
1424                 {
1425                         __pCutLinkListInfo->RemoveText(elementTextOffset, elementTextLength);
1426                 }
1427
1428                 __length -= elementTextLength;
1429
1430                 if (deallocate)
1431                 {
1432                         delete pTextElement;
1433                         pTextElement = null;
1434                 }
1435         }
1436
1437         return r;
1438 }
1439
1440 result
1441 TextComposite::RemoveAllElements(bool deallocate)
1442 {
1443         result r = E_SUCCESS;
1444
1445         if (__pCutLinkListInfo)
1446         {
1447                 __pCutLinkListInfo->RemoveAllCutLinkElementInfos();
1448         }
1449
1450         __pTextElementList->RemoveAll(deallocate);
1451
1452         SysTryCatch(NID_GRP
1453                 , __pTextElementList->GetCount() == 0
1454                 , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to remove all elements.");
1455
1456         __workStart = 0;
1457         __workLength = 0;
1458         __length = 0;
1459         __displayBlock = false;
1460         __ignoreRearBlank = false;
1461         __ignoreFrontBlank = false;
1462         __cursorIndex = -1;
1463         __rearSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_NONE;
1464         __frontSpaceHideMode = TEXT_OBJECT_SPACE_HIDE_TYPE_NONE;
1465
1466         return E_SUCCESS;
1467
1468 CATCH:
1469         __workStart = 0;
1470         __workLength = 0;
1471         __length = 0;
1472         __cursorIndex = -1;
1473
1474         return r;
1475 }
1476
1477 TextElement*
1478 TextComposite::SearchTextElement(TextElementType type, int textIndex, int& elementTextOffset) const
1479 {
1480         SysTryReturn(NID_GRP
1481                         , 0 <= textIndex && textIndex < __length
1482                         , null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1483
1484         result r = E_SUCCESS;
1485         IEnumerator* pEnum = null;
1486         TextElement* pTextElement = null;
1487
1488         int elementIndex = 0;
1489         int currentLength = 0;
1490         int textIndexFromElementOffset = 0;
1491
1492         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
1493                                                                                                  textIndexFromElementOffset);
1494         SysTryReturn(NID_GRP
1495                 , pTextElement
1496                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1497
1498         if (pTextElement->GetType() == type)
1499         {
1500                 return pTextElement;
1501         }
1502
1503         elementTextOffset += pTextElement->GetTextLength();
1504
1505         pEnum = __pTextElementList->GetEnumeratorN();
1506         for (int i = 0; i < elementIndex; i++)
1507         {
1508                 r = pEnum->MoveNext();
1509                 SysTryCatch(NID_GRP
1510                                 , r == E_SUCCESS
1511                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
1512         }
1513
1514         while (pEnum->MoveNext() == E_SUCCESS)
1515         {
1516                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1517                 if (pTextElement == null)
1518                 {
1519                         continue;
1520                 }
1521
1522                 if (pTextElement->GetType() == type)
1523                 {
1524                         Release(pEnum);
1525                         SetLastResult(E_SUCCESS);
1526                         return pTextElement;
1527                 }
1528
1529                 elementTextOffset += pTextElement->GetTextLength();
1530         }
1531
1532         Release(pEnum);
1533         SetLastResult(E_SUCCESS);
1534         return null;
1535
1536 CATCH:
1537         Release(pEnum);
1538         return null;
1539 }
1540
1541 result
1542 TextComposite::GetText(TextComposite* pTargetCompsiteText, int textIndex, int textLength)
1543 {
1544         SysTryReturn(NID_GRP
1545                 , pTargetCompsiteText
1546                 , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1547
1548         SysTryReturn(NID_GRP
1549                 , 0 < textLength
1550                 , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1551
1552         result r = E_SUCCESS;
1553         IEnumerator* pEnum = null;
1554         TextElement* pTextElement = null;
1555         TextElement* pNewTextElement = null;
1556
1557         int currentLength = 0;
1558         int elementTextOffset = 0;
1559         int elementIndex = 0;
1560         int textIndexFromElementOffset = 0;
1561
1562         if (textIndex == -1 || textIndex < 0)
1563         {
1564                 textIndex = 0;
1565         }
1566
1567         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
1568                                                                                          textIndexFromElementOffset);
1569         SysTryReturn(NID_GRP
1570                 , pTextElement
1571                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get element.");
1572
1573         textIndexFromElementOffset = textIndex - elementTextOffset;
1574
1575         pEnum = __pTextElementList->GetEnumeratorN();
1576         for (int i = 0; i < elementIndex; i++)
1577         {
1578                 r = pEnum->MoveNext();
1579                 SysTryCatch(NID_GRP
1580                                 , r == E_SUCCESS
1581                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
1582         }
1583
1584         while (pEnum->MoveNext() == E_SUCCESS)
1585         {
1586                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1587                 if (pTextElement == null)
1588                 {
1589                         continue;
1590                 }
1591
1592                 textIndexFromElementOffset = 0;
1593                 currentLength = Math::Min(pTextElement->GetTextLength(), textLength);
1594
1595                 pNewTextElement = pTextElement->CopyN(textIndexFromElementOffset, currentLength);
1596                 if (pNewTextElement != null)
1597                 {
1598                         pTargetCompsiteText->AppendElement(*pNewTextElement);
1599                 }
1600
1601                 textLength -= currentLength;
1602         }
1603
1604         Release(pEnum);
1605         return E_SUCCESS;
1606
1607 CATCH :
1608         Release(pEnum);
1609         return r;
1610 }
1611
1612 int
1613 TextComposite::Compose(Rectangle& rect, TextColumn* pTextColumn)
1614 {
1615         SysTryReturn(NID_GRP
1616                 , pTextColumn
1617                 , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1618
1619         __pCurrentTextColumn = pTextColumn;
1620
1621         int lineCount = 0;
1622
1623         if (__pTextElementList->GetCount() == 0 || __length == 0)
1624         {
1625                 pTextColumn->RemoveAllLines();
1626
1627                 return -1;
1628         }
1629
1630         switch (__wrap)
1631         {
1632         case TEXT_OBJECT_WRAP_TYPE_NONE:
1633         {
1634                 if (__drawAbbrevText)
1635                 {
1636                         __pCurrentTextColumn->PrepareCompose();
1637
1638                         __drawTextEllipsis = false;
1639                         if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_TAIL)
1640                         {
1641                                 lineCount = ComposeInNoneWrap(rect);
1642                         }
1643                         else if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_MIDDLE)
1644                         {
1645                                 lineCount = ComposeInNoneWrapMiddleEllipsis(rect);
1646                         }
1647                         else
1648                         {
1649                                 lineCount = ComposeInNoneWrapHeadEllipsis(rect);
1650                         }
1651                 }
1652                 else
1653                 {
1654                         bool setNoneWrapComposeInfo = false;
1655                         NoneWrapComposeInfo noneWrapComposeInfo;
1656
1657                         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
1658                         if (pTextLine != null)
1659                         {
1660
1661                                 noneWrapComposeInfo.prevTextOffset = pTextLine->GetTextOffset();
1662                                 noneWrapComposeInfo.prevTextLength = pTextLine->GetTextLength();
1663                                 pTextLine->GetRegion(0, noneWrapComposeInfo.prevTextLength,
1664                                                                                                         noneWrapComposeInfo.prevWidth, noneWrapComposeInfo.prevHeight);
1665                                 noneWrapComposeInfo.prevEndType = pTextLine->GetEndType();
1666                                 setNoneWrapComposeInfo = true;
1667                         }
1668
1669                         __pCurrentTextColumn->PrepareCompose();
1670                         __drawTextEllipsis = false;
1671                         if (setNoneWrapComposeInfo)
1672                         {
1673                                 lineCount = ComposeInNoneWrap(rect, &noneWrapComposeInfo);
1674                         }
1675                         else
1676                         {
1677                                 lineCount = ComposeInNoneWrap(rect);
1678                         }
1679                 }
1680
1681                 __pCurrentTextColumn->FinishCompose();
1682                 break;
1683         }
1684
1685         case TEXT_OBJECT_WRAP_TYPE_CHARACTER:
1686         {
1687                 __pCurrentTextColumn->PrepareCompose();
1688                 lineCount = ComposeInNormalWrap(rect);
1689                 __pCurrentTextColumn->FinishCompose();
1690                 break;
1691         }
1692
1693         case TEXT_OBJECT_WRAP_TYPE_WORD:
1694         {
1695                 if (IsPartialComposingModeEnabled())
1696                 {
1697                         if (__pCurrentTextColumn->GetTotalLineCount() == 0)
1698                         {
1699                                 __pCurrentTextColumn->PrepareCompose();
1700                         }
1701                         lineCount = ComposeInPartialMode(rect);
1702                 }
1703                 else
1704                 {
1705                         __pCurrentTextColumn->PrepareCompose();
1706                         lineCount = ComposeInWordWrap(rect);
1707                         __pCurrentTextColumn->CompareDeletedLine();
1708                         __pCurrentTextColumn->FinishCompose();
1709                 }
1710
1711                 break;
1712         }
1713         }
1714
1715         return lineCount;
1716 }
1717
1718 result
1719 TextComposite::SetRange(int textStartIndex, int textLength)
1720 {
1721         SysTryReturn(NID_GRP
1722                 , 0 <= textStartIndex && textStartIndex <= __length
1723                 , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1724
1725         __workStart = textStartIndex;
1726         __workLength = textLength;
1727
1728         return E_SUCCESS;
1729 }
1730
1731 void
1732 TextComposite::GetRange(int& startTextIndex, int& textLength) const
1733 {
1734         startTextIndex = __workStart;
1735         textLength = __workLength;
1736 }
1737
1738 result
1739 TextComposite::SetFont(Font* pFont)
1740 {
1741         return SetValueToAllTextElements(SET_FONT, (unsigned int)pFont);
1742 }
1743
1744 Font*
1745 TextComposite::GetFont(int textIndex) const
1746 {
1747         unsigned int value = 0;
1748
1749         GetValue(textIndex, SET_FONT, &value);
1750         Font* pFont = static_cast < Font* >((void*)value);
1751
1752         SetLastResult(E_SUCCESS);
1753
1754         return pFont;
1755 }
1756
1757 result
1758 TextComposite::SetForegroundColor(const Color& color)
1759 {
1760         return SetValueToAllTextElements(SET_FONT_FGCOLOR, (unsigned int)color.GetRGB32());
1761 }
1762
1763 Color
1764 TextComposite::GetForegroundColor(int textIndex) const
1765 {
1766         result r = E_SUCCESS;
1767         unsigned int value = 0;
1768
1769         r = GetValue(textIndex, SET_FONT_FGCOLOR, &value);
1770         SysTryReturn(NID_GRP
1771                 , r == E_SUCCESS
1772                 , Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
1773
1774         return Color(value);
1775 }
1776
1777 result
1778 TextComposite::SetBackgroundColor(const Color& color)
1779 {
1780         return SetValueToAllTextElements(SET_FONT_BGCOLOR, (unsigned int)color.GetRGB32());
1781 }
1782
1783 Color
1784 TextComposite::GetBackgroundColor(int textIndex) const
1785 {
1786         result r = E_SUCCESS;
1787         unsigned int value = 0;
1788
1789         r = GetValue(textIndex, SET_FONT_BGCOLOR, &value);
1790         SysTryReturn(NID_GRP
1791                 , r == E_SUCCESS
1792                 , Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
1793
1794         return Color(value);
1795 }
1796
1797 result
1798 TextComposite::SetOutlineColor(const Color& color)
1799 {
1800         return SetValueToAllTextElements(SET_FONT_OUTLINECOLOR, (unsigned int)color.GetRGB32());
1801 }
1802
1803 Color
1804 TextComposite::GetOutlineColor(int textIndex) const
1805 {
1806         result r = E_SUCCESS;
1807         unsigned int value = 0;
1808
1809         r = GetValue(textIndex, SET_FONT_OUTLINECOLOR, &value);
1810         SysTryReturn(NID_GRP
1811                 , r == E_SUCCESS
1812                 , Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
1813
1814         return Color(value);
1815 }
1816
1817 Color
1818 TextComposite::GetAlternativeForegroundColor(int textIndex) const
1819 {
1820         SysTryReturn(NID_GRP
1821                         , 0 <= textIndex && textIndex < __length
1822                         , Color::GetColor(COLOR_ID_BLACK), E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1823
1824         result r = E_SUCCESS;
1825         unsigned int value = 0;
1826
1827         r = GetValue(textIndex, SET_ALTERNATIVE_FGCOLOR, &value);
1828         SysTryReturn(NID_GRP
1829                 , r == E_SUCCESS
1830                 , Color::GetColor(COLOR_ID_BLACK), r, "[%s] Propagating.", GetErrorMessage(r));
1831
1832         return Color(value);
1833 }
1834
1835 result
1836 TextComposite::SetAlternateLookEnabled(bool enable)
1837 {
1838         return SetValueToAllTextElements(SET_ALTERNATE_LOOK, (unsigned int)enable);
1839 }
1840
1841 int
1842 TextComposite::GetMaxLineHeight(void) const
1843 {
1844         IEnumerator* pEnum = null;
1845         TextElement* pTextElement = null;
1846         int height = 0;
1847         int maxHeight = 0;
1848
1849         pEnum = __pTextElementList->GetEnumeratorN();
1850         while (pEnum->MoveNext() == E_SUCCESS)
1851         {
1852                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1853                 if (pTextElement == null)
1854                 {
1855                         continue;
1856                 }
1857
1858                 height = pTextElement->GetHeight();
1859                 maxHeight = Math::Max(maxHeight, height);
1860         }
1861
1862         Release(pEnum);
1863         return maxHeight;
1864 }
1865
1866 TextElement*
1867 TextComposite::GetElementAtTextIndex(int textIndex, int& elementTextOffset, int& elementIndex, int& elementTextLength,
1868                                                                    int& textIndexFromElementOffset) const
1869 {
1870         result r = E_SUCCESS;
1871         IEnumerator* pEnum = null;
1872         TextElement* pTextElement = null;
1873         int offset = 0;
1874         int currentElementLength = 0;
1875
1876         elementTextOffset = 0;
1877         elementIndex = 0;
1878         elementTextLength = 0;
1879         textIndexFromElementOffset = 0;
1880
1881         if (__pTextElementList->GetCount() == 0)
1882         {
1883                 return null;
1884         }
1885
1886         pEnum = __pTextElementList->GetEnumeratorN();
1887         r = pEnum->MoveNext();
1888         SysTryReturn(NID_GRP
1889                 , r == E_SUCCESS
1890                 , null, r, "[%s] Fail to move next element. Now Elements count is (%d)", GetErrorMessage(r), __pTextElementList->GetCount());
1891
1892         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1893         SysTryReturn(NID_GRP
1894                 , pTextElement
1895                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1896
1897         while (1)
1898         {
1899                 currentElementLength = pTextElement->GetTextLength();
1900                 if (textIndex < elementTextOffset + currentElementLength)
1901                 {
1902                         offset = pTextElement->GetValue(SET_TEXT_OFFSET);
1903                         textIndexFromElementOffset = offset + (textIndex - elementTextOffset);
1904                         break;
1905                 }
1906                 else
1907                 {
1908                         if (currentElementLength == 0 && textIndex == elementTextOffset)
1909                         {
1910                                 offset = pTextElement->GetValue(SET_TEXT_OFFSET);
1911                                 textIndexFromElementOffset = offset + (textIndex - elementTextOffset);
1912                                 break;
1913                         }
1914                 }
1915
1916                 pTextElement = null;
1917                 if (pEnum->MoveNext() != E_SUCCESS)
1918                 {
1919                         break;
1920                 }
1921
1922                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1923                 if (pTextElement == null)
1924                 {
1925                         break;
1926                 }
1927
1928                 elementTextOffset += currentElementLength;
1929                 elementIndex++;
1930         }
1931
1932         if (pTextElement != null)
1933         {
1934                 elementTextLength = elementTextOffset + currentElementLength - textIndex;
1935         }
1936
1937         Release(pEnum);
1938         return pTextElement;
1939 }
1940
1941 TextElement*
1942 TextComposite::GetElementAtTextIndex(int textIndex) const
1943 {
1944         result r = E_SUCCESS;
1945         IEnumerator* pEnum = null;
1946         TextElement* pTextElement = null;
1947         int currentElementLength = 0;
1948         int elementTextOffset = 0;
1949
1950         if (__pTextElementList->GetCount() == 0)
1951         {
1952                 return null;
1953         }
1954
1955         pEnum = __pTextElementList->GetEnumeratorN();
1956         r = pEnum->MoveNext();
1957         SysTryReturn(NID_GRP
1958                 , r == E_SUCCESS
1959                 , null, r, "[%s] Fail to move next element. Now Elements count is (%d)", GetErrorMessage(r), __pTextElementList->GetCount());
1960
1961         pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1962         SysTryReturn(NID_GRP
1963                 , pTextElement
1964                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
1965
1966         while (1)
1967         {
1968                 currentElementLength = pTextElement->GetTextLength();
1969                 if (textIndex < elementTextOffset + currentElementLength)
1970                 {
1971                         break;
1972                 }
1973                 else
1974                 {
1975                         if (currentElementLength == 0 && textIndex == elementTextOffset)
1976                         {
1977                                 break;
1978                         }
1979                 }
1980
1981                 pTextElement = null;
1982                 if (pEnum->MoveNext() != E_SUCCESS)
1983                 {
1984                         break;
1985                 }
1986
1987                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
1988                 if (pTextElement == null)
1989                 {
1990                         break;
1991                 }
1992
1993                 elementTextOffset += currentElementLength;
1994         }
1995
1996         Release(pEnum);
1997         return pTextElement;
1998 }
1999
2000 result
2001 TextComposite::SetWrap(TextObjectWrapType wrap)
2002 {
2003         if (__wrap == wrap)
2004         {
2005                 return E_SUCCESS;
2006         }
2007
2008         __wrap = wrap;
2009
2010         IEnumerator* pEnum = null;
2011         TextElement* pTextElement = null;
2012
2013         pEnum = __pTextElementList->GetEnumeratorN();
2014         while (pEnum->MoveNext() == E_SUCCESS)
2015         {
2016                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2017                 if (pTextElement == null)
2018                 {
2019                         continue;
2020                 }
2021
2022                 TextElementType objectType = pTextElement->GetType();
2023                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2024                 {
2025                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2026                         if (pSimpleText != null)
2027                         {
2028                                 pSimpleText->SetUserWrap(__wrap);
2029                         }
2030                 }
2031         }
2032
2033         Release(pEnum);
2034         return E_SUCCESS;
2035 }
2036
2037 result
2038 TextComposite::Optimize(int startElementIndex, int endElementIndex)
2039 {
2040         int elementCount = 0;
2041         int nodeIndex = 0;
2042
2043         TextElement* pStartTextElement = null;
2044         TextElement* pEndTextElement = null;
2045         TextElement* pCurrentTextElement = null;
2046         TextElement* pNextTextElement = null;
2047
2048         elementCount = __pTextElementList->GetCount();
2049         if (elementCount == 0)
2050         {
2051                 return E_SUCCESS;
2052         }
2053
2054         if (startElementIndex == -1 || startElementIndex < 0)
2055         {
2056                 startElementIndex = 0;
2057         }
2058
2059         if (endElementIndex == -1 || endElementIndex < 0 || endElementIndex > elementCount - 1)
2060         {
2061                 endElementIndex = elementCount - 1;
2062         }
2063
2064         if (0 < startElementIndex)
2065         {
2066                 startElementIndex--;
2067         }
2068
2069         if (endElementIndex < elementCount - 1)
2070         {
2071                 endElementIndex++;
2072         }
2073
2074         if (endElementIndex - startElementIndex < 1)
2075         {
2076                 return E_SUCCESS;
2077         }
2078
2079         pStartTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(startElementIndex));
2080         SysTryReturn(NID_GRP
2081                 , pStartTextElement
2082                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2083
2084         pEndTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(endElementIndex));
2085         SysTryReturn(NID_GRP
2086                 , pEndTextElement
2087                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2088
2089         do
2090         {
2091                 pCurrentTextElement = pStartTextElement;
2092
2093                 nodeIndex = startElementIndex + 1;
2094
2095                 pNextTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(nodeIndex));
2096                 if (pNextTextElement == null)
2097                 {
2098                         break;
2099                 }
2100
2101                 if (TextUtility::CanMerge(pCurrentTextElement, pNextTextElement))
2102                 {
2103                         pCurrentTextElement->SetTextLength(pCurrentTextElement->GetTextLength() + pNextTextElement->GetTextLength());
2104                         __pTextElementList->Remove(*pNextTextElement, true);
2105                 }
2106                 else
2107                 {
2108                         pStartTextElement = pNextTextElement;
2109                 }
2110
2111                 startElementIndex++;
2112                 pStartTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(startElementIndex));
2113         }
2114         while (startElementIndex != endElementIndex);
2115
2116         return E_SUCCESS;
2117 }
2118
2119 result
2120 TextComposite::ChangeTextOffset(wchar_t* pText, int elementIndex, int gap)
2121 {
2122         SysTryReturn(NID_GRP
2123                         , 0 <= elementIndex
2124                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2125
2126         SysTryReturn(NID_GRP
2127                         , gap != 0
2128                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
2129
2130         result r = E_SUCCESS;
2131         IEnumerator* pEnum = null;
2132         TextElement* pTextElement = null;
2133
2134         pEnum = __pTextElementList->GetEnumeratorN();
2135         for (int i = 0; i < elementIndex; i++)
2136         {
2137                 r = pEnum->MoveNext();
2138                 SysTryCatch(NID_GRP
2139                                 , r == E_SUCCESS
2140                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2141         }
2142
2143         while (pEnum->MoveNext() == E_SUCCESS)
2144         {
2145                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2146                 if (pTextElement == null)
2147                 {
2148                         continue;
2149                 }
2150
2151                 TextElementType objectType = pTextElement->GetType();
2152                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2153                 {
2154                         TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2155                         if (pSimpleText != null)
2156                         {
2157                                 pSimpleText->ChangeTextOffset(pText, gap);
2158                         }
2159                 }
2160         }
2161
2162         Release(pEnum);
2163         return E_SUCCESS;
2164
2165 CATCH:
2166         Release(pEnum);
2167         return r;
2168 }
2169
2170 result
2171 TextComposite::NotifyTextChanged(wchar_t* pText, int startTextIndex, int textLength, int gap, Font* pFont,
2172                                                   const Color& fgColor, const Color& bgColor, const Color& outlineColor)
2173 {
2174         if (gap == 0)
2175         {
2176                 return E_SUCCESS;
2177         }
2178
2179         result r = E_SUCCESS;
2180         TextElement* pTextElement = null;
2181         TextElement* pNextTextElement = null;
2182
2183         int currentLength = 0;
2184         int elementTextOffset = 0;
2185         int elementIndex = 0;
2186         int textIndexFromElementOffset = 0;
2187         bool isOptimized = false;
2188
2189         SetWorkWidth(pFont, pText, __workStart, textLength);
2190
2191         if (gap > 0)
2192         {
2193                 bool checkNextElement = false;
2194
2195                 if (__workStart == startTextIndex)
2196                 {
2197                         pTextElement = GetElementAtTextIndex(__workStart, elementTextOffset, elementIndex, currentLength,
2198                                                                                                          textIndexFromElementOffset);
2199                 }
2200                 else
2201                 {
2202                         pTextElement = GetElementAtTextIndex(__workStart - 1, elementTextOffset, elementIndex, currentLength,
2203                                                                                                          textIndexFromElementOffset);
2204                         checkNextElement = true;
2205                 }
2206
2207                 if (pTextElement == null)
2208                 {
2209                         TextSimple* pSimpleText = null;
2210                         pSimpleText = new (std::nothrow)TextSimple(pText, gap, TEXT_ELEMENT_SOURCE_TYPE_EXTERNAL, pFont, fgColor, bgColor,
2211                                                                                           outlineColor);
2212                         SysTryReturn(NID_GRP
2213                                 , pSimpleText
2214                                 , E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
2215
2216                         pSimpleText->SetTextOffset(__workStart - startTextIndex);
2217                         InsertElementAt(*pSimpleText, __workStart);
2218
2219                         return E_SUCCESS;
2220                 }
2221                 else
2222                 {
2223                         TextSimple* pSimpleText = null;
2224                         bool canMerge = false;
2225
2226                         TextElementType objectType = pTextElement->GetType();
2227                         if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2228                         {
2229                                 pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2230                                 if (pSimpleText != null)
2231                                 {
2232                                         if (pSimpleText->IsSame(pText, pFont, fgColor, bgColor, outlineColor))
2233                                         {
2234                                                 canMerge = true;
2235                                         }
2236                                         else
2237                                         {
2238                                                 pTextElement = null;
2239                                         }
2240                                 }
2241                         }
2242                         else
2243                         {
2244                                 pTextElement = null;
2245                         }
2246
2247                         if (!canMerge && checkNextElement)
2248                         {
2249                                 pTextElement = null;
2250
2251                                 if (currentLength == 1)
2252                                 {
2253                                         pNextTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(elementIndex+1));
2254                                         if (pNextTextElement != null)
2255                                         {
2256                                                 objectType = pNextTextElement->GetType();
2257                                                 if (objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK)
2258                                                 {
2259                                                         pSimpleText = dynamic_cast < TextSimple* >(pNextTextElement);
2260                                                         if (pSimpleText != null)
2261                                                         {
2262                                                                 if (pSimpleText->IsSame(pText, pFont, fgColor, bgColor, outlineColor))
2263                                                                 {
2264                                                                         elementIndex++;
2265                                                                         pTextElement = pNextTextElement;
2266                                                                 }
2267                                                                 else
2268                                                                 {
2269                                                                         pTextElement = null;
2270                                                                 }
2271                                                         }
2272                                                 }
2273                                                 else
2274                                                 {
2275                                                         pTextElement = null;
2276                                                 }
2277                                         }
2278                                         else
2279                                         {
2280                                                 pTextElement = null;
2281                                         }
2282                                 }
2283                         }
2284
2285                         if (pTextElement == null)
2286                         {
2287                                 TextSimple* pSimpleText = null;
2288                                 pSimpleText = new (std::nothrow)TextSimple(pText, gap, TEXT_ELEMENT_SOURCE_TYPE_EXTERNAL, pFont, fgColor, bgColor,
2289                                                                                                   outlineColor);
2290                                 SysTryReturn(NID_GRP
2291                                         , pSimpleText
2292                                         , E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
2293
2294                                 pSimpleText->SetTextOffset(__workStart - startTextIndex);
2295                                 InsertElementAt(*pSimpleText, __workStart);
2296
2297                                 isOptimized = true;
2298                                 r = __pTextElementList->IndexOf(*pSimpleText, elementIndex);
2299                                 SysTryReturn(NID_GRP
2300                                         , r == E_SUCCESS
2301                                         , r, r, "[%s] Fail to get element index.", GetErrorMessage(r));
2302                         }
2303                         else
2304                         {
2305                                 __pCutLinkListInfo->InsertText(startTextIndex, gap);
2306                                 __length += gap;
2307                                 pTextElement->SetTextLength(pTextElement->GetTextLength() + gap);
2308                         }
2309                 }
2310         }
2311         else if (gap < 0)
2312         {
2313                 int remainingGap = -gap;
2314                 int currentGap = 0;
2315                 int textIndex = 0;
2316                 int currentelementIndex = 0;
2317
2318                 textIndex = __workStart + remainingGap;
2319                 pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
2320                                                                                                  textIndexFromElementOffset);
2321                 if (pTextElement == null || elementTextOffset == textIndex)
2322                 {
2323                         pTextElement = GetElementAtTextIndex(textIndex - 1, elementTextOffset, elementIndex, currentLength,
2324                                                                                                          textIndexFromElementOffset);
2325                 }
2326
2327                 SysTryReturn(NID_GRP
2328                         , pTextElement
2329                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2330
2331                 currentelementIndex = elementIndex;
2332                 currentGap = Math::Min(remainingGap, textIndex - elementTextOffset);
2333                 if (currentGap == pTextElement->GetTextLength())
2334                 {
2335                         RemoveElementAt(currentelementIndex);
2336                         elementIndex--;
2337                         isOptimized = true;
2338                 }
2339                 else
2340                 {
2341                         pTextElement->SetTextLength(pTextElement->GetTextLength() - currentGap);
2342                         __length -= currentGap;
2343                         if (currentGap < remainingGap)
2344                         {
2345                                 TextSimple* pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
2346                                 if (pSimpleText != null)
2347                                 {
2348                                         int offset = pSimpleText->GetTextOffset();
2349                                         offset -= (remainingGap - currentGap);
2350                                         pSimpleText->SetTextOffset(offset);
2351                                 }
2352                         }
2353                 }
2354
2355                 remainingGap -= currentGap;
2356                 while (remainingGap > 0)
2357                 {
2358                         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(--currentelementIndex));
2359                         SysTryReturn(NID_GRP
2360                                 , pTextElement
2361                                 , r, r, "[%s] Fail to get element.", GetErrorMessage(r));
2362
2363                         int elementTextLength = pTextElement->GetTextLength();
2364                         currentGap = Math::Min(elementTextLength, remainingGap);
2365
2366                         if (currentGap == elementTextLength)
2367                         {
2368                                 RemoveElementAt(currentelementIndex);
2369                                 elementIndex--;
2370                                 isOptimized = true;
2371                         }
2372                         else
2373                         {
2374                                 __pCutLinkListInfo->RemoveText(__workStart, currentGap);
2375                                 pTextElement->SetTextLength(elementTextLength - currentGap);
2376                                 __length -= currentGap;
2377                         }
2378
2379                         remainingGap -= currentGap;
2380                 }
2381         }
2382
2383         ChangeTextOffset(pText, elementIndex + 1, gap);
2384
2385         if (isOptimized)
2386         {
2387                 Optimize(elementIndex, elementIndex);
2388         }
2389
2390         return E_SUCCESS;
2391 }
2392
2393 int
2394 TextComposite::ForwardAnalyzeWithFocusedObjectType(int textIndex, int textLength, int maxWidth,
2395                                                                                                         int& cursorIndex, TextElementType& type)
2396 {
2397         result r = E_SUCCESS;
2398         Dimension textSize;
2399         int currentLength = 0;
2400         int elementTextOffset = 0;
2401         int elementIndex = 0;
2402         int textIndexFromElementOffset = 0;
2403         int textCount = 0;
2404         int remainingWidth = 0;
2405         int remainingLength = 0;
2406         int ret = TEXT_RETBY_NORMAL;
2407
2408         IEnumerator* pEnum = null;
2409         TextElement* pTextElement = null;
2410
2411         bool isFirstWord = true;
2412         int index = 0;
2413
2414         cursorIndex = 0;
2415         type = TEXT_ELEMENT_TYPE_MAX;
2416
2417         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
2418                                                                                          textIndexFromElementOffset);
2419         SysTryReturn(NID_GRP
2420                 , pTextElement
2421                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2422
2423         remainingWidth = maxWidth;
2424         remainingLength = textLength;
2425
2426         pEnum = __pTextElementList->GetEnumeratorN();
2427         for (int i = 0; i <= elementIndex; i++)
2428         {
2429                 r = pEnum->MoveNext();
2430                 SysTryCatch(NID_GRP
2431                                 , r == E_SUCCESS
2432                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2433         }
2434
2435         currentLength = Math::Min(remainingLength, currentLength);
2436
2437         while (remainingWidth > 0 || remainingLength > 0)
2438         {
2439                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth, __wrap, textCount , textSize.width, textSize.height);
2440                 TextElementType objectType = pTextElement->GetType();
2441
2442                 if ((objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK) && (ret == TEXT_RETBY_LIMITWIDTH))
2443                 {
2444                         Dimension tempTextSize;
2445                         r = pTextElement->GetRegion(textIndexFromElementOffset, textCount  + 1, tempTextSize.width, tempTextSize.height);
2446                         SysTryReturn(NID_GRP
2447                                 , r == E_SUCCESS
2448                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
2449
2450                         if ((remainingWidth - textSize.width) > (tempTextSize.width - remainingWidth))
2451                         {
2452                                 textSize.width = tempTextSize.width;
2453                                 textCount++;
2454                         }
2455                 }
2456
2457                 remainingWidth -= textSize.width;
2458                 if (remainingWidth < 0)
2459                 {
2460                         remainingWidth = 0;
2461                 }
2462
2463                 remainingLength -= textCount;
2464                 currentLength -= textCount ;
2465                 cursorIndex += textCount ;
2466
2467                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
2468                 {
2469                         index = cursorIndex;
2470                 }
2471
2472                 if (remainingLength <= currentLength)
2473                 {
2474                         break;
2475                 }
2476
2477                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
2478                 {
2479                         break;
2480                 }
2481
2482                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
2483                 {
2484                         if (ret == TEXT_RETBY_LIMITWIDTH)
2485                         {
2486                                 if (isFirstWord == false)
2487                                 {
2488                                         cursorIndex = index;
2489                                         ret = TEXT_RETBY_NORMAL;
2490                                 }
2491                                 break;
2492                         }
2493
2494                         isFirstWord = false;
2495
2496                         if (currentLength > 0)
2497                         {
2498                                 textIndexFromElementOffset += textCount ;
2499                                 continue;
2500                         }
2501                 }
2502                 else
2503                 {
2504                         if (ret == TEXT_RETBY_LIMITWIDTH)
2505                         {
2506                                 break;
2507                         }
2508                 }
2509
2510                 if (pEnum->MoveNext() != E_SUCCESS)
2511                 {
2512                         break;
2513                 }
2514
2515                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2516                 if (pTextElement == null)
2517                 {
2518                         break;
2519                 }
2520
2521                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
2522                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
2523         }
2524
2525         if (ret == TEXT_RETBY_LIMITLENGTH)
2526         {
2527                 ret = TEXT_RETBY_NORMAL;
2528         }
2529
2530         SetLastResult(E_SUCCESS);
2531         Release(pEnum);
2532         return ret;
2533
2534 CATCH:
2535         Release(pEnum);
2536         return -1;
2537 }
2538
2539 void
2540 TextComposite::HideFrontSpace(TextObjectSpaceHideType mode)
2541 {
2542         __ignoreFrontBlank = true;
2543         __frontSpaceHideMode = mode;
2544 }
2545
2546 void
2547 TextComposite::HideRearSpace(TextObjectSpaceHideType mode)
2548 {
2549         __ignoreRearBlank = true;
2550         __rearSpaceHideMode = mode;
2551 }
2552
2553 int
2554 TextComposite::ForwardAnalyzeInNoneCursorMode(int startTextIndex, int textLength, int maxWidth, int& textIndex)
2555 {
2556         result r = E_SUCCESS;
2557         Dimension textSize;
2558         int currentLength = 0;
2559         int elementTextOffset = 0;
2560         int elementIndex = 0;
2561         int textIndexFromElementOffset = 0;
2562         int textCount = 0;
2563         int remainingWidth = 0;
2564         int remainingLength = 0;
2565         int ret = TEXT_RETBY_NORMAL;
2566
2567         IEnumerator* pEnum = null;
2568         TextElement* pTextElement = null;
2569
2570         bool isFirstWord = true;
2571         int index = 0;
2572         textIndex = 0;
2573
2574         pTextElement = GetElementAtTextIndex(startTextIndex, elementTextOffset, elementIndex, currentLength,
2575                                                                                          textIndexFromElementOffset);
2576         SysTryReturn(NID_GRP
2577                 , pTextElement
2578                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2579
2580         textCount = 0;
2581         remainingWidth = maxWidth;
2582         remainingLength = textLength;
2583
2584         pEnum = __pTextElementList->GetEnumeratorN();
2585         for (int i = 0; i <= elementIndex; i++)
2586         {
2587                 r = pEnum->MoveNext();
2588                 SysTryCatch(NID_GRP
2589                                 , r == E_SUCCESS
2590                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2591         }
2592
2593         currentLength = Math::Min(remainingLength, currentLength);
2594
2595         while (remainingWidth > 0 || remainingLength > 0)
2596         {
2597                 ret = pTextElement->ForwardAnalyze(textIndexFromElementOffset, currentLength, remainingWidth,
2598                                                                                                                                                 __wrap, textCount, textSize.width, textSize.width);
2599
2600                 TextElementType objectType = pTextElement->GetType();
2601
2602                 if ((objectType == TEXT_ELEMENT_TYPE_TEXT || objectType == TEXT_ELEMENT_TYPE_CUTLINK) && (ret == TEXT_RETBY_LIMITWIDTH))
2603                 {
2604                         Dimension tempTextSize;
2605                         r = pTextElement->GetRegion(textIndexFromElementOffset, textCount + 1, tempTextSize.width, tempTextSize.height);
2606                         SysTryReturn(NID_GRP
2607                                 , r == E_SUCCESS
2608                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
2609
2610                         textSize.width = tempTextSize.width;
2611                         textCount++;
2612                 }
2613
2614                 remainingWidth -= textSize.width;
2615                 if (remainingWidth < 0)
2616                 {
2617                         remainingWidth = 0;
2618                 }
2619
2620                 remainingLength -= textCount;
2621                 currentLength -= textCount;
2622                 textIndex += textCount;
2623
2624                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD && ret != TEXT_RETBY_LIMITWIDTH)
2625                 {
2626                         index = textIndex;
2627                 }
2628
2629                 if (remainingLength <= currentLength)
2630                 {
2631                         break;
2632                 }
2633
2634                 if (ret == TEXT_RETBY_OVERWIDTH || ret == TEXT_RETBY_LINEFEED)
2635                 {
2636                         break;
2637                 }
2638
2639                 if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
2640                 {
2641                         if (ret == TEXT_RETBY_LIMITWIDTH)
2642                         {
2643                                 if (isFirstWord == false)
2644                                 {
2645                                         textIndex = index;
2646                                         ret = TEXT_RETBY_NORMAL;
2647                                 }
2648                                 break;
2649                         }
2650
2651                         isFirstWord = false;
2652
2653                         if (currentLength > 0)
2654                         {
2655                                 textIndexFromElementOffset += textCount;
2656                                 continue;
2657                         }
2658                 }
2659                 else
2660                 {
2661                         if (ret == TEXT_RETBY_LIMITWIDTH)
2662                         {
2663                                 break;
2664                         }
2665                 }
2666
2667                 if (pEnum->MoveNext() != E_SUCCESS)
2668                 {
2669                         break;
2670                 }
2671
2672                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2673                 if (pTextElement == null)
2674                 {
2675                         break;
2676                 }
2677
2678                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
2679                 currentLength = Math::Min(pTextElement->GetTextLength(), remainingLength);
2680         }
2681
2682         if (ret == TEXT_RETBY_LIMITLENGTH)
2683         {
2684                 ret = TEXT_RETBY_NORMAL;
2685         }
2686
2687         SetLastResult(E_SUCCESS);
2688         Release(pEnum);
2689         return ret;
2690
2691 CATCH:
2692         Release(pEnum);
2693         return ret;
2694 }
2695
2696 int
2697 TextComposite::GetCutLinkElementCount(void) const
2698 {
2699         return __pCutLinkListInfo->GetCutLinkElementCount();
2700 }
2701
2702 int
2703 TextComposite::GetCutLinkElementIndexAt(int textIndex) const
2704 {
2705         return __pCutLinkListInfo->GetCutLinkElementIndexAt(textIndex);
2706 }
2707
2708 TextCutLink*
2709 TextComposite::GetCutLinkElementAtCutLinkElementIndex(int index) const
2710 {
2711         return __pCutLinkListInfo->GetCutLinkElementAtCutLinkElementIndex(index);
2712 }
2713
2714 result
2715 TextComposite::ResetAllCutLinkElementsState(void)
2716 {
2717         return __pCutLinkListInfo->ResetAllCutLinkElementsState();
2718 }
2719
2720 result
2721 TextComposite::ChangeCutLinkState(int linkIndex, bool select)
2722 {
2723         return __pCutLinkListInfo->ChangeCutLinkState(linkIndex, select);
2724 }
2725
2726 result
2727 TextComposite::SetValueToAllTextElements(TextComponentInfoValueType type, unsigned int value)
2728 {
2729         result r = E_SUCCESS;
2730         IEnumerator* pEnum = null;
2731         TextElement* pTextElement = null;
2732         TextElement* pNewTextElement = null;
2733
2734         int startelementIndex = -1;
2735         int endelementIndex = -1;
2736         int textIndex = 0;
2737         int textLength = 0;
2738         int elementTextOffset = 0;
2739         int elementIndex = 0;
2740         int currentLength = 0;
2741         int textIndexFromElementOffset = 0;
2742         int found = false;
2743
2744         textIndex = __workStart;
2745         textLength = __workLength;
2746
2747         if (textLength == 0)
2748         {
2749                 return E_SUCCESS;
2750         }
2751
2752         while (0 < textLength)
2753         {
2754                 pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
2755                                                                                                  textIndexFromElementOffset);
2756                 SysTryReturn(NID_GRP
2757                         , pTextElement
2758                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
2759
2760                 SysTryReturn(NID_GRP
2761                         , 0 < currentLength
2762                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element node.");
2763
2764                 TextElementType objectType = pTextElement->GetType();
2765                 TextElementType objectTypeFromValueType = TextUtility::GetObjectTypeFromValueType(type);
2766
2767                 unsigned int objectValue = pTextElement->GetValue(type);
2768                 if ((objectType == objectTypeFromValueType) && (value != objectValue))
2769                 {
2770                         found = true;
2771                         startelementIndex = elementIndex;
2772                         break;
2773                 }
2774                 else if ((COMMONOBJECT_VALUE_START <= type && type < MAX_COMMONOBJECT_VALUE) && (value != objectValue))
2775                 {
2776                         found = true;
2777                         startelementIndex = elementIndex;
2778                         break;
2779                 }
2780                 textIndex += currentLength;
2781                 textLength -= currentLength;
2782         }
2783
2784         if (found == false)
2785         {
2786                 return E_SUCCESS;
2787         }
2788
2789         if (elementTextOffset == textIndex && textLength == currentLength)
2790         {
2791                 pTextElement->SetValue(type, value);
2792                 goto TRUE_CATCH;
2793         }
2794         else if ((elementTextOffset < textIndex) && (textLength < currentLength))
2795         {
2796                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2797
2798                 pNewTextElement = pTextElement->CloneN(type, value);
2799                 SysTryReturn(NID_GRP
2800                         , pNewTextElement
2801                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2802
2803                 pNewTextElement->SetTextLength(textLength);
2804                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
2805
2806                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2807                 SysTryCatch(NID_GRP
2808                         , r == E_SUCCESS
2809                         , , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2810
2811                 pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
2812                 SysTryReturn(NID_GRP
2813                         , pNewTextElement
2814                         , r, r, "[E_SYSTEM] Fail to clone text element.");
2815
2816                 pNewTextElement->SetTextLength(currentLength - textLength);
2817                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
2818
2819                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2820                 SysTryCatch(NID_GRP
2821                         , r == E_SUCCESS
2822                         , , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2823
2824                 endelementIndex = elementIndex;
2825                 goto TRUE_CATCH;
2826         }
2827         else if (elementTextOffset < textIndex)
2828         {
2829                 pTextElement->SetTextLength(pTextElement->GetTextLength() - currentLength);
2830
2831                 pNewTextElement = pTextElement->CloneN(type, value);
2832                 SysTryReturn(NID_GRP
2833                         , pNewTextElement
2834                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2835
2836                 pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset);
2837                 pNewTextElement->SetTextLength(currentLength);
2838
2839                 r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2840                 SysTryCatch(NID_GRP
2841                         , r == E_SUCCESS
2842                         , , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2843
2844                 textIndex += currentLength;
2845                 textLength -= currentLength;
2846                 if (textLength > 0)
2847                 {
2848                         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, elementIndex, currentLength,
2849                                                                                                          textIndexFromElementOffset);
2850                         if (pTextElement == null)
2851                         {
2852                                 goto TRUE_CATCH;
2853                         }
2854                 }
2855                 else
2856                 {
2857                         endelementIndex = elementIndex;
2858                         goto TRUE_CATCH;
2859                 }
2860         }
2861
2862         pEnum = __pTextElementList->GetEnumeratorN();
2863         for (int i = 0; i <= elementIndex; i++)
2864         {
2865                 r = pEnum->MoveNext();
2866                 SysTryCatch(NID_GRP
2867                                 , r == E_SUCCESS
2868                                 , , r, "[%s] Fail to move next element.", GetErrorMessage(r));
2869         }
2870
2871         while (textLength > 0)
2872         {
2873                 TextElementType objectType = pTextElement->GetType();
2874                 TextElementType objectTypeFromValueType = TextUtility::GetObjectTypeFromValueType(type);
2875
2876                 if (objectType == objectTypeFromValueType)
2877                 {
2878                         if (value != objectTypeFromValueType)
2879                         {
2880                                 if (textLength < currentLength)
2881                                 {
2882                                         pNewTextElement = pTextElement->CloneN(SET_ALLVALUE_CLONE, 0);
2883                                         SysTryReturn(NID_GRP
2884                                                 , pNewTextElement
2885                                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to clone text element.");
2886
2887                                         pNewTextElement->SetTextLength(currentLength - textLength);
2888                                         pNewTextElement->SetValue(SET_TEXT_OFFSET, textIndexFromElementOffset + textLength);
2889
2890                                         pTextElement->SetValue(type, value);
2891                                         pTextElement->SetTextLength(textLength);
2892
2893                                         r = __pTextElementList->InsertAt(*pNewTextElement, ++elementIndex);
2894                                         SysTryCatch(NID_GRP
2895                                                 , r == E_SUCCESS
2896                                                 , , r, "[%s] Fail to insert element.", GetErrorMessage(r));
2897
2898                                         break;
2899                                 }
2900                                 else
2901                                 {
2902                                         pTextElement->SetValue(type, value);
2903                                 }
2904
2905                                 endelementIndex = elementIndex;
2906                         }
2907                 }
2908
2909                 elementTextOffset += currentLength;
2910                 textLength -= currentLength;
2911                 elementIndex++;
2912
2913                 if (pEnum->MoveNext() != E_SUCCESS)
2914                 {
2915                         break;
2916                 }
2917
2918                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
2919                 if (pTextElement == null)
2920                 {
2921                         break;
2922                 }
2923
2924                 currentLength = pTextElement->GetTextLength();
2925                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
2926         }
2927
2928 TRUE_CATCH:
2929         Optimize(startelementIndex, endelementIndex);
2930         Release(pEnum);
2931         return E_SUCCESS;
2932
2933 CATCH:
2934         if (pNewTextElement != null)
2935         {
2936                 delete pNewTextElement;
2937                 pNewTextElement = null;
2938         }
2939
2940         Release(pEnum);
2941         return r;
2942 }
2943
2944 bool
2945 TextComposite::SetAbbrevObjectFontInfo(TextSimple* pSimpleText)
2946 {
2947         SysTryReturn(NID_GRP
2948                         , __pAbbrevTextElement
2949                         , false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
2950
2951         __pAbbrevTextElement->SetFont(pSimpleText->GetFont());
2952         __pAbbrevTextElement->SetForegroundColor(pSimpleText->GetForegroundColor());
2953         __pAbbrevTextElement->SetBackgroundColor(pSimpleText->GetBackgroundColor());
2954         __pAbbrevTextElement->SetOutlineColor(pSimpleText->GetOutlineColor());
2955         __pAbbrevTextElement->SetAlternativeForegroundColor(pSimpleText->GetAlternativeForegroundColor());
2956         __pAbbrevTextElement->SetAlternateLookEnabled(pSimpleText->IsAlternateLookEnabled());
2957
2958         return true;
2959 }
2960
2961 int
2962 TextComposite::ComposeInNoneWrap(Rectangle& rect, NoneWrapComposeInfo* pNoneWrapComposeInfo)
2963 {
2964         SysTryReturn(NID_GRP
2965                         , __pCurrentTextColumn
2966                         , -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
2967
2968         TextLine* pTextLine = null;
2969         Rectangle lineBounds;
2970         Dimension textSize;
2971         int lineOffset = 0;
2972         int lineLength = 0;
2973         int endType = TEXT_RETBY_NORMAL;
2974         bool isChanged = false;
2975         bool forwardSearch = true;
2976         int textIndex = __workStart;
2977         int baseline = 0;
2978
2979         if (textIndex < 0)
2980         {
2981                 textIndex = 0;
2982         }
2983
2984         if (textIndex > __length)
2985         {
2986                 textIndex = __length;
2987         }
2988
2989         if (textIndex == __length)
2990         {
2991                 forwardSearch = false;
2992         }
2993
2994         if (__pCurrentTextColumn->GetTotalLineCount() > 0)
2995         {
2996                 pTextLine = __pCurrentTextColumn->GetTextLine(0);
2997                 SysTryReturn(NID_GRP
2998                         , pTextLine
2999                         , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
3000
3001                 lineBounds = pTextLine->GetBounds();
3002                 endType = pTextLine->GetEndType();
3003
3004                 if (lineBounds.width != rect.width)
3005                 {
3006                         isChanged = true;
3007                 }
3008
3009                 lineOffset = pTextLine->GetTextOffset();
3010                 lineLength = pTextLine->GetTextLength();
3011
3012                 if (lineOffset <= textIndex && textIndex < lineOffset + lineLength)
3013                 {
3014                         isChanged = true;
3015                 }
3016         }
3017         else
3018         {
3019                 pTextLine = new (std::nothrow)TextLine(this);
3020                 SysTryReturn(NID_GRP
3021                         , pTextLine
3022                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3023
3024                 if (forwardSearch)
3025                 {
3026                         if (pNoneWrapComposeInfo != null)
3027                         {
3028                                 lineOffset = pNoneWrapComposeInfo->prevTextOffset;
3029                         }
3030                         else
3031                         {
3032                                 lineOffset = 0;
3033                         }
3034                 }
3035                 else
3036                 {
3037                         lineOffset = __length - 1;
3038                 }
3039
3040                 lineLength = 0;
3041                 lineBounds.width = rect.width;
3042                 lineBounds.x = 0;
3043                 lineBounds.y = 0;
3044                 lineBounds.height = 0;
3045
3046                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3047
3048                 isChanged = true;
3049         }
3050
3051         if (isChanged)
3052         {
3053                 lineBounds.width = rect.width;
3054                 lineBounds.x = 0;
3055                 lineBounds.y = 0;
3056
3057                 if (forwardSearch)
3058                 {
3059 //                      endType = ForwardAnalyze(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
3060 //                                                                        lineLength, textSize.width, textSize.height);
3061                         endType = ForwardAnalyzeWithBaseline(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
3062                                                                           lineLength, textSize.width, textSize.height, baseline);
3063
3064                         lineBounds.height = textSize.height;
3065                         pTextLine->SetBounds(lineBounds);
3066                         pTextLine->SetTextOffset(lineOffset);
3067                         pTextLine->SetTextLength(lineLength);
3068                         pTextLine->SetRegion(textSize.width, textSize.height);
3069                         pTextLine->SetEndType(endType);
3070                         pTextLine->SetBaseline(baseline);
3071                 }
3072                 else
3073                 {
3074                         int textCount = 0;
3075
3076                         BackwardAnalyze(lineOffset, lineBounds.width, &textCount, &textSize.width, &textSize.height);
3077
3078                         lineBounds.height = textSize.height;
3079                         lineOffset -= (textCount - 1);
3080                         lineLength = textCount;
3081                         if (lineOffset == 0)
3082                         {
3083                                 endType = TEXT_RETBY_NORMAL;
3084                         }
3085                         else
3086                         {
3087                                 endType = TEXT_RETBY_LIMITWIDTH;
3088                         }
3089
3090                         pTextLine->SetBounds(lineBounds);
3091                         pTextLine->SetTextOffset(lineOffset);
3092                         pTextLine->SetTextLength(lineLength);
3093                         pTextLine->SetRegion(textSize.width, textSize.height);
3094                         pTextLine->SetEndType(endType);
3095                         pTextLine->SetBaseline(baseline);
3096                 }
3097         }
3098
3099         if (__length == 0)
3100         {
3101                 pTextLine->SetEndType(TEXT_RETBY_NORMAL);
3102                 return 1;
3103         }
3104
3105         rect.height = lineBounds.height;
3106
3107         if (textIndex < lineOffset)
3108         {
3109                 lineOffset = textIndex;
3110                 endType = ForwardAnalyze(lineOffset, __length - lineOffset, lineBounds.width, __wrap,
3111                                                                   lineLength, textSize.width, textSize.height);
3112
3113                 lineBounds.height = textSize.height;
3114         }
3115         else if (forwardSearch && textIndex >= lineOffset + lineLength)
3116         {
3117                 Dimension needDim;
3118                 GetRegion(lineOffset + lineLength, textIndex - (lineOffset + lineLength) + 1,
3119                                   needDim.width, needDim.height);
3120
3121                 int index = 0;
3122                 int remainingWidth = needDim.width - (lineBounds.width - textSize.width);
3123
3124                 Dimension charDim;
3125                 textSize.width += needDim.width;
3126                 lineLength += textIndex - (lineOffset + lineLength) + 1;
3127
3128                 while (1)
3129                 {
3130                         GetRegion(lineOffset, 1, charDim.width, charDim.height);
3131                         lineOffset++;
3132                         index++;
3133                         remainingWidth -= charDim.width;
3134                         textSize.width -= charDim.width;
3135
3136                         if (remainingWidth <= 0)
3137                         {
3138                                 break;
3139                         }
3140                 }
3141
3142                 lineLength -= index;
3143         }
3144         else if (endType != TEXT_RETBY_LIMITWIDTH && lineLength != __length)
3145         {
3146                 if (lineOffset > 0)
3147                 {
3148                         Dimension lineTextSize;
3149                         int textCount = 0;
3150                         int remainingWidth = 0;
3151
3152                         pTextLine->GetRegion(0, lineLength, lineTextSize.width, lineTextSize.height);
3153                         remainingWidth = lineBounds.width - lineTextSize.width;
3154                         BackwardAnalyze(lineOffset - 1, remainingWidth, &textCount, &textSize.width, &textSize.height);
3155
3156                         if (textSize.width > 0)
3157                         {
3158                                 lineOffset -= textCount;
3159                                 lineLength += textCount;
3160                                 textSize.width += lineTextSize.width;
3161                                 lineBounds.height = textSize.height;
3162                                 endType = TEXT_RETBY_LIMITLENGTH;
3163                         }
3164                         else
3165                         {
3166                                 return 1;
3167                         }
3168                 }
3169                 else
3170                 {
3171                         return 1;
3172                 }
3173         }
3174         else
3175         {
3176                 return 1;
3177         }
3178
3179         pTextLine->SetBounds(lineBounds);
3180         pTextLine->SetRegion(textSize.width, textSize.height);
3181         pTextLine->SetTextLength(lineLength);
3182         pTextLine->SetTextOffset(lineOffset);
3183         pTextLine->SetEndType(endType);
3184         pTextLine->SetBaseline(baseline);
3185
3186         return 1;
3187 }
3188
3189 int
3190 TextComposite::ComposeInWrap(Rectangle& rect)
3191 {
3192         SysTryReturn(NID_GRP
3193                         , __pCurrentTextColumn
3194                         , -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
3195
3196         int textCount = 0;
3197         int lineCount = 0;
3198         int textIndex = 0;
3199         int remainingLength = 0;
3200         int remainingWidth = 0;
3201         int remainingHeight = 0;
3202         int offsetY = 0;
3203         bool hasPrevLine = false;
3204         Dimension textSize;
3205         TextLine* pTextLine = null;
3206         int ret = 0;
3207         int endType = TEXT_RETBY_NORMAL;
3208         Rectangle lineBounds;
3209         Dimension lineTextSize;
3210         int lineOffset = 0;
3211         int lineLength = 0;
3212         int displayLineCount = 0;
3213         int displayHeight = 0;
3214         int baseline = 0;
3215         int lineBaseline = 0;
3216
3217         pTextLine = __pCurrentTextColumn->GetPrevLineChangedStartLine();
3218         if (pTextLine != null)
3219         {
3220                 endType = pTextLine->GetEndType();
3221                 lineOffset = pTextLine->GetTextOffset();
3222                 lineLength = pTextLine->GetTextLength();
3223                 lineBounds = pTextLine->GetBounds();
3224                 lineBaseline = pTextLine->GetBaseline();
3225                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineTextSize.width, lineTextSize.height);
3226
3227                 if (endType != TEXT_RETBY_LINEFEED)
3228                 {
3229                         textIndex = lineOffset + lineLength;
3230                         remainingLength = __length - textIndex;
3231                         remainingWidth = lineBounds.width - lineTextSize.width;
3232                         hasPrevLine = true;
3233
3234                         if (remainingLength == 0)
3235                         {
3236                                 return -1;
3237                         }
3238                 }
3239                 else
3240                 {
3241                         textIndex = lineOffset + lineLength;
3242                         remainingLength = __length - textIndex;
3243                         remainingWidth = rect.width;
3244                         offsetY = lineBounds.y + lineBounds.height;
3245
3246                         if (remainingLength == 0)
3247                         {
3248                                 int nextY = offsetY;
3249                                 lineTextSize.height = lineBounds.height;
3250
3251                                 pTextLine = new (std::nothrow)TextLine(this);
3252                                 SysTryReturn(NID_GRP
3253                                         , pTextLine
3254                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3255
3256                                 lineBounds.y = nextY;
3257
3258                                 pTextLine->SetBounds(lineBounds);
3259                                 pTextLine->SetRegion(0, lineTextSize.height);
3260                                 pTextLine->SetTextLength(0);
3261                                 pTextLine->SetTextOffset(textIndex);
3262                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
3263                                 pTextLine->SetBaseline(0);
3264
3265                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3266
3267                                 if (lineBounds.y + lineBounds.height <= rect.height)
3268                                 {
3269                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3270                                         displayHeight += lineBounds.height;
3271                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3272                                 }
3273
3274                                 return 1;
3275                         }
3276                 }
3277         }
3278         else
3279         {
3280                 textIndex = 0;
3281                 remainingLength = __length;
3282                 remainingWidth = rect.width;
3283
3284                 __pCurrentTextColumn->SetChangedStartLineIndex(0);
3285         }
3286
3287         if (!hasPrevLine)
3288         {
3289                 pTextLine = new (std::nothrow)TextLine(this);
3290                 SysTryReturn(NID_GRP
3291                         , pTextLine
3292                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3293
3294                 lineBounds.x = rect.x;
3295                 lineBounds.width = rect.width;
3296                 lineBounds.y = offsetY;
3297                 lineTextSize.height = 0;
3298
3299                 if (remainingLength == 0)
3300                 {
3301                         lineTextSize.height = GetHeight(0);
3302                         lineBounds.height = lineTextSize.height;
3303
3304                         pTextLine->SetBounds(lineBounds);
3305                         pTextLine->SetRegion(0, lineTextSize.height);
3306                         pTextLine->SetTextLength(0);
3307                         pTextLine->SetTextOffset(textIndex);
3308                         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
3309                         pTextLine->SetBaseline(0);
3310
3311                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3312
3313                         if (lineBounds.y + lineBounds.height <= rect.height)
3314                         {
3315                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3316                                 displayHeight += lineBounds.height;
3317                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3318                         }
3319
3320                         return 1;
3321                 }
3322         }
3323
3324         remainingHeight = rect.height;
3325
3326         while (remainingLength != 0)
3327         {
3328                 ret = ForwardAnalyzeWithBaseline(textIndex, remainingLength, remainingWidth, __wrap, textCount, textSize.width, textSize.height, baseline);
3329
3330                 if (ret == -1)
3331                 {
3332                         delete pTextLine;
3333                         pTextLine = null;
3334                         break;
3335                 }
3336
3337                 if (!hasPrevLine)
3338                 {
3339                         if (textCount == 0)
3340                         {
3341                                 textCount = 1;
3342                         }
3343
3344                         lineOffset = textIndex;
3345                         lineLength = textCount;
3346                         lineTextSize.width = textSize.width;
3347                         lineTextSize.height = textSize.height;
3348                         lineBounds.height = textSize.height;
3349                         endType = ret;
3350
3351                         pTextLine->SetBounds(lineBounds);
3352                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3353                         pTextLine->SetTextLength(lineLength);
3354                         pTextLine->SetTextOffset(lineOffset);
3355                         pTextLine->SetEndType(ret);
3356                         pTextLine->SetBaseline(baseline);
3357
3358                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3359                         lineCount++;
3360
3361                         if (lineBounds.y + lineBounds.height <= rect.height)
3362                         {
3363                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3364                                 displayHeight += lineBounds.height;
3365                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3366                         }
3367                 }
3368                 else
3369                 {
3370                         if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
3371                         {
3372                                 if (ret != TEXT_RETBY_LIMITWIDTH)
3373                                 {
3374                                         lineLength += textCount;
3375                                         lineTextSize.width += textSize.width;
3376                                         lineBounds.height = Math::Max(lineBounds.height, textSize.height);
3377                                         lineTextSize.height = lineBounds.height;
3378                                         endType = ret;
3379                                         baseline = Math::Min(lineBaseline, baseline);
3380
3381                                         pTextLine->SetBounds(lineBounds);
3382                                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3383                                         pTextLine->SetTextLength(lineLength);
3384                                         pTextLine->SetEndType(endType);
3385                                         pTextLine->SetBaseline(baseline);
3386                                 }
3387                                 else
3388                                 {
3389                                         textCount = 0;
3390                                 }
3391                         }
3392                         else
3393                         {
3394                                 lineLength += textCount;
3395                                 lineTextSize.width += textSize.width;
3396                                 lineBounds.height = Math::Max(lineBounds.height, textSize.height);
3397                                 lineTextSize.height = lineBounds.height;
3398                                 endType = ret;
3399                                 baseline = Math::Min(lineBaseline, baseline);
3400
3401                                 pTextLine->SetBounds(lineBounds);
3402                                 pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3403                                 pTextLine->SetTextLength(lineLength);
3404                                 pTextLine->SetEndType(endType);
3405                                 pTextLine->SetBaseline(baseline);
3406                         }
3407
3408                         if (textCount > 0)
3409                         {
3410                                 __pCurrentTextColumn->SetChangedStartLineIndex(pTextLine->GetIndex());
3411                         }
3412
3413                         hasPrevLine = false;
3414                 }
3415
3416                 if (__pCurrentTextColumn->IsComposeDone())
3417                 {
3418                         break;
3419                 }
3420
3421                 textIndex += textCount;
3422                 remainingLength -= textCount;
3423
3424                 remainingHeight -= lineTextSize.height;
3425
3426                 if (remainingLength > 0)
3427                 {
3428                         int nextY = lineBounds.y + lineBounds.height;
3429
3430                         pTextLine = new (std::nothrow)TextLine(this);
3431                         SysTryReturn(NID_GRP
3432                                 , pTextLine
3433                                 , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3434
3435                         lineBounds.x = rect.x;
3436                         lineBounds.y = nextY;
3437                         lineBounds.width = rect.width;
3438                         lineTextSize.height = 0;
3439
3440                         remainingWidth = rect.width;
3441                 }
3442                 else
3443                 {
3444                         if (endType == TEXT_RETBY_LINEFEED)
3445                         {
3446                                 int nextY = lineBounds.y + lineBounds.height;
3447                                 lineTextSize.height = lineBounds.height;
3448
3449                                 pTextLine = new (std::nothrow)TextLine(this);
3450                                 SysTryReturn(NID_GRP
3451                                         , pTextLine
3452                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3453
3454                                 lineBounds.x = rect.x;
3455                                 lineBounds.y = nextY;
3456                                 lineBounds.width = rect.width;
3457                                 lineBounds.height = lineTextSize.height;
3458
3459                                 pTextLine->SetBounds(lineBounds);
3460                                 pTextLine->SetRegion(0, lineTextSize.height);
3461                                 pTextLine->SetTextLength(0);
3462                                 pTextLine->SetTextOffset(textIndex);
3463                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
3464                                 pTextLine->SetBaseline(0);
3465
3466                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3467                                 lineCount++;
3468
3469                                 if (lineBounds.y + lineBounds.height <= rect.height)
3470                                 {
3471                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3472                                         displayHeight += lineBounds.height;
3473                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3474                                 }
3475
3476                                 pTextLine = null;
3477                                 break;
3478                         }
3479                 }
3480         }
3481
3482         Dimension columnTextSize;
3483         __pCurrentTextColumn->GetRegion(0, __length, columnTextSize.width, columnTextSize.height);
3484         rect.height = columnTextSize.height;
3485
3486         if (pTextLine)
3487         {
3488                 __pCurrentTextColumn->SetChangedLastLineIndex(pTextLine->GetIndex());
3489         }
3490
3491         if (Tizen::App::_AppInfo::IsOspCompat())
3492         {
3493                 __pCurrentTextColumn->SetDisplayLineCount(0);
3494                 __pCurrentTextColumn->SetDisplayHeight(0);
3495         }
3496
3497         return lineCount;
3498 }
3499
3500 int
3501 TextComposite::ComposeInPartialMode(Rectangle& rect)
3502 {
3503         SysTryReturn(NID_GRP
3504                         , __pCurrentTextColumn
3505                         , -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
3506
3507         int textCount = 0;
3508         int lineCount = 0;
3509         int textIndex = 0;
3510         int remainingLength = 0;
3511         int remainingWidth = 0;
3512         int remainingHeight = 0;
3513         int lineOffset = 0;
3514         int lineLength = 0;
3515         int offsetY = 0;
3516         int ret = 0;
3517         Dimension textSize;
3518         Dimension lineTextSize;
3519         Rectangle lineBounds;
3520         bool hasPrevLine = false;
3521         int displayLineCount = 0;
3522         int displayHeight = 0;
3523         int baseline = 0;
3524         int lineBaseline = 0;
3525
3526         TextLine* pTextLine = null;
3527         int endType = TEXT_RETBY_NORMAL;
3528
3529         if (__lineIndexCompositeDone != 0)
3530         {
3531                 pTextLine = __pCurrentTextColumn->GetTextLine(__lineIndexCompositeDone - 1);
3532                 lineCount = __lineIndexCompositeDone;
3533         }
3534
3535         if (pTextLine != null)
3536         {
3537                 endType = pTextLine->GetEndType();
3538                 lineOffset = pTextLine->GetTextOffset();
3539                 lineLength = pTextLine->GetTextLength();
3540                 lineBounds = pTextLine->GetBounds();
3541                 lineBaseline = pTextLine->GetBaseline();
3542                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineTextSize.width, lineTextSize.height);
3543
3544                 if (endType != TEXT_RETBY_LINEFEED)
3545                 {
3546                         textIndex = lineOffset + lineLength;
3547                         remainingLength = __length - textIndex;
3548                         remainingWidth = lineBounds.width - lineTextSize.width;
3549                         hasPrevLine = true;
3550
3551                         if (remainingLength == 0)
3552                         {
3553                                 return -1;
3554                         }
3555                 }
3556                 else
3557                 {
3558                         textIndex = lineOffset + lineLength;
3559                         remainingLength = __length - textIndex;
3560                         remainingWidth = rect.width;
3561                         offsetY = lineBounds.y + lineBounds.height;
3562
3563                         if (remainingLength == 0)
3564                         {
3565                                 int nextY = offsetY;
3566                                 lineTextSize.height = lineBounds.height;
3567
3568                                 pTextLine = new (std::nothrow)TextLine(this);
3569                                 SysTryReturn(NID_GRP
3570                                         , pTextLine
3571                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3572
3573                                 lineBounds.y = nextY;
3574
3575                                 pTextLine->SetBounds(lineBounds);
3576                                 pTextLine->SetRegion(0, lineTextSize.height);
3577                                 pTextLine->SetTextLength(0);
3578                                 pTextLine->SetTextOffset(textIndex);
3579                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
3580                                 pTextLine->SetBaseline(0);
3581
3582                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3583
3584                                 if (lineBounds.y + lineBounds.height <= rect.height)
3585                                 {
3586                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3587                                         displayHeight += lineBounds.height;
3588                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3589                                 }
3590
3591                                 return 1;
3592                         }
3593                 }
3594         }
3595         else
3596         {
3597                 textIndex = 0;
3598                 remainingLength = __length;
3599                 remainingWidth = rect.width;
3600
3601                 __pCurrentTextColumn->SetChangedStartLineIndex(0);
3602         }
3603
3604         if (!hasPrevLine)
3605         {
3606                 pTextLine = new (std::nothrow)TextLine(this);
3607                 SysTryReturn(NID_GRP
3608                         , pTextLine
3609                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3610
3611                 lineBounds.x = rect.x;
3612                 lineBounds.width = rect.width;
3613                 lineBounds.y = offsetY;
3614                 lineTextSize.height = 0;
3615
3616                 if (remainingLength == 0)
3617                 {
3618                         lineTextSize.height = GetHeight(0);
3619                         lineBounds.height = lineTextSize.height;
3620
3621                         pTextLine->SetBounds(lineBounds);
3622                         pTextLine->SetRegion(0, lineTextSize.height);
3623                         pTextLine->SetTextLength(0);
3624                         pTextLine->SetTextOffset(textIndex);
3625                         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
3626                         pTextLine->SetBaseline(0);
3627
3628                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3629
3630                         if (lineBounds.y + lineBounds.height <= rect.height)
3631                         {
3632                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3633                                 displayHeight += lineBounds.height;
3634                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3635                         }
3636
3637                         return 1;
3638                 }
3639         }
3640
3641         remainingHeight = GetComposePartialLimitHeight();
3642         if (remainingHeight == 0)
3643         {
3644                 remainingHeight = rect.height;
3645         }
3646         if (remainingHeight < lineBounds.height && remainingLength > 0)
3647         {
3648                 remainingHeight = lineBounds.height;
3649         }
3650
3651         while (remainingLength != 0)
3652         {
3653                 //ret = ForwardAnalyze(textIndex, remainingLength, remainingWidth, __wrap, textCount, textSize.width, textSize.height);
3654                 ret = ForwardAnalyzeWithBaseline(textIndex, remainingLength, remainingWidth, __wrap, textCount, textSize.width, textSize.height, baseline);
3655
3656                 if (ret == -1)
3657                 {
3658                         delete pTextLine;
3659                         pTextLine = null;
3660                         break;
3661                 }
3662
3663                 if (!hasPrevLine)
3664                 {
3665                         if (textCount == 0)
3666                         {
3667                                 textCount = 1;
3668                         }
3669
3670                         lineOffset = textIndex;
3671                         lineLength = textCount;
3672                         lineTextSize.width = textSize.width;
3673                         lineTextSize.height = textSize.height;
3674                         lineBounds.height = textSize.height;
3675                         endType = ret;
3676
3677                         pTextLine->SetBounds(lineBounds);
3678                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3679                         pTextLine->SetTextLength(lineLength);
3680                         pTextLine->SetTextOffset(lineOffset);
3681                         pTextLine->SetEndType(endType);
3682                         pTextLine->SetBaseline(baseline);
3683
3684                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3685
3686                         if (lineBounds.y + lineBounds.height <= rect.height)
3687                         {
3688                                 __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3689                                 displayHeight += lineBounds.height;
3690                                 __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3691                         }
3692
3693                         lineCount++;
3694                         __lineIndexCompositeDone++;
3695                         __totalComposedHeight += lineTextSize.height;
3696                 }
3697                 else
3698                 {
3699                         if (__wrap == TEXT_OBJECT_WRAP_TYPE_WORD)
3700                         {
3701                                 if (ret != TEXT_RETBY_LIMITWIDTH)
3702                                 {
3703                                         lineLength += textCount;
3704                                         lineTextSize.width += textSize.width;
3705                                         lineBounds.height = Math::Max(lineBounds.height, textSize.height);
3706                                         lineTextSize.height = lineBounds.height;
3707                                         endType = ret;
3708                                         baseline = Math::Min(lineBaseline, baseline);
3709
3710                                         pTextLine->SetBounds(lineBounds);
3711                                         pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3712                                         pTextLine->SetTextLength(lineLength);
3713                                         pTextLine->SetEndType(endType);
3714                                         pTextLine->SetBaseline(baseline);
3715                                 }
3716                                 else
3717                                 {
3718                                         textCount = 0;
3719                                 }
3720                         }
3721                         else
3722                         {
3723                                 lineLength += textCount;
3724                                 lineTextSize.width += textSize.width;
3725                                 lineBounds.height = Math::Max(lineBounds.height, textSize.height);
3726                                 lineTextSize.height = lineBounds.height;
3727                                 endType = ret;
3728                                 baseline = Math::Min(lineBaseline, baseline);
3729
3730                                 pTextLine->SetBounds(lineBounds);
3731                                 pTextLine->SetRegion(lineTextSize.width, lineTextSize.height);
3732                                 pTextLine->SetTextLength(lineLength);
3733                                 pTextLine->SetEndType(endType);
3734                                 pTextLine->SetBaseline(baseline);
3735                         }
3736
3737                         if (textCount > 0)
3738                         {
3739                                 __pCurrentTextColumn->SetChangedStartLineIndex(pTextLine->GetIndex());
3740                         }
3741
3742                         hasPrevLine = false;
3743                 }
3744
3745                 if (__pCurrentTextColumn->IsComposeDone())
3746                 {
3747                         break;
3748                 }
3749
3750                 textIndex += textCount;
3751                 remainingLength -= textCount;
3752                 remainingHeight -= lineTextSize.height;
3753
3754                 if (remainingHeight < 0)
3755                 {
3756                         return lineCount;
3757                 }
3758
3759                 if (remainingLength > 0)
3760                 {
3761                         int nextY = lineBounds.y + lineBounds.height;
3762
3763                         pTextLine = new (std::nothrow)TextLine(this);
3764                         SysTryReturn(NID_GRP
3765                                 , pTextLine
3766                                 , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3767
3768                         lineBounds.x = rect.x;
3769                         lineBounds.y = nextY;
3770                         lineBounds.width = rect.width;
3771                         lineTextSize.height = 0;
3772
3773                         remainingWidth = rect.width;
3774                 }
3775                 else
3776                 {
3777                         if (endType == TEXT_RETBY_LINEFEED)
3778                         {
3779                                 int nextY = lineBounds.y + lineBounds.height;
3780                                 lineTextSize.height = lineBounds.height;
3781
3782                                 pTextLine = new (std::nothrow)TextLine(this);
3783                                 SysTryReturn(NID_GRP
3784                                         , pTextLine
3785                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3786
3787                                 lineBounds.x = rect.x;
3788                                 lineBounds.y = nextY;
3789                                 lineBounds.width = rect.width;
3790                                 lineBounds.height = lineTextSize.height;
3791
3792                                 pTextLine->SetBounds(lineBounds);
3793                                 pTextLine->SetRegion(0, lineTextSize.height);
3794                                 pTextLine->SetTextLength(0);
3795                                 pTextLine->SetTextOffset(textIndex);
3796                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
3797                                 pTextLine->SetBaseline(0);
3798
3799                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3800
3801                                 lineCount++;
3802
3803                                 if (lineBounds.y + lineBounds.height <= rect.height)
3804                                 {
3805                                         __pCurrentTextColumn->SetDisplayLineCount(++displayLineCount);
3806                                         displayHeight += lineBounds.height;
3807                                         __pCurrentTextColumn->SetDisplayHeight(displayHeight);
3808                                 }
3809
3810                                 __lineIndexCompositeDone++;
3811                                 __totalComposedHeight += lineTextSize.height;
3812                                 __pCurrentTextColumn->FinishCompose();
3813
3814                                 pTextLine = null;
3815                                 break;
3816                         }
3817                         else
3818                         {
3819                                 __pCurrentTextColumn->FinishCompose();
3820                         }
3821                 }
3822         }
3823
3824         rect.height = __totalComposedHeight;
3825
3826         if (pTextLine)
3827         {
3828                 __pCurrentTextColumn->SetChangedLastLineIndex(pTextLine->GetIndex());
3829         }
3830
3831         if (Tizen::App::_AppInfo::IsOspCompat())
3832         {
3833                 __pCurrentTextColumn->SetDisplayLineCount(0);
3834                 __pCurrentTextColumn->SetDisplayHeight(0);
3835         }
3836
3837         return lineCount;
3838 }
3839
3840 int
3841 TextComposite::ComposeInNormalWrap(Rectangle& rect)
3842 {
3843         return ComposeInWrap(rect);
3844 }
3845
3846 int
3847 TextComposite::ComposeInWordWrap(Rectangle& rect)
3848 {
3849         if (IsWidthManagerEnabled())
3850         {
3851                 return ComposeInWrapByTextWidth(rect);
3852         }
3853         else
3854         {
3855                 return ComposeInWrap(rect);
3856         }
3857 }
3858
3859 int
3860 TextComposite::ComposeInNoneWrapMiddleEllipsis(Rectangle& rect)
3861 {
3862         int endType = TEXT_RETBY_NORMAL;
3863         Rectangle lineBounds;
3864         Dimension abbrevTextDim;
3865         Dimension textSize;
3866         int length = 0;
3867         int maxHeight = 0;
3868         int baseline = 0;
3869
3870         lineBounds.width = rect.width;
3871         lineBounds.x = 0;
3872         lineBounds.y = 0;
3873         lineBounds.height = rect.height;
3874         endType = ForwardAnalyzeWithBaseline(0, __length, lineBounds.width, __wrap, length, textSize.width, textSize.height, baseline);
3875
3876         if (endType != TEXT_RETBY_LIMITWIDTH)
3877         {
3878                 __drawTextEllipsis = false;
3879                 return ComposeInNoneWrap(rect);
3880         }
3881
3882         __drawTextEllipsis = true;
3883
3884         TextElement* pTextElement = null;
3885         TextSimple* pSimpleText = null;
3886
3887         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
3888         SysTryReturn(NID_GRP
3889                 , pTextElement
3890                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3891
3892         TextElementType objectType = pTextElement->GetType();
3893         SysTryReturn(NID_GRP
3894                 , objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
3895                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3896
3897         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3898         if (pSimpleText != null)
3899         {
3900                 SetAbbrevObjectFontInfo(pSimpleText);
3901         }
3902
3903         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
3904         __middleEllipsisWidth = abbrevTextDim.width;
3905
3906         ForwardAnalyze(0, __length, ((lineBounds.width - __middleEllipsisWidth + 10) >> 1), __wrap, length, textSize.width, textSize.height);
3907         __middleEllipsisTextLengthInHead = length;
3908         __middleEllipsisHeadWidth = textSize.width;
3909
3910         maxHeight = textSize.height;
3911
3912         ForwardAnalyze(__middleEllipsisTextLengthInHead, __length - __middleEllipsisTextLengthInHead, lineBounds.width - __middleEllipsisWidth -
3913                                    __middleEllipsisHeadWidth, __wrap, length, textSize.width, textSize.height);
3914         __middleEllipsisTextLengthInTail = length;
3915
3916         if (maxHeight < textSize.height)
3917         {
3918                 maxHeight = textSize.height;
3919         }
3920
3921         TextLine* pTextLine = new (std::nothrow)TextLine(this);
3922         SysTryReturn(NID_GRP
3923                 , pTextLine
3924                 , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3925
3926         pTextLine->SetBounds(lineBounds);
3927         pTextLine->SetRegion(lineBounds.width, maxHeight);
3928         pTextLine->SetTextLength(__length);
3929         pTextLine->SetTextOffset(0);
3930         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
3931         pTextLine->SetBaseline(baseline);
3932
3933         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
3934
3935         lineBounds.height = maxHeight;
3936
3937         return 1;
3938 }
3939
3940 int
3941 TextComposite::ComposeInNoneWrapHeadEllipsis(Rectangle& rect)
3942 {
3943         SysTryReturn(NID_GRP
3944                         , __pCurrentTextColumn
3945                         , -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
3946
3947         int endType = TEXT_RETBY_NORMAL;
3948         Rectangle lineBounds;
3949         Dimension abbrevTextDim;
3950         Dimension textSize;
3951         int length = 0;
3952         int maxHeight = 0;
3953         int baseline = 0;
3954
3955         lineBounds.width = rect.width;
3956         lineBounds.x = 0;
3957         lineBounds.y = 0;
3958         lineBounds.height = rect.height;
3959         endType = ForwardAnalyzeWithBaseline(0, __length, lineBounds.width, __wrap, length, textSize.width, textSize.height, baseline);
3960
3961         if (endType != TEXT_RETBY_LIMITWIDTH)
3962         {
3963                 __drawTextEllipsis = false;
3964                 return ComposeInNoneWrap(rect);
3965         }
3966
3967         __drawTextEllipsis = true;
3968         TextElement* pTextElement = null;
3969         TextSimple* pSimpleText = null;
3970
3971         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
3972         SysTryReturn(NID_GRP
3973                 , pTextElement
3974                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3975
3976         TextElementType objectType = pTextElement->GetType();
3977         SysTryReturn(NID_GRP
3978                 , objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
3979                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
3980
3981         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
3982         if (pSimpleText != null)
3983         {
3984                 SetAbbrevObjectFontInfo(pSimpleText);
3985         }
3986
3987         __pAbbrevTextElement->GetRegion(0, 1, abbrevTextDim.width, abbrevTextDim.height);
3988         __headEllipsisWidth = abbrevTextDim.width;
3989
3990         BackwardAnalyze(__length - 1, lineBounds.width - abbrevTextDim.width, &__headEllipsisTextLength, &textSize.width, &textSize.height);
3991         maxHeight = textSize.height;
3992
3993         TextLine* pTextLine = new (std::nothrow)TextLine(this);
3994         SysTryReturn(NID_GRP
3995                 , pTextLine
3996                 , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
3997
3998         pTextLine->SetBounds(lineBounds);
3999         pTextLine->SetRegion(lineBounds.width, maxHeight);
4000         pTextLine->SetTextLength(__length);
4001         pTextLine->SetTextOffset(0);
4002         pTextLine->SetEndType(TEXT_RETBY_NORMAL);
4003         pTextLine->SetBaseline(baseline);
4004
4005         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4006
4007         lineBounds.height = maxHeight;
4008
4009         return 1;
4010 }
4011
4012 result
4013 TextComposite::DrawAbbrev(_CanvasImpl& canvasImpl, const Rectangle& displayRect, const TextObjectAlignment align)
4014 {
4015         if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_MIDDLE)
4016         {
4017                 return DrawAbbrevInMiddleEllipsis(canvasImpl, displayRect, align);
4018         }
4019         else if (__TextObjectEllipsisType == TEXT_OBJECT_ELLIPSIS_TYPE_HEAD)
4020         {
4021                 return DrawAbbrevInHeadEllipsis(canvasImpl, displayRect, align);
4022         }
4023
4024         return E_SYSTEM;
4025 }
4026
4027 result
4028 TextComposite::GetValue(int textIndex, TextComponentInfoValueType type, unsigned int* value) const
4029 {
4030         IEnumerator* pEnum = null;
4031         TextElement* pTextElement = null;
4032         int offset = 0;
4033         int elementTextLength = 0;
4034
4035         pEnum = __pTextElementList->GetEnumeratorN();
4036         while (pEnum->MoveNext() == E_SUCCESS)
4037         {
4038                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
4039                 if (pTextElement == null)
4040                 {
4041                         continue;
4042                 }
4043
4044                 elementTextLength = pTextElement->GetTextLength();
4045
4046                 if (textIndex < offset + elementTextLength)
4047                 {
4048                         TextElementType objectType = pTextElement->GetType();
4049
4050                         if (objectType != TextUtility::GetObjectTypeFromValueType(type) && objectType != TEXT_ELEMENT_TYPE_CUTLINK)
4051                         {
4052                                 Release(pEnum);
4053                                 return E_INVALID_ARG;
4054                         }
4055
4056                         *value = pTextElement->GetValue(type);
4057                         Release(pEnum);
4058                         return E_SUCCESS;
4059                 }
4060
4061                 offset += elementTextLength;
4062         }
4063
4064         Release(pEnum);
4065         return E_INVALID_ARG;
4066 }
4067
4068 bool
4069 TextComposite::BackwardAnalyze(int startTextIndex, int maxWidth, int* actualLength, int* width, int* height)
4070 {
4071         int remainingWidth = 0;
4072         int length = 0;
4073         Dimension textSize;
4074
4075         *actualLength = 0;
4076         *width = 0;
4077         *height = 0;
4078
4079         remainingWidth = maxWidth;
4080         length = 1;
4081
4082         while (startTextIndex >= 0 && textSize.width < remainingWidth)
4083         {
4084                 GetRegion(startTextIndex, length, textSize.width, textSize.height);
4085
4086                 if (textSize.width <= remainingWidth)
4087                 {
4088                         *actualLength = length;
4089                         *width = textSize.width;
4090                         *height = textSize.height;
4091                 }
4092
4093                 startTextIndex--;
4094                 length++;
4095         }
4096
4097         return true;
4098 }
4099
4100 int
4101 TextComposite::GetFirstTextIndexAt(int elementIndex) const
4102 {
4103         SysTryReturn(NID_GRP
4104                         , elementIndex >= 0 && elementIndex < __pTextElementList->GetCount()
4105                         , -1, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
4106
4107         IEnumerator* pEnum = null;
4108         TextElement* pTextElement = null;
4109
4110         int index = 0;
4111         int elementTextOffset = 0;
4112
4113         if (elementIndex == 0)
4114         {
4115                 return 0;
4116         }
4117
4118         pEnum = __pTextElementList->GetEnumeratorN();
4119         while (pEnum->MoveNext() == E_SUCCESS)
4120         {
4121                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
4122                 if (pTextElement == null)
4123                 {
4124                         continue;
4125                 }
4126
4127                 if (index == elementIndex)
4128                 {
4129                         break;
4130                 }
4131
4132                 elementTextOffset += pTextElement->GetTextLength();
4133
4134                 pTextElement = null;
4135                 index++;
4136         }
4137
4138         Release(pEnum);
4139
4140         if (pTextElement != null)
4141         {
4142                 return elementTextOffset;
4143         }
4144
4145         return -1;
4146 }
4147
4148 result
4149 TextComposite::DrawAbbrevInMiddleEllipsis(_CanvasImpl& canvasImpl, const Rectangle& displayRect, const TextObjectAlignment alignment)
4150 {
4151         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
4152         SysTryReturn(NID_GRP
4153                 , pTextLine
4154                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
4155
4156         Dimension textSize;
4157         Rectangle adjustedRect;
4158
4159         pTextLine->GetRegion(0, __length, textSize.width, textSize.height);
4160         adjustedRect.x = displayRect.x;
4161         adjustedRect.width = displayRect.width;
4162
4163         switch (alignment & TEXT_ALIGNMASK_VERT)
4164         {
4165         case TEXT_OBJECT_ALIGNMENT_TOP:
4166                 // fall through
4167         default:
4168                 adjustedRect.y = displayRect.y;
4169                 break;
4170
4171         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
4172                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
4173                 break;
4174
4175         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
4176                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
4177                 break;
4178         }
4179         adjustedRect.height = displayRect.height - (displayRect.y - adjustedRect.y);
4180
4181         TextElement* pTextElement = null;
4182         TextSimple* pSimpleText = null;
4183
4184         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
4185         SysTryReturn(NID_GRP
4186                 , pTextElement
4187                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
4188
4189         TextElementType objectType = pTextElement->GetType();
4190         SysTryReturn(NID_GRP
4191                 , objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
4192                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to draw to symbol object.");
4193
4194         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
4195         if (pSimpleText != null)
4196         {
4197                 SetAbbrevObjectFontInfo(pSimpleText);
4198         }
4199
4200         DrawPartial(canvasImpl, adjustedRect, 0, __middleEllipsisTextLengthInHead);
4201
4202         adjustedRect.x += __middleEllipsisHeadWidth;
4203         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), TEXT_OBJECT_ACTION_TYPE_NONE);
4204
4205         adjustedRect.x += __middleEllipsisWidth;
4206         DrawPartial(canvasImpl, adjustedRect, __length - __middleEllipsisTextLengthInTail, __middleEllipsisTextLengthInTail);
4207
4208         return E_SUCCESS;
4209 }
4210
4211 result
4212 TextComposite::DrawAbbrevInHeadEllipsis(_CanvasImpl& canvasImpl, const Rectangle& displayRect, const TextObjectAlignment alignment)
4213 {
4214         TextLine* pTextLine = __pCurrentTextColumn->GetTextLine(0);
4215         SysTryReturn(NID_GRP
4216                 , pTextLine
4217                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
4218
4219         result r = E_SUCCESS;
4220         Dimension textSize;
4221         Rectangle adjustedRect;
4222
4223         pTextLine->GetRegion(0, __length, textSize.width, textSize.height);
4224         adjustedRect.x = displayRect.x;
4225         adjustedRect.width = displayRect.width;
4226
4227         switch (alignment & TEXT_ALIGNMASK_VERT)
4228         {
4229         case TEXT_OBJECT_ALIGNMENT_TOP:
4230                 // fall through
4231         default:
4232                 adjustedRect.y = displayRect.y;
4233                 break;
4234
4235         case TEXT_OBJECT_ALIGNMENT_MIDDLE:
4236                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height) / 2;
4237                 break;
4238
4239         case TEXT_OBJECT_ALIGNMENT_BOTTOM:
4240                 adjustedRect.y = displayRect.y + (displayRect.height - textSize.height);
4241                 break;
4242         }
4243         adjustedRect.height = displayRect.height - (displayRect.y - adjustedRect.y);
4244
4245         TextElement* pTextElement = null;
4246         TextSimple* pSimpleText = null;
4247
4248         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(0));
4249         r = GetLastResult();
4250         SysTryReturn(NID_GRP
4251                 , pTextElement
4252                 , r, r, "[%s] Fail to get element.", GetErrorMessage(r));
4253
4254         TextElementType objectType = pTextElement->GetType();
4255         SysTryReturn(NID_GRP
4256                 , objectType == TEXT_ELEMENT_TYPE_CUTLINK || objectType == TEXT_ELEMENT_TYPE_TEXT
4257                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to draw to symbol object.");
4258
4259         pSimpleText = dynamic_cast < TextSimple* >(pTextElement);
4260         if (pSimpleText != null)
4261         {
4262                 SetAbbrevObjectFontInfo(pSimpleText);
4263         }
4264
4265         __pAbbrevTextElement->Draw(canvasImpl, adjustedRect, 0, 1, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT), TEXT_OBJECT_ACTION_TYPE_NONE);
4266
4267         adjustedRect.x += __headEllipsisWidth;
4268         DrawPartial(canvasImpl, adjustedRect, __length - __headEllipsisTextLength, __headEllipsisTextLength);
4269
4270         return E_SUCCESS;
4271 }
4272
4273 result
4274 TextComposite::DrawPartial(_CanvasImpl& canvasImpl, Rectangle& displayRect, int startTextIndex, int textLength)
4275 {
4276         SysTryReturn(NID_GRP
4277                         , 0 <= startTextIndex && startTextIndex < __length
4278                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
4279
4280         SysTryReturn(NID_GRP
4281                         , textLength <= __length
4282                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
4283
4284         result r = E_SUCCESS;
4285         IEnumerator* pEnum = null;
4286         TextElement* pTextElement = null;
4287
4288         Dimension textSize;
4289         int currentLength = 0;
4290         int textIndexFromElementOffset = 0;
4291         int nodeIndex = 0;
4292         int elementTextOffset = 0;
4293         Rectangle adjustedRect = displayRect;
4294         int blockStartTextIndex = 0;
4295         int blockEndTextIndex = 0;
4296         bool isAlternateLookEnabled = false;
4297         int textIndex = startTextIndex;
4298
4299         _Canvas* pCanvas = _Canvas::GetInstance(canvasImpl);
4300         SysTryReturn(NID_GRP
4301                         , pCanvas
4302                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get native canvas instance.");
4303
4304         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset, nodeIndex, currentLength,
4305                                                                                          textIndexFromElementOffset);
4306         SysTryReturn(NID_GRP
4307                 , pTextElement
4308                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text element.");
4309
4310         currentLength = Math::Min(textLength, currentLength);
4311
4312         pEnum = __pTextElementList->GetEnumeratorN();
4313         while (textLength > 0)
4314         {
4315                 textLength -= currentLength;
4316
4317                 pTextElement->GetRegion(textIndexFromElementOffset, currentLength, textSize.width, textSize.height);
4318
4319                 if (pTextElement->IsBackGroundDrawingModeEnable())
4320                 {
4321                         r = pCanvas->FillRectangle(pTextElement->GetBackgroundColor(), Rectangle(adjustedRect.x, displayRect.y, textSize.width, displayRect.height));
4322                         SysTryReturn(NID_GRP
4323                                 , r == E_SUCCESS
4324                                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
4325                 }
4326
4327                 isAlternateLookEnabled = pTextElement->GetValue(SET_ALTERNATE_LOOK);
4328                 if ((__displayBlock) && (isAlternateLookEnabled == false))
4329                 {
4330                         Dimension tempTextSize;
4331                         int adjustedX = 0;
4332
4333                         blockStartTextIndex = Math::Max(__workStart, textIndex);
4334                         blockEndTextIndex = Math::Min(__workStart + __workLength, textIndex + currentLength);
4335                         if (blockStartTextIndex < blockEndTextIndex)
4336                         {
4337                                 blockStartTextIndex = textIndexFromElementOffset + (blockStartTextIndex - textIndex);
4338                                 blockEndTextIndex = textIndexFromElementOffset + (blockEndTextIndex - textIndex);
4339                                 adjustedX = adjustedRect.x;
4340
4341                                 if (textIndexFromElementOffset < blockStartTextIndex)
4342                                 {
4343                                         pTextElement->GetRegion(textIndexFromElementOffset, blockStartTextIndex - textIndexFromElementOffset,
4344                                                                                                         tempTextSize.width, tempTextSize.height);
4345                                         adjustedX += tempTextSize.width;
4346                                 }
4347
4348                                 Rectangle blockRect = adjustedRect;
4349                                 blockRect.x = adjustedX;
4350                         }
4351                 }
4352
4353                 pTextElement->Draw(canvasImpl, adjustedRect, textIndexFromElementOffset, currentLength, (TextObjectAlignment)(TEXT_OBJECT_ALIGNMENT_TOP | TEXT_OBJECT_ALIGNMENT_LEFT),
4354                                                          TEXT_OBJECT_ACTION_TYPE_NONE);
4355
4356                 adjustedRect.x += textSize.width;
4357                 adjustedRect.width -= textSize.width;
4358
4359                 if (!textLength || adjustedRect.width <= 0)
4360                 {
4361                         break;
4362                 }
4363
4364                 textIndex += currentLength;
4365
4366                 if (pEnum->MoveNext() != E_SUCCESS)
4367                 {
4368                         break;
4369                 }
4370
4371                 pTextElement = static_cast < TextElement* >(pEnum->GetCurrent());
4372
4373                 textIndexFromElementOffset = pTextElement->GetValue(SET_TEXT_OFFSET);
4374                 currentLength = Math::Min(textLength, pTextElement->GetTextLength());
4375
4376                 if (currentLength == 0)
4377                 {
4378                         break;
4379                 }
4380         }
4381
4382         Release(pEnum);
4383         return E_SUCCESS;
4384 }
4385
4386 void
4387 TextComposite::SetPartialComposingModeEnabled(bool enable)
4388 {
4389         __partialComposingModeEnabled = enable;
4390 }
4391
4392 bool
4393 TextComposite::IsPartialComposingModeEnabled(void) const
4394 {
4395         return __partialComposingModeEnabled;
4396 }
4397
4398 bool
4399 TextComposite::InitPartialComposeMode(void)
4400 {
4401         __lineIndexCompositeDone = 0;
4402         __totalComposedHeight = 0;
4403         __composePartialLimitHeight = 0;
4404
4405         SysTryReturn(NID_GRP
4406                         , __pCurrentTextColumn
4407                         , false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
4408
4409         __pCurrentTextColumn->SetFirstDisplayLineIndex(0);
4410         __pCurrentTextColumn->SetFirstDisplayPositionY(0);
4411         __pCurrentTextColumn->PrepareCompose();
4412
4413         return true;
4414 }
4415
4416 bool
4417 TextComposite::IsComposeDone() const
4418 {
4419         SysTryReturn(NID_GRP
4420                         , __pCurrentTextColumn
4421                         , false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
4422
4423         return __pCurrentTextColumn->IsComposeDone();
4424 }
4425
4426 int
4427 TextComposite::ComposeInWrapByTextWidth(Rectangle& rect)
4428 {
4429         SysTryReturn(NID_GRP
4430                         , __pCurrentTextColumn
4431                         , false, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
4432
4433         Rectangle lineBounds;
4434         int lineCount = 0;
4435         int textIndex = 0;
4436         int remainingLength = 0;
4437         int remainingWidth = 0;
4438         int remainingHeight = 0;
4439         int offsetY = 0;
4440         bool hasPrevLine = false;
4441         int endType = TEXT_RETBY_NORMAL;
4442         Dimension lineTextSize;
4443         int lineOffset = 0;
4444         int lineLength = 0;
4445         TextLine* pTextLine = null;
4446
4447         pTextLine = __pCurrentTextColumn->GetPrevLineChangedStartLine();
4448         if (pTextLine != null)
4449         {
4450                 endType = pTextLine->GetEndType();
4451                 lineOffset = pTextLine->GetTextOffset();
4452                 lineLength = pTextLine->GetTextLength();
4453                 lineBounds = pTextLine->GetBounds();
4454                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineTextSize.width, lineTextSize.height);
4455
4456                 if (endType != TEXT_RETBY_LINEFEED)
4457                 {
4458                         textIndex = lineOffset;
4459                         remainingLength = __length - textIndex;
4460                         remainingWidth = rect.width;
4461                         hasPrevLine = true;
4462
4463                         if (remainingLength == 0)
4464                         {
4465                                 return -1;
4466                         }
4467                 }
4468                 else
4469                 {
4470                         textIndex = lineOffset + lineLength;
4471                         remainingLength = __length - textIndex;
4472                         remainingWidth = rect.width;
4473                         offsetY = lineBounds.y + lineBounds.height;
4474                         lineBounds.y = offsetY;
4475
4476                         if (remainingLength == 0)
4477                         {
4478                                 lineTextSize.height = lineBounds.height;
4479
4480                                 pTextLine = new (std::nothrow)TextLine(this);
4481                                 SysTryReturn(NID_GRP
4482                                         , pTextLine
4483                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4484
4485                                 pTextLine->SetBounds(lineBounds);
4486                                 pTextLine->SetRegion(0, lineTextSize.height);
4487                                 pTextLine->SetTextLength(0);
4488                                 pTextLine->SetTextOffset(textIndex);
4489                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4490
4491                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4492
4493                                 return 1;
4494                         }
4495                 }
4496         }
4497         else
4498         {
4499                 textIndex = 0;
4500                 remainingLength = __length;
4501                 remainingWidth = rect.width;
4502                 lineBounds.x = rect.x;
4503                 lineBounds.y = 0;
4504                 lineBounds.width = rect.width;
4505         }
4506
4507         remainingHeight = rect.height;
4508
4509         __pTextWidthManager->StartCompose(textIndex);
4510
4511         TextLineComposeInfo composeInfo;
4512         composeInfo.height = 0;
4513         composeInfo.width = 0;
4514         composeInfo.length = 0;
4515         composeInfo.endType = TEXT_RETBY_NORMAL;
4516
4517         while (remainingLength != 0)
4518         {
4519                 __pTextWidthManager->GetCurrentLineInfo(remainingWidth, composeInfo);
4520                 composeInfo.height += __lineSpacing;
4521
4522                 if (hasPrevLine)
4523                 {
4524                         lineBounds.height = composeInfo.height;
4525                         pTextLine->SetBounds(lineBounds);
4526                         pTextLine->SetRegion(composeInfo.width, composeInfo.height);
4527                         pTextLine->SetTextLength(composeInfo.length);
4528                         pTextLine->SetEndType(composeInfo.endType);
4529                         hasPrevLine = false;
4530                 }
4531                 else
4532                 {
4533                         if (composeInfo.length == 0)
4534                         {
4535                                 composeInfo.length = 1;
4536                         }
4537
4538                         pTextLine = new (std::nothrow)TextLine(this);
4539                         SysTryReturn(NID_GRP
4540                                 , pTextLine
4541                                 , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4542
4543                         lineBounds.height = composeInfo.height;
4544
4545                         pTextLine->SetBounds(lineBounds);
4546                         pTextLine->SetTextOffset(textIndex);
4547                         pTextLine->SetRegion(composeInfo.width, composeInfo.height);
4548                         pTextLine->SetTextLength(composeInfo.length);
4549                         pTextLine->SetEndType(composeInfo.endType);
4550
4551                         __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4552                         lineCount++;
4553                 }
4554
4555                 if (__pCurrentTextColumn->IsComposeDone())
4556                 {
4557                         break;
4558                 }
4559
4560                 textIndex += composeInfo.length;
4561                 remainingLength -= composeInfo.length;
4562                 remainingHeight -= composeInfo.height;
4563
4564                 if (remainingLength > 0)
4565                 {
4566                         int nextY = lineBounds.y + lineBounds.height;
4567
4568                         lineBounds.x = rect.x;
4569                         lineBounds.y = nextY;
4570                         lineBounds.width = rect.width;
4571                         lineTextSize.height = 0;
4572                         remainingWidth = rect.width;
4573                 }
4574                 else
4575                 {
4576                         if (composeInfo.endType == TEXT_RETBY_LINEFEED)
4577                         {
4578                                 int nextY = lineBounds.y + lineBounds.height;
4579                                 lineTextSize.height = lineBounds.height;
4580
4581                                 pTextLine = new (std::nothrow)TextLine(this);
4582                                 SysTryReturn(NID_GRP
4583                                         , pTextLine
4584                                         , -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
4585
4586                                 lineBounds.x = rect.x;
4587                                 lineBounds.y = nextY;
4588                                 lineBounds.width = rect.width;
4589                                 lineBounds.height = lineTextSize.height;
4590
4591                                 pTextLine->SetBounds(lineBounds);
4592                                 pTextLine->SetRegion(0, lineTextSize.height);
4593                                 pTextLine->SetTextLength(0);
4594                                 pTextLine->SetTextOffset(textIndex);
4595                                 pTextLine->SetEndType(TEXT_RETBY_LINEFEED);
4596                                 __pCurrentTextColumn->AddLineDuringCompose(pTextLine);
4597
4598                                 lineCount++;
4599
4600                                 pTextLine = null;
4601                                 break;
4602                         }
4603                         else
4604                         {
4605                                 pTextLine = null;
4606                         }
4607                 }
4608         }
4609
4610         __pTextWidthManager->EndCompose();
4611
4612         Dimension columnSize;
4613         __pCurrentTextColumn->GetRegion(0, __length, columnSize.width, columnSize.height);
4614         rect.height = columnSize.height;
4615
4616         return lineCount;
4617 }
4618
4619 result
4620 TextComposite::GetCutLinkObjectInfo(int cutLinkIndex, int& textStartIndex, int& textLength) const
4621 {
4622         return __pCutLinkListInfo->GetCutLinkObjectInfo(cutLinkIndex, textStartIndex, textLength);
4623 }
4624
4625 int
4626 TextComposite::GetTotalComposedHeight(void) const
4627 {
4628         return __totalComposedHeight;
4629 }
4630
4631 int
4632 TextComposite::GetAnalysedTotalHeight(void) const
4633 {
4634         TextLine* pTextLine = null;
4635         pTextLine = __pCurrentTextColumn->GetTextLine(__lineIndexCompositeDone - 1);
4636
4637         if (!pTextLine)
4638         {
4639                 return 0;
4640         }
4641
4642         int lineOffset = pTextLine->GetTextOffset();
4643         int lineLength = pTextLine->GetTextLength();
4644
4645         int composedLength = lineOffset + lineLength;
4646         if (composedLength == 0)
4647         {
4648                 return 0;
4649         }
4650
4651         return (int)(GetTotalComposedHeight() * __length / composedLength);
4652 }
4653
4654 void
4655 TextComposite::SetComposePartialLimitHeight(int limitHeight)
4656 {
4657         __composePartialLimitHeight = limitHeight;
4658 }
4659
4660 int
4661 TextComposite::GetComposePartialLimitHeight(void) const
4662 {
4663         return __composePartialLimitHeight;
4664
4665 }
4666
4667 TextElementType
4668 TextComposite::GetObjectType(int textIndex) const
4669 {
4670         TextElement* pTextElement = null;
4671
4672         int currentLength = 0;
4673         int elementIndex = 0;
4674         int textIndexFromElementOffset = 0;
4675         int elementTextOffset = 0;
4676
4677         pTextElement = GetElementAtTextIndex(textIndex, elementTextOffset
4678                                                                                                         , elementIndex, currentLength, textIndexFromElementOffset);
4679         if (pTextElement == null)
4680         {
4681                 return TEXT_ELEMENT_TYPE_NONE;
4682         }
4683         else
4684         {
4685                 return pTextElement->GetType();
4686         }
4687 }
4688
4689 int
4690 TextComposite::GetElementIndexOf(TextElement& textElement) const
4691 {
4692         int index = 0;
4693
4694         result r = E_SUCCESS;
4695
4696         r = __pTextElementList->IndexOf(textElement, index);
4697         SysTryReturn(NID_GRP
4698                         , r == E_SUCCESS
4699                         , false, r, "[%s] Fail to add element.", GetErrorMessage(r));
4700
4701         return index;
4702 }
4703
4704 TextElement*
4705 TextComposite::GetElementAtElementIndex(int nodeIndex) const
4706 {
4707         result r = E_SUCCESS;
4708
4709         TextElement* pTextElement = null;
4710         pTextElement = static_cast < TextElement* >(__pTextElementList->GetAt(nodeIndex));
4711         SysTryReturn(NID_GRP
4712                 , r == E_SUCCESS
4713                 , null, r, "[%s] Fail to add element.", GetErrorMessage(r));
4714
4715         return pTextElement;
4716 }
4717
4718 int
4719 TextComposite::GetTextLength(void) const
4720 {
4721         return __length;
4722 }
4723
4724 int
4725 TextComposite::GetElementCount(void) const
4726 {
4727         return __pTextElementList->GetCount();
4728 }
4729
4730 void
4731 TextComposite::SetBlock(bool enable)
4732 {
4733         __displayBlock = enable;
4734 }
4735
4736 result
4737 TextComposite::SetImageAlign(TextObjectAlignment align)
4738 {
4739         return SetValueToAllTextElements(SET_IMAGE_ALIGN, (unsigned int)align);
4740 }
4741
4742 TextObjectWrapType
4743 TextComposite::GetWrap(void) const
4744 {
4745         return __wrap;
4746 }
4747
4748 void
4749 TextComposite::SetLineSpace(int gap)
4750 {
4751         __lineSpacing = gap;
4752 }
4753
4754 int
4755 TextComposite::GetLineSpace(void) const
4756 {
4757         return __lineSpacing;
4758 }
4759
4760 void
4761 TextComposite::SetElementVerticalAlignment(TextObjectAlignment alignment)
4762 {
4763         __elementVertialAlignment = alignment;
4764 }
4765
4766 TextObjectAlignment
4767 TextComposite::GetElementVerticalAlignment(void) const
4768 {
4769         return __elementVertialAlignment;
4770 }
4771
4772 void
4773 TextComposite::SetCursorIndex(int cursorIndex)
4774 {
4775         __cursorIndex = cursorIndex;
4776 }
4777
4778 int
4779 TextComposite::GetCursorIndex(void) const
4780 {
4781         return __cursorIndex;
4782 }
4783
4784 void
4785 TextComposite::SetTextObjectEllipsisType(TextObjectEllipsisType type)
4786 {
4787         __TextObjectEllipsisType = type;
4788 }
4789
4790 TextObjectEllipsisType
4791 TextComposite::GetTextObjectEllipsisType(void) const
4792 {
4793         return __TextObjectEllipsisType;
4794 }
4795
4796 void
4797 TextComposite::SetTextAbbreviationEnabled(bool enable)
4798 {
4799         __drawAbbrevText = enable;
4800 }
4801
4802 bool
4803 TextComposite::IsTextAbbreviationEnabled(void) const
4804 {
4805         if (__drawAbbrevText && __drawTextEllipsis)
4806         {
4807                 return true;
4808         }
4809
4810         return false;
4811 }
4812
4813 bool
4814 TextComposite::GetBlock(void) const
4815 {
4816         return __displayBlock;
4817 }
4818
4819 int
4820 TextComposite::GetWorkStart(void) const
4821 {
4822         return __workStart;
4823 }
4824
4825 int
4826 TextComposite::GetWorkLength(void) const
4827 {
4828         return __workLength;
4829 }
4830
4831 TextObjectAlignment
4832 TextComposite::GetImageAlign(int textIndex) const
4833 {
4834         result r = E_SUCCESS;
4835         unsigned int value = 0;
4836
4837         r = GetValue(textIndex, SET_IMAGE_ALIGN, &value);
4838         SysTryReturn(NID_GRP
4839                 , r == E_SUCCESS
4840                 , TEXT_OBJECT_ALIGNMENT_INVALID, r, "[%s] Propagating.", GetErrorMessage(r));
4841
4842         return (TextObjectAlignment)value;
4843 }
4844
4845 bool
4846 TextComposite::IsChanged(void) const
4847 {
4848         return __isChanged;
4849 }
4850
4851 void
4852 TextComposite::SetBlockColor(const Color& color)
4853 {
4854         __defaultBlockColor = color;
4855 }
4856
4857 Color
4858 TextComposite::GetBlockColor(void) const
4859 {
4860         return __defaultBlockColor;
4861 }
4862
4863 void
4864 TextComposite::SetTextWidthManager(TextWidthManager* pTextWidthManager)
4865 {
4866         __pTextWidthManager = pTextWidthManager;
4867 }
4868
4869 void
4870 TextComposite::SetWidthManagerEnabled(bool widthManagerEnable)
4871 {
4872         __widthManagerEnabled = widthManagerEnable;
4873 }
4874
4875 bool
4876 TextComposite::IsWidthManagerEnabled(void) const
4877 {
4878         return __widthManagerEnabled;
4879 }
4880
4881 result
4882 TextComposite::SetWorkWidth(Font* pFont, wchar_t* pText, int workStart, int textLength)
4883 {
4884         result r = E_SUCCESS;
4885         int width = 0;
4886         int height = 0;
4887         int workLength = 0;
4888         const wchar_t* pSrc = &pText[workStart];
4889
4890         workLength = Math::Abs(textLength);
4891
4892         r = TextUtility::GetTextExtent(pFont, pSrc, workLength, false, width, height);
4893         SysTryReturn(NID_GRP
4894                 , r == E_SUCCESS
4895                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
4896
4897         if (textLength < 0)
4898         {
4899                 __workWidth = -width;
4900         }
4901         else
4902         {
4903                 __workWidth = width;
4904         }
4905
4906         return E_SUCCESS;
4907 }
4908
4909 int
4910 TextComposite::GetWorkWidth(void)
4911 {
4912    return __workWidth;
4913 }
4914
4915 void
4916 TextComposite::SetTextSweepInfo(TextObjectSweepInfo* pTextSweepInfo)
4917 {
4918         __pSweepInfo = pTextSweepInfo;
4919 }
4920
4921 void
4922 TextComposite::GetTextSweepInfo(TextObjectSweepInfo& textSweepInfo)
4923 {
4924         textSweepInfo.isValid = __pSweepInfo->isValid;
4925         textSweepInfo.sweepType = __pSweepInfo->sweepType;
4926         textSweepInfo.sweepEventType = __pSweepInfo->sweepEventType;
4927         textSweepInfo.anchorTextIndex = __pSweepInfo->anchorTextIndex;
4928         textSweepInfo.anchorLineIndex = __pSweepInfo->anchorLineIndex;
4929         textSweepInfo.sweepRegionStartLineIndex = __pSweepInfo->sweepRegionStartLineIndex;
4930         textSweepInfo.sweepRegionLineCount = __pSweepInfo->sweepRegionLineCount;
4931         textSweepInfo.insertedLineCount = __pSweepInfo->insertedLineCount;
4932         textSweepInfo.deletedLineCount = __pSweepInfo->deletedLineCount;
4933         textSweepInfo.widthChanged = __pSweepInfo->widthChanged;
4934 }
4935
4936 void
4937 TextComposite::UpdateTextSweepInfo(TextObjectSweepInfo* pTextSweepInfo)
4938 {
4939         __pSweepInfo->isValid = pTextSweepInfo->isValid;
4940         __pSweepInfo->sweepType = pTextSweepInfo->sweepType;
4941         __pSweepInfo->sweepEventType = pTextSweepInfo->sweepEventType;
4942         __pSweepInfo->anchorTextIndex = pTextSweepInfo->anchorTextIndex;
4943         __pSweepInfo->anchorLineIndex = pTextSweepInfo->anchorLineIndex;
4944         __pSweepInfo->sweepRegionStartLineIndex = pTextSweepInfo->sweepRegionStartLineIndex;
4945         __pSweepInfo->sweepRegionLineCount = pTextSweepInfo->sweepRegionLineCount;
4946         __pSweepInfo->insertedLineCount = pTextSweepInfo->insertedLineCount;
4947         __pSweepInfo->deletedLineCount = pTextSweepInfo->deletedLineCount;
4948         __pSweepInfo->widthChanged = pTextSweepInfo->widthChanged;
4949 }
4950
4951 }}} // Tizen::Graphics::_Text