Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / text / FGrp_TextTextColumn.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_TextTextColumn.cpp
20  * @brief       This is the implementation file for TextColumn class.
21  */
22
23 #include <new>
24 #include <FBaseSysLog.h>
25 #include "FGrp_CanvasImpl.h"
26 #include "FGrp_TextCommon.h"
27 #include "FGrp_TextTextComposite.h"
28 #include "FGrp_TextTextLine.h"
29 #include "FGrp_TextTextColumn.h"
30 #include "FGrp_TextTextUtility.h"
31
32 using namespace Tizen::Base::Utility;
33
34 namespace Tizen { namespace Graphics
35 {
36
37 namespace _Text
38 {
39
40 struct ChangeActionEventInfo
41 {
42         TextColumn::ChangeAction action;
43         int changedTextIndex;
44         int changedTextLength;
45 };
46
47 TextColumn::TextColumn(TextComposite* pCompositeText)
48 {
49         __totalLineCount = 0;
50         __displayLineCount = 0;
51         __firstDisplayLineIndex = 0;
52         __firstDisplayPositionY = -1;
53         __displayHeight = -1;
54         __slidingPosition = 0;
55         __pCompositeText = pCompositeText;
56         __textChangeAction = TEXT_CHANGE_INSERT;
57         __setChangeAction = false;
58         __pCachedLineNode = null;
59         __cachedLineIndex = 0;
60         __cachedLinePositionY = 0;
61         __chagedStartTextIndex = 0;
62         __changedTextLength = 0;
63         __changedStartLineIndex = 0;
64         __changedLastLineIndex = 0;
65         __prevLineIndexBeforeChangedStartLine = 0;
66         __nextLineIndexAfterChangedLastLine = 0;
67         __textOffsetOfNextLineAfterChangedLine = 0;
68         __currentLineIndexToAddDuringCompose = 0;
69         __isComposeDone = false;
70
71         __pLines = new (std::nothrow) SimpleList;
72         if (__pLines)
73         {
74                 TextSimpleList::Init(__pLines);
75         }
76
77         __pTextChangeActionList = new (std::nothrow) SimpleList;
78         if (__pTextChangeActionList)
79         {
80                 TextSimpleList::Init(__pTextChangeActionList);
81         }
82
83         __pKeepLines = new (std::nothrow) SimpleList;
84         if (__pKeepLines)
85         {
86                 TextSimpleList::Init(__pKeepLines);
87         }
88
89         __keepLineCount = 0;
90         __insertedLineCountDuringCompose = 0;
91 }
92
93 TextColumn::~TextColumn(void)
94 {
95         if (__pLines)
96         {
97                 RemoveAllLines();
98                 delete __pLines;
99                 __pLines = null;
100         }
101
102         if (__pKeepLines)
103         {
104                 RemoveAllKeepLines();
105                 delete __pKeepLines;
106                 __pKeepLines = null;
107         }
108
109         if (__pTextChangeActionList)
110         {
111                 RemoveAllChangeActions();
112                 delete __pTextChangeActionList;
113                 __pTextChangeActionList = null;
114         }
115 }
116
117 result
118 TextColumn::GetRegion(int textIndex, int textLength, int& width, int& height) const
119 {
120         result r = E_SUCCESS;
121
122         width = 0;
123         height = 0;
124
125         int totalLength = __pCompositeText->GetTextLength();
126
127         if (textIndex != 0 || textLength != totalLength)
128         {
129                 return __pCompositeText->GetRegion(textIndex, textLength, width, height);
130         }
131
132         Rectangle lineBounds;
133         SimpleNode* pTextLineNode = null;
134         TextLine* pTextLine = null;
135
136         pTextLineNode = TextSimpleList::GetFirstNode(__pLines);
137         while (pTextLineNode)
138         {
139                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
140                 SysTryReturn(NID_GRP
141                         , pTextLine
142                         , r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
143
144                 lineBounds = pTextLine->GetBounds();
145
146                 width = Math::Max(width, lineBounds.width);
147                 height += lineBounds.height;
148
149                 pTextLineNode = pTextLineNode->pNext;
150         }
151
152         return r;
153 }
154
155 int
156 TextColumn::GetHeight(int textIndex) const
157 {
158         if (textIndex < 0)
159         {
160                 return GetTotalHeight();
161         }
162
163         return __pCompositeText->GetHeight(textIndex);
164 }
165
166 result
167 TextColumn::Draw(_CanvasImpl& canvasImpl, Rectangle& displayRect, int startTextIndex, int textLength,
168                 const TextObjectAlignment alignment, const TextObjectActionType action)
169 {
170         result r = E_SUCCESS;
171         TextLine* pTextLine = null;
172         SimpleNode* pTextLineNode = null;
173         TextObjectActionType lineAction = TEXT_OBJECT_ACTION_TYPE_NONE;
174         Rectangle lineBounds;
175
176         __displayLineCount = 0;
177         __displayHeight = 0;
178
179         pTextLineNode = TextSimpleList::GetNthNode(__pLines, __firstDisplayLineIndex);
180         if (pTextLineNode == null)
181         {
182                 return E_SUCCESS;
183         }
184
185         pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
186         SysTryReturn(NID_GRP
187                 , pTextLine
188                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
189
190         if (__pLines->nodeCount < pTextLine->GetIndex())
191         {
192                 return E_SUCCESS;
193         }
194
195         lineBounds = pTextLine->GetBounds();
196
197         if (__firstDisplayPositionY != lineBounds.y)
198         {
199                 displayRect.y -= __firstDisplayPositionY - lineBounds.y;
200                 displayRect.height += __firstDisplayPositionY - lineBounds.y;
201                 __displayHeight -= __firstDisplayPositionY - lineBounds.y;
202         }
203
204         while (pTextLineNode != null && 0 <= displayRect.height)
205         {
206                 if (action == TEXT_OBJECT_ACTION_TYPE_ABBREV)
207                 {
208                         TextLine* pNextTextLine = null;
209                         if (pTextLineNode->pNext == null)
210                         {
211                                 pNextTextLine = null;
212                         }
213                         else
214                         {
215                                 pNextTextLine = static_cast < TextLine* >(pTextLineNode->pNext->pObject);
216                         }
217
218                         if (pNextTextLine == null)
219                         {
220                                 if (pTextLine->GetTextOffset() + pTextLine->GetTextLength() < __pCompositeText->GetTextLength())
221                                 {
222                                         lineAction = TEXT_OBJECT_ACTION_TYPE_ABBREV;
223                                 }
224                         }
225                         else
226                         {
227                                 Rectangle nextLineBounds;
228                                 if (__pLines->nodeCount < pNextTextLine->GetIndex())
229                                 {
230                                         return E_SUCCESS;
231                                 }
232
233                                 nextLineBounds = pNextTextLine->GetBounds();
234                                 if (displayRect.height < (lineBounds.height + nextLineBounds.height))
235                                 {
236                                         lineAction = TEXT_OBJECT_ACTION_TYPE_ABBREV;
237                                 }
238                         }
239                 }
240
241                 int lineLength = pTextLine->GetTextLength();
242
243                 TextObjectAlignment horizontalAlignment = (TextObjectAlignment)(alignment & TEXT_ALIGNMASK_HORIZ);
244                 r = pTextLine->Draw(canvasImpl, displayRect, 0, lineLength, horizontalAlignment, lineAction);
245                 SysTryReturn(NID_GRP
246                         , r == E_SUCCESS
247                         , r, r, "[%s] Propagating.", GetErrorMessage(r));
248
249                 __displayLineCount++;
250
251                 if (lineBounds.height <= displayRect.height)
252                 {
253                         displayRect.height -= lineBounds.height;
254                         displayRect.y += lineBounds.height;
255                         __displayHeight += lineBounds.height;
256                 }
257                 else
258                 {
259                         lineBounds.height += displayRect.height;
260                         break;
261                 }
262
263                 if (lineAction == TEXT_OBJECT_ACTION_TYPE_ABBREV)
264                 {
265                         break;
266                 }
267
268                 pTextLineNode = pTextLineNode->pNext;
269                 if (pTextLineNode == null)
270                 {
271                         break;
272                 }
273
274                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
275                 SysTryReturn(NID_GRP
276                         , pTextLine
277                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
278
279                 if (__pLines->nodeCount < pTextLine->GetIndex())
280                 {
281                         return E_SUCCESS;
282                 }
283
284                 lineBounds = pTextLine->GetBounds();
285         }
286
287         return E_SUCCESS;
288 }
289
290 int
291 TextColumn::GetTextLength(void) const
292 {
293         return __pCompositeText->GetTextLength();
294 }
295
296 int
297 TextColumn::GetLineIndexAtTextIndex(int textIndex) const
298 {
299         SimpleNode* pTextLineNode = null;
300         TextLine* pTextLine = null;
301         int lineIndex = 0;
302         int lineOffset = 0;
303         int lineLength = 0;
304         int lineEndType = TEXT_RETBY_NORMAL;
305
306         pTextLineNode = TextSimpleList::GetFirstNode(__pLines);
307         if (textIndex == 0 && (pTextLineNode != null))
308         {
309                 return 0;
310         }
311
312         while (pTextLineNode)
313         {
314                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
315                 SysTryReturn(NID_GRP
316                         , pTextLine
317                         , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
318
319                 lineOffset = pTextLine->GetTextOffset();
320                 lineLength = pTextLine->GetTextLength();
321                 lineEndType = pTextLine->GetEndType();
322
323                 if (lineOffset <= textIndex)
324                 {
325                         if (textIndex < lineOffset + lineLength)
326                         {
327                                 return lineIndex;
328                         }
329                 }
330
331                 lineIndex++;
332                 pTextLineNode = pTextLineNode->pNext;
333         }
334
335         if (__pCompositeText->GetTextLength() == textIndex)
336         {
337                 return lineIndex - 1;
338         }
339
340         return -1;
341 }
342
343 int
344 TextColumn::GetLineIndexAtPositionY(int y)
345 {
346         SimpleNode* pTextLineNode = null;
347         TextLine* pTextLine = null;
348
349         int lineIndex = 0;
350         Rectangle lineBounds;
351
352         if (GetTotalLineCount() == 0)
353         {
354                 return 0;
355         }
356
357         if (__pCachedLineNode == null)
358         {
359                 pTextLineNode = TextSimpleList::GetFirstNode(__pLines);
360                 while (pTextLineNode)
361                 {
362                         pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
363                         SysTryReturn(NID_GRP
364                                 , pTextLine
365                                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
366
367                         lineBounds = pTextLine->GetBounds();
368
369                         if (y >= lineBounds.y && y < lineBounds.y + lineBounds.height)
370                         {
371                                 __pCachedLineNode = pTextLineNode;
372                                 __cachedLineIndex = lineIndex;
373                                 __cachedLinePositionY = lineBounds.y;
374                                 return lineIndex;
375                         }
376
377                         lineIndex++;
378                         pTextLineNode = pTextLineNode->pNext;
379                 }
380         }
381         else
382         {
383                 bool searchForward = true;
384
385                 if (__cachedLinePositionY < y)
386                 {
387                         searchForward = true;
388                 }
389                 else if (y < __cachedLinePositionY)
390                 {
391                         searchForward = false;
392                 }
393                 else
394                 {
395                         return __cachedLineIndex;
396                 }
397
398                 pTextLineNode = __pCachedLineNode;
399                 lineIndex = __cachedLineIndex;
400                 while (pTextLineNode)
401                 {
402                         pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
403                         SysTryReturn(NID_GRP
404                                 , pTextLine
405                                 , -1, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
406
407                         lineBounds = pTextLine->GetBounds();
408
409                         if (y >= lineBounds.y && y < lineBounds.y + lineBounds.height)
410                         {
411                                 __pCachedLineNode = pTextLineNode;
412                                 __cachedLineIndex = lineIndex;
413                                 __cachedLinePositionY = lineBounds.y;
414
415                                 return lineIndex;
416                         }
417
418                         if (searchForward)
419                         {
420                                 lineIndex++;
421                                 pTextLineNode = pTextLineNode->pNext;
422                         }
423                         else
424                         {
425                                 lineIndex--;
426                                 pTextLineNode = pTextLineNode->pPrev;
427                         }
428                 }
429         }
430
431         return lineIndex;
432 }
433
434 int
435 TextColumn::GetTotalHeight(void) const
436 {
437         SimpleNode* pTextLineNode = null;
438         TextLine* pTextLine = null;
439         Rectangle lineBounds;
440         int height = 0;
441
442         pTextLineNode = TextSimpleList::GetFirstNode(__pLines);
443         while (pTextLineNode)
444         {
445                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
446                 SysTryReturn(NID_GRP
447                         , pTextLine
448                         , 0, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
449
450                 lineBounds = pTextLine->GetBounds();
451
452                 height += lineBounds.height;
453                 pTextLineNode = pTextLineNode->pNext;
454         }
455
456         return height;
457 }
458
459 int
460 TextColumn::GetLineHeightAt(int index) const
461 {
462         TextLine* pTextLine = null;
463         pTextLine = static_cast < TextLine* >(TextSimpleList::GetNthObject(__pLines, index));
464
465         SysTryReturn(NID_GRP
466                 , pTextLine
467                 , 0, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
468
469         Rectangle lineRect;
470         lineRect = pTextLine->GetBounds();
471
472         return lineRect.height;
473 }
474
475 int
476 TextColumn::GetTextLengthAt(int lineIndex) const
477 {
478         TextLine* pTextLine = null;
479
480         pTextLine = static_cast < TextLine* >(TextSimpleList::GetNthObject(__pLines, lineIndex));
481         SysTryReturn(NID_GRP
482                 , pTextLine
483                 , 0, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
484
485         return pTextLine->GetTextLength();
486 }
487
488 int
489 TextColumn::GetFirstTextIndexAt(int lineIndex) const
490 {
491         TextLine* pTextLine = null;
492
493         pTextLine = static_cast < TextLine* >(TextSimpleList::GetNthObject(__pLines, lineIndex));
494         SysTryReturn(NID_GRP
495                 , pTextLine
496                 , 0, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
497
498         return pTextLine->GetTextOffset();
499 }
500
501 result
502 TextColumn::Append(TextLine* pTextLine)
503 {
504         SysTryReturn(NID_GRP
505                         , pTextLine
506                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
507
508         TextSimpleList::AppendObject(__pLines, pTextLine);
509         __totalLineCount++;
510
511         return E_SUCCESS;
512 }
513
514 result
515 TextColumn::RemoveAllLines(void)
516 {
517         TextLine* pTextLine = null;
518
519         while (1)
520         {
521                 pTextLine = static_cast < TextLine* >(TextSimpleList::DeleteNthObject(__pLines, 0));
522                 if (pTextLine == null)
523                 {
524                         break;
525                 }
526
527                 delete pTextLine;
528                 pTextLine = null;
529         }
530
531         __totalLineCount = 0;
532
533         return E_SUCCESS;
534 }
535
536 result
537 TextColumn::Remove(TextLine* pTextLine)
538 {
539         SysTryReturn(NID_GRP
540                         , pTextLine
541                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
542
543         int index = pTextLine->GetIndex();
544
545         SimpleNode* pNode = TextSimpleList::GetNthNode(__pLines, index);
546         SysTryReturn(NID_GRP
547                         , pNode
548                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get node.");
549
550         bool r = TextSimpleList::DeleteNode(__pLines, pNode);
551         if (r == true)
552         {
553                 return E_SUCCESS;
554         }
555         else
556         {
557                 return E_SYSTEM;
558         }
559 }
560
561 TextLine*
562 TextColumn::GetTextLine(int lineIndex) const
563 {
564         SysTryReturn(NID_GRP
565                         , 0 <= lineIndex || lineIndex < __totalLineCount
566                         , null, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
567
568         TextLine* pTextLine = static_cast < TextLine* >(TextSimpleList::GetNthObject(__pLines, lineIndex));
569
570         return pTextLine;
571 }
572
573 result
574 TextColumn::SetChangeAction(ChangeAction changeAction, int textIndex, int textLength)
575 {
576         SysTryReturn(NID_GRP
577                         , changeAction == TEXT_CHANGE_INSERT || changeAction == TEXT_CHANGE_REMOVE || changeAction == TEXT_CHANGE_UNKONWN
578                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
579
580         SysTryReturn(NID_GRP
581                         , 0 <= textIndex
582                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
583
584         int textIndexBeforeChanged = textIndex;
585         int textLengthBeforeChanged = textLength;
586         int textIndexAfterChanged = 0;
587         int textLengthAfterChanged = 0;
588
589         ChangeActionEventInfo* pChangeActionEventInfo = null;
590         SimpleNode* pCurrentChangeActionEventInfoNode = null;
591         ChangeActionEventInfo* pCurrentChangeActionEventInfo = null;
592         int currentChangeActionEventInfoIndex = 0;
593
594         pCurrentChangeActionEventInfoNode = TextSimpleList::GetFirstNode(__pTextChangeActionList);
595         if (pCurrentChangeActionEventInfoNode)
596         {
597                 pCurrentChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(pCurrentChangeActionEventInfoNode->pObject);
598         }
599
600         while (pCurrentChangeActionEventInfo)
601         {
602                 bool isLineInserted = false;
603                 bool isActionCollapsed = false;
604                 ActionProcessResult actionEventResult = DoProcessTextAction(changeAction, textIndexBeforeChanged,
605                                 textLengthBeforeChanged, pCurrentChangeActionEventInfo, textIndexAfterChanged, textLengthAfterChanged);
606
607                 switch (actionEventResult)
608                 {
609                 case BEFORE_ACTION:
610                         isLineInserted = true;
611                         break;
612
613                 case MERGE_AND_BEFORE_ACTION:
614                         isLineInserted = true;
615                         textLengthBeforeChanged = textLengthAfterChanged;
616                         break;
617
618                 case AFTER_ACTION:
619                         textIndexBeforeChanged = textIndexAfterChanged;
620                         break;
621
622                 case MERGE_ACTION:
623                         textLengthBeforeChanged = -1;
624                         break;
625
626                 case MERGE_AND_AFTER_ACTION:
627                         textIndexBeforeChanged = textIndexAfterChanged;
628                         textLengthBeforeChanged = textLengthAfterChanged;
629                         break;
630
631                 case COLLAPSE_ACTION:
632                         isActionCollapsed = true;
633                         textLengthBeforeChanged = textLengthAfterChanged;
634                         break;
635
636                 case ERROR_ACTION:
637                         return false;
638                 }
639
640                 if (isActionCollapsed)
641                 {
642                         TextSimpleList::DeleteNthObject(__pTextChangeActionList, currentChangeActionEventInfoIndex);
643                         delete pCurrentChangeActionEventInfo;
644                         pCurrentChangeActionEventInfo = null;
645
646                         if (textLengthBeforeChanged == 0)
647                         {
648                                 textLengthBeforeChanged = -1;
649                                 break;
650                         }
651
652                         pCurrentChangeActionEventInfoNode = TextSimpleList::GetNthNode(__pTextChangeActionList,
653                                                                                                                                                                  currentChangeActionEventInfoIndex);
654                         if (pCurrentChangeActionEventInfoNode)
655                         {
656                                 pCurrentChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(pCurrentChangeActionEventInfoNode->pObject);
657                         }
658
659                         continue;
660                 }
661
662                 if (isLineInserted)
663                 {
664                         pChangeActionEventInfo = new (std::nothrow)ChangeActionEventInfo;
665                         SysTryReturn(NID_GRP
666                                 , pChangeActionEventInfo
667                                 , E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
668
669                         pChangeActionEventInfo->action = changeAction;
670                         pChangeActionEventInfo->changedTextIndex = textIndexBeforeChanged;
671                         pChangeActionEventInfo->changedTextLength = textLengthBeforeChanged;
672                         TextSimpleList::InsertObject(__pTextChangeActionList, pChangeActionEventInfo,
673                                                                                                                                                         currentChangeActionEventInfoIndex);
674
675                         textLengthBeforeChanged = -1;
676                         break;
677                 }
678
679                 if (textLengthBeforeChanged < 0)
680                 {
681                         break;
682                 }
683
684                 pCurrentChangeActionEventInfo = null;
685
686                 currentChangeActionEventInfoIndex++;
687                 pCurrentChangeActionEventInfoNode = pCurrentChangeActionEventInfoNode->pNext;
688                 if (pCurrentChangeActionEventInfoNode)
689                 {
690                         pCurrentChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(pCurrentChangeActionEventInfoNode->pObject);
691                 }
692         }
693
694         if (0 <= textLengthBeforeChanged)
695         {
696                 pChangeActionEventInfo = new (std::nothrow)ChangeActionEventInfo;
697                 SysTryReturn(NID_GRP
698                         , pChangeActionEventInfo
699                         , E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
700
701                 pChangeActionEventInfo->action = changeAction;
702                 pChangeActionEventInfo->changedTextIndex = textIndexBeforeChanged;
703                 pChangeActionEventInfo->changedTextLength = textLengthBeforeChanged;
704                 TextSimpleList::AppendObject(__pTextChangeActionList, pChangeActionEventInfo);
705         }
706
707         __setChangeAction = true;
708
709         return E_SUCCESS;
710 }
711
712 int
713 TextColumn::GetChangedStrStartIndex(void) const
714 {
715         SysTryReturn(NID_GRP
716                         , __setChangeAction
717                         , -1, E_INVALID_STATE, "[E_INVALID_STATE] This instance is set change action list yet.");
718
719         ChangeActionEventInfo* pChangeActionEventInfo = null;
720         pChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(TextSimpleList::GetFirstObject(__pTextChangeActionList));
721
722         if (pChangeActionEventInfo == null)
723         {
724                 return -1;
725         }
726
727         return pChangeActionEventInfo->changedTextIndex;
728 }
729
730 result
731 TextColumn::PrepareCompose(void)
732 {
733         __isComposeDone = false;
734         __pCachedLineNode = null;
735
736         if (!__setChangeAction)
737         {
738                 RemoveAllLines();
739                 __currentLineIndexToAddDuringCompose = 0;
740                 __textOffsetOfNextLineAfterChangedLine = -1;
741
742                 return E_SUCCESS;
743         }
744
745         result r = E_SUCCESS;
746         int textChangedStartIndex = 0;
747         int textChangedEndIndex = 0;
748         int textChangedLength = 0;
749         bool hasETCAction = false;
750
751         r = GetTextChangedInfo(textChangedStartIndex, textChangedEndIndex, textChangedLength, hasETCAction);
752         SysTryCatch(NID_GRP
753                 , r == E_SUCCESS
754                 , , r, "[%s] Propagating.", GetErrorMessage(r));
755
756         r = UpdateCompositionInfo(textChangedStartIndex, textChangedEndIndex, textChangedLength, hasETCAction);
757         SysTryCatch(NID_GRP
758                 , r == E_SUCCESS
759                 , , r, "[%s] Propagating.", GetErrorMessage(r));
760
761         if (__changedLastLineIndex != -1)
762         {
763                 SysTryReturn(NID_GRP
764                                 , __changedStartLineIndex != -1
765                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to update information.");
766
767                 int count = __changedLastLineIndex - __changedStartLineIndex + 1;
768
769                 KeepLines( __changedStartLineIndex, count);
770                 RemoveLines(__changedStartLineIndex, count);
771         }
772         else
773         {
774                 if (__changedStartLineIndex == -1)
775                 {
776                         RemoveAllLines();
777                         __currentLineIndexToAddDuringCompose = 0;
778                 }
779                 else
780                 {
781                         KeepLines( __prevLineIndexBeforeChangedStartLine, __totalLineCount - __prevLineIndexBeforeChangedStartLine);
782
783                         RemoveLinesFrom(__changedStartLineIndex);
784                         __changedLastLineIndex = __changedStartLineIndex;
785                 }
786         }
787
788         if (__prevLineIndexBeforeChangedStartLine >= 0)
789         {
790                 __currentLineIndexToAddDuringCompose = __prevLineIndexBeforeChangedStartLine + 1;
791         }
792         else
793         {
794                 __currentLineIndexToAddDuringCompose = 0;
795         }
796
797         return E_SUCCESS;
798
799 CATCH:
800         RemoveAllLines();
801         __currentLineIndexToAddDuringCompose = 0;
802         __textOffsetOfNextLineAfterChangedLine = -1;
803         __nextLineIndexAfterChangedLastLine = -1;
804
805         return r;
806 }
807
808 result
809 TextColumn::AddLineDuringCompose(TextLine* pTextLine)
810 {
811         SysTryReturn(NID_GRP
812                         , pTextLine
813                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
814
815         if (!__setChangeAction)
816         {
817                 SimpleNode* pTextLineNode = TextSimpleList::InsertObject(__pLines, pTextLine, __currentLineIndexToAddDuringCompose);
818                 if (pTextLineNode == null)
819                 {
820                         delete pTextLine;
821                         pTextLine = null;
822
823                         return E_SYSTEM;
824                 }
825
826                 pTextLine->SetIndex(__currentLineIndexToAddDuringCompose);
827                 __currentLineIndexToAddDuringCompose++;
828                 __totalLineCount++;
829
830                 return E_SUCCESS;
831         }
832
833         TextSimpleList::InsertObject(__pLines, pTextLine, __currentLineIndexToAddDuringCompose);
834
835         pTextLine->SetIndex(__currentLineIndexToAddDuringCompose);
836         __currentLineIndexToAddDuringCompose++;
837    __insertedLineCountDuringCompose++;
838         __totalLineCount++;
839
840         if (__textOffsetOfNextLineAfterChangedLine == -1)
841         {
842                 return E_SUCCESS;
843         }
844
845         int lineOffset = pTextLine->GetTextOffset();
846         int lineLength = pTextLine->GetTextLength();
847         int lineEndType = pTextLine->GetEndType();
848
849         if (lineOffset + lineLength == __textOffsetOfNextLineAfterChangedLine)
850         {
851                 TextElementType nextObjectType = __pCompositeText->GetObjectType(__textOffsetOfNextLineAfterChangedLine);
852
853                 if (nextObjectType == TEXT_ELEMENT_TYPE_TEXT || nextObjectType == TEXT_ELEMENT_TYPE_CUTLINK ||
854                         nextObjectType == TEXT_ELEMENT_TYPE_NONE)
855                 {
856                         if (lineEndType == TEXT_RETBY_LINEFEED)
857                         {
858                                 __isComposeDone = true;
859                         }
860                 }
861                 else
862                 {
863                         if (lineEndType == TEXT_RETBY_LINEFEED)
864                         {
865                                 if (lineLength == 0)
866                                 {
867                                         __isComposeDone = true;
868                                 }
869                         }
870                         else
871                         {
872                                 __isComposeDone = true;
873                         }
874                 }
875         }
876
877         return E_SUCCESS;
878 }
879
880 bool
881 TextColumn::IsComposeDone(void)
882 {
883         return __isComposeDone;
884 }
885
886 result
887 TextColumn::FinishCompose(bool isUpdateSweepInfo)
888 {
889         __setChangeAction = false;
890         __isComposeDone = true;
891
892         RemoveAllChangeActions();
893
894         if (__nextLineIndexAfterChangedLastLine < 0)
895         {
896                 if (isUpdateSweepInfo)
897                 {
898                         UpdateSweepInfo();
899                 }
900
901                 RemoveAllKeepLines();
902                 __insertedLineCountDuringCompose = 0;
903
904                 return E_SUCCESS;
905         }
906
907         int changedTextLength = __changedTextLength;
908
909         SimpleNode* pTextLineNode = null;
910         TextLine* pTextLine = null;
911         Rectangle lineBounds;
912
913         if (__currentLineIndexToAddDuringCompose == 0)
914         {
915                 if (isUpdateSweepInfo)
916                 {
917                         UpdateSweepInfo();
918                 }
919
920                 RemoveAllKeepLines();
921                 __insertedLineCountDuringCompose = 0;
922
923                 return E_SUCCESS;
924         }
925
926         pTextLineNode = TextSimpleList::GetNthNode(__pLines, __currentLineIndexToAddDuringCompose - 1);
927         SysTryReturn(NID_GRP
928                 , pTextLineNode
929                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line node.");
930
931         pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
932         SysTryReturn(NID_GRP
933                 , pTextLine
934                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
935
936         lineBounds = pTextLine->GetBounds();
937         int nextLineY = lineBounds.y + lineBounds.height;
938
939         pTextLineNode = TextSimpleList::GetNthNode(__pLines, __currentLineIndexToAddDuringCompose);
940
941         while (pTextLineNode != null)
942         {
943                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
944                 SysTryReturn(NID_GRP
945                         , pTextLine
946                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
947
948                 int lineOffset = pTextLine->GetTextOffset();
949                 lineOffset += changedTextLength;
950                 lineBounds = pTextLine->GetBounds();
951                 lineBounds.y = nextLineY;
952                 nextLineY += lineBounds.height;
953
954                 pTextLine->SetTextOffset(lineOffset);
955                 pTextLine->SetBounds(lineBounds);
956                 pTextLine->SetIndex(__currentLineIndexToAddDuringCompose);
957                 __currentLineIndexToAddDuringCompose++;
958
959                 pTextLineNode = pTextLineNode->pNext;
960         }
961
962         if (isUpdateSweepInfo)
963         {
964                 UpdateSweepInfo();
965         }
966
967         RemoveAllKeepLines();
968         __insertedLineCountDuringCompose = 0;
969
970         return E_SUCCESS;
971 }
972
973 TextLine*
974 TextColumn::GetPrevLineChangedStartLine(void) const
975 {
976         SysTryReturn(NID_GRP
977                         , __setChangeAction
978                         , null, E_INVALID_STATE, "[E_INVALID_STATE] This instance is set change action list yet.");
979
980         if (__prevLineIndexBeforeChangedStartLine < 0)
981         {
982                 return null;
983         }
984
985         TextLine* pTextLine = GetTextLine(__prevLineIndexBeforeChangedStartLine);
986         SysTryReturn(NID_GRP
987                 , pTextLine
988                 , null, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
989
990         SetLastResult(E_SUCCESS);
991
992         return pTextLine;
993 }
994
995 result
996 TextColumn::RemoveLines(int lineIndex, int lineCount)
997 {
998         SysTryReturn(NID_GRP
999                         , 0 <= lineIndex || lineCount <= __totalLineCount
1000                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1001
1002         SimpleNode* pNextTextLineNode = null;
1003         SimpleNode* pTextLineNode = null;
1004         TextLine* pTextLine = null;
1005         int count = 0;
1006
1007         pTextLineNode = TextSimpleList::GetNthNode(__pLines, lineIndex);
1008
1009         while ((pTextLineNode != null) && (count < lineCount))
1010         {
1011                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1012                 pNextTextLineNode = pTextLineNode->pNext;
1013
1014                 TextSimpleList::DeleteNode(__pLines, pTextLineNode);
1015
1016                 if (pTextLine != null)
1017                 {
1018                         delete pTextLine;
1019                         pTextLine = null;
1020                 }
1021
1022                 count++;
1023                 pTextLineNode = pNextTextLineNode;
1024         }
1025
1026         __totalLineCount -= count;
1027
1028         return E_SUCCESS;
1029 }
1030
1031 int
1032 TextColumn::GetChangeActionEventCount(void) const
1033 {
1034         return __pTextChangeActionList->nodeCount;
1035 }
1036
1037 result
1038 TextColumn::RemoveLinesFrom(int lineIndex)
1039 {
1040         SysTryReturn(NID_GRP
1041                         , 0 <= lineIndex
1042                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1043
1044         TextLine* pTextLine = null;
1045         int count = 0;
1046
1047         pTextLine = static_cast < TextLine* >(TextSimpleList::DeleteNthObject(__pLines, lineIndex));
1048         while (pTextLine)
1049         {
1050                 delete pTextLine;
1051                 pTextLine = static_cast < TextLine* >(TextSimpleList::DeleteNthObject(__pLines, lineIndex));
1052                 count++;
1053         }
1054
1055         __totalLineCount -= count;
1056
1057         return E_SUCCESS;
1058 }
1059
1060 void
1061 TextColumn::RemoveAllChangeActions(void)
1062 {
1063         ChangeActionEventInfo* pChangeActionEventInfo = null;
1064
1065         pChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(TextSimpleList::DeleteNthObject(__pTextChangeActionList, 0));
1066         while (pChangeActionEventInfo)
1067         {
1068                 delete pChangeActionEventInfo;
1069                 pChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(TextSimpleList::DeleteNthObject(__pTextChangeActionList, 0));
1070         }
1071 }
1072
1073 result
1074 TextColumn::GetTextChangedInfo(int& changedStartTextIndex, int& changedEndTextIndex, int& changedTextLength,
1075                                                                                                                 bool& existUnkownAction) const
1076 {
1077         SimpleNode* pChangeActionEventNode = null;
1078         ChangeActionEventInfo* pChangeActionEventInfo = null;
1079
1080         pChangeActionEventNode = TextSimpleList::GetFirstNode(__pTextChangeActionList);
1081         SysTryReturn(NID_GRP
1082                 , pChangeActionEventNode
1083                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get change action event information node.");
1084
1085         pChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(pChangeActionEventNode->pObject);
1086         SysTryReturn(NID_GRP
1087                 , pChangeActionEventInfo
1088                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get change action event information.");
1089
1090         changedTextLength = 0;
1091         changedStartTextIndex = -1;
1092         changedEndTextIndex = -1;
1093         existUnkownAction = false;
1094
1095         while (pChangeActionEventInfo)
1096         {
1097                 switch (pChangeActionEventInfo->action)
1098                 {
1099                 case TEXT_CHANGE_INSERT:
1100                         if (changedStartTextIndex == -1)
1101                         {
1102                                 changedStartTextIndex = pChangeActionEventInfo->changedTextIndex;
1103                         }
1104                         changedTextLength += pChangeActionEventInfo->changedTextLength;
1105                         changedEndTextIndex = pChangeActionEventInfo->changedTextIndex;
1106                         break;
1107
1108                 case TEXT_CHANGE_REMOVE:
1109                         if (changedStartTextIndex == -1)
1110                         {
1111                                 changedStartTextIndex = pChangeActionEventInfo->changedTextIndex;
1112                         }
1113                         changedTextLength -= pChangeActionEventInfo->changedTextLength;
1114                         changedEndTextIndex = pChangeActionEventInfo->changedTextIndex + pChangeActionEventInfo->changedTextLength;
1115                         break;
1116
1117                 case TEXT_CHANGE_UNKONWN:
1118                         existUnkownAction = true;
1119                         if (changedStartTextIndex == -1)
1120                         {
1121                                 changedStartTextIndex = pChangeActionEventInfo->changedTextIndex;
1122                         }
1123                         break;
1124
1125                 default:
1126                         // fall through
1127                         return E_SYSTEM;
1128                 }
1129
1130                 pChangeActionEventNode = pChangeActionEventNode->pNext;
1131                 if (pChangeActionEventNode == null)
1132                 {
1133                         break;
1134                 }
1135
1136                 pChangeActionEventInfo = static_cast < ChangeActionEventInfo* >(pChangeActionEventNode->pObject);
1137         }
1138
1139         return E_SUCCESS;
1140 }
1141
1142 result
1143 TextColumn::UpdateCompositionInfo(int changedStartTextIndex, int changedEndTextIndex, int changedTextLength,
1144                                                                                  bool existUnkownAction)
1145 {
1146         __chagedStartTextIndex = changedStartTextIndex;
1147         __changedTextLength = changedTextLength;
1148
1149         int firstChangedLineIndex = GetLineIndexAtTextIndex(__chagedStartTextIndex);
1150         if (firstChangedLineIndex == -1)
1151         {
1152                 if (__chagedStartTextIndex + __changedTextLength >= __pCompositeText->GetTextLength())
1153                 {
1154                         firstChangedLineIndex = __totalLineCount - 1;
1155                 }
1156                 else
1157                 {
1158                         firstChangedLineIndex = -1;
1159                 }
1160         }
1161
1162         __changedStartLineIndex = firstChangedLineIndex;
1163
1164         if (__changedStartLineIndex == -1)
1165         {
1166                 __nextLineIndexAfterChangedLastLine = -1;
1167                 __textOffsetOfNextLineAfterChangedLine = -1;
1168                 __changedLastLineIndex = -1;
1169                 __prevLineIndexBeforeChangedStartLine = -1;
1170                 return E_SUCCESS;
1171         }
1172
1173         __prevLineIndexBeforeChangedStartLine = __changedStartLineIndex - 1;
1174
1175         if (__changedStartLineIndex == __totalLineCount - 1)
1176         {
1177                 __nextLineIndexAfterChangedLastLine = -1;
1178                 __textOffsetOfNextLineAfterChangedLine = -1;
1179                 __changedLastLineIndex = -1;
1180                 return E_SUCCESS;
1181         }
1182
1183         if (existUnkownAction)
1184         {
1185                 __changedLastLineIndex = __totalLineCount - 1;
1186                 __nextLineIndexAfterChangedLastLine = -1;
1187                 __textOffsetOfNextLineAfterChangedLine = -1;
1188                 return E_SUCCESS;
1189         }
1190
1191         int lastChangedLineIndex = GetLineIndexAtTextIndex(changedEndTextIndex);
1192         if (lastChangedLineIndex == -1)
1193         {
1194                 __changedLastLineIndex = __totalLineCount - 1;
1195                 __nextLineIndexAfterChangedLastLine = -1;
1196                 __textOffsetOfNextLineAfterChangedLine = -1;
1197                 return E_SUCCESS;
1198         }
1199
1200         int nextLineIndexAfterChangedLineCandidate = lastChangedLineIndex;
1201
1202         __nextLineIndexAfterChangedLastLine = -1;
1203
1204         SimpleNode* pTextLineNode = null;
1205         TextLine* pTextLine = null;
1206
1207         pTextLineNode = TextSimpleList::GetNthNode(__pLines, nextLineIndexAfterChangedLineCandidate);
1208         while (pTextLineNode)
1209         {
1210                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1211                 SysTryReturn(NID_GRP
1212                         , pTextLine
1213                         , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
1214
1215                 int lineEndType = pTextLine->GetEndType();
1216                 if ((lineEndType == TEXT_RETBY_LINEFEED) && (pTextLine->GetTextLength() != 0))
1217                 {
1218                         pTextLineNode = pTextLineNode->pNext;
1219                         if (pTextLineNode == null)
1220                         {
1221                                 break;
1222                         }
1223
1224                         pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1225                         SysTryReturn(NID_GRP
1226                                 , pTextLine
1227                                 , E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fail to get text line.");
1228
1229                         __nextLineIndexAfterChangedLastLine = nextLineIndexAfterChangedLineCandidate + 1;
1230                         break;
1231                 }
1232
1233                 pTextLineNode = pTextLineNode->pNext;
1234                 nextLineIndexAfterChangedLineCandidate++;
1235         }
1236
1237         if (__nextLineIndexAfterChangedLastLine > 0)
1238         {
1239                 __textOffsetOfNextLineAfterChangedLine = pTextLine->GetTextOffset();
1240                 __textOffsetOfNextLineAfterChangedLine += __changedTextLength;
1241                 __changedLastLineIndex = __nextLineIndexAfterChangedLastLine - 1;
1242         }
1243         else
1244         {
1245                 __textOffsetOfNextLineAfterChangedLine = -1;
1246                 __changedLastLineIndex = __totalLineCount - 1;
1247         }
1248
1249         return E_SUCCESS;
1250 }
1251
1252 TextColumn::ActionProcessResult
1253 TextColumn::DoProcessTextAction(ChangeAction inputAction, int textIndex, int textLength,
1254                                                                   ChangeActionEventInfo* pCurrentStrActionEventInfo, int& changedStartTextIndex,
1255                                                                   int& strOutputChangedNum)
1256 {
1257         switch (inputAction)
1258         {
1259         case TextColumn::TEXT_CHANGE_INSERT:
1260         {
1261                 switch (pCurrentStrActionEventInfo->action)
1262                 {
1263                 case TextColumn::TEXT_CHANGE_INSERT:
1264                         return DoProcessInsertThroughInsert(textIndex, textLength, pCurrentStrActionEventInfo,
1265                                                                                                   changedStartTextIndex);
1266
1267                 case TextColumn::TEXT_CHANGE_REMOVE:
1268                         return DoProcessInsertThroughRemove(textIndex, pCurrentStrActionEventInfo, changedStartTextIndex);
1269
1270                 case TextColumn::TEXT_CHANGE_UNKONWN:
1271                         changedStartTextIndex = textIndex;
1272                         return DoProcessInsertThroughUnkown(textIndex, pCurrentStrActionEventInfo);
1273
1274                 default:
1275                         break;
1276                 }
1277         }
1278         break;
1279
1280         case TextColumn::TEXT_CHANGE_REMOVE:
1281         {
1282                 switch (pCurrentStrActionEventInfo->action)
1283                 {
1284                 case TextColumn::TEXT_CHANGE_INSERT:
1285                         return DoProcessRemoveThroughInsert(textIndex, textLength, pCurrentStrActionEventInfo,
1286                                                                                                   changedStartTextIndex, strOutputChangedNum);
1287
1288                 case TextColumn::TEXT_CHANGE_REMOVE:
1289                         return DoProcessRemoveThroughRemove(textIndex, pCurrentStrActionEventInfo, changedStartTextIndex);
1290
1291                 case TextColumn::TEXT_CHANGE_UNKONWN:
1292                         changedStartTextIndex = textIndex;
1293                         return DoProcessRemoveThroughUnkown(textIndex, pCurrentStrActionEventInfo);
1294
1295                 default:
1296                         break;
1297                 }
1298         }
1299         break;
1300
1301         case TextColumn::TEXT_CHANGE_UNKONWN:
1302         {
1303                 switch (pCurrentStrActionEventInfo->action)
1304                 {
1305                 case TextColumn::TEXT_CHANGE_INSERT:
1306                         return DoProcessUnkownThroughInsert(textIndex, pCurrentStrActionEventInfo, changedStartTextIndex);
1307
1308                 case TextColumn::TEXT_CHANGE_REMOVE:
1309                         return DoProcessUnkownThroughRemove(textIndex, pCurrentStrActionEventInfo, changedStartTextIndex);
1310
1311                 case TextColumn::TEXT_CHANGE_UNKONWN:
1312                         changedStartTextIndex = textIndex;
1313                         return DoProcessUnknownThroughUnknown(textIndex, pCurrentStrActionEventInfo);
1314
1315                 default:
1316                         break;
1317                 }
1318         }
1319         break;
1320
1321         default:
1322                 break;
1323         }
1324
1325         return ERROR_ACTION;
1326 }
1327
1328 TextColumn::ActionProcessResult
1329 TextColumn::DoProcessUnknownThroughUnknown(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo)
1330 {
1331         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1332         {
1333                 return BEFORE_ACTION;
1334         }
1335         else if (textIndex == pCurrentActionEventInfo->changedTextIndex)
1336         {
1337                 return MERGE_ACTION;
1338         }
1339         else
1340         {
1341                 return AFTER_ACTION;
1342         }
1343 }
1344
1345 TextColumn::ActionProcessResult
1346 TextColumn::DoProcessUnkownThroughInsert(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo,
1347                                                                                  int& changedStartTextIndex)
1348 {
1349         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1350         {
1351                 changedStartTextIndex = textIndex;
1352                 return BEFORE_ACTION;
1353         }
1354
1355         if (textIndex < pCurrentActionEventInfo->changedTextIndex + pCurrentActionEventInfo->changedTextLength)
1356         {
1357                 changedStartTextIndex = pCurrentActionEventInfo->changedTextIndex;
1358                 return BEFORE_ACTION;
1359         }
1360
1361         changedStartTextIndex = textIndex - pCurrentActionEventInfo->changedTextLength;
1362         return AFTER_ACTION;
1363 }
1364
1365 TextColumn::ActionProcessResult
1366 TextColumn::DoProcessUnkownThroughRemove(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo,
1367                                                                                  int& changedStartTextIndex)
1368 {
1369         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1370         {
1371                 changedStartTextIndex = textIndex;
1372                 return BEFORE_ACTION;
1373         }
1374
1375         changedStartTextIndex = textIndex + pCurrentActionEventInfo->changedTextLength;
1376         return AFTER_ACTION;
1377 }
1378
1379 TextColumn::ActionProcessResult
1380 TextColumn::DoProcessInsertThroughUnkown(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo)
1381 {
1382         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1383         {
1384                 return BEFORE_ACTION;
1385         }
1386
1387         return AFTER_ACTION;
1388 }
1389
1390 TextColumn::ActionProcessResult
1391 TextColumn::DoProcessInsertThroughInsert(int textIndex, int textLength, ChangeActionEventInfo* pCurrentActionEventInfo,
1392                                                                                         int& changedStartTextIndex)
1393 {
1394         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1395         {
1396                 return BEFORE_ACTION;
1397         }
1398
1399         if (textIndex <= pCurrentActionEventInfo->changedTextIndex + pCurrentActionEventInfo->changedTextLength)
1400         {
1401                 pCurrentActionEventInfo->changedTextLength += textLength;
1402                 return MERGE_ACTION;
1403         }
1404
1405         changedStartTextIndex = textIndex - pCurrentActionEventInfo->changedTextLength;
1406         return AFTER_ACTION;
1407 }
1408
1409 TextColumn::ActionProcessResult
1410 TextColumn::DoProcessInsertThroughRemove(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo,
1411                                                                                         int& changedStartTextIndex)
1412 {
1413         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1414         {
1415                 return BEFORE_ACTION;
1416         }
1417
1418         changedStartTextIndex = textIndex + pCurrentActionEventInfo->changedTextLength;
1419         return AFTER_ACTION;
1420 }
1421
1422 TextColumn::ActionProcessResult
1423 TextColumn::DoProcessRemoveThroughUnkown(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo)
1424 {
1425         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1426         {
1427                 return BEFORE_ACTION;
1428         }
1429
1430         return AFTER_ACTION;
1431 }
1432
1433 TextColumn::ActionProcessResult
1434 TextColumn::DoProcessRemoveThroughInsert(int textIndex, int textLength,
1435                                                                                         ChangeActionEventInfo* pCurrentActionEventInfo, int& changedStartTextIndex,
1436                                                                                         int& strOutputChangedNum)
1437 {
1438         if (textIndex + textLength <= pCurrentActionEventInfo->changedTextIndex)
1439         {
1440                 return BEFORE_ACTION;
1441         }
1442
1443         if (textIndex >= pCurrentActionEventInfo->changedTextIndex + pCurrentActionEventInfo->changedTextLength)
1444         {
1445                 changedStartTextIndex = textIndex - pCurrentActionEventInfo->changedTextLength;
1446
1447                 return AFTER_ACTION;
1448         }
1449
1450         if ((textIndex <= pCurrentActionEventInfo->changedTextIndex) &&
1451                 (textIndex + textLength >= pCurrentActionEventInfo->changedTextIndex +
1452                                 pCurrentActionEventInfo->changedTextLength))
1453         {
1454                 changedStartTextIndex = textIndex;
1455                 strOutputChangedNum = textLength - pCurrentActionEventInfo->changedTextLength;
1456
1457                 return COLLAPSE_ACTION;
1458         }
1459
1460         if ((textIndex >= pCurrentActionEventInfo->changedTextIndex) &&
1461                 (textIndex + textLength <= pCurrentActionEventInfo->changedTextIndex +
1462                                 pCurrentActionEventInfo->changedTextLength))
1463         {
1464                 pCurrentActionEventInfo->changedTextLength -= textLength;
1465                 return MERGE_ACTION;
1466         }
1467
1468         if ((textIndex < pCurrentActionEventInfo->changedTextIndex) &&
1469                 (textIndex + textLength > pCurrentActionEventInfo->changedTextIndex))
1470         {
1471                 int mergedLength = textIndex + textLength - pCurrentActionEventInfo->changedTextIndex;
1472                 pCurrentActionEventInfo->changedTextLength -= mergedLength;
1473                 strOutputChangedNum -= mergedLength;
1474                 return MERGE_AND_BEFORE_ACTION;
1475         }
1476
1477         if ((textIndex >= pCurrentActionEventInfo->changedTextIndex) &&
1478                 (textIndex < pCurrentActionEventInfo->changedTextIndex + pCurrentActionEventInfo->changedTextLength))
1479         {
1480                 int mergedLength = pCurrentActionEventInfo->changedTextIndex + pCurrentActionEventInfo->changedTextLength
1481                                                                                                 - textIndex;
1482                 pCurrentActionEventInfo->changedTextLength -= mergedLength;
1483                 changedStartTextIndex = textIndex + 1;
1484                 strOutputChangedNum -= mergedLength;
1485                 return MERGE_AND_AFTER_ACTION;
1486         }
1487
1488         return ERROR_ACTION;
1489 }
1490
1491 TextColumn::ActionProcessResult
1492 TextColumn::DoProcessRemoveThroughRemove(int textIndex, ChangeActionEventInfo* pCurrentActionEventInfo,
1493                                                                                         int& changedStartTextIndex)
1494 {
1495         if (textIndex < pCurrentActionEventInfo->changedTextIndex)
1496         {
1497                 return BEFORE_ACTION;
1498         }
1499
1500         changedStartTextIndex += pCurrentActionEventInfo->changedTextLength;
1501         return AFTER_ACTION;
1502 }
1503
1504 int
1505 TextColumn::GetTotalLineCount(void) const
1506 {
1507         return __totalLineCount;
1508 }
1509
1510 int
1511 TextColumn::GetDisplayLineCount(void) const
1512 {
1513         return __displayLineCount;
1514 }
1515
1516 void
1517 TextColumn::SetDisplayLineCount(int displayLineCount)
1518 {
1519         __displayLineCount = displayLineCount;
1520 }
1521
1522 void
1523 TextColumn::SetFirstDisplayLineIndex(int lineIndex)
1524 {
1525         __firstDisplayLineIndex = lineIndex;
1526 }
1527
1528 int
1529 TextColumn::GetFirstDisplayLineIndex(void) const
1530 {
1531         return __firstDisplayLineIndex;
1532 }
1533
1534 void
1535 TextColumn::SetFirstDisplayPositionY(int y)
1536 {
1537         __firstDisplayPositionY = y;
1538 }
1539
1540 int
1541 TextColumn::GetFirstDisplayPositionY(void) const
1542 {
1543         return __firstDisplayPositionY;
1544 }
1545
1546 void
1547 TextColumn::SetDisplayHeight(int height)
1548 {
1549         __displayHeight = height;
1550 }
1551
1552 int
1553 TextColumn::GetDisplayHeight(void) const
1554 {
1555         return __displayHeight;
1556 }
1557
1558 SimpleNode*
1559 TextColumn::GetTextLineNode(int lineIndex) const
1560 {
1561         return TextSimpleList::GetNthNode(__pLines, lineIndex);
1562 }
1563
1564 result
1565 TextColumn::SetSlidingDimension(Dimension& slidingDimension)
1566 {
1567         SysTryReturn(NID_GRP
1568                         , slidingDimension.width >= 0 && slidingDimension.height >=0
1569                         , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1570
1571         __slidingDimension = slidingDimension;
1572
1573         return E_SUCCESS;
1574 }
1575
1576 Dimension
1577 TextColumn::GetSlidingDimension(void) const
1578 {
1579         return __slidingDimension;
1580 }
1581
1582 void
1583 TextColumn::SetSlidingPosition(int slidingPosition)
1584 {
1585         __slidingPosition = slidingPosition;
1586 }
1587
1588 int
1589 TextColumn::GetSlidingPosition(void) const
1590 {
1591         return __slidingPosition;
1592 }
1593
1594 void
1595 TextColumn::SetChangedStartLineIndex(int changedStartLineIndex)
1596 {
1597         __changedStartLineIndex = changedStartLineIndex;
1598 }
1599
1600 int
1601 TextColumn::GetChangedStartLineIndex(void) const
1602 {
1603         return __changedStartLineIndex;
1604 }
1605
1606 void
1607 TextColumn::SetChangedLastLineIndex(int changedLastLineIndex)
1608 {
1609         __changedLastLineIndex = changedLastLineIndex;
1610 }
1611
1612 int
1613 TextColumn::GetChangedLastLineIndex(void) const
1614 {
1615         return __changedLastLineIndex;
1616 }
1617
1618 int
1619 TextColumn::ForwardAnalyze(int startTextIndex, int textLength, int maxWidth, TextObjectWrapType wrap,
1620                                                                         int& actualLength, int& width, int& height)
1621 {
1622         return -1;
1623 }
1624
1625 result
1626 TextColumn::RemoveAllKeepLines(void)
1627 {
1628         SysTryReturn(NID_GRP
1629                         , __pKeepLines
1630                         , E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] This instance is not constructed yet.");
1631
1632         TextLine* pTextLine = null;
1633
1634         while (1)
1635         {
1636                 pTextLine = static_cast < TextLine* >(TextSimpleList::DeleteNthObject(__pKeepLines, 0));
1637                 if (pTextLine == null)
1638                 {
1639                         break;
1640                 }
1641
1642                 delete pTextLine;
1643                 pTextLine = null;
1644         }
1645
1646         __keepLineCount = 0;
1647
1648         return E_SUCCESS;
1649 }
1650
1651 result
1652 TextColumn::UpdateSweepInfoFirstLine(void)
1653 {
1654         TextObjectSweepInfo textSweepInfo;
1655         __pCompositeText->GetTextSweepInfo(textSweepInfo);
1656
1657         Dimension lineSize;
1658         int width = 0;
1659         SimpleNode* pTextLineNode = null;
1660         TextLine* pTextLine;
1661         int sweepLineCount = 0;
1662         int     insertedLineCount = 0;
1663
1664         pTextLineNode = TextSimpleList::GetFirstNode(__pLines);
1665
1666         while (pTextLineNode != null)
1667         {
1668                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1669                 pTextLine->GetRegion(0, pTextLine->GetTextLength(), lineSize.width, lineSize.height);
1670                 width += lineSize.width;
1671                 sweepLineCount++;
1672                 insertedLineCount++;
1673
1674                 pTextLineNode  = pTextLineNode->pNext;
1675         }
1676
1677         textSweepInfo.isValid = true;
1678         textSweepInfo.sweepType = ((1 < sweepLineCount) ? TEXT_OBJECT_SWEEP_TYPE_FORWARD : TEXT_OBJECT_SWEEP_TYPE_KEYINPUT);
1679         textSweepInfo.anchorLineIndex = 0;
1680         textSweepInfo.sweepRegionStartLineIndex = 0;
1681         textSweepInfo.sweepRegionLineCount = sweepLineCount;
1682         textSweepInfo.widthChanged = width;
1683         textSweepInfo.insertedLineCount = insertedLineCount;
1684         textSweepInfo.deletedLineCount = 0;
1685
1686         __pCompositeText->UpdateTextSweepInfo(&textSweepInfo);
1687
1688         return true;
1689 }
1690
1691 result
1692 TextColumn::UpdateSweepInfo(void)
1693 {
1694         if (TextSimpleList::IsEmpty(__pKeepLines))
1695         {
1696                 return UpdateSweepInfoFirstLine();
1697         }
1698
1699         TextObjectSweepInfo textSweepInfo;
1700         __pCompositeText->GetTextSweepInfo(textSweepInfo);
1701
1702         SimpleNode*     pOldTextLineNode = null;
1703         SimpleNode*     pNewTextLineNode = null;
1704         TextLine*       pOldTextLine = null;
1705         TextLine*       pNewTextLine = null;
1706         Dimension oldLineSize;
1707         Dimension newLineSize;
1708         int oldLineWidth        = 0;
1709         int     newLineWidth = 0;
1710         int sweepLineCount = 0;
1711         int changedStartLineIndex = 0;
1712         int insertedLineCount = 0;
1713         int deleteLineCount = 0;
1714
1715         int anchorLineIndex = GetLineIndexAtTextIndex(textSweepInfo.anchorTextIndex);
1716         if (anchorLineIndex == -1)
1717         {
1718                 anchorLineIndex = GetTotalLineCount() - 1;
1719         }
1720
1721         int     widthChanged = 0;
1722         TextObjectSweepType     sweepType = TEXT_OBJECT_SWEEP_TYPE_INVALID;
1723
1724         pOldTextLineNode  = TextSimpleList::GetFirstNode(__pKeepLines);
1725         if (pOldTextLineNode == null)
1726         {
1727                 return E_SUCCESS;
1728         }
1729
1730         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
1731         changedStartLineIndex   = pOldTextLine->GetIndex();
1732         pNewTextLineNode = TextSimpleList::GetNthNode(__pLines, changedStartLineIndex);
1733
1734         while (pOldTextLineNode || pNewTextLineNode)
1735         {
1736                 TextObjectSweepComposeLineInfo textSweepComposeLineInfo;
1737
1738                 if (pOldTextLineNode == null)
1739                 {
1740                         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
1741
1742                         if (pNewTextLine->GetIndex() >= changedStartLineIndex + __insertedLineCountDuringCompose)
1743                         {
1744                                 break;
1745                         }
1746
1747                         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
1748
1749                         newLineWidth += newLineSize.width;
1750                         sweepLineCount++;
1751                         insertedLineCount++;
1752
1753                         textSweepComposeLineInfo.isValid = true;
1754                         textSweepComposeLineInfo.prevLineTextOffset = 0;
1755                         textSweepComposeLineInfo.prevLineTextLength = 0;
1756                         textSweepComposeLineInfo.prevLineWidth = 0;
1757                         textSweepComposeLineInfo.currentLineTextOffset = pNewTextLine->GetTextOffset();
1758                         textSweepComposeLineInfo.currentLineTextLength = pNewTextLine->GetTextLength();
1759                         textSweepComposeLineInfo.currentLineWidth = newLineSize.width;
1760
1761                         pNewTextLine->SetSweepComposeInfo(textSweepComposeLineInfo);
1762
1763                         sweepType = TEXT_OBJECT_SWEEP_TYPE_FORWARD;
1764
1765                         pNewTextLineNode  = pNewTextLineNode->pNext;
1766                 }
1767                 else if (pNewTextLineNode == null)
1768                 {
1769                         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
1770                         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
1771
1772                         oldLineWidth += oldLineSize.width;
1773                         sweepLineCount++;
1774                         deleteLineCount++;
1775                         sweepType = TEXT_OBJECT_SWEEP_TYPE_BACKWARD;
1776
1777                         pOldTextLineNode  = pOldTextLineNode->pNext;
1778                 }
1779                 else
1780                 {
1781                         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
1782                         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
1783
1784                         if (pNewTextLine->GetIndex() > changedStartLineIndex + __insertedLineCountDuringCompose)
1785                         {
1786                                 pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
1787
1788                                 oldLineWidth += oldLineSize.width;
1789                                 sweepLineCount++;
1790
1791                                 sweepType = TEXT_OBJECT_SWEEP_TYPE_BACKWARD;
1792
1793                                 pOldTextLineNode = pOldTextLineNode->pNext;
1794                                 pNewTextLineNode = pNewTextLineNode->pNext;
1795
1796                                 continue;
1797                         }
1798
1799                         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
1800                         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
1801
1802                         if ((oldLineSize.width == newLineSize.width) && (pOldTextLine->GetTextLength() == pNewTextLine->GetTextLength()))
1803                         {
1804                                 if (pNewTextLine->GetIndex() == changedStartLineIndex)
1805                                 {
1806                                         changedStartLineIndex++;
1807                                 }
1808                                 else
1809                                 {
1810                                         break;
1811                                 }
1812                         }
1813                         else
1814                         {
1815                                 oldLineWidth += oldLineSize.width;
1816                                 newLineWidth += newLineSize.width;
1817                                 sweepLineCount++;
1818
1819                                 textSweepComposeLineInfo.isValid = true;
1820                                 textSweepComposeLineInfo.prevLineTextOffset = pOldTextLine->GetTextOffset();
1821                                 textSweepComposeLineInfo.prevLineTextLength = pOldTextLine->GetTextLength();
1822                                 textSweepComposeLineInfo.prevLineWidth = oldLineSize.width;
1823                                 textSweepComposeLineInfo.currentLineTextOffset = pNewTextLine->GetTextOffset();
1824                                 textSweepComposeLineInfo.currentLineTextLength = pNewTextLine->GetTextLength();
1825                                 textSweepComposeLineInfo.currentLineWidth = newLineSize.width;
1826                                 pNewTextLine->SetSweepComposeInfo(textSweepComposeLineInfo);
1827                         }
1828
1829                         pOldTextLineNode  = pOldTextLineNode->pNext;
1830                         pNewTextLineNode  = pNewTextLineNode->pNext;
1831                 }
1832         }
1833
1834         widthChanged = newLineWidth - oldLineWidth;
1835
1836         if (sweepLineCount == 1)
1837         {
1838                 sweepType = TEXT_OBJECT_SWEEP_TYPE_KEYINPUT;
1839         }
1840
1841         if (sweepType == TEXT_OBJECT_SWEEP_TYPE_INVALID)
1842         {
1843                 sweepType = ((oldLineSize.width < newLineSize.width) ? TEXT_OBJECT_SWEEP_TYPE_FORWARD : TEXT_OBJECT_SWEEP_TYPE_BACKWARD);
1844         }
1845
1846         if (anchorLineIndex == -1)
1847         {
1848                 anchorLineIndex = pNewTextLine->GetIndex();
1849         }
1850
1851         textSweepInfo.isValid = true;
1852         textSweepInfo.sweepType = sweepType;
1853         textSweepInfo.anchorLineIndex = anchorLineIndex;
1854         textSweepInfo.sweepRegionStartLineIndex = changedStartLineIndex;
1855         textSweepInfo.sweepRegionLineCount = sweepLineCount;
1856         textSweepInfo.widthChanged = widthChanged;
1857         textSweepInfo.insertedLineCount = insertedLineCount;
1858         textSweepInfo.deletedLineCount = deleteLineCount;
1859
1860         __pCompositeText->UpdateTextSweepInfo(&textSweepInfo);
1861
1862         return true;
1863 }
1864
1865 result
1866 TextColumn::KeepLines(int lineIndex, int lineCount)
1867 {
1868         SimpleNode* pTextLineNode = null;
1869         SimpleNode* pNextTextLineNode = null;
1870         TextLine* pTextLine = null;
1871         TextLine* pKeepTextLine = null;
1872         int deletedLineCount = 0;
1873
1874         if (lineIndex < 0)
1875         {
1876                 lineIndex = 0;
1877                 lineCount--;
1878         }
1879
1880         pTextLineNode = TextSimpleList::GetNthNode(__pLines, lineIndex);
1881
1882         while ((pTextLineNode != null) && (deletedLineCount < lineCount))
1883         {
1884                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1885                 pKeepTextLine = pTextLine->CopyN();
1886
1887                 pNextTextLineNode = pTextLineNode->pNext;
1888
1889                 TextSimpleList::AppendObject(__pKeepLines, pKeepTextLine);
1890
1891                 deletedLineCount++;
1892
1893                 pTextLineNode = pNextTextLineNode;
1894         }
1895
1896         __keepLineCount += deletedLineCount;
1897
1898         return E_SUCCESS;
1899 }
1900
1901 result
1902 TextColumn::SetKeyInputLine(int changedStartlineIndex, int lineCount)
1903 {
1904         int keyInputTextIndex = 0;
1905         int keyInputTextLength = 0;
1906
1907         SimpleNode* pTextLineNode = null;
1908         TextLine* pTextLine = null;
1909         int changedLineCount = lineCount;
1910
1911         __pCompositeText->GetRange(keyInputTextIndex, keyInputTextLength);
1912
1913         pTextLineNode = TextSimpleList::GetNthNode(__pLines, changedStartlineIndex);
1914         while (pTextLineNode != null && changedLineCount)
1915         {
1916                 pTextLine = static_cast < TextLine* >(pTextLineNode->pObject);
1917
1918                 if (pTextLine->GetTextOffset() <= keyInputTextIndex && keyInputTextIndex < pTextLine->GetTextOffset() + pTextLine->GetTextLength())
1919                 {
1920                         pTextLine->NotifyLineChanged(true);
1921                         pTextLine->SetKeyInputOffset(keyInputTextIndex - pTextLine->GetTextOffset());
1922                         pTextLine->SetKeyInputLength(keyInputTextLength);
1923
1924                         break;
1925                 }
1926
1927                 changedLineCount--;
1928
1929                 pTextLineNode = pTextLineNode->pNext;
1930         }
1931
1932         return E_SUCCESS;
1933 }
1934
1935 result
1936 TextColumn::CompareDeletedLine(void)
1937 {
1938         result r = E_SUCCESS;
1939
1940         SimpleNode* pOldTextLineNode = null;
1941         SimpleNode* pNewTextLineNode = null;
1942         TextLine* pOldTextLine = null;
1943         TextLine* pNewTextLine = null;
1944
1945         Dimension newLineSize;
1946         Dimension oldLineSize;
1947         int sweepResult = 0;
1948         int sweepIn = 0;
1949         int sweepOut = 0;
1950         int prevLineSweepIn = 0;
1951         int prevLineSweepOut = 0;
1952         int changedStartLineIndex = 0;
1953         int keyInputWidth = 0;
1954
1955         if (TextSimpleList::GetCount(__pKeepLines) == 0)
1956         {
1957                 return E_SUCCESS; // E_SUCCESS right??
1958         }
1959
1960         keyInputWidth = __pCompositeText->GetWorkWidth();
1961         pOldTextLineNode  = TextSimpleList::GetFirstNode(__pKeepLines);
1962         SysTryReturn(NID_GRP
1963                         , pOldTextLineNode
1964                         , E_SYSTEM, E_SYSTEM
1965                         , "[E_SYSTEM] Fail to get text line node.");
1966
1967         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
1968         changedStartLineIndex = pOldTextLine->GetIndex();
1969         pNewTextLineNode = TextSimpleList::GetNthNode(__pLines, changedStartLineIndex);
1970         SysTryReturn(NID_GRP
1971                         , pNewTextLineNode
1972                         , E_INVALID_STATE, E_INVALID_STATE
1973                         , "[E_INVALID_STATE] This instance is not constructed yet. changedStartLineIndex = %d", changedStartLineIndex);
1974
1975         r = SetKeyInputLine(changedStartLineIndex, TextSimpleList::GetCount(__pLines) - changedStartLineIndex);
1976         SysTryReturn(NID_GRP
1977                 , r == E_SUCCESS
1978                 , r, r, "[%s] Propagating.", GetErrorMessage(r));
1979
1980         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
1981         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
1982
1983         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
1984         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
1985
1986
1987         if (oldLineSize.width == newLineSize.width)
1988         {
1989                 sweepResult = NOT_CHANGED;
1990
1991                 pNewTextLine->SetKeyInputResult(sweepResult);
1992                 pNewTextLine->SetSweepIn(0);
1993                 pNewTextLine->SetSweepOut(0);
1994
1995                 pOldTextLineNode = pOldTextLineNode->pNext;
1996                 pNewTextLineNode = pNewTextLineNode->pNext;
1997
1998                 if (pOldTextLineNode && pNewTextLineNode)
1999                 {
2000
2001                         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
2002                         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
2003
2004                         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
2005                         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
2006
2007                         if (0 < keyInputWidth)
2008                         {
2009                                 sweepResult = FORWARD_SWEEP;
2010
2011                                 sweepIn = 0;
2012                                 sweepOut = oldLineSize.width - newLineSize.width;
2013                                 if (pNewTextLine->isChanged())
2014                                 {
2015                                         sweepOut += keyInputWidth;
2016                                 }
2017
2018                                 pNewTextLine->SetKeyInputResult(sweepResult);
2019                                 pNewTextLine->SetSweepIn(sweepIn);
2020                                 pNewTextLine->SetSweepOut(sweepOut);
2021                         }
2022                         else
2023                         {
2024                                 sweepResult = BACKWARD_SWEEP;
2025
2026                                 sweepIn = newLineSize.width - oldLineSize.width;
2027                                 sweepOut = 0;
2028                                 if (pNewTextLine->isChanged())
2029                                 {
2030                                         sweepIn -= keyInputWidth;
2031                                 }
2032
2033                                 pNewTextLine->SetKeyInputResult(sweepResult);
2034                                 pNewTextLine->SetSweepIn(sweepIn);
2035                                 pNewTextLine->SetSweepOut(sweepOut);
2036                         }
2037                 }
2038         }
2039         else if (oldLineSize.width < newLineSize.width)
2040         {
2041                 sweepResult = BACKWARD_SWEEP;
2042
2043                 sweepIn = newLineSize.width - oldLineSize.width;
2044                 sweepOut = 0;
2045                 if (pNewTextLine->isChanged())
2046                 {
2047                         sweepIn -= keyInputWidth;
2048                 }
2049
2050                 pNewTextLine->SetKeyInputResult(sweepResult);
2051                 pNewTextLine->SetSweepIn(sweepIn);
2052                 pNewTextLine->SetSweepOut(sweepOut);
2053         }
2054         else
2055         {
2056                 sweepResult = FORWARD_SWEEP;
2057
2058                 sweepIn = 0;
2059                 sweepOut = oldLineSize.width - newLineSize.width;
2060                 if (pNewTextLine->isChanged())
2061                 {
2062                         sweepOut += keyInputWidth;
2063                 }
2064
2065                 pNewTextLine->SetKeyInputResult(sweepResult);
2066                 pNewTextLine->SetSweepIn(sweepIn);
2067                 pNewTextLine->SetSweepOut(sweepOut);
2068         }
2069
2070         pOldTextLineNode  = TextSimpleList::GetFirstNode(__pKeepLines);
2071         SysTryReturn(NID_GRP
2072                         , pOldTextLineNode
2073                         , E_SYSTEM, E_SYSTEM
2074                         , "[E_SYSTEM] Fail to get text line node.");
2075
2076         pNewTextLineNode = TextSimpleList::GetNthNode(__pLines, changedStartLineIndex);
2077         SysTryReturn(NID_GRP
2078                         , pNewTextLineNode
2079                         , E_SYSTEM, E_SYSTEM
2080                         , "[E_SYSTEM] Fail to get text line node.");
2081
2082         prevLineSweepIn = pNewTextLine->GetSweepIn();
2083         prevLineSweepOut = pNewTextLine->GetSweepOut();
2084
2085         pOldTextLineNode = pOldTextLineNode->pNext;
2086         pNewTextLineNode = pNewTextLineNode->pNext;
2087
2088         switch (sweepResult)
2089         {
2090         case BACKWARD_SWEEP:
2091                 while (pOldTextLineNode != null && pNewTextLineNode != null)
2092                 {
2093                         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
2094                         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
2095
2096                         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
2097                         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
2098
2099                         if (oldLineSize.width == newLineSize.width)
2100                         {
2101                                 if (pOldTextLine->GetTextLength() == pNewTextLine->GetTextLength())
2102                                 {
2103                                         pNewTextLine->SetKeyInputResult(NOT_CHANGED);
2104                                         pNewTextLine->SetSweepIn(0);
2105                                         pNewTextLine->SetSweepOut(0);
2106
2107                                         break;
2108                                 }
2109                         }
2110
2111                         sweepIn = newLineSize.width - oldLineSize.width + prevLineSweepIn;
2112                         sweepOut = prevLineSweepIn;
2113
2114                         if (pNewTextLine->isChanged())
2115                         {
2116                                 sweepIn -= keyInputWidth;
2117                         }
2118
2119                         pNewTextLine->SetKeyInputResult(BACKWARD_SWEEP);
2120                         pNewTextLine->SetSweepIn(sweepIn);
2121                         pNewTextLine->SetSweepOut(sweepOut);
2122
2123                         prevLineSweepIn = pNewTextLine->GetSweepIn();
2124                         pOldTextLineNode = pOldTextLineNode->pNext;
2125                         pNewTextLineNode = pNewTextLineNode->pNext;
2126                 }
2127
2128         break;
2129
2130         case FORWARD_SWEEP:
2131                 while (pNewTextLineNode != null)
2132                 {
2133                         if (pOldTextLineNode == null)
2134                         {
2135                                 pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
2136
2137                                 pNewTextLine->SetKeyInputResult(FORWARD_SWEEP);
2138                                 pNewTextLine->SetSweepIn(prevLineSweepOut);
2139                                 pNewTextLine->SetSweepOut(0);
2140
2141                                 break;
2142                         }
2143
2144                         pOldTextLine = static_cast < TextLine* >(pOldTextLineNode->pObject);
2145                         pNewTextLine = static_cast < TextLine* >(pNewTextLineNode->pObject);
2146
2147                         pOldTextLine->GetRegion(0, pOldTextLine->GetTextLength(), oldLineSize.width, oldLineSize.height);
2148                         pNewTextLine->GetRegion(0, pNewTextLine->GetTextLength(), newLineSize.width, newLineSize.height);
2149
2150                         if (oldLineSize.width == newLineSize.width)
2151                         {
2152                                 if (pOldTextLine->GetTextLength() == pNewTextLine->GetTextLength())
2153                                 {
2154                                         pNewTextLine->SetKeyInputResult(NOT_CHANGED);
2155                                         pNewTextLine->SetSweepIn(0);
2156                                         pNewTextLine->SetSweepOut(0);
2157
2158                                         break;
2159                                 }
2160                         }
2161
2162                         sweepIn = prevLineSweepOut;
2163                         sweepOut = oldLineSize.width - newLineSize.width + prevLineSweepOut;
2164
2165                         if (pNewTextLine->isChanged())
2166                         {
2167                                 sweepOut += keyInputWidth;
2168                         }
2169
2170                         pNewTextLine->SetKeyInputResult(FORWARD_SWEEP);
2171                         pNewTextLine->SetSweepIn(sweepIn);
2172                         pNewTextLine->SetSweepOut(sweepOut);
2173
2174                         prevLineSweepOut = pNewTextLine->GetSweepOut();
2175                         pOldTextLineNode = pOldTextLineNode->pNext;
2176                         pNewTextLineNode = pNewTextLineNode->pNext;
2177                 }
2178
2179         break;
2180
2181         case NOT_CHANGED:
2182         default:
2183         break;
2184         }
2185
2186         return E_SUCCESS;
2187 }
2188
2189
2190 }}} // Tizen::Graphics::Text