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