FX Bool considered harmful, part 3
[pdfium.git] / fpdfsdk / src / fxedit / fxet_edit.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/fxedit/fxet_stub.h"
8 #include "../../include/fxedit/fxet_edit.h"
9
10 #define FX_EDIT_UNDO_MAXITEM                10000
11
12 /* ---------------------------- CFX_Edit_Iterator ---------------------------- */
13
14 CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit * pEdit,IPDF_VariableText_Iterator * pVTIterator) :
15     m_pEdit(pEdit),
16     m_pVTIterator(pVTIterator)
17 {
18 }
19
20 CFX_Edit_Iterator::~CFX_Edit_Iterator()
21 {
22 }
23
24 bool CFX_Edit_Iterator::NextWord()
25 {
26     return m_pVTIterator->NextWord();
27 }
28
29 bool CFX_Edit_Iterator::NextLine()
30 {
31     return m_pVTIterator->NextLine();
32 }
33
34 bool CFX_Edit_Iterator::NextSection()
35 {
36     return m_pVTIterator->NextSection();
37 }
38
39 bool CFX_Edit_Iterator::PrevWord()
40 {
41     return m_pVTIterator->PrevWord();
42 }
43
44 bool CFX_Edit_Iterator::PrevLine()
45 {
46     return m_pVTIterator->PrevLine();
47 }
48
49 bool CFX_Edit_Iterator::PrevSection()
50 {
51     return m_pVTIterator->PrevSection();
52 }
53
54 bool CFX_Edit_Iterator::GetWord(CPVT_Word & word) const
55 {
56     ASSERT(m_pEdit);
57
58     if (m_pVTIterator->GetWord(word))
59     {
60         word.ptWord = m_pEdit->VTToEdit(word.ptWord);
61         return true;
62     }
63     return false;
64 }
65
66 bool CFX_Edit_Iterator::GetLine(CPVT_Line & line) const
67 {
68     ASSERT(m_pEdit);
69
70     if (m_pVTIterator->GetLine(line))
71     {
72         line.ptLine = m_pEdit->VTToEdit(line.ptLine);
73         return true;
74     }
75     return false;
76 }
77
78 bool CFX_Edit_Iterator::GetSection(CPVT_Section & section) const
79 {
80     ASSERT(m_pEdit);
81
82     if (m_pVTIterator->GetSection(section))
83     {
84         section.rcSection = m_pEdit->VTToEdit(section.rcSection);
85         return true;
86     }
87     return false;
88 }
89
90 void CFX_Edit_Iterator::SetAt(int32_t nWordIndex)
91 {
92     m_pVTIterator->SetAt(nWordIndex);
93 }
94
95 void CFX_Edit_Iterator::SetAt(const CPVT_WordPlace & place)
96 {
97     m_pVTIterator->SetAt(place);
98 }
99
100 const CPVT_WordPlace & CFX_Edit_Iterator::GetAt() const
101 {
102     return m_pVTIterator->GetAt();
103 }
104
105 IFX_Edit* CFX_Edit_Iterator::GetEdit() const
106 {
107     return m_pEdit;
108 }
109
110 /* --------------------------- CFX_Edit_Provider ------------------------------- */
111
112 CFX_Edit_Provider::CFX_Edit_Provider(IFX_Edit_FontMap * pFontMap) : m_pFontMap(pFontMap)
113 {
114     ASSERT(m_pFontMap != NULL);
115 }
116
117 CFX_Edit_Provider::~CFX_Edit_Provider()
118 {
119 }
120
121 IFX_Edit_FontMap* CFX_Edit_Provider::GetFontMap()
122 {
123     return m_pFontMap;
124 }
125
126 int32_t CFX_Edit_Provider::GetCharWidth(int32_t nFontIndex, FX_WORD word, int32_t nWordStyle)
127 {
128     if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
129     {
130         FX_DWORD charcode = word;
131
132         if (pPDFFont->IsUnicodeCompatible())
133             charcode = pPDFFont->CharCodeFromUnicode(word);
134         else
135             charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word);
136
137         if (charcode != -1)
138             return pPDFFont->GetCharWidthF(charcode);
139     }
140
141     return 0;
142 }
143
144 int32_t CFX_Edit_Provider::GetTypeAscent(int32_t nFontIndex)
145 {
146     if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
147         return pPDFFont->GetTypeAscent();
148
149     return 0;
150 }
151
152 int32_t CFX_Edit_Provider::GetTypeDescent(int32_t nFontIndex)
153 {
154     if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
155         return pPDFFont->GetTypeDescent();
156
157     return 0;
158 }
159
160 int32_t CFX_Edit_Provider::GetWordFontIndex(FX_WORD word, int32_t charset, int32_t nFontIndex)
161 {
162     return m_pFontMap->GetWordFontIndex(word,charset,nFontIndex);
163 }
164
165 int32_t CFX_Edit_Provider::GetDefaultFontIndex()
166 {
167     return 0;
168 }
169
170 bool CFX_Edit_Provider::IsLatinWord(FX_WORD word)
171 {
172     return FX_EDIT_ISLATINWORD(word);
173 }
174
175 /* --------------------------------- CFX_Edit_Refresh --------------------------------- */
176
177 CFX_Edit_Refresh::CFX_Edit_Refresh()
178 {
179 }
180
181 CFX_Edit_Refresh::~CFX_Edit_Refresh()
182 {
183 }
184
185 void CFX_Edit_Refresh::BeginRefresh()
186 {
187     m_RefreshRects.Empty();
188     m_OldLineRects = m_NewLineRects;
189 }
190
191 void CFX_Edit_Refresh::Push(const CPVT_WordRange & linerange,const CPDF_Rect & rect)
192 {
193     m_NewLineRects.Add(linerange,rect);
194 }
195
196 void CFX_Edit_Refresh::NoAnalyse()
197 {
198     {
199         for (int32_t i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++)
200             if (CFX_Edit_LineRect * pOldRect = m_OldLineRects.GetAt(i))
201                 m_RefreshRects.Add(pOldRect->m_rcLine);
202     }
203
204     {
205         for (int32_t i = 0, sz = m_NewLineRects.GetSize(); i < sz; i++)
206             if (CFX_Edit_LineRect * pNewRect = m_NewLineRects.GetAt(i))
207                 m_RefreshRects.Add(pNewRect->m_rcLine);
208     }
209 }
210
211 void CFX_Edit_Refresh::Analyse(int32_t nAlignment)
212 {
213     bool bLineTopChanged = false;
214     CPDF_Rect rcResult;
215     FX_FLOAT fWidthDiff;
216
217     int32_t szMax = FX_EDIT_MAX(m_OldLineRects.GetSize(),m_NewLineRects.GetSize());
218     int32_t i = 0;
219
220     while (i < szMax)
221     {
222         CFX_Edit_LineRect * pOldRect = m_OldLineRects.GetAt(i);
223         CFX_Edit_LineRect * pNewRect = m_NewLineRects.GetAt(i);
224
225         if (pOldRect)
226         {
227             if (pNewRect)
228             {
229                 if (bLineTopChanged)
230                 {
231                     rcResult = pOldRect->m_rcLine;
232                     rcResult.Union(pNewRect->m_rcLine);
233                     m_RefreshRects.Add(rcResult);
234                 }
235                 else
236                 {
237                     if (*pNewRect != *pOldRect)
238                     {
239                         if (!pNewRect->IsSameTop(*pOldRect) || !pNewRect->IsSameHeight(*pOldRect))
240                         {
241                             bLineTopChanged = true;
242                             continue;
243                         }
244
245                         if (nAlignment == 0)
246                         {
247                             if (pNewRect->m_wrLine.BeginPos != pOldRect->m_wrLine.BeginPos)
248                             {
249                                 rcResult = pOldRect->m_rcLine;
250                                 rcResult.Union(pNewRect->m_rcLine);
251                                 m_RefreshRects.Add(rcResult);
252                             }
253                             else
254                             {
255                                 if (!pNewRect->IsSameLeft(*pOldRect))
256                                 {
257                                     rcResult = pOldRect->m_rcLine;
258                                     rcResult.Union(pNewRect->m_rcLine);
259                                 }
260                                 else
261                                 {
262                                     fWidthDiff = pNewRect->m_rcLine.Width() - pOldRect->m_rcLine.Width();
263                                     rcResult = pNewRect->m_rcLine;
264                                     if (fWidthDiff > 0.0f)
265                                         rcResult.left = rcResult.right - fWidthDiff;
266                                     else
267                                     {
268                                         rcResult.left = rcResult.right;
269                                         rcResult.right += (-fWidthDiff);
270                                     }
271                                 }
272                                 m_RefreshRects.Add(rcResult);
273                             }
274                         }
275                         else
276                         {
277                             rcResult = pOldRect->m_rcLine;
278                             rcResult.Union(pNewRect->m_rcLine);
279                             m_RefreshRects.Add(rcResult);
280                         }
281                     }
282                     else
283                     {
284                         //don't need to do anything
285                     }
286                 }
287             }
288             else
289             {
290                 m_RefreshRects.Add(pOldRect->m_rcLine);
291             }
292         }
293         else
294         {
295             if (pNewRect)
296             {
297                 m_RefreshRects.Add(pNewRect->m_rcLine);
298             }
299             else
300             {
301                 //error
302             }
303         }
304         i++;
305     }
306 }
307
308 void CFX_Edit_Refresh::AddRefresh(const CPDF_Rect & rect)
309 {
310     m_RefreshRects.Add(rect);
311 }
312
313 const CFX_Edit_RectArray * CFX_Edit_Refresh::GetRefreshRects() const
314 {
315     return &m_RefreshRects;
316 }
317
318 void CFX_Edit_Refresh::EndRefresh()
319 {
320     m_RefreshRects.Empty();
321 }
322
323 /* ------------------------------------- CFX_Edit_Undo ------------------------------------- */
324
325 CFX_Edit_Undo::CFX_Edit_Undo(int32_t nBufsize) : m_nCurUndoPos(0),
326     m_nBufSize(nBufsize),
327     m_bModified(false),
328     m_bVirgin(true),
329     m_bWorking(false)
330 {
331 }
332
333 CFX_Edit_Undo::~CFX_Edit_Undo()
334 {
335     Reset();
336 }
337
338 bool CFX_Edit_Undo::CanUndo() const
339 {
340     return m_nCurUndoPos > 0;
341 }
342
343 void CFX_Edit_Undo::Undo()
344 {
345     m_bWorking = true;
346
347     if (m_nCurUndoPos > 0)
348     {
349         IFX_Edit_UndoItem * pItem = m_UndoItemStack.GetAt(m_nCurUndoPos-1);
350         ASSERT(pItem != NULL);
351
352         pItem->Undo();
353
354         m_nCurUndoPos--;
355         m_bModified = (m_nCurUndoPos != 0);
356     }
357
358     m_bWorking = false;
359 }
360
361 bool CFX_Edit_Undo::CanRedo() const
362 {
363     return m_nCurUndoPos < m_UndoItemStack.GetSize();
364 }
365
366 void CFX_Edit_Undo::Redo()
367 {
368     m_bWorking = true;
369
370     int32_t nStackSize = m_UndoItemStack.GetSize();
371
372     if (m_nCurUndoPos < nStackSize)
373     {
374         IFX_Edit_UndoItem * pItem = m_UndoItemStack.GetAt(m_nCurUndoPos);
375         ASSERT(pItem != NULL);
376
377         pItem->Redo();
378
379         m_nCurUndoPos++;
380         m_bModified = (m_nCurUndoPos != 0);
381     }
382
383     m_bWorking = false;
384 }
385
386 bool CFX_Edit_Undo::IsWorking() const
387 {
388     return m_bWorking;
389 }
390
391 void CFX_Edit_Undo::AddItem(IFX_Edit_UndoItem* pItem)
392 {
393     ASSERT(!m_bWorking);
394     ASSERT(pItem != NULL);
395     ASSERT(m_nBufSize > 1);
396
397     if (m_nCurUndoPos < m_UndoItemStack.GetSize())
398         RemoveTails();
399
400     if (m_UndoItemStack.GetSize() >= m_nBufSize)
401     {
402         RemoveHeads();
403         m_bVirgin = false;
404     }
405
406     m_UndoItemStack.Add(pItem);
407     m_nCurUndoPos = m_UndoItemStack.GetSize();
408
409     m_bModified = (m_nCurUndoPos != 0);
410 }
411
412 bool CFX_Edit_Undo::IsModified() const
413 {
414     return m_bVirgin ? m_bModified : true;
415 }
416
417 IFX_Edit_UndoItem* CFX_Edit_Undo::GetItem(int32_t nIndex)
418 {
419     if (nIndex>=0 && nIndex < m_UndoItemStack.GetSize())
420         return m_UndoItemStack.GetAt(nIndex);
421
422     return NULL;
423 }
424
425 void CFX_Edit_Undo::RemoveHeads()
426 {
427     ASSERT(m_UndoItemStack.GetSize() > 1);
428
429     delete m_UndoItemStack.GetAt(0);
430     m_UndoItemStack.RemoveAt(0);
431 }
432
433 void CFX_Edit_Undo::RemoveTails()
434 {
435     for (int32_t i = m_UndoItemStack.GetSize()-1; i >= m_nCurUndoPos; i--)
436     {
437         delete m_UndoItemStack.GetAt(i);
438         m_UndoItemStack.RemoveAt(i);
439     }
440 }
441
442 void CFX_Edit_Undo::Reset()
443 {
444     for (int32_t i=0, sz=m_UndoItemStack.GetSize(); i < sz; i++)
445     {
446         delete m_UndoItemStack.GetAt(i);
447     }
448     m_nCurUndoPos = 0;
449     m_UndoItemStack.RemoveAll();
450 }
451
452 /* -------------------------------- CFX_Edit_GroupUndoItem -------------------------------- */
453
454 CFX_Edit_GroupUndoItem::CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle) : m_sTitle(sTitle)
455 {
456 }
457
458 CFX_Edit_GroupUndoItem::~CFX_Edit_GroupUndoItem()
459 {
460     for (int i=0,sz=m_Items.GetSize(); i<sz; i++)
461     {
462         delete m_Items[i];
463     }
464
465     m_Items.RemoveAll();
466 }
467
468 void CFX_Edit_GroupUndoItem::AddUndoItem(CFX_Edit_UndoItem* pUndoItem)
469 {
470     ASSERT(pUndoItem != NULL);
471
472     pUndoItem->SetFirst(false);
473     pUndoItem->SetLast(false);
474
475     m_Items.Add(pUndoItem);
476
477     if (m_sTitle.IsEmpty())
478         m_sTitle = pUndoItem->GetUndoTitle();
479 }
480
481 void CFX_Edit_GroupUndoItem::UpdateItems()
482 {
483     if (m_Items.GetSize() > 0)
484     {
485         CFX_Edit_UndoItem* pFirstItem = m_Items[0];
486         ASSERT(pFirstItem != NULL);
487         pFirstItem->SetFirst(true);
488
489         CFX_Edit_UndoItem* pLastItem = m_Items[m_Items.GetSize() - 1];
490         ASSERT(pLastItem != NULL);
491         pLastItem->SetLast(true);
492     }
493 }
494
495 void CFX_Edit_GroupUndoItem::Undo()
496 {
497     for (int i=m_Items.GetSize()-1; i>=0; i--)
498     {
499         CFX_Edit_UndoItem* pUndoItem = m_Items[i];
500         ASSERT(pUndoItem != NULL);
501
502         pUndoItem->Undo();
503     }
504 }
505
506 void CFX_Edit_GroupUndoItem::Redo()
507 {
508     for (int i=0,sz=m_Items.GetSize(); i<sz; i++)
509     {
510         CFX_Edit_UndoItem* pUndoItem = m_Items[i];
511         ASSERT(pUndoItem != NULL);
512
513         pUndoItem->Redo();
514     }
515 }
516
517 CFX_WideString CFX_Edit_GroupUndoItem::GetUndoTitle()
518 {
519     return m_sTitle;
520 }
521
522 /* ------------------------------------- CFX_Edit_UndoItem derived classes ------------------------------------- */
523
524 CFXEU_InsertWord::CFXEU_InsertWord(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
525                                  FX_WORD word, int32_t charset, const CPVT_WordProps * pWordProps)
526     : m_pEdit(pEdit), m_wpOld(wpOldPlace), m_wpNew(wpNewPlace), m_Word(word), m_nCharset(charset), m_WordProps()
527 {
528     if (pWordProps)
529         m_WordProps = *pWordProps;
530 }
531
532 CFXEU_InsertWord::~CFXEU_InsertWord()
533 {
534 }
535
536 void CFXEU_InsertWord::Redo()
537 {
538     if (m_pEdit)
539     {
540         m_pEdit->SelectNone();
541         m_pEdit->SetCaret(m_wpOld);
542         m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,false,true);
543     }
544 }
545
546 void CFXEU_InsertWord::Undo()
547 {
548     if (m_pEdit)
549     {
550         m_pEdit->SelectNone();
551         m_pEdit->SetCaret(m_wpNew);
552         m_pEdit->Backspace(false,true);
553     }
554 }
555
556 /* -------------------------------------------------------------------------- */
557
558 CFXEU_InsertReturn::CFXEU_InsertReturn(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
559              const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps) :
560             m_pEdit(pEdit),
561             m_wpOld(wpOldPlace),
562             m_wpNew(wpNewPlace),
563             m_SecProps(),
564             m_WordProps()
565 {
566     if (pSecProps)
567         m_SecProps = *pSecProps;
568     if (pWordProps)
569         m_WordProps = *pWordProps;
570 }
571
572 CFXEU_InsertReturn::~CFXEU_InsertReturn()
573 {
574 }
575
576 void CFXEU_InsertReturn::Redo()
577 {
578     if (m_pEdit)
579     {
580         m_pEdit->SelectNone();
581         m_pEdit->SetCaret(m_wpOld);
582         m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,false,true);
583     }
584 }
585
586 void CFXEU_InsertReturn::Undo()
587 {
588     if (m_pEdit)
589     {
590         m_pEdit->SelectNone();
591         m_pEdit->SetCaret(m_wpNew);
592         m_pEdit->Backspace(false,true);
593     }
594 }
595
596 /* -------------------------------------------------------------------------- */
597 //CFXEU_Backspace
598
599 CFXEU_Backspace::CFXEU_Backspace(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
600                                FX_WORD word, int32_t charset,
601                                const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps) :
602             m_pEdit(pEdit),
603             m_wpOld(wpOldPlace),
604             m_wpNew(wpNewPlace),
605             m_Word(word),
606             m_nCharset(charset),
607             m_SecProps(SecProps),
608             m_WordProps(WordProps)
609 {
610 }
611
612 CFXEU_Backspace::~CFXEU_Backspace()
613 {
614 }
615
616 void CFXEU_Backspace::Redo()
617 {
618     if (m_pEdit)
619     {
620         m_pEdit->SelectNone();
621         m_pEdit->SetCaret(m_wpOld);
622         m_pEdit->Backspace(false,true);
623     }
624 }
625
626 void CFXEU_Backspace::Undo()
627 {
628     if (m_pEdit)
629     {
630         m_pEdit->SelectNone();
631         m_pEdit->SetCaret(m_wpNew);
632         if (m_wpNew.SecCmp(m_wpOld) != 0)
633         {
634             m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,false,true);
635         }
636         else
637         {
638             m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,false,true);
639         }
640     }
641 }
642
643 /* -------------------------------------------------------------------------- */
644 //CFXEU_Delete
645
646 CFXEU_Delete::CFXEU_Delete(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
647                                FX_WORD word, int32_t charset,
648                                const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps, bool bSecEnd) :
649             m_pEdit(pEdit),
650             m_wpOld(wpOldPlace),
651             m_wpNew(wpNewPlace),
652             m_Word(word),
653             m_nCharset(charset),
654             m_SecProps(SecProps),
655             m_WordProps(WordProps),
656             m_bSecEnd(bSecEnd)
657 {
658 }
659
660 CFXEU_Delete::~CFXEU_Delete()
661 {
662 }
663
664 void CFXEU_Delete::Redo()
665 {
666     if (m_pEdit)
667     {
668         m_pEdit->SelectNone();
669         m_pEdit->SetCaret(m_wpOld);
670         m_pEdit->Delete(false,true);
671     }
672 }
673
674 void CFXEU_Delete::Undo()
675 {
676     if (m_pEdit)
677     {
678         m_pEdit->SelectNone();
679         m_pEdit->SetCaret(m_wpNew);
680         if (m_bSecEnd)
681         {
682             m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,false,true);
683         }
684         else
685         {
686             m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,false,true);
687         }
688     }
689 }
690
691 /* -------------------------------------------------------------------------- */
692 //CFXEU_Clear
693
694 CFXEU_Clear::CFXEU_Clear(CFX_Edit * pEdit,  const CPVT_WordRange & wrSel, const CFX_WideString & swText) :
695             m_pEdit(pEdit),
696             m_wrSel(wrSel),
697             m_swText(swText)
698 {
699 }
700
701 CFXEU_Clear::~CFXEU_Clear()
702 {
703 }
704
705 void CFXEU_Clear::Redo()
706 {
707     if (m_pEdit)
708     {
709         m_pEdit->SelectNone();
710         m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
711         m_pEdit->Clear(false,true);
712     }
713 }
714
715 void CFXEU_Clear::Undo()
716 {
717     if (m_pEdit)
718     {
719         m_pEdit->SelectNone();
720         m_pEdit->SetCaret(m_wrSel.BeginPos);
721         m_pEdit->InsertText(m_swText.c_str(), DEFAULT_CHARSET, NULL, NULL, false, true);
722         m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
723     }
724 }
725
726 /* -------------------------------------------------------------------------- */
727 //CFXEU_ClearRich
728
729 CFXEU_ClearRich::CFXEU_ClearRich(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
730                                const CPVT_WordRange & wrSel, FX_WORD word, int32_t charset,
731                                const CPVT_SecProps & SecProps, const CPVT_WordProps & WordProps) :
732             m_pEdit(pEdit),
733             m_wpOld(wpOldPlace),
734             m_wpNew(wpNewPlace),
735             m_wrSel(wrSel),
736             m_Word(word),
737             m_nCharset(charset),
738             m_SecProps(SecProps),
739             m_WordProps(WordProps)
740 {
741 }
742
743 CFXEU_ClearRich::~CFXEU_ClearRich()
744 {
745 }
746
747 void CFXEU_ClearRich::Redo()
748 {
749     if (m_pEdit && IsLast())
750     {
751         m_pEdit->SelectNone();
752         m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
753         m_pEdit->Clear(false,true);
754     }
755 }
756
757 void CFXEU_ClearRich::Undo()
758 {
759     if (m_pEdit)
760     {
761         m_pEdit->SelectNone();
762         m_pEdit->SetCaret(m_wpOld);
763         if (m_wpNew.SecCmp(m_wpOld) != 0)
764         {
765             m_pEdit->InsertReturn(&m_SecProps,&m_WordProps,false,false);
766         }
767         else
768         {
769             m_pEdit->InsertWord(m_Word,m_nCharset,&m_WordProps,false,false);
770         }
771
772         if (IsFirst())
773         {
774             m_pEdit->PaintInsertText(m_wrSel.BeginPos,m_wrSel.EndPos);
775             m_pEdit->SetSel(m_wrSel.BeginPos,m_wrSel.EndPos);
776         }
777     }
778 }
779 /* -------------------------------------------------------------------------- */
780 //CFXEU_InsertText
781
782 CFXEU_InsertText::CFXEU_InsertText(CFX_Edit * pEdit, const CPVT_WordPlace & wpOldPlace, const CPVT_WordPlace & wpNewPlace,
783                                const CFX_WideString & swText, int32_t charset,
784                                const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps) :
785             m_pEdit(pEdit),
786             m_wpOld(wpOldPlace),
787             m_wpNew(wpNewPlace),
788             m_swText(swText),
789             m_nCharset(charset),
790             m_SecProps(),
791             m_WordProps()
792 {
793     if (pSecProps)
794         m_SecProps = *pSecProps;
795     if (pWordProps)
796         m_WordProps = *pWordProps;
797 }
798
799 CFXEU_InsertText::~CFXEU_InsertText()
800 {
801 }
802
803 void CFXEU_InsertText::Redo()
804 {
805     if (m_pEdit && IsLast())
806     {
807         m_pEdit->SelectNone();
808         m_pEdit->SetCaret(m_wpOld);
809         m_pEdit->InsertText(m_swText.c_str(), m_nCharset, &m_SecProps, &m_WordProps, false, true);
810     }
811 }
812
813 void CFXEU_InsertText::Undo()
814 {
815     if (m_pEdit)
816     {
817         m_pEdit->SelectNone();
818         m_pEdit->SetSel(m_wpOld,m_wpNew);
819         m_pEdit->Clear(false,true);
820     }
821 }
822
823 /* -------------------------------------------------------------------------- */
824
825 CFXEU_SetSecProps::CFXEU_SetSecProps(CFX_Edit * pEdit, const CPVT_WordPlace & place, EDIT_PROPS_E ep,
826         const CPVT_SecProps & oldsecprops, const CPVT_WordProps & oldwordprops,
827         const CPVT_SecProps & newsecprops, const CPVT_WordProps & newwordprops, const CPVT_WordRange & range)
828         : m_pEdit(pEdit),
829         m_wpPlace(place),
830         m_wrPlace(range),
831         m_eProps(ep),
832         m_OldSecProps(oldsecprops),
833         m_NewSecProps(newsecprops),
834         m_OldWordProps(oldwordprops),
835         m_NewWordProps(newwordprops)
836 {
837 }
838
839 CFXEU_SetSecProps::~CFXEU_SetSecProps()
840 {
841 }
842
843 void CFXEU_SetSecProps::Redo()
844 {
845     if (m_pEdit)
846     {
847         m_pEdit->SetSecProps(m_eProps,m_wpPlace,&m_NewSecProps,&m_NewWordProps,m_wrPlace,false);
848         if (IsLast())
849         {
850             m_pEdit->SelectNone();
851             m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
852             m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
853         }
854     }
855 }
856
857 void CFXEU_SetSecProps::Undo()
858 {
859     if (m_pEdit)
860     {
861         m_pEdit->SetSecProps(m_eProps,m_wpPlace,&m_OldSecProps,&m_OldWordProps,m_wrPlace,false);
862         if (IsFirst())
863         {
864             m_pEdit->SelectNone();
865             m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
866             m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
867         }
868     }
869 }
870
871 /* -------------------------------------------------------------------------- */
872
873 CFXEU_SetWordProps::CFXEU_SetWordProps(CFX_Edit * pEdit, const CPVT_WordPlace & place, EDIT_PROPS_E ep,
874         const CPVT_WordProps & oldprops, const CPVT_WordProps & newprops, const CPVT_WordRange & range)
875         : m_pEdit(pEdit),
876         m_wpPlace(place),
877         m_wrPlace(range),
878         m_eProps(ep),
879         m_OldWordProps(oldprops),
880         m_NewWordProps(newprops)
881 {
882 }
883
884 CFXEU_SetWordProps::~CFXEU_SetWordProps()
885 {
886 }
887
888 void CFXEU_SetWordProps::Redo()
889 {
890     if (m_pEdit)
891     {
892         m_pEdit->SetWordProps(m_eProps,m_wpPlace,&m_NewWordProps,m_wrPlace,false);
893         if (IsLast())
894         {
895             m_pEdit->SelectNone();
896             m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
897             m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
898         }
899     }
900 }
901
902 void CFXEU_SetWordProps::Undo()
903 {
904     if (m_pEdit)
905     {
906         m_pEdit->SetWordProps(m_eProps,m_wpPlace,&m_OldWordProps,m_wrPlace,false);
907         if (IsFirst())
908         {
909             m_pEdit->SelectNone();
910             m_pEdit->PaintSetProps(m_eProps,m_wrPlace);
911             m_pEdit->SetSel(m_wrPlace.BeginPos,m_wrPlace.EndPos);
912         }
913     }
914 }
915
916 /* ------------------------------------- CFX_Edit ------------------------------------- */
917
918 CFX_Edit::CFX_Edit(IPDF_VariableText * pVT) :
919     m_pVT(pVT),
920     m_pNotify(NULL),
921     m_pOprNotify(NULL),
922     m_pVTProvide(NULL),
923     m_wpCaret(-1,-1,-1),
924     m_wpOldCaret(-1,-1,-1),
925     m_SelState(),
926     m_ptScrollPos(0,0),
927     m_ptRefreshScrollPos(0,0),
928     m_bEnableScroll(false),
929     m_pIterator(NULL),
930     m_ptCaret(0.0f,0.0f),
931     m_Undo(FX_EDIT_UNDO_MAXITEM),
932     m_nAlignment(0),
933     m_bNotifyFlag(false),
934     m_bEnableOverflow(false),
935     m_bEnableRefresh(true),
936     m_rcOldContent(0.0f,0.0f,0.0f,0.0f),
937     m_bEnableUndo(true),
938     m_bNotify(true),
939     m_bOprNotify(false),
940     m_pGroupUndoItem(NULL)
941 {
942     ASSERT(pVT != NULL);
943 }
944
945 CFX_Edit::~CFX_Edit()
946 {
947     delete m_pVTProvide;
948     m_pVTProvide = NULL;
949     delete m_pIterator;
950     m_pIterator = NULL;
951     ASSERT(m_pGroupUndoItem == NULL);
952 }
953
954 // public methods
955
956 void CFX_Edit::Initialize()
957 {
958     m_pVT->Initialize();
959     SetCaret(m_pVT->GetBeginWordPlace());
960     SetCaretOrigin();
961 }
962
963 void CFX_Edit::SetFontMap(IFX_Edit_FontMap * pFontMap)
964 {
965     delete m_pVTProvide;
966     m_pVT->SetProvider(m_pVTProvide = new CFX_Edit_Provider(pFontMap));
967 }
968
969 void CFX_Edit::SetVTProvider(IPDF_VariableText_Provider* pProvider)
970 {
971     m_pVT->SetProvider(pProvider);
972 }
973
974 void CFX_Edit::SetNotify(IFX_Edit_Notify* pNotify)
975 {
976     m_pNotify = pNotify;
977 }
978
979 void CFX_Edit::SetOprNotify(IFX_Edit_OprNotify* pOprNotify)
980 {
981     m_pOprNotify = pOprNotify;
982 }
983
984 IFX_Edit_Iterator * CFX_Edit::GetIterator()
985 {
986     if (!m_pIterator)
987         m_pIterator = new CFX_Edit_Iterator(this,m_pVT->GetIterator());
988
989     return m_pIterator;
990 }
991
992 IPDF_VariableText * CFX_Edit::GetVariableText()
993 {
994     return m_pVT;
995 }
996
997 IFX_Edit_FontMap* CFX_Edit::GetFontMap()
998 {
999     if (m_pVTProvide)
1000         return m_pVTProvide->GetFontMap();
1001
1002     return NULL;
1003 }
1004
1005 void CFX_Edit::SetPlateRect(const CPDF_Rect & rect, bool bPaint/* = true*/)
1006 {
1007     m_pVT->SetPlateRect(rect);
1008     m_ptScrollPos = CPDF_Point(rect.left,rect.top);
1009     if (bPaint) Paint();
1010 }
1011
1012 void CFX_Edit::SetAlignmentH(int32_t nFormat/* =0 */, bool bPaint/* = true*/)
1013 {
1014     m_pVT->SetAlignment(nFormat);
1015     if (bPaint) Paint();
1016 }
1017
1018 void CFX_Edit::SetAlignmentV(int32_t nFormat/* =0 */, bool bPaint/* = true*/)
1019 {
1020     m_nAlignment = nFormat;
1021     if (bPaint) Paint();
1022 }
1023
1024 void CFX_Edit::SetPasswordChar(FX_WORD wSubWord/* ='*' */, bool bPaint/* = true*/)
1025 {
1026     m_pVT->SetPasswordChar(wSubWord);
1027     if (bPaint) Paint();
1028 }
1029
1030 void CFX_Edit::SetLimitChar(int32_t nLimitChar/* =0 */, bool bPaint/* = true*/)
1031 {
1032     m_pVT->SetLimitChar(nLimitChar);
1033     if (bPaint) Paint();
1034 }
1035
1036 void CFX_Edit::SetCharArray(int32_t nCharArray/* =0 */, bool bPaint/* = true*/)
1037 {
1038     m_pVT->SetCharArray(nCharArray);
1039     if (bPaint) Paint();
1040 }
1041
1042 void CFX_Edit::SetCharSpace(FX_FLOAT fCharSpace/* =0.0f */, bool bPaint/* = true*/)
1043 {
1044     m_pVT->SetCharSpace(fCharSpace);
1045     if (bPaint) Paint();
1046 }
1047
1048 void CFX_Edit::SetHorzScale(int32_t nHorzScale/* =100 */, bool bPaint/* = true*/)
1049 {
1050     m_pVT->SetHorzScale(nHorzScale);
1051     if (bPaint) Paint();
1052 }
1053
1054 void CFX_Edit::SetMultiLine(bool bMultiLine/* =true */, bool bPaint/* = true*/)
1055 {
1056     m_pVT->SetMultiLine(bMultiLine);
1057     if (bPaint) Paint();
1058 }
1059
1060 void CFX_Edit::SetAutoReturn(bool bAuto/* =true */, bool bPaint/* = true*/)
1061 {
1062     m_pVT->SetAutoReturn(bAuto);
1063     if (bPaint) Paint();
1064 }
1065
1066 void CFX_Edit::SetLineLeading(FX_FLOAT fLineLeading/* =true */, bool bPaint/* = true*/)
1067 {
1068     m_pVT->SetLineLeading(fLineLeading);
1069     if (bPaint) Paint();
1070 }
1071
1072 void CFX_Edit::SetAutoFontSize(bool bAuto/* =true */, bool bPaint/* = true*/)
1073 {
1074     m_pVT->SetAutoFontSize(bAuto);
1075     if (bPaint) Paint();
1076 }
1077
1078 void CFX_Edit::SetFontSize(FX_FLOAT fFontSize, bool bPaint/* = true*/)
1079 {
1080     m_pVT->SetFontSize(fFontSize);
1081     if (bPaint) Paint();
1082 }
1083
1084 void CFX_Edit::SetAutoScroll(bool bAuto/* =true */, bool bPaint/* = true*/)
1085 {
1086     m_bEnableScroll = bAuto;
1087     if (bPaint) Paint();
1088 }
1089
1090 void CFX_Edit::SetTextOverflow(bool bAllowed /*= false*/, bool bPaint/* = true*/)
1091 {
1092     m_bEnableOverflow = bAllowed;
1093     if (bPaint) Paint();
1094 }
1095
1096 void CFX_Edit::SetSel(int32_t nStartChar,int32_t nEndChar)
1097 {
1098     if (m_pVT->IsValid())
1099     {
1100         if (nStartChar == 0 && nEndChar < 0)
1101         {
1102             SelectAll();
1103         }
1104         else if (nStartChar < 0)
1105         {
1106             SelectNone();
1107         }
1108         else
1109         {
1110             if (nStartChar < nEndChar)
1111             {
1112                 SetSel(m_pVT->WordIndexToWordPlace(nStartChar),m_pVT->WordIndexToWordPlace(nEndChar));
1113             }
1114             else
1115             {
1116                 SetSel(m_pVT->WordIndexToWordPlace(nEndChar),m_pVT->WordIndexToWordPlace(nStartChar));
1117             }
1118         }
1119     }
1120 }
1121
1122 void CFX_Edit::SetSel(const CPVT_WordPlace & begin,const CPVT_WordPlace & end)
1123 {
1124     if (m_pVT->IsValid())
1125     {
1126         SelectNone();
1127
1128         m_SelState.Set(begin,end);
1129
1130         SetCaret(m_SelState.EndPos);
1131
1132         if (m_SelState.IsExist())
1133         {
1134             ScrollToCaret();
1135             CPVT_WordRange wr(m_SelState.BeginPos,m_SelState.EndPos);
1136             Refresh(RP_OPTIONAL,&wr);
1137             SetCaretInfo();
1138         }
1139         else
1140         {
1141             ScrollToCaret();
1142             SetCaretInfo();
1143         }
1144     }
1145 }
1146
1147 void CFX_Edit::GetSel(int32_t & nStartChar, int32_t & nEndChar) const
1148 {
1149     nStartChar = -1;
1150     nEndChar = -1;
1151
1152     if (m_pVT->IsValid())
1153     {
1154         if (m_SelState.IsExist())
1155         {
1156             if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
1157             {
1158                 nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
1159                 nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
1160             }
1161             else
1162             {
1163                 nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
1164                 nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
1165             }
1166         }
1167         else
1168         {
1169             nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
1170             nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
1171         }
1172     }
1173 }
1174
1175 int32_t CFX_Edit::GetCaret() const
1176 {
1177     if (m_pVT->IsValid())
1178         return m_pVT->WordPlaceToWordIndex(m_wpCaret);
1179
1180     return -1;
1181 }
1182
1183 CPVT_WordPlace CFX_Edit::GetCaretWordPlace() const
1184 {
1185     return m_wpCaret;
1186 }
1187
1188 CFX_WideString CFX_Edit::GetText() const
1189 {
1190     CFX_WideString swRet;
1191
1192     if (m_pVT->IsValid())
1193     {
1194         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1195         {
1196             bool bRich = m_pVT->IsRichText();
1197
1198             pIterator->SetAt(0);
1199
1200             CPVT_Word wordinfo;
1201             CPVT_WordPlace oldplace = pIterator->GetAt();
1202             while (pIterator->NextWord())
1203             {
1204                 CPVT_WordPlace place = pIterator->GetAt();
1205
1206                 if (pIterator->GetWord(wordinfo))
1207                 {
1208                     if (bRich)
1209                     {
1210                         swRet += wordinfo.Word;
1211                     }
1212                     else
1213                     {
1214                         swRet += wordinfo.Word;
1215                     }
1216                 }
1217
1218                 if (oldplace.SecCmp(place) != 0)
1219                 {
1220                     swRet += 0x0D;
1221                     swRet += 0x0A;
1222                 }
1223
1224                 oldplace = place;
1225             }
1226         }
1227     }
1228
1229     return swRet;
1230 }
1231
1232 CFX_WideString CFX_Edit::GetRangeText(const CPVT_WordRange & range) const
1233 {
1234     CFX_WideString swRet;
1235
1236     if (m_pVT->IsValid())
1237     {
1238         bool bRich = m_pVT->IsRichText();
1239
1240         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1241         {
1242             CPVT_WordRange wrTemp = range;
1243             m_pVT->UpdateWordPlace(wrTemp.BeginPos);
1244             m_pVT->UpdateWordPlace(wrTemp.EndPos);
1245             pIterator->SetAt(wrTemp.BeginPos);
1246
1247             CPVT_Word wordinfo;
1248             CPVT_WordPlace oldplace = wrTemp.BeginPos;
1249             while (pIterator->NextWord())
1250             {
1251                 CPVT_WordPlace place = pIterator->GetAt();
1252                 if (place.WordCmp(wrTemp.EndPos) > 0)break;
1253
1254                 if (pIterator->GetWord(wordinfo))
1255                 {
1256                     if (bRich)
1257                     {
1258                         swRet += wordinfo.Word;
1259                     }
1260                     else
1261                     {
1262                         swRet += wordinfo.Word;
1263                     }
1264                 }
1265
1266                 if (oldplace.SecCmp(place) != 0)
1267                 {
1268                     swRet += 0x0D;
1269                     swRet += 0x0A;
1270                 }
1271
1272                 oldplace = place;
1273             }
1274         }
1275     }
1276
1277     return swRet;
1278 }
1279
1280 CFX_WideString CFX_Edit::GetSelText() const
1281 {
1282     return GetRangeText(m_SelState.ConvertToWordRange());
1283 }
1284
1285 int32_t CFX_Edit::GetTotalWords() const
1286 {
1287     return m_pVT->GetTotalWords();
1288 }
1289
1290 int32_t CFX_Edit::GetTotalLines() const
1291 {
1292     int32_t nLines = 0;
1293
1294     if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1295     {
1296         pIterator->SetAt(0);
1297         while (pIterator->NextLine())
1298             nLines++;
1299     }
1300
1301     return nLines+1;
1302 }
1303
1304 CPVT_WordRange CFX_Edit::GetSelectWordRange() const
1305 {
1306     return m_SelState.ConvertToWordRange();
1307 }
1308
1309 CPVT_WordRange CFX_Edit::CombineWordRange(const CPVT_WordRange & wr1, const CPVT_WordRange & wr2)
1310 {
1311     CPVT_WordRange wrRet;
1312
1313     if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0)
1314     {
1315         wrRet.BeginPos = wr1.BeginPos;
1316     }
1317     else
1318     {
1319         wrRet.BeginPos = wr2.BeginPos;
1320     }
1321
1322     if (wr1.EndPos.WordCmp(wr2.EndPos) < 0)
1323     {
1324         wrRet.EndPos = wr2.EndPos;
1325     }
1326     else
1327     {
1328         wrRet.EndPos = wr1.EndPos;
1329     }
1330
1331     return wrRet;
1332 }
1333
1334 bool CFX_Edit::IsRichText() const
1335 {
1336     return m_pVT->IsRichText();
1337 }
1338
1339 void CFX_Edit::SetRichText(bool bRichText/* =true */, bool bPaint/* = true*/)
1340 {
1341     m_pVT->SetRichText(bRichText);
1342     if (bPaint) Paint();
1343 }
1344
1345 bool CFX_Edit::SetRichFontIndex(int32_t nFontIndex)
1346 {
1347     CPVT_WordProps WordProps;
1348     WordProps.nFontIndex = nFontIndex;
1349     return SetRichTextProps(EP_FONTINDEX,NULL,&WordProps);
1350 }
1351
1352 bool CFX_Edit::SetRichFontSize(FX_FLOAT fFontSize)
1353 {
1354     CPVT_WordProps WordProps;
1355     WordProps.fFontSize = fFontSize;
1356     return SetRichTextProps(EP_FONTSIZE,NULL,&WordProps);
1357 }
1358
1359 bool CFX_Edit::SetRichTextColor(FX_COLORREF dwColor)
1360 {
1361     CPVT_WordProps WordProps;
1362     WordProps.dwWordColor = dwColor;
1363     return SetRichTextProps(EP_WORDCOLOR,NULL,&WordProps);
1364 }
1365
1366 bool CFX_Edit::SetRichTextScript(int32_t nScriptType)
1367 {
1368     CPVT_WordProps WordProps;
1369     WordProps.nScriptType = nScriptType;
1370     return SetRichTextProps(EP_SCRIPTTYPE,NULL,&WordProps);
1371 }
1372
1373 bool CFX_Edit::SetRichTextBold(bool bBold)
1374 {
1375     CPVT_WordProps WordProps;
1376     if (bBold)
1377         WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
1378     return SetRichTextProps(EP_BOLD,NULL,&WordProps);
1379 }
1380
1381 bool CFX_Edit::SetRichTextItalic(bool bItalic)
1382 {
1383     CPVT_WordProps WordProps;
1384     if (bItalic)
1385         WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
1386     return SetRichTextProps(EP_ITALIC,NULL,&WordProps);
1387 }
1388
1389 bool CFX_Edit::SetRichTextUnderline(bool bUnderline)
1390 {
1391     CPVT_WordProps WordProps;
1392     if (bUnderline)
1393         WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
1394     return SetRichTextProps(EP_UNDERLINE,NULL,&WordProps);
1395 }
1396
1397 bool CFX_Edit::SetRichTextCrossout(bool bCrossout)
1398 {
1399     CPVT_WordProps WordProps;
1400     if (bCrossout)
1401         WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
1402     return SetRichTextProps(EP_CROSSOUT,NULL,&WordProps);
1403 }
1404
1405 bool CFX_Edit::SetRichTextCharSpace(FX_FLOAT fCharSpace)
1406 {
1407     CPVT_WordProps WordProps;
1408     WordProps.fCharSpace = fCharSpace;
1409     return SetRichTextProps(EP_CHARSPACE,NULL,&WordProps);
1410 }
1411
1412 bool CFX_Edit::SetRichTextHorzScale(int32_t nHorzScale /*= 100*/)
1413 {
1414     CPVT_WordProps WordProps;
1415     WordProps.nHorzScale = nHorzScale;
1416     return SetRichTextProps(EP_HORZSCALE,NULL,&WordProps);
1417 }
1418
1419 bool CFX_Edit::SetRichTextLineLeading(FX_FLOAT fLineLeading)
1420 {
1421     CPVT_SecProps SecProps;
1422     SecProps.fLineLeading = fLineLeading;
1423     return SetRichTextProps(EP_LINELEADING,&SecProps,NULL);
1424 }
1425
1426 bool CFX_Edit::SetRichTextLineIndent(FX_FLOAT fLineIndent)
1427 {
1428     CPVT_SecProps SecProps;
1429     SecProps.fLineIndent = fLineIndent;
1430     return SetRichTextProps(EP_LINEINDENT,&SecProps,NULL);
1431 }
1432
1433 bool CFX_Edit::SetRichTextAlignment(int32_t nAlignment)
1434 {
1435     CPVT_SecProps SecProps;
1436     SecProps.nAlignment = nAlignment;
1437     return SetRichTextProps(EP_ALIGNMENT,&SecProps,NULL);
1438 }
1439
1440 bool CFX_Edit::SetRichTextProps(EDIT_PROPS_E eProps, const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps)
1441 {
1442     bool bSet = false;
1443     bool bSet1,bSet2;
1444     if (m_pVT->IsValid() && m_pVT->IsRichText())
1445     {
1446         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1447         {
1448             CPVT_WordRange wrTemp = m_SelState.ConvertToWordRange();
1449
1450             m_pVT->UpdateWordPlace(wrTemp.BeginPos);
1451             m_pVT->UpdateWordPlace(wrTemp.EndPos);
1452             pIterator->SetAt(wrTemp.BeginPos);
1453
1454             BeginGroupUndo(L"");;
1455
1456             bSet = SetSecProps(eProps,wrTemp.BeginPos,pSecProps,pWordProps,wrTemp,true);
1457
1458             while (pIterator->NextWord())
1459             {
1460                 CPVT_WordPlace place = pIterator->GetAt();
1461                 if (place.WordCmp(wrTemp.EndPos) > 0) break;
1462                 bSet1 = SetSecProps(eProps,place,pSecProps,pWordProps,wrTemp,true);
1463                 bSet2 = SetWordProps(eProps,place,pWordProps,wrTemp,true);
1464
1465                 if (!bSet)
1466                     bSet = (bSet1 || bSet2);
1467             }
1468
1469             EndGroupUndo();
1470
1471             if (bSet)
1472             {
1473                 PaintSetProps(eProps,wrTemp);
1474             }
1475         }
1476     }
1477
1478     return bSet;
1479 }
1480
1481 void CFX_Edit::PaintSetProps(EDIT_PROPS_E eProps, const CPVT_WordRange & wr)
1482 {
1483     switch(eProps)
1484     {
1485     case EP_LINELEADING:
1486     case EP_LINEINDENT:
1487     case EP_ALIGNMENT:
1488         RearrangePart(wr);
1489         ScrollToCaret();
1490         Refresh(RP_ANALYSE);
1491         SetCaretOrigin();
1492         SetCaretInfo();
1493         break;
1494     case EP_WORDCOLOR:
1495     case EP_UNDERLINE:
1496     case EP_CROSSOUT:
1497         Refresh(RP_OPTIONAL,&wr);
1498         break;
1499     case EP_FONTINDEX:
1500     case EP_FONTSIZE:
1501     case EP_SCRIPTTYPE:
1502     case EP_CHARSPACE:
1503     case EP_HORZSCALE:
1504     case EP_BOLD:
1505     case EP_ITALIC:
1506         RearrangePart(wr);
1507         ScrollToCaret();
1508
1509         CPVT_WordRange wrRefresh(m_pVT->GetSectionBeginPlace(wr.BeginPos),
1510             m_pVT->GetSectionEndPlace(wr.EndPos));
1511         Refresh(RP_ANALYSE,&wrRefresh);
1512
1513         SetCaretOrigin();
1514         SetCaretInfo();
1515         break;
1516     }
1517 }
1518
1519 bool CFX_Edit::SetSecProps(EDIT_PROPS_E eProps, const CPVT_WordPlace & place,
1520                                const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps,
1521                                const CPVT_WordRange & wr, bool bAddUndo)
1522 {
1523     if (m_pVT->IsValid() && m_pVT->IsRichText())
1524     {
1525         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1526         {
1527             bool bSet = false;
1528             CPVT_Section secinfo;
1529             CPVT_Section OldSecinfo;
1530
1531             CPVT_WordPlace oldplace = pIterator->GetAt();
1532
1533             if (eProps == EP_LINELEADING || eProps == EP_LINEINDENT || eProps == EP_ALIGNMENT)
1534             {
1535                 if (pSecProps)
1536                 {
1537                     pIterator->SetAt(place);
1538                     if (pIterator->GetSection(secinfo))
1539                     {
1540                         if (bAddUndo) OldSecinfo = secinfo;
1541
1542                         switch(eProps)
1543                         {
1544                         case EP_LINELEADING:
1545                             if (!FX_EDIT_IsFloatEqual(secinfo.SecProps.fLineLeading,pSecProps->fLineLeading))
1546                             {
1547                                 secinfo.SecProps.fLineLeading = pSecProps->fLineLeading;
1548                                 bSet = true;
1549                             }
1550                             break;
1551                         case EP_LINEINDENT:
1552                             if (!FX_EDIT_IsFloatEqual(secinfo.SecProps.fLineIndent,pSecProps->fLineIndent))
1553                             {
1554                                 secinfo.SecProps.fLineIndent = pSecProps->fLineIndent;
1555                                 bSet = true;
1556                             }
1557                             break;
1558                         case EP_ALIGNMENT:
1559                             if (secinfo.SecProps.nAlignment != pSecProps->nAlignment)
1560                             {
1561                                 secinfo.SecProps.nAlignment = pSecProps->nAlignment;
1562                                 bSet = true;
1563                             }
1564                             break;
1565                         default:
1566                             break;
1567                         }
1568                     }
1569                 }
1570             }
1571             else
1572             {
1573                 if (pWordProps && place == m_pVT->GetSectionBeginPlace(place))
1574                 {
1575                     pIterator->SetAt(place);
1576                     if (pIterator->GetSection(secinfo))
1577                     {
1578                         if (bAddUndo) OldSecinfo = secinfo;
1579
1580                         switch(eProps)
1581                         {
1582                         case EP_FONTINDEX:
1583                             if (secinfo.WordProps.nFontIndex != pWordProps->nFontIndex)
1584                             {
1585                                 secinfo.WordProps.nFontIndex = pWordProps->nFontIndex;
1586                                 bSet = true;
1587                             }
1588                             break;
1589                         case EP_FONTSIZE:
1590                             if (!FX_EDIT_IsFloatEqual(secinfo.WordProps.fFontSize,pWordProps->fFontSize))
1591                             {
1592                                 secinfo.WordProps.fFontSize = pWordProps->fFontSize;
1593                                 bSet = true;
1594                             }
1595                             break;
1596                         case EP_WORDCOLOR:
1597                             if (secinfo.WordProps.dwWordColor != pWordProps->dwWordColor)
1598                             {
1599                                 secinfo.WordProps.dwWordColor = pWordProps->dwWordColor;
1600                                 bSet = true;
1601                             }
1602                             break;
1603                         case EP_SCRIPTTYPE:
1604                             if (secinfo.WordProps.nScriptType != pWordProps->nScriptType)
1605                             {
1606                                 secinfo.WordProps.nScriptType = pWordProps->nScriptType;
1607                                 bSet = true;
1608                             }
1609                             break;
1610                         case EP_CHARSPACE:
1611                             if (!FX_EDIT_IsFloatEqual(secinfo.WordProps.fCharSpace,pWordProps->fCharSpace))
1612                             {
1613                                 secinfo.WordProps.fCharSpace = pWordProps->fCharSpace;
1614                                 bSet = true;
1615                             }
1616                             break;
1617                         case EP_HORZSCALE:
1618                             if (secinfo.WordProps.nHorzScale != pWordProps->nHorzScale)
1619                             {
1620                                 secinfo.WordProps.nHorzScale = pWordProps->nHorzScale;
1621                                 bSet = true;
1622                             }
1623                             break;
1624                         case EP_UNDERLINE:
1625                             if (pWordProps->nWordStyle & PVTWORD_STYLE_UNDERLINE)
1626                             {
1627                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) == 0)
1628                                 {
1629                                     secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
1630                                     bSet = true;
1631                                 }
1632                             }
1633                             else
1634                             {
1635                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) != 0)
1636                                 {
1637                                     secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_UNDERLINE;
1638                                     bSet = true;
1639                                 }
1640                             }
1641                             break;
1642                         case EP_CROSSOUT:
1643                             if (pWordProps->nWordStyle & PVTWORD_STYLE_CROSSOUT)
1644                             {
1645                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) == 0)
1646                                 {
1647                                     secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
1648                                     bSet = true;
1649                                 }
1650                             }
1651                             else
1652                             {
1653                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) != 0)
1654                                 {
1655                                     secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_CROSSOUT;
1656                                     bSet = true;
1657                                 }
1658                             }
1659                             break;
1660                         case EP_BOLD:
1661                             if (pWordProps->nWordStyle & PVTWORD_STYLE_BOLD)
1662                             {
1663                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) == 0)
1664                                 {
1665                                     secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
1666                                     bSet = true;
1667                                 }
1668                             }
1669                             else
1670                             {
1671                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) != 0)
1672                                 {
1673                                     secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_BOLD;
1674                                     bSet = true;
1675                                 }
1676                             }
1677                             break;
1678                         case EP_ITALIC:
1679                             if (pWordProps->nWordStyle & PVTWORD_STYLE_ITALIC)
1680                             {
1681                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) == 0)
1682                                 {
1683                                     secinfo.WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
1684                                     bSet = true;
1685                                 }
1686                             }
1687                             else
1688                             {
1689                                 if ((secinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) != 0)
1690                                 {
1691                                     secinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_ITALIC;
1692                                     bSet = true;
1693                                 }
1694                             }
1695                             break;
1696                         default:
1697                             break;
1698                         }
1699                     }
1700                 }
1701             }
1702
1703             if (bSet)
1704             {
1705                 pIterator->SetSection(secinfo);
1706
1707                 if (bAddUndo && m_bEnableUndo)
1708                 {
1709                     AddEditUndoItem(new CFXEU_SetSecProps
1710                         (this,place,eProps,OldSecinfo.SecProps,OldSecinfo.WordProps,secinfo.SecProps,secinfo.WordProps,wr));
1711                 }
1712             }
1713
1714             pIterator->SetAt(oldplace);
1715
1716             return bSet;
1717         }
1718     }
1719
1720     return false;
1721 }
1722
1723 bool CFX_Edit::SetWordProps(EDIT_PROPS_E eProps, const CPVT_WordPlace & place,
1724                                 const CPVT_WordProps * pWordProps, const CPVT_WordRange & wr, bool bAddUndo)
1725 {
1726     if (m_pVT->IsValid() && m_pVT->IsRichText())
1727     {
1728         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
1729         {
1730             bool bSet = false;
1731             CPVT_Word wordinfo;
1732             CPVT_Word OldWordinfo;
1733
1734             CPVT_WordPlace oldplace = pIterator->GetAt();
1735
1736             if (pWordProps)
1737             {
1738                 pIterator->SetAt(place);
1739                 if (pIterator->GetWord(wordinfo))
1740                 {
1741                     if (bAddUndo) OldWordinfo = wordinfo;
1742
1743                     switch(eProps)
1744                     {
1745                     case EP_FONTINDEX:
1746                         if (wordinfo.WordProps.nFontIndex != pWordProps->nFontIndex)
1747                         {
1748                             if (IFX_Edit_FontMap* pFontMap = GetFontMap())
1749                             {
1750                                 wordinfo.WordProps.nFontIndex = pFontMap->GetWordFontIndex(wordinfo.Word,wordinfo.nCharset,pWordProps->nFontIndex);
1751                             }
1752                             bSet = true;
1753                         }
1754                         break;
1755                     case EP_FONTSIZE:
1756                         if (!FX_EDIT_IsFloatEqual(wordinfo.WordProps.fFontSize,pWordProps->fFontSize))
1757                         {
1758                             wordinfo.WordProps.fFontSize = pWordProps->fFontSize;
1759                             bSet = true;
1760                         }
1761                         break;
1762                     case EP_WORDCOLOR:
1763                         if (wordinfo.WordProps.dwWordColor != pWordProps->dwWordColor)
1764                         {
1765                             wordinfo.WordProps.dwWordColor = pWordProps->dwWordColor;
1766                             bSet = true;
1767                         }
1768                         break;
1769                     case EP_SCRIPTTYPE:
1770                         if (wordinfo.WordProps.nScriptType != pWordProps->nScriptType)
1771                         {
1772                             wordinfo.WordProps.nScriptType = pWordProps->nScriptType;
1773                             bSet = true;
1774                         }
1775                         break;
1776                     case EP_CHARSPACE:
1777                         if (!FX_EDIT_IsFloatEqual(wordinfo.WordProps.fCharSpace,pWordProps->fCharSpace))
1778                         {
1779                             wordinfo.WordProps.fCharSpace = pWordProps->fCharSpace;
1780                             bSet = true;
1781                         }
1782                         break;
1783                     case EP_HORZSCALE:
1784                         if (wordinfo.WordProps.nHorzScale != pWordProps->nHorzScale)
1785                         {
1786                             wordinfo.WordProps.nHorzScale = pWordProps->nHorzScale;
1787                             bSet = true;
1788                         }
1789                         break;
1790                     case EP_UNDERLINE:
1791                         if (pWordProps->nWordStyle & PVTWORD_STYLE_UNDERLINE)
1792                         {
1793                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) == 0)
1794                             {
1795                                 wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_UNDERLINE;
1796                                 bSet = true;
1797                             }
1798                         }
1799                         else
1800                         {
1801                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) != 0)
1802                             {
1803                                 wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_UNDERLINE;
1804                                 bSet = true;
1805                             }
1806                         }
1807                         break;
1808                     case EP_CROSSOUT:
1809                         if (pWordProps->nWordStyle & PVTWORD_STYLE_CROSSOUT)
1810                         {
1811                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) == 0)
1812                             {
1813                                 wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_CROSSOUT;
1814                                 bSet = true;
1815                             }
1816                         }
1817                         else
1818                         {
1819                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) != 0)
1820                             {
1821                                 wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_CROSSOUT;
1822                                 bSet = true;
1823                             }
1824                         }
1825                         break;
1826                     case EP_BOLD:
1827                         if (pWordProps->nWordStyle & PVTWORD_STYLE_BOLD)
1828                         {
1829                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) == 0)
1830                             {
1831                                 wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_BOLD;
1832                                 bSet = true;
1833                             }
1834                         }
1835                         else
1836                         {
1837                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_BOLD) != 0)
1838                             {
1839                                 wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_BOLD;
1840                                 bSet = true;
1841                             }
1842                         }
1843                         break;
1844                     case EP_ITALIC:
1845                         if (pWordProps->nWordStyle & PVTWORD_STYLE_ITALIC)
1846                         {
1847                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) == 0)
1848                             {
1849                                 wordinfo.WordProps.nWordStyle |= PVTWORD_STYLE_ITALIC;
1850                                 bSet = true;
1851                             }
1852                         }
1853                         else
1854                         {
1855                             if ((wordinfo.WordProps.nWordStyle & PVTWORD_STYLE_ITALIC) != 0)
1856                             {
1857                                 wordinfo.WordProps.nWordStyle &= ~PVTWORD_STYLE_ITALIC;
1858                                 bSet = true;
1859                             }
1860                         }
1861                         break;
1862                     default:
1863                         break;
1864                     }
1865                 }
1866             }
1867
1868             if (bSet)
1869             {
1870                 pIterator->SetWord(wordinfo);
1871
1872                 if (bAddUndo && m_bEnableUndo)
1873                 {
1874                     AddEditUndoItem(new CFXEU_SetWordProps
1875                         (this,place,eProps,OldWordinfo.WordProps,wordinfo.WordProps,wr));
1876                 }
1877             }
1878
1879             pIterator->SetAt(oldplace);
1880             return bSet;
1881         }
1882     }
1883
1884     return false;
1885 }
1886
1887 void CFX_Edit::SetText(const FX_WCHAR* text,int32_t charset /*= DEFAULT_CHARSET*/,
1888                         const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
1889 {
1890     SetText(text,charset,pSecProps,pWordProps,true,true);
1891 }
1892
1893 bool CFX_Edit::InsertWord(FX_WORD word, int32_t charset /*= DEFAULT_CHARSET*/, const CPVT_WordProps * pWordProps /*= NULL*/)
1894 {
1895     return InsertWord(word,charset,pWordProps,true,true);
1896 }
1897
1898 bool CFX_Edit::InsertReturn(const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
1899 {
1900     return InsertReturn(pSecProps,pWordProps,true,true);
1901 }
1902
1903 bool CFX_Edit::Backspace()
1904 {
1905     return Backspace(true,true);
1906 }
1907
1908 bool CFX_Edit::Delete()
1909 {
1910     return Delete(true,true);
1911 }
1912
1913 bool CFX_Edit::Clear()
1914 {
1915     return Clear(true,true);
1916 }
1917
1918 bool CFX_Edit::InsertText(const FX_WCHAR* text, int32_t charset /*= DEFAULT_CHARSET*/,
1919                                 const CPVT_SecProps * pSecProps /*= NULL*/,const CPVT_WordProps * pWordProps /*= NULL*/)
1920 {
1921     return InsertText(text,charset,pSecProps,pWordProps,true,true);
1922 }
1923
1924 FX_FLOAT CFX_Edit::GetFontSize() const
1925 {
1926     return m_pVT->GetFontSize();
1927 }
1928
1929 FX_WORD CFX_Edit::GetPasswordChar() const
1930 {
1931     return m_pVT->GetPasswordChar();
1932 }
1933
1934 int32_t CFX_Edit::GetCharArray() const
1935 {
1936     return m_pVT->GetCharArray();
1937 }
1938
1939 CPDF_Rect CFX_Edit::GetPlateRect() const
1940 {
1941     return m_pVT->GetPlateRect();
1942 }
1943
1944 CPDF_Rect CFX_Edit::GetContentRect() const
1945 {
1946     return VTToEdit(m_pVT->GetContentRect());
1947 }
1948
1949 int32_t CFX_Edit::GetHorzScale() const
1950 {
1951     return m_pVT->GetHorzScale();
1952 }
1953
1954 FX_FLOAT CFX_Edit::GetCharSpace() const
1955 {
1956     return m_pVT->GetCharSpace();
1957 }
1958
1959 // inner methods
1960
1961 CPVT_WordRange CFX_Edit::GetWholeWordRange() const
1962 {
1963     if (m_pVT->IsValid())
1964         return CPVT_WordRange(m_pVT->GetBeginWordPlace(),m_pVT->GetEndWordPlace());
1965
1966     return CPVT_WordRange();
1967 }
1968
1969 CPVT_WordRange CFX_Edit::GetVisibleWordRange() const
1970 {
1971     if (m_bEnableOverflow) return GetWholeWordRange();
1972
1973     if (m_pVT->IsValid())
1974     {
1975         CPDF_Rect rcPlate = m_pVT->GetPlateRect();
1976
1977         CPVT_WordPlace place1 = m_pVT->SearchWordPlace(EditToVT(CPDF_Point(rcPlate.left,rcPlate.top)));
1978         CPVT_WordPlace place2 = m_pVT->SearchWordPlace(EditToVT(CPDF_Point(rcPlate.right,rcPlate.bottom)));
1979
1980         return CPVT_WordRange(place1,place2);
1981     }
1982
1983     return CPVT_WordRange();
1984 }
1985
1986 CPVT_WordPlace CFX_Edit::SearchWordPlace(const CPDF_Point& point) const
1987 {
1988     if (m_pVT->IsValid())
1989     {
1990         return m_pVT->SearchWordPlace(EditToVT(point));
1991     }
1992
1993     return CPVT_WordPlace();
1994 }
1995
1996 void CFX_Edit::Paint()
1997 {
1998     if (m_pVT->IsValid())
1999     {
2000         RearrangeAll();
2001         ScrollToCaret();
2002         Refresh(RP_NOANALYSE);
2003         SetCaretOrigin();
2004         SetCaretInfo();
2005     }
2006 }
2007
2008 void CFX_Edit::RearrangeAll()
2009 {
2010     if (m_pVT->IsValid())
2011     {
2012         m_pVT->UpdateWordPlace(m_wpCaret);
2013         m_pVT->RearrangeAll();
2014         m_pVT->UpdateWordPlace(m_wpCaret);
2015         SetScrollInfo();
2016         SetContentChanged();
2017     }
2018 }
2019
2020 void CFX_Edit::RearrangePart(const CPVT_WordRange & range)
2021 {
2022     if (m_pVT->IsValid())
2023     {
2024         m_pVT->UpdateWordPlace(m_wpCaret);
2025         m_pVT->RearrangePart(range);
2026         m_pVT->UpdateWordPlace(m_wpCaret);
2027         SetScrollInfo();
2028         SetContentChanged();
2029     }
2030 }
2031
2032 void CFX_Edit::SetContentChanged()
2033 {
2034     if (m_bNotify && m_pNotify)
2035     {
2036         CPDF_Rect rcContent = m_pVT->GetContentRect();
2037         if (rcContent.Width() != m_rcOldContent.Width() ||
2038             rcContent.Height() != m_rcOldContent.Height())
2039         {
2040             if (!m_bNotifyFlag)
2041             {
2042                 m_bNotifyFlag = true;
2043                 m_pNotify->IOnContentChange(rcContent);
2044                 m_bNotifyFlag = false;
2045             }
2046             m_rcOldContent = rcContent;
2047         }
2048     }
2049 }
2050
2051 void CFX_Edit::SelectAll()
2052 {
2053     if (m_pVT->IsValid())
2054     {
2055         m_SelState = GetWholeWordRange();
2056         SetCaret(m_SelState.EndPos);
2057
2058         ScrollToCaret();
2059         CPVT_WordRange wrVisible = GetVisibleWordRange();
2060         Refresh(RP_OPTIONAL,&wrVisible);
2061         SetCaretInfo();
2062     }
2063 }
2064
2065 void CFX_Edit::SelectNone()
2066 {
2067     if (m_pVT->IsValid())
2068     {
2069         if (m_SelState.IsExist())
2070         {
2071             CPVT_WordRange wrTemp = m_SelState.ConvertToWordRange();
2072             m_SelState.Default();
2073             Refresh(RP_OPTIONAL,&wrTemp);
2074         }
2075     }
2076 }
2077
2078 bool CFX_Edit::IsSelected() const
2079 {
2080     return m_SelState.IsExist();
2081 }
2082
2083 CPDF_Point CFX_Edit::VTToEdit(const CPDF_Point & point) const
2084 {
2085     CPDF_Rect rcContent = m_pVT->GetContentRect();
2086     CPDF_Rect rcPlate = m_pVT->GetPlateRect();
2087
2088     FX_FLOAT fPadding = 0.0f;
2089
2090     switch (m_nAlignment)
2091     {
2092     case 0:
2093         fPadding = 0.0f;
2094         break;
2095     case 1:
2096         fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
2097         break;
2098     case 2:
2099         fPadding = rcPlate.Height() - rcContent.Height();
2100         break;
2101     }
2102
2103     return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left),
2104         point.y - (m_ptScrollPos.y + fPadding - rcPlate.top));
2105 }
2106
2107 CPDF_Point CFX_Edit::EditToVT(const CPDF_Point & point) const
2108 {
2109     CPDF_Rect rcContent = m_pVT->GetContentRect();
2110     CPDF_Rect rcPlate = m_pVT->GetPlateRect();
2111
2112     FX_FLOAT fPadding = 0.0f;
2113
2114     switch (m_nAlignment)
2115     {
2116     case 0:
2117         fPadding = 0.0f;
2118         break;
2119     case 1:
2120         fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
2121         break;
2122     case 2:
2123         fPadding = rcPlate.Height() - rcContent.Height();
2124         break;
2125     }
2126
2127     return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left),
2128         point.y + (m_ptScrollPos.y + fPadding - rcPlate.top));
2129 }
2130
2131 CPDF_Rect CFX_Edit::VTToEdit(const CPDF_Rect & rect) const
2132 {
2133     CPDF_Point ptLeftBottom = VTToEdit(CPDF_Point(rect.left,rect.bottom));
2134     CPDF_Point ptRightTop = VTToEdit(CPDF_Point(rect.right,rect.top));
2135
2136     return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
2137 }
2138
2139 CPDF_Rect CFX_Edit::EditToVT(const CPDF_Rect & rect) const
2140 {
2141     CPDF_Point ptLeftBottom = EditToVT(CPDF_Point(rect.left,rect.bottom));
2142     CPDF_Point ptRightTop = EditToVT(CPDF_Point(rect.right,rect.top));
2143
2144     return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
2145 }
2146
2147 void CFX_Edit::SetScrollInfo()
2148 {
2149     if (m_bNotify && m_pNotify)
2150     {
2151         CPDF_Rect rcPlate = m_pVT->GetPlateRect();
2152         CPDF_Rect rcContent = m_pVT->GetContentRect();
2153
2154         if (!m_bNotifyFlag)
2155         {
2156             m_bNotifyFlag = true;
2157             m_pNotify->IOnSetScrollInfoX(rcPlate.left, rcPlate.right,
2158                                 rcContent.left, rcContent.right, rcPlate.Width() / 3, rcPlate.Width());
2159
2160             m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
2161                     rcContent.bottom, rcContent.top, rcPlate.Height() / 3, rcPlate.Height());
2162             m_bNotifyFlag = false;
2163         }
2164     }
2165 }
2166
2167 void CFX_Edit::SetScrollPosX(FX_FLOAT fx)
2168 {
2169     if (!m_bEnableScroll) return;
2170
2171     if (m_pVT->IsValid())
2172     {
2173         if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.x,fx))
2174         {
2175             m_ptScrollPos.x = fx;
2176             Refresh(RP_NOANALYSE);
2177
2178             if (m_bNotify && m_pNotify)
2179             {
2180                 if (!m_bNotifyFlag)
2181                 {
2182                     m_bNotifyFlag = true;
2183                     m_pNotify->IOnSetScrollPosX(fx);
2184                     m_bNotifyFlag = false;
2185                 }
2186             }
2187         }
2188     }
2189 }
2190
2191 void CFX_Edit::SetScrollPosY(FX_FLOAT fy)
2192 {
2193     if (!m_bEnableScroll) return;
2194
2195     if (m_pVT->IsValid())
2196     {
2197         if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y,fy))
2198         {
2199             m_ptScrollPos.y = fy;
2200             Refresh(RP_NOANALYSE);
2201
2202             if (m_bNotify && m_pNotify)
2203             {
2204                 if (!m_bNotifyFlag)
2205                 {
2206                     m_bNotifyFlag = true;
2207                     m_pNotify->IOnSetScrollPosY(fy);
2208                     m_bNotifyFlag = false;
2209                 }
2210             }
2211         }
2212     }
2213 }
2214
2215 void CFX_Edit::SetScrollPos(const CPDF_Point & point)
2216 {
2217     SetScrollPosX(point.x);
2218     SetScrollPosY(point.y);
2219     SetScrollLimit();
2220     SetCaretInfo();
2221 }
2222
2223 CPDF_Point CFX_Edit::GetScrollPos() const
2224 {
2225     return m_ptScrollPos;
2226 }
2227
2228 void CFX_Edit::SetScrollLimit()
2229 {
2230     if (m_pVT->IsValid())
2231     {
2232         CPDF_Rect rcContent = m_pVT->GetContentRect();
2233         CPDF_Rect rcPlate = m_pVT->GetPlateRect();
2234
2235         if (rcPlate.Width() > rcContent.Width())
2236         {
2237             SetScrollPosX(rcPlate.left);
2238         }
2239         else
2240         {
2241             if (FX_EDIT_IsFloatSmaller(m_ptScrollPos.x, rcContent.left))
2242             {
2243                 SetScrollPosX(rcContent.left);
2244             }
2245             else if (FX_EDIT_IsFloatBigger(m_ptScrollPos.x, rcContent.right - rcPlate.Width()))
2246             {
2247                 SetScrollPosX(rcContent.right - rcPlate.Width());
2248             }
2249         }
2250
2251         if (rcPlate.Height() > rcContent.Height())
2252         {
2253             SetScrollPosY(rcPlate.top);
2254         }
2255         else
2256         {
2257             if (FX_EDIT_IsFloatSmaller(m_ptScrollPos.y, rcContent.bottom + rcPlate.Height()))
2258             {
2259                 SetScrollPosY(rcContent.bottom + rcPlate.Height());
2260             }
2261             else if (FX_EDIT_IsFloatBigger(m_ptScrollPos.y, rcContent.top))
2262             {
2263                 SetScrollPosY(rcContent.top);
2264             }
2265         }
2266     }
2267 }
2268
2269 void CFX_Edit::ScrollToCaret()
2270 {
2271     SetScrollLimit();
2272
2273     if (m_pVT->IsValid())
2274     {
2275         CPDF_Point ptHead(0,0);
2276         CPDF_Point ptFoot(0,0);
2277
2278         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2279         {
2280             pIterator->SetAt(m_wpCaret);
2281
2282             CPVT_Word word;
2283             CPVT_Line line;
2284             if (pIterator->GetWord(word))
2285             {
2286                 ptHead.x = word.ptWord.x + word.fWidth;
2287                 ptHead.y = word.ptWord.y + word.fAscent;
2288                 ptFoot.x = word.ptWord.x + word.fWidth;
2289                 ptFoot.y = word.ptWord.y + word.fDescent;
2290             }
2291             else if (pIterator->GetLine(line))
2292             {
2293                 ptHead.x = line.ptLine.x;
2294                 ptHead.y = line.ptLine.y + line.fLineAscent;
2295                 ptFoot.x = line.ptLine.x;
2296                 ptFoot.y = line.ptLine.y + line.fLineDescent;
2297             }
2298         }
2299
2300         CPDF_Point ptHeadEdit = VTToEdit(ptHead);
2301         CPDF_Point ptFootEdit = VTToEdit(ptFoot);
2302
2303         CPDF_Rect rcPlate = m_pVT->GetPlateRect();
2304
2305         if (!FX_EDIT_IsFloatEqual(rcPlate.left,rcPlate.right))
2306         {
2307             if (FX_EDIT_IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
2308                 FX_EDIT_IsFloatEqual(ptHeadEdit.x, rcPlate.left))
2309             {
2310                 SetScrollPosX(ptHead.x);
2311             }
2312             else if (FX_EDIT_IsFloatBigger(ptHeadEdit.x, rcPlate.right))
2313             {
2314                 SetScrollPosX(ptHead.x - rcPlate.Width());
2315             }
2316         }
2317
2318         if (!FX_EDIT_IsFloatEqual(rcPlate.top,rcPlate.bottom))
2319         {
2320             if (FX_EDIT_IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
2321                 FX_EDIT_IsFloatEqual(ptFootEdit.y, rcPlate.bottom))
2322             {
2323                 if (FX_EDIT_IsFloatSmaller(ptHeadEdit.y, rcPlate.top))
2324                 {
2325                     SetScrollPosY(ptFoot.y + rcPlate.Height());
2326                 }
2327             }
2328             else if (FX_EDIT_IsFloatBigger(ptHeadEdit.y, rcPlate.top))
2329             {
2330                 if (FX_EDIT_IsFloatBigger(ptFootEdit.y, rcPlate.bottom))
2331                 {
2332                     SetScrollPosY(ptHead.y);
2333                 }
2334             }
2335         }
2336     }
2337 }
2338
2339 void CFX_Edit::Refresh(REFRESH_PLAN_E ePlan,const CPVT_WordRange * pRange1,const CPVT_WordRange * pRange2)
2340 {
2341     if (m_bEnableRefresh && m_pVT->IsValid())
2342     {
2343         m_Refresh.BeginRefresh();
2344         RefreshPushLineRects(GetVisibleWordRange());
2345
2346 //      if (!FX_EDIT_IsFloatEqual(m_ptRefreshScrollPos.x,m_ptScrollPos.x) ||
2347 //          !FX_EDIT_IsFloatEqual(m_ptRefreshScrollPos.y,m_ptScrollPos.y))
2348 //      {
2349             m_Refresh.NoAnalyse();
2350             m_ptRefreshScrollPos = m_ptScrollPos;
2351 //      }
2352 //      else
2353 //      {
2354 //          switch (ePlan)
2355 //          {
2356 //          case RP_ANALYSE:
2357 //              m_Refresh.Analyse(m_pVT->GetAlignment());
2358 //
2359 //              if (pRange1) RefreshPushRandomRects(*pRange1);
2360 //              if (pRange2) RefreshPushRandomRects(*pRange2);
2361 //              break;
2362 //          case RP_NOANALYSE:
2363 //              m_Refresh.NoAnalyse();
2364 //              break;
2365 //          case RP_OPTIONAL:
2366 //              if (pRange1) RefreshPushRandomRects(*pRange1);
2367 //              if (pRange2) RefreshPushRandomRects(*pRange2);
2368 //              break;
2369 //          }
2370 //      }
2371
2372         if (m_bNotify && m_pNotify)
2373         {
2374             if (!m_bNotifyFlag)
2375             {
2376                 m_bNotifyFlag = true;
2377                 if (const CFX_Edit_RectArray * pRects = m_Refresh.GetRefreshRects())
2378                 {
2379                     for (int32_t i = 0, sz = pRects->GetSize(); i < sz; i++)
2380                         m_pNotify->IOnInvalidateRect(pRects->GetAt(i));
2381                 }
2382                 m_bNotifyFlag = false;
2383             }
2384         }
2385
2386         m_Refresh.EndRefresh();
2387     }
2388 }
2389
2390 void CFX_Edit::RefreshPushLineRects(const CPVT_WordRange & wr)
2391 {
2392     if (m_pVT->IsValid())
2393     {
2394         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2395         {
2396             CPVT_WordPlace wpBegin = wr.BeginPos;
2397             m_pVT->UpdateWordPlace(wpBegin);
2398             CPVT_WordPlace wpEnd = wr.EndPos;
2399             m_pVT->UpdateWordPlace(wpEnd);
2400             pIterator->SetAt(wpBegin);
2401
2402             CPVT_Line lineinfo;
2403             do
2404             {
2405                 if (!pIterator->GetLine(lineinfo))break;
2406                 if (lineinfo.lineplace.LineCmp(wpEnd) > 0)break;
2407
2408                 CPDF_Rect rcLine(lineinfo.ptLine.x,
2409                                     lineinfo.ptLine.y + lineinfo.fLineDescent,
2410                                     lineinfo.ptLine.x + lineinfo.fLineWidth,
2411                                     lineinfo.ptLine.y + lineinfo.fLineAscent);
2412
2413                 m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace,lineinfo.lineEnd),VTToEdit(rcLine));
2414
2415             }while (pIterator->NextLine());
2416         }
2417     }
2418 }
2419
2420 void CFX_Edit::RefreshPushRandomRects(const CPVT_WordRange & wr)
2421 {
2422     if (m_pVT->IsValid())
2423     {
2424         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2425         {
2426             CPVT_WordRange wrTemp = wr;
2427
2428             m_pVT->UpdateWordPlace(wrTemp.BeginPos);
2429             m_pVT->UpdateWordPlace(wrTemp.EndPos);
2430             pIterator->SetAt(wrTemp.BeginPos);
2431
2432             CPVT_Word wordinfo;
2433             CPVT_Line lineinfo;
2434             CPVT_WordPlace place;
2435
2436             while (pIterator->NextWord())
2437             {
2438                 place = pIterator->GetAt();
2439                 if (place.WordCmp(wrTemp.EndPos) > 0) break;
2440
2441                 pIterator->GetWord(wordinfo);
2442                 pIterator->GetLine(lineinfo);
2443
2444                 if (place.LineCmp(wrTemp.BeginPos) == 0 || place.LineCmp(wrTemp.EndPos) == 0)
2445                 {
2446                     CPDF_Rect rcWord(wordinfo.ptWord.x,
2447                                         lineinfo.ptLine.y + lineinfo.fLineDescent,
2448                                         wordinfo.ptWord.x + wordinfo.fWidth,
2449                                         lineinfo.ptLine.y + lineinfo.fLineAscent);
2450
2451                     m_Refresh.AddRefresh(VTToEdit(rcWord));
2452                 }
2453                 else
2454                 {
2455                     CPDF_Rect rcLine(lineinfo.ptLine.x,
2456                                         lineinfo.ptLine.y + lineinfo.fLineDescent,
2457                                         lineinfo.ptLine.x + lineinfo.fLineWidth,
2458                                         lineinfo.ptLine.y + lineinfo.fLineAscent);
2459
2460                     m_Refresh.AddRefresh(VTToEdit(rcLine));
2461
2462                     pIterator->NextLine();
2463                 }
2464             }
2465         }
2466     }
2467 }
2468
2469 void CFX_Edit::RefreshWordRange(const CPVT_WordRange& wr)
2470 {
2471     if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2472     {
2473         CPVT_WordRange wrTemp = wr;
2474
2475         m_pVT->UpdateWordPlace(wrTemp.BeginPos);
2476         m_pVT->UpdateWordPlace(wrTemp.EndPos);
2477         pIterator->SetAt(wrTemp.BeginPos);
2478
2479         CPVT_Word wordinfo;
2480         CPVT_Line lineinfo;
2481         CPVT_WordPlace place;
2482
2483         while (pIterator->NextWord())
2484         {
2485             place = pIterator->GetAt();
2486             if (place.WordCmp(wrTemp.EndPos) > 0) break;
2487
2488             pIterator->GetWord(wordinfo);
2489             pIterator->GetLine(lineinfo);
2490
2491             if (place.LineCmp(wrTemp.BeginPos) == 0 || place.LineCmp(wrTemp.EndPos) == 0)
2492             {
2493                 CPDF_Rect rcWord(wordinfo.ptWord.x,
2494                                     lineinfo.ptLine.y + lineinfo.fLineDescent,
2495                                     wordinfo.ptWord.x + wordinfo.fWidth,
2496                                     lineinfo.ptLine.y + lineinfo.fLineAscent);
2497
2498                 if (m_bNotify && m_pNotify)
2499                 {
2500                     if (!m_bNotifyFlag)
2501                     {
2502                         m_bNotifyFlag = true;
2503                         CPDF_Rect rcRefresh = VTToEdit(rcWord);
2504                         m_pNotify->IOnInvalidateRect(&rcRefresh);
2505                         m_bNotifyFlag = false;
2506                     }
2507                 }
2508             }
2509             else
2510             {
2511                 CPDF_Rect rcLine(lineinfo.ptLine.x,
2512                                     lineinfo.ptLine.y + lineinfo.fLineDescent,
2513                                     lineinfo.ptLine.x + lineinfo.fLineWidth,
2514                                     lineinfo.ptLine.y + lineinfo.fLineAscent);
2515
2516                 if (m_bNotify && m_pNotify)
2517                 {
2518                     if (!m_bNotifyFlag)
2519                     {
2520                         m_bNotifyFlag = true;
2521                         CPDF_Rect rcRefresh = VTToEdit(rcLine);
2522                         m_pNotify->IOnInvalidateRect(&rcRefresh);
2523                         m_bNotifyFlag = false;
2524                     }
2525                 }
2526
2527                 pIterator->NextLine();
2528             }
2529         }
2530     }
2531 }
2532
2533 void CFX_Edit::SetCaret(const CPVT_WordPlace & place)
2534 {
2535     m_wpOldCaret = m_wpCaret;
2536     m_wpCaret = place;
2537 }
2538
2539 void CFX_Edit::SetCaretInfo()
2540 {
2541     if (m_bNotify && m_pNotify)
2542     {
2543         if (!m_bNotifyFlag)
2544         {
2545             CPDF_Point ptHead(0.0f,0.0f),ptFoot(0.0f,0.0f);
2546
2547             if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2548             {
2549                 pIterator->SetAt(m_wpCaret);
2550                 CPVT_Word word;
2551                 CPVT_Line line;
2552                 if (pIterator->GetWord(word))
2553                 {
2554                     ptHead.x = word.ptWord.x + word.fWidth;
2555                     ptHead.y = word.ptWord.y + word.fAscent;
2556                     ptFoot.x = word.ptWord.x + word.fWidth;
2557                     ptFoot.y = word.ptWord.y + word.fDescent;
2558                 }
2559                 else if (pIterator->GetLine(line))
2560                 {
2561                     ptHead.x = line.ptLine.x;
2562                     ptHead.y = line.ptLine.y + line.fLineAscent;
2563                     ptFoot.x = line.ptLine.x;
2564                     ptFoot.y = line.ptLine.y + line.fLineDescent;
2565                 }
2566             }
2567
2568             m_bNotifyFlag = true;
2569             m_pNotify->IOnSetCaret(!m_SelState.IsExist(),VTToEdit(ptHead),VTToEdit(ptFoot), m_wpCaret);
2570             m_bNotifyFlag = false;
2571         }
2572     }
2573
2574     SetCaretChange();
2575 }
2576
2577 void CFX_Edit::SetCaretChange()
2578 {
2579     if (m_wpCaret == m_wpOldCaret) return;
2580
2581     if (m_bNotify && m_pVT->IsRichText() && m_pNotify)
2582     {
2583         CPVT_SecProps SecProps;
2584         CPVT_WordProps WordProps;
2585
2586         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
2587         {
2588             pIterator->SetAt(m_wpCaret);
2589             CPVT_Word word;
2590             CPVT_Section section;
2591
2592             if (pIterator->GetSection(section))
2593             {
2594                 SecProps = section.SecProps;
2595                 WordProps = section.WordProps;
2596             }
2597
2598             if (pIterator->GetWord(word))
2599             {
2600                 WordProps = word.WordProps;
2601             }
2602         }
2603
2604         if (!m_bNotifyFlag)
2605         {
2606             m_bNotifyFlag = true;
2607             m_pNotify->IOnCaretChange(SecProps,WordProps);
2608             m_bNotifyFlag = false;
2609         }
2610     }
2611 }
2612
2613 void CFX_Edit::SetCaret(int32_t nPos)
2614 {
2615     if (m_pVT->IsValid())
2616     {
2617         SelectNone();
2618         SetCaret(m_pVT->WordIndexToWordPlace(nPos));
2619         m_SelState.Set(m_wpCaret,m_wpCaret);
2620
2621         ScrollToCaret();
2622         SetCaretOrigin();
2623         SetCaretInfo();
2624     }
2625 }
2626
2627 void CFX_Edit::OnMouseDown(const CPDF_Point & point,bool bShift,bool bCtrl)
2628 {
2629     if (m_pVT->IsValid())
2630     {
2631         SelectNone();
2632         SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
2633         m_SelState.Set(m_wpCaret,m_wpCaret);
2634
2635         ScrollToCaret();
2636         SetCaretOrigin();
2637         SetCaretInfo();
2638     }
2639 }
2640
2641 void CFX_Edit::OnMouseMove(const CPDF_Point & point,bool bShift,bool bCtrl)
2642 {
2643     if (m_pVT->IsValid())
2644     {
2645         SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
2646
2647         if (m_wpCaret != m_wpOldCaret)
2648         {
2649             m_SelState.SetEndPos(m_wpCaret);
2650
2651             ScrollToCaret();
2652             CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
2653             Refresh(RP_OPTIONAL,&wr);
2654             SetCaretOrigin();
2655             SetCaretInfo();
2656         }
2657     }
2658 }
2659
2660 void CFX_Edit::OnVK_UP(bool bShift,bool bCtrl)
2661 {
2662     if (m_pVT->IsValid())
2663     {
2664         SetCaret(m_pVT->GetUpWordPlace(m_wpCaret,m_ptCaret));
2665
2666         if (bShift)
2667         {
2668             if (m_SelState.IsExist())
2669                 m_SelState.SetEndPos(m_wpCaret);
2670             else
2671                 m_SelState.Set(m_wpOldCaret,m_wpCaret);
2672
2673             if (m_wpOldCaret != m_wpCaret)
2674             {
2675                 ScrollToCaret();
2676                 CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
2677                 Refresh(RP_OPTIONAL, &wr);
2678                 SetCaretInfo();
2679             }
2680         }
2681         else
2682         {
2683             SelectNone();
2684
2685             ScrollToCaret();
2686             SetCaretInfo();
2687         }
2688     }
2689 }
2690
2691 void CFX_Edit::OnVK_DOWN(bool bShift,bool bCtrl)
2692 {
2693     if (m_pVT->IsValid())
2694     {
2695         SetCaret(m_pVT->GetDownWordPlace(m_wpCaret,m_ptCaret));
2696
2697         if (bShift)
2698         {
2699             if (m_SelState.IsExist())
2700                 m_SelState.SetEndPos(m_wpCaret);
2701             else
2702                 m_SelState.Set(m_wpOldCaret,m_wpCaret);
2703
2704             if (m_wpOldCaret != m_wpCaret)
2705             {
2706                 ScrollToCaret();
2707                 CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
2708                 Refresh(RP_OPTIONAL, &wr);
2709                 SetCaretInfo();
2710             }
2711         }
2712         else
2713         {
2714             SelectNone();
2715
2716             ScrollToCaret();
2717             SetCaretInfo();
2718         }
2719     }
2720 }
2721
2722 void CFX_Edit::OnVK_LEFT(bool bShift,bool bCtrl)
2723 {
2724     if (m_pVT->IsValid())
2725     {
2726         if (bShift)
2727         {
2728             if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
2729                 m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
2730                 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
2731
2732             SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
2733
2734             if (m_SelState.IsExist())
2735                 m_SelState.SetEndPos(m_wpCaret);
2736             else
2737                 m_SelState.Set(m_wpOldCaret, m_wpCaret);
2738
2739             if (m_wpOldCaret != m_wpCaret)
2740             {
2741                 ScrollToCaret();
2742                 CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
2743                 Refresh(RP_OPTIONAL,&wr);
2744                 SetCaretInfo();
2745             }
2746         }
2747         else
2748         {
2749             if (m_SelState.IsExist())
2750             {
2751                 if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
2752                     SetCaret(m_SelState.BeginPos);
2753                 else
2754                     SetCaret(m_SelState.EndPos);
2755
2756                 SelectNone();
2757                 ScrollToCaret();
2758                 SetCaretInfo();
2759             }
2760             else
2761             {
2762                 if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
2763                     m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
2764                     SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
2765
2766                 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
2767
2768                 ScrollToCaret();
2769                 SetCaretOrigin();
2770                 SetCaretInfo();
2771             }
2772         }
2773     }
2774 }
2775
2776 void CFX_Edit::OnVK_RIGHT(bool bShift,bool bCtrl)
2777 {
2778     if (m_pVT->IsValid())
2779     {
2780         if (bShift)
2781         {
2782             SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
2783
2784             if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
2785                 m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
2786                 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
2787
2788             if (m_SelState.IsExist())
2789                 m_SelState.SetEndPos(m_wpCaret);
2790             else
2791                 m_SelState.Set(m_wpOldCaret,m_wpCaret);
2792
2793             if (m_wpOldCaret != m_wpCaret)
2794             {
2795                 ScrollToCaret();
2796                 CPVT_WordRange wr(m_wpOldCaret,m_wpCaret);
2797                 Refresh(RP_OPTIONAL,&wr);
2798                 SetCaretInfo();
2799             }
2800         }
2801         else
2802         {
2803             if (m_SelState.IsExist())
2804             {
2805                 if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)>0)
2806                     SetCaret(m_SelState.BeginPos);
2807                 else
2808                     SetCaret(m_SelState.EndPos);
2809
2810                 SelectNone();
2811                 ScrollToCaret();
2812                 SetCaretInfo();
2813             }
2814             else
2815             {
2816                 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
2817
2818                 if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
2819                     m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
2820                     SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
2821
2822                 ScrollToCaret();
2823                 SetCaretOrigin();
2824                 SetCaretInfo();
2825             }
2826         }
2827     }
2828 }
2829
2830 void CFX_Edit::OnVK_HOME(bool bShift,bool bCtrl)
2831 {
2832     if (m_pVT->IsValid())
2833     {
2834         if (bShift)
2835         {
2836             if (bCtrl)
2837                 SetCaret(m_pVT->GetBeginWordPlace());
2838             else
2839                 SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
2840
2841             if (m_SelState.IsExist())
2842                 m_SelState.SetEndPos(m_wpCaret);
2843             else
2844                 m_SelState.Set(m_wpOldCaret,m_wpCaret);
2845
2846             ScrollToCaret();
2847             CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
2848             Refresh(RP_OPTIONAL, &wr);
2849             SetCaretInfo();
2850         }
2851         else
2852         {
2853             if (m_SelState.IsExist())
2854             {
2855                 if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)<0)
2856                     SetCaret(m_SelState.BeginPos);
2857                 else
2858                     SetCaret(m_SelState.EndPos);
2859
2860                 SelectNone();
2861                 ScrollToCaret();
2862                 SetCaretInfo();
2863             }
2864             else
2865             {
2866                 if (bCtrl)
2867                     SetCaret(m_pVT->GetBeginWordPlace());
2868                 else
2869                     SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
2870
2871                 ScrollToCaret();
2872                 SetCaretOrigin();
2873                 SetCaretInfo();
2874             }
2875         }
2876     }
2877 }
2878
2879 void CFX_Edit::OnVK_END(bool bShift,bool bCtrl)
2880 {
2881     if (m_pVT->IsValid())
2882     {
2883         if (bShift)
2884         {
2885             if (bCtrl)
2886                 SetCaret(m_pVT->GetEndWordPlace());
2887             else
2888                 SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
2889
2890             if (m_SelState.IsExist())
2891                 m_SelState.SetEndPos(m_wpCaret);
2892             else
2893                 m_SelState.Set(m_wpOldCaret, m_wpCaret);
2894
2895             ScrollToCaret();
2896             CPVT_WordRange wr(m_wpOldCaret, m_wpCaret);
2897             Refresh(RP_OPTIONAL, &wr);
2898             SetCaretInfo();
2899         }
2900         else
2901         {
2902             if (m_SelState.IsExist())
2903             {
2904                 if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos)>0)
2905                     SetCaret(m_SelState.BeginPos);
2906                 else
2907                     SetCaret(m_SelState.EndPos);
2908
2909                 SelectNone();
2910                 ScrollToCaret();
2911                 SetCaretInfo();
2912             }
2913             else
2914             {
2915                 if (bCtrl)
2916                     SetCaret(m_pVT->GetEndWordPlace());
2917                 else
2918                     SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
2919
2920                 ScrollToCaret();
2921                 SetCaretOrigin();
2922                 SetCaretInfo();
2923             }
2924         }
2925     }
2926 }
2927
2928 void CFX_Edit::SetText(const FX_WCHAR* text,int32_t charset,
2929                         const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps, bool bAddUndo, bool bPaint)
2930 {
2931     Empty();
2932     DoInsertText(CPVT_WordPlace(0,0,-1), text, charset, pSecProps, pWordProps);
2933     if (bPaint) Paint();
2934     if (m_bOprNotify && m_pOprNotify)
2935         m_pOprNotify->OnSetText(m_wpCaret, m_wpOldCaret);
2936     //if (bAddUndo)
2937 }
2938
2939 bool CFX_Edit::InsertWord(FX_WORD word, int32_t charset, const CPVT_WordProps * pWordProps, bool bAddUndo, bool bPaint)
2940 {
2941     if (IsTextOverflow()) return false;
2942
2943     if (m_pVT->IsValid())
2944     {
2945         m_pVT->UpdateWordPlace(m_wpCaret);
2946
2947         SetCaret(m_pVT->InsertWord(m_wpCaret,word,GetCharSetFromUnicode(word, charset),pWordProps));
2948         m_SelState.Set(m_wpCaret,m_wpCaret);
2949
2950         if (m_wpCaret != m_wpOldCaret)
2951         {
2952             if (bAddUndo && m_bEnableUndo)
2953             {
2954                 AddEditUndoItem(new CFXEU_InsertWord(this,m_wpOldCaret,m_wpCaret,word,charset,pWordProps));
2955             }
2956
2957             if (bPaint)
2958                 PaintInsertText(m_wpOldCaret, m_wpCaret);
2959
2960             if (m_bOprNotify && m_pOprNotify)
2961                 m_pOprNotify->OnInsertWord(m_wpCaret, m_wpOldCaret);
2962
2963             return true;
2964         }
2965     }
2966
2967     return false;
2968 }
2969
2970 bool CFX_Edit::InsertReturn(const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,
2971                                bool bAddUndo, bool bPaint)
2972 {
2973     if (IsTextOverflow()) return false;
2974
2975     if (m_pVT->IsValid())
2976     {
2977         m_pVT->UpdateWordPlace(m_wpCaret);
2978         SetCaret(m_pVT->InsertSection(m_wpCaret,pSecProps,pWordProps));
2979         m_SelState.Set(m_wpCaret,m_wpCaret);
2980
2981         if (m_wpCaret != m_wpOldCaret)
2982         {
2983             if (bAddUndo && m_bEnableUndo)
2984             {
2985                 AddEditUndoItem(new CFXEU_InsertReturn(this,m_wpOldCaret,m_wpCaret,pSecProps,pWordProps));
2986             }
2987
2988             if (bPaint)
2989             {
2990                 RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
2991                 ScrollToCaret();
2992                 CPVT_WordRange wr(m_wpOldCaret, GetVisibleWordRange().EndPos);
2993                 Refresh(RP_ANALYSE, &wr);
2994                 SetCaretOrigin();
2995                 SetCaretInfo();
2996             }
2997
2998             if (m_bOprNotify && m_pOprNotify)
2999                 m_pOprNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret);
3000
3001             return true;
3002         }
3003     }
3004
3005     return false;
3006 }
3007
3008 bool CFX_Edit::Backspace(bool bAddUndo, bool bPaint)
3009 {
3010     if (m_pVT->IsValid())
3011     {
3012         if (m_wpCaret == m_pVT->GetBeginWordPlace()) return false;
3013
3014         CPVT_Section section;
3015         CPVT_Word word;
3016
3017         if (bAddUndo)
3018         {
3019             if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
3020             {
3021                 pIterator->SetAt(m_wpCaret);
3022                 pIterator->GetSection(section);
3023                 pIterator->GetWord(word);
3024             }
3025         }
3026
3027         m_pVT->UpdateWordPlace(m_wpCaret);
3028         SetCaret(m_pVT->BackSpaceWord(m_wpCaret));
3029         m_SelState.Set(m_wpCaret,m_wpCaret);
3030
3031         if (m_wpCaret != m_wpOldCaret)
3032         {
3033             if (bAddUndo && m_bEnableUndo)
3034             {
3035                 if (m_wpCaret.SecCmp(m_wpOldCaret) != 0)
3036                     AddEditUndoItem(new CFXEU_Backspace(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
3037                         section.SecProps,section.WordProps));
3038                 else
3039                     AddEditUndoItem(new CFXEU_Backspace(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
3040                         section.SecProps,word.WordProps));
3041             }
3042
3043             if (bPaint)
3044             {
3045                 RearrangePart(CPVT_WordRange(m_wpCaret,m_wpOldCaret));
3046                 ScrollToCaret();
3047
3048                 CPVT_WordRange wr;
3049                 if (m_wpCaret.SecCmp(m_wpOldCaret) !=0)
3050                     wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpCaret),GetVisibleWordRange().EndPos);
3051                 else if (m_wpCaret.LineCmp(m_wpOldCaret) !=0)
3052                     wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
3053                 else
3054                     wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
3055
3056                 Refresh(RP_ANALYSE, &wr);
3057
3058                 SetCaretOrigin();
3059                 SetCaretInfo();
3060             }
3061
3062             if (m_bOprNotify && m_pOprNotify)
3063                 m_pOprNotify->OnBackSpace(m_wpCaret, m_wpOldCaret);
3064
3065             return true;
3066         }
3067     }
3068
3069     return false;
3070 }
3071
3072 bool CFX_Edit::Delete(bool bAddUndo, bool bPaint)
3073 {
3074     if (m_pVT->IsValid())
3075     {
3076         if (m_wpCaret == m_pVT->GetEndWordPlace()) return false;
3077
3078         CPVT_Section section;
3079         CPVT_Word word;
3080
3081         if (bAddUndo)
3082         {
3083             if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
3084             {
3085                 pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret));
3086                 pIterator->GetSection(section);
3087                 pIterator->GetWord(word);
3088             }
3089         }
3090
3091         m_pVT->UpdateWordPlace(m_wpCaret);
3092         bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret));
3093
3094         SetCaret(m_pVT->DeleteWord(m_wpCaret));
3095         m_SelState.Set(m_wpCaret,m_wpCaret);
3096
3097         if (bAddUndo && m_bEnableUndo)
3098         {
3099             if (bSecEnd)
3100                 AddEditUndoItem(new CFXEU_Delete(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
3101                     section.SecProps,section.WordProps,bSecEnd));
3102             else
3103                 AddEditUndoItem(new CFXEU_Delete(this,m_wpOldCaret,m_wpCaret,word.Word,word.nCharset,
3104                     section.SecProps,word.WordProps,bSecEnd));
3105         }
3106
3107         if (bPaint)
3108         {
3109             RearrangePart(CPVT_WordRange(m_wpOldCaret,m_wpCaret));
3110             ScrollToCaret();
3111
3112             CPVT_WordRange wr;
3113             if (bSecEnd)
3114                 wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpOldCaret),GetVisibleWordRange().EndPos);
3115             else if (m_wpCaret.LineCmp(m_wpOldCaret) !=0)
3116                 wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(m_wpCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
3117             else
3118                 wr = CPVT_WordRange(m_pVT->GetPrevWordPlace(m_wpOldCaret),m_pVT->GetSectionEndPlace(m_wpCaret));
3119
3120             Refresh(RP_ANALYSE, &wr);
3121
3122             SetCaretOrigin();
3123             SetCaretInfo();
3124         }
3125
3126         if (m_bOprNotify && m_pOprNotify)
3127             m_pOprNotify->OnDelete(m_wpCaret, m_wpOldCaret);
3128
3129         return true;
3130     }
3131
3132     return false;
3133 }
3134
3135 bool CFX_Edit::Empty()
3136 {
3137     if (m_pVT->IsValid())
3138     {
3139         m_pVT->DeleteWords(GetWholeWordRange());
3140         SetCaret(m_pVT->GetBeginWordPlace());
3141
3142         return true;
3143     }
3144
3145     return false;
3146 }
3147
3148 bool CFX_Edit::Clear(bool bAddUndo, bool bPaint)
3149 {
3150     if (m_pVT->IsValid())
3151     {
3152         if (m_SelState.IsExist())
3153         {
3154             CPVT_WordRange range = m_SelState.ConvertToWordRange();
3155
3156             if (bAddUndo && m_bEnableUndo)
3157             {
3158                 if (m_pVT->IsRichText())
3159                 {
3160                     BeginGroupUndo(L"");
3161
3162                     if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
3163                     {
3164                         pIterator->SetAt(range.EndPos);
3165
3166                         CPVT_Word wordinfo;
3167                         CPVT_Section secinfo;
3168                         do
3169                         {
3170                             CPVT_WordPlace place = pIterator->GetAt();
3171                             if (place.WordCmp(range.BeginPos) <= 0)break;
3172
3173                             CPVT_WordPlace oldplace = m_pVT->GetPrevWordPlace(place);
3174
3175                             if (oldplace.SecCmp(place) != 0)
3176                             {
3177                                 if (pIterator->GetSection(secinfo))
3178                                 {
3179                                     AddEditUndoItem(new CFXEU_ClearRich(this,oldplace,place,range,wordinfo.Word,
3180                                         wordinfo.nCharset,secinfo.SecProps,secinfo.WordProps));
3181                                 }
3182                             }
3183                             else
3184                             {
3185                                 if (pIterator->GetWord(wordinfo))
3186                                 {
3187                                     oldplace = m_pVT->AjustLineHeader(oldplace,true);
3188                                     place = m_pVT->AjustLineHeader(place,true);
3189
3190                                     AddEditUndoItem(new CFXEU_ClearRich(this,oldplace,place,range,wordinfo.Word,
3191                                         wordinfo.nCharset,secinfo.SecProps,wordinfo.WordProps));
3192                                 }
3193                             }
3194                         }while (pIterator->PrevWord());
3195                     }
3196                     EndGroupUndo();
3197                 }
3198                 else
3199                 {
3200                     AddEditUndoItem(new CFXEU_Clear(this,range,GetSelText()));
3201                 }
3202             }
3203
3204             SelectNone();
3205             SetCaret(m_pVT->DeleteWords(range));
3206             m_SelState.Set(m_wpCaret,m_wpCaret);
3207
3208             if (bPaint)
3209             {
3210                 RearrangePart(range);
3211                 ScrollToCaret();
3212
3213                 CPVT_WordRange wr(m_wpOldCaret, GetVisibleWordRange().EndPos);
3214                 Refresh(RP_ANALYSE, &wr);
3215
3216                 SetCaretOrigin();
3217                 SetCaretInfo();
3218             }
3219
3220             if (m_bOprNotify && m_pOprNotify)
3221                 m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret);
3222
3223             return true;
3224         }
3225     }
3226
3227     return false;
3228 }
3229
3230 bool CFX_Edit::InsertText(const FX_WCHAR* text, int32_t charset,
3231                     const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps, bool bAddUndo, bool bPaint)
3232 {
3233     if (IsTextOverflow()) return false;
3234
3235     m_pVT->UpdateWordPlace(m_wpCaret);
3236     SetCaret(DoInsertText(m_wpCaret, text, charset, pSecProps, pWordProps));
3237     m_SelState.Set(m_wpCaret,m_wpCaret);
3238
3239     if (m_wpCaret != m_wpOldCaret)
3240     {
3241         if (bAddUndo && m_bEnableUndo)
3242         {
3243             AddEditUndoItem(new CFXEU_InsertText(this,m_wpOldCaret,m_wpCaret,text,charset,pSecProps,pWordProps));
3244         }
3245
3246         if (bPaint)
3247             PaintInsertText(m_wpOldCaret, m_wpCaret);
3248
3249         if (m_bOprNotify && m_pOprNotify)
3250             m_pOprNotify->OnInsertText(m_wpCaret, m_wpOldCaret);
3251
3252         return true;
3253     }
3254     return false;
3255 }
3256
3257 void CFX_Edit::PaintInsertText(const CPVT_WordPlace & wpOld, const CPVT_WordPlace & wpNew)
3258 {
3259     if (m_pVT->IsValid())
3260     {
3261         RearrangePart(CPVT_WordRange(wpOld,wpNew));
3262         ScrollToCaret();
3263
3264         CPVT_WordRange wr;
3265         if (m_wpCaret.LineCmp(wpOld) !=0)
3266             wr = CPVT_WordRange(m_pVT->GetLineBeginPlace(wpOld),m_pVT->GetSectionEndPlace(wpNew));
3267         else
3268             wr = CPVT_WordRange(wpOld,m_pVT->GetSectionEndPlace(wpNew));
3269         Refresh(RP_ANALYSE, &wr);
3270         SetCaretOrigin();
3271         SetCaretInfo();
3272     }
3273 }
3274
3275 bool CFX_Edit::Redo()
3276 {
3277     if (m_bEnableUndo)
3278     {
3279         if (m_Undo.CanRedo())
3280         {
3281             m_Undo.Redo();
3282             return true;
3283         }
3284     }
3285
3286     return false;
3287 }
3288
3289 bool CFX_Edit::Undo()
3290 {
3291     if (m_bEnableUndo)
3292     {
3293         if (m_Undo.CanUndo())
3294         {
3295             m_Undo.Undo();
3296             return true;
3297         }
3298     }
3299
3300     return false;
3301 }
3302
3303 void CFX_Edit::SetCaretOrigin()
3304 {
3305     if (m_pVT->IsValid())
3306     {
3307         if (IPDF_VariableText_Iterator * pIterator = m_pVT->GetIterator())
3308         {
3309             pIterator->SetAt(m_wpCaret);
3310             CPVT_Word word;
3311             CPVT_Line line;
3312             if (pIterator->GetWord(word))
3313             {
3314                 m_ptCaret.x = word.ptWord.x + word.fWidth;
3315                 m_ptCaret.y = word.ptWord.y;
3316             }
3317             else if (pIterator->GetLine(line))
3318             {
3319                 m_ptCaret.x = line.ptLine.x;
3320                 m_ptCaret.y = line.ptLine.y;
3321             }
3322         }
3323     }
3324 }
3325
3326 int32_t CFX_Edit::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
3327 {
3328     if (m_pVT->IsValid())
3329         return m_pVT->WordPlaceToWordIndex(place);
3330
3331     return -1;
3332 }
3333
3334 CPVT_WordPlace CFX_Edit::WordIndexToWordPlace(int32_t index) const
3335 {
3336     if (m_pVT->IsValid())
3337         return m_pVT->WordIndexToWordPlace(index);
3338
3339     return CPVT_WordPlace();
3340 }
3341
3342 bool CFX_Edit::IsTextFull() const
3343 {
3344     int32_t nTotalWords = m_pVT->GetTotalWords();
3345     int32_t nLimitChar = m_pVT->GetLimitChar();
3346     int32_t nCharArray = m_pVT->GetCharArray();
3347
3348     return IsTextOverflow() || (nLimitChar>0 && nTotalWords >= nLimitChar)
3349         || (nCharArray>0 && nTotalWords >= nCharArray);
3350 }
3351
3352 bool CFX_Edit::IsTextOverflow() const
3353 {
3354     if (!m_bEnableScroll && !m_bEnableOverflow)
3355     {
3356         CPDF_Rect rcPlate = m_pVT->GetPlateRect();
3357         CPDF_Rect rcContent = m_pVT->GetContentRect();
3358
3359         if (m_pVT->IsMultiLine() && GetTotalLines() > 1)
3360         {
3361             if (FX_EDIT_IsFloatBigger(rcContent.Height(),rcPlate.Height())) return true;
3362         }
3363
3364         if (FX_EDIT_IsFloatBigger(rcContent.Width(),rcPlate.Width())) return true;
3365     }
3366
3367     return false;
3368 }
3369
3370 CPVT_WordPlace CFX_Edit::GetLineBeginPlace(const CPVT_WordPlace & place) const
3371 {
3372     return m_pVT->GetLineBeginPlace(place);
3373 }
3374
3375 CPVT_WordPlace CFX_Edit::GetLineEndPlace(const CPVT_WordPlace & place) const
3376 {
3377     return m_pVT->GetLineEndPlace(place);
3378 }
3379
3380 CPVT_WordPlace CFX_Edit::GetSectionBeginPlace(const CPVT_WordPlace & place) const
3381 {
3382     return m_pVT->GetSectionBeginPlace(place);
3383 }
3384
3385 CPVT_WordPlace CFX_Edit::GetSectionEndPlace(const CPVT_WordPlace & place) const
3386 {
3387     return m_pVT->GetSectionEndPlace(place);
3388 }
3389
3390 bool CFX_Edit::CanUndo() const
3391 {
3392     if (m_bEnableUndo)
3393     {
3394         return m_Undo.CanUndo();
3395     }
3396
3397     return false;
3398 }
3399
3400 bool CFX_Edit::CanRedo() const
3401 {
3402     if (m_bEnableUndo)
3403     {
3404         return m_Undo.CanRedo();
3405     }
3406
3407     return false;
3408 }
3409
3410 bool CFX_Edit::IsModified() const
3411 {
3412     if (m_bEnableUndo)
3413     {
3414         return m_Undo.IsModified();
3415     }
3416
3417     return false;
3418 }
3419
3420 void CFX_Edit::EnableRefresh(bool bRefresh)
3421 {
3422     m_bEnableRefresh = bRefresh;
3423 }
3424
3425 void CFX_Edit::EnableUndo(bool bUndo)
3426 {
3427     m_bEnableUndo = bUndo;
3428 }
3429
3430 void CFX_Edit::EnableNotify(bool bNotify)
3431 {
3432     m_bNotify = bNotify;
3433 }
3434
3435 void CFX_Edit::EnableOprNotify(bool bNotify)
3436 {
3437     m_bOprNotify = bNotify;
3438 }
3439
3440 FX_FLOAT CFX_Edit::GetLineTop(const CPVT_WordPlace& place) const
3441 {
3442     if (IPDF_VariableText_Iterator* pIterator = m_pVT->GetIterator())
3443     {
3444         CPVT_WordPlace wpOld = pIterator->GetAt();
3445
3446         pIterator->SetAt(place);
3447         CPVT_Line line;
3448         pIterator->GetLine(line);
3449
3450         pIterator->SetAt(wpOld);
3451
3452         return line.ptLine.y + line.fLineAscent;
3453     }
3454
3455     return 0.0f;
3456 }
3457
3458 FX_FLOAT CFX_Edit::GetLineBottom(const CPVT_WordPlace& place) const
3459 {
3460     if (IPDF_VariableText_Iterator* pIterator = m_pVT->GetIterator())
3461     {
3462         CPVT_WordPlace wpOld = pIterator->GetAt();
3463
3464         pIterator->SetAt(place);
3465         CPVT_Line line;
3466         pIterator->GetLine(line);
3467
3468         pIterator->SetAt(wpOld);
3469
3470         return line.ptLine.y + line.fLineDescent;
3471     }
3472
3473     return 0.0f;
3474 }
3475
3476 CPVT_WordPlace CFX_Edit::DoInsertText(const CPVT_WordPlace& place, const FX_WCHAR* text, int32_t charset,
3477                                       const CPVT_SecProps * pSecProps, const CPVT_WordProps * pWordProps)
3478 {
3479     CPVT_WordPlace wp = place;
3480
3481     if (m_pVT->IsValid())
3482     {
3483         CFX_WideString sText = text;
3484
3485         for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++)
3486         {
3487             FX_WORD word = sText[i];
3488             switch (word)
3489             {
3490             case 0x0D:
3491                 wp = m_pVT->InsertSection(wp,pSecProps,pWordProps);
3492                 if (sText[i+1] == 0x0A)
3493                     i++;
3494                 break;
3495             case 0x0A:
3496                 wp = m_pVT->InsertSection(wp,pSecProps,pWordProps);
3497                 if (sText[i+1] == 0x0D)
3498                     i++;
3499                 break;
3500             case 0x09:
3501                 word = 0x20;
3502             default:
3503                 wp = m_pVT->InsertWord(wp,word,GetCharSetFromUnicode(word, charset),pWordProps);
3504                 break;
3505             }
3506         }
3507     }
3508
3509     return wp;
3510 }
3511
3512 int32_t CFX_Edit::GetCharSetFromUnicode(FX_WORD word, int32_t nOldCharset)
3513 {
3514     if (IFX_Edit_FontMap* pFontMap = GetFontMap())
3515         return pFontMap->CharSetFromUnicode(word, nOldCharset);
3516     return nOldCharset;
3517 }
3518
3519 void CFX_Edit::BeginGroupUndo(const CFX_WideString& sTitle)
3520 {
3521     ASSERT(m_pGroupUndoItem == NULL);
3522
3523     m_pGroupUndoItem = new CFX_Edit_GroupUndoItem(sTitle);
3524 }
3525
3526 void CFX_Edit::EndGroupUndo()
3527 {
3528     ASSERT(m_pGroupUndoItem != NULL);
3529
3530     m_pGroupUndoItem->UpdateItems();
3531     m_Undo.AddItem(m_pGroupUndoItem);
3532     if (m_bOprNotify && m_pOprNotify)
3533         m_pOprNotify->OnAddUn