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 
CFX_Edit_Iterator(CFX_Edit * pEdit,IPDF_VariableText_Iterator * pVTIterator)15 CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit* pEdit,
16                                      IPDF_VariableText_Iterator* pVTIterator)
17     : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {}
18 
~CFX_Edit_Iterator()19 CFX_Edit_Iterator::~CFX_Edit_Iterator() {}
20 
NextWord()21 FX_BOOL CFX_Edit_Iterator::NextWord() {
22   return m_pVTIterator->NextWord();
23 }
24 
NextLine()25 FX_BOOL CFX_Edit_Iterator::NextLine() {
26   return m_pVTIterator->NextLine();
27 }
28 
NextSection()29 FX_BOOL CFX_Edit_Iterator::NextSection() {
30   return m_pVTIterator->NextSection();
31 }
32 
PrevWord()33 FX_BOOL CFX_Edit_Iterator::PrevWord() {
34   return m_pVTIterator->PrevWord();
35 }
36 
PrevLine()37 FX_BOOL CFX_Edit_Iterator::PrevLine() {
38   return m_pVTIterator->PrevLine();
39 }
40 
PrevSection()41 FX_BOOL CFX_Edit_Iterator::PrevSection() {
42   return m_pVTIterator->PrevSection();
43 }
44 
GetWord(CPVT_Word & word) const45 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 
GetLine(CPVT_Line & line) const55 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 
GetSection(CPVT_Section & section) const65 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 
SetAt(int32_t nWordIndex)75 void CFX_Edit_Iterator::SetAt(int32_t nWordIndex) {
76   m_pVTIterator->SetAt(nWordIndex);
77 }
78 
SetAt(const CPVT_WordPlace & place)79 void CFX_Edit_Iterator::SetAt(const CPVT_WordPlace& place) {
80   m_pVTIterator->SetAt(place);
81 }
82 
GetAt() const83 const CPVT_WordPlace& CFX_Edit_Iterator::GetAt() const {
84   return m_pVTIterator->GetAt();
85 }
86 
GetEdit() const87 IFX_Edit* CFX_Edit_Iterator::GetEdit() const {
88   return m_pEdit;
89 }
90 
CFX_Edit_Provider(IFX_Edit_FontMap * pFontMap)91 CFX_Edit_Provider::CFX_Edit_Provider(IFX_Edit_FontMap* pFontMap)
92     : m_pFontMap(pFontMap) {
93   ASSERT(m_pFontMap);
94 }
95 
~CFX_Edit_Provider()96 CFX_Edit_Provider::~CFX_Edit_Provider() {}
97 
GetFontMap()98 IFX_Edit_FontMap* CFX_Edit_Provider::GetFontMap() {
99   return m_pFontMap;
100 }
101 
GetCharWidth(int32_t nFontIndex,FX_WORD word,int32_t nWordStyle)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 
GetTypeAscent(int32_t nFontIndex)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 
GetTypeDescent(int32_t nFontIndex)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 
GetWordFontIndex(FX_WORD word,int32_t charset,int32_t nFontIndex)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 
GetDefaultFontIndex()140 int32_t CFX_Edit_Provider::GetDefaultFontIndex() {
141   return 0;
142 }
143 
IsLatinWord(FX_WORD word)144 FX_BOOL CFX_Edit_Provider::IsLatinWord(FX_WORD word) {
145   return FX_EDIT_ISLATINWORD(word);
146 }
147 
CFX_Edit_Refresh()148 CFX_Edit_Refresh::CFX_Edit_Refresh() {}
149 
~CFX_Edit_Refresh()150 CFX_Edit_Refresh::~CFX_Edit_Refresh() {}
151 
BeginRefresh()152 void CFX_Edit_Refresh::BeginRefresh() {
153   m_RefreshRects.Empty();
154   m_OldLineRects = m_NewLineRects;
155 }
156 
Push(const CPVT_WordRange & linerange,const CPDF_Rect & rect)157 void CFX_Edit_Refresh::Push(const CPVT_WordRange& linerange,
158                             const CPDF_Rect& rect) {
159   m_NewLineRects.Add(linerange, rect);
160 }
161 
NoAnalyse()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 
Analyse(int32_t nAlignment)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 
AddRefresh(const CPDF_Rect & rect)243 void CFX_Edit_Refresh::AddRefresh(const CPDF_Rect& rect) {
244   m_RefreshRects.Add(rect);
245 }
246 
GetRefreshRects() const247 const CFX_Edit_RectArray* CFX_Edit_Refresh::GetRefreshRects() const {
248   return &m_RefreshRects;
249 }
250 
EndRefresh()251 void CFX_Edit_Refresh::EndRefresh() {
252   m_RefreshRects.Empty();
253 }
254 
CFX_Edit_Undo(int32_t nBufsize)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 
~CFX_Edit_Undo()262 CFX_Edit_Undo::~CFX_Edit_Undo() {
263   Reset();
264 }
265 
CanUndo() const266 FX_BOOL CFX_Edit_Undo::CanUndo() const {
267   return m_nCurUndoPos > 0;
268 }
269 
Undo()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 
CanRedo() const284 FX_BOOL CFX_Edit_Undo::CanRedo() const {
285   return m_nCurUndoPos < m_UndoItemStack.GetSize();
286 }
287 
Redo()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 
IsWorking() const304 FX_BOOL CFX_Edit_Undo::IsWorking() const {
305   return m_bWorking;
306 }
307 
AddItem(IFX_Edit_UndoItem * pItem)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 
IsModified() const327 FX_BOOL CFX_Edit_Undo::IsModified() const {
328   return m_bVirgin ? m_bModified : TRUE;
329 }
330 
GetItem(int32_t nIndex)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 
RemoveHeads()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 
RemoveTails()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 
Reset()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 
CFX_Edit_GroupUndoItem(const CFX_WideString & sTitle)360 CFX_Edit_GroupUndoItem::CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle)
361     : m_sTitle(sTitle) {}
362 
~CFX_Edit_GroupUndoItem()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 
AddUndoItem(CFX_Edit_UndoItem * pUndoItem)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 
UpdateItems()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 
Undo()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 
Redo()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 
GetUndoTitle()405 CFX_WideString CFX_Edit_GroupUndoItem::GetUndoTitle() {
406   return m_sTitle;
407 }
408 
CFXEU_InsertWord(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,FX_WORD word,int32_t charset,const CPVT_WordProps * pWordProps)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 
~CFXEU_InsertWord()425 CFXEU_InsertWord::~CFXEU_InsertWord() {}
426 
Redo()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 
Undo()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 
CFXEU_InsertReturn(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
~CFXEU_InsertReturn()459 CFXEU_InsertReturn::~CFXEU_InsertReturn() {}
460 
Redo()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 
Undo()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 
CFXEU_Backspace(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,FX_WORD word,int32_t charset,const CPVT_SecProps & SecProps,const CPVT_WordProps & WordProps)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 
~CFXEU_Backspace()492 CFXEU_Backspace::~CFXEU_Backspace() {}
493 
Redo()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 
Undo()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 
CFXEU_Delete(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,FX_WORD word,int32_t charset,const CPVT_SecProps & SecProps,const CPVT_WordProps & WordProps,FX_BOOL bSecEnd)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 
~CFXEU_Delete()531 CFXEU_Delete::~CFXEU_Delete() {}
532 
Redo()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 
Undo()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 
CFXEU_Clear(CFX_Edit * pEdit,const CPVT_WordRange & wrSel,const CFX_WideString & swText)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 
~CFXEU_Clear()558 CFXEU_Clear::~CFXEU_Clear() {}
559 
Redo()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 
Undo()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 
CFXEU_ClearRich(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,const CPVT_WordRange & wrSel,FX_WORD word,int32_t charset,const CPVT_SecProps & SecProps,const CPVT_WordProps & WordProps)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 
~CFXEU_ClearRich()595 CFXEU_ClearRich::~CFXEU_ClearRich() {}
596 
Redo()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 
Undo()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 }
CFXEU_InsertText(CFX_Edit * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,const CFX_WideString & swText,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
~CFXEU_InsertText()641 CFXEU_InsertText::~CFXEU_InsertText() {}
642 
Redo()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 
Undo()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 
CFXEU_SetSecProps(CFX_Edit * pEdit,const CPVT_WordPlace & place,EDIT_PROPS_E ep,const CPVT_SecProps & oldsecprops,const CPVT_WordProps & oldwordprops,const CPVT_SecProps & newsecprops,const CPVT_WordProps & newwordprops,const CPVT_WordRange & range)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 
~CFXEU_SetSecProps()677 CFXEU_SetSecProps::~CFXEU_SetSecProps() {}
678 
Redo()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 
Undo()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 
CFXEU_SetWordProps(CFX_Edit * pEdit,const CPVT_WordPlace & place,EDIT_PROPS_E ep,const CPVT_WordProps & oldprops,const CPVT_WordProps & newprops,const CPVT_WordRange & range)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 
~CFXEU_SetWordProps()716 CFXEU_SetWordProps::~CFXEU_SetWordProps() {}
717 
Redo()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 
Undo()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 
CFX_Edit(IPDF_VariableText * pVT)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 
~CFX_Edit()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 
Initialize()776 void CFX_Edit::Initialize() {
777   m_pVT->Initialize();
778   SetCaret(m_pVT->GetBeginWordPlace());
779   SetCaretOrigin();
780 }
781 
SetFontMap(IFX_Edit_FontMap * pFontMap)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 
SetVTProvider(IPDF_VariableText_Provider * pProvider)787 void CFX_Edit::SetVTProvider(IPDF_VariableText_Provider* pProvider) {
788   m_pVT->SetProvider(pProvider);
789 }
790 
SetNotify(IFX_Edit_Notify * pNotify)791 void CFX_Edit::SetNotify(IFX_Edit_Notify* pNotify) {
792   m_pNotify = pNotify;
793 }
794 
SetOprNotify(IFX_Edit_OprNotify * pOprNotify)795 void CFX_Edit::SetOprNotify(IFX_Edit_OprNotify* pOprNotify) {
796   m_pOprNotify = pOprNotify;
797 }
798 
GetIterator()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 
GetVariableText()806 IPDF_VariableText* CFX_Edit::GetVariableText() {
807   return m_pVT;
808 }
809 
GetFontMap()810 IFX_Edit_FontMap* CFX_Edit::GetFontMap() {
811   if (m_pVTProvide)
812     return m_pVTProvide->GetFontMap();
813 
814   return NULL;
815 }
816 
SetPlateRect(const CPDF_Rect & rect,FX_BOOL bPaint)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 
SetAlignmentH(int32_t nFormat,FX_BOOL bPaint)824 void CFX_Edit::SetAlignmentH(int32_t nFormat, FX_BOOL bPaint) {
825   m_pVT->SetAlignment(nFormat);
826   if (bPaint)
827     Paint();
828 }
829 
SetAlignmentV(int32_t nFormat,FX_BOOL bPaint)830 void CFX_Edit::SetAlignmentV(int32_t nFormat, FX_BOOL bPaint) {
831   m_nAlignment = nFormat;
832   if (bPaint)
833     Paint();
834 }
835 
SetPasswordChar(FX_WORD wSubWord,FX_BOOL bPaint)836 void CFX_Edit::SetPasswordChar(FX_WORD wSubWord, FX_BOOL bPaint) {
837   m_pVT->SetPasswordChar(wSubWord);
838   if (bPaint)
839     Paint();
840 }
841 
SetLimitChar(int32_t nLimitChar,FX_BOOL bPaint)842 void CFX_Edit::SetLimitChar(int32_t nLimitChar, FX_BOOL bPaint) {
843   m_pVT->SetLimitChar(nLimitChar);
844   if (bPaint)
845     Paint();
846 }
847 
SetCharArray(int32_t nCharArray,FX_BOOL bPaint)848 void CFX_Edit::SetCharArray(int32_t nCharArray, FX_BOOL bPaint) {
849   m_pVT->SetCharArray(nCharArray);
850   if (bPaint)
851     Paint();
852 }
853 
SetCharSpace(FX_FLOAT fCharSpace,FX_BOOL bPaint)854 void CFX_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint) {
855   m_pVT->SetCharSpace(fCharSpace);
856   if (bPaint)
857     Paint();
858 }
859 
SetHorzScale(int32_t nHorzScale,FX_BOOL bPaint)860 void CFX_Edit::SetHorzScale(int32_t nHorzScale, FX_BOOL bPaint) {
861   m_pVT->SetHorzScale(nHorzScale);
862   if (bPaint)
863     Paint();
864 }
865 
SetMultiLine(FX_BOOL bMultiLine,FX_BOOL bPaint)866 void CFX_Edit::SetMultiLine(FX_BOOL bMultiLine, FX_BOOL bPaint) {
867   m_pVT->SetMultiLine(bMultiLine);
868   if (bPaint)
869     Paint();
870 }
871 
SetAutoReturn(FX_BOOL bAuto,FX_BOOL bPaint)872 void CFX_Edit::SetAutoReturn(FX_BOOL bAuto, FX_BOOL bPaint) {
873   m_pVT->SetAutoReturn(bAuto);
874   if (bPaint)
875     Paint();
876 }
877 
SetLineLeading(FX_FLOAT fLineLeading,FX_BOOL bPaint)878 void CFX_Edit::SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint) {
879   m_pVT->SetLineLeading(fLineLeading);
880   if (bPaint)
881     Paint();
882 }
883 
SetAutoFontSize(FX_BOOL bAuto,FX_BOOL bPaint)884 void CFX_Edit::SetAutoFontSize(FX_BOOL bAuto, FX_BOOL bPaint) {
885   m_pVT->SetAutoFontSize(bAuto);
886   if (bPaint)
887     Paint();
888 }
889 
SetFontSize(FX_FLOAT fFontSize,FX_BOOL bPaint)890 void CFX_Edit::SetFontSize(FX_FLOAT fFontSize, FX_BOOL bPaint) {
891   m_pVT->SetFontSize(fFontSize);
892   if (bPaint)
893     Paint();
894 }
895 
SetAutoScroll(FX_BOOL bAuto,FX_BOOL bPaint)896 void CFX_Edit::SetAutoScroll(FX_BOOL bAuto, FX_BOOL bPaint) {
897   m_bEnableScroll = bAuto;
898   if (bPaint)
899     Paint();
900 }
901 
SetTextOverflow(FX_BOOL bAllowed,FX_BOOL bPaint)902 void CFX_Edit::SetTextOverflow(FX_BOOL bAllowed, FX_BOOL bPaint) {
903   m_bEnableOverflow = bAllowed;
904   if (bPaint)
905     Paint();
906 }
907 
SetSel(int32_t nStartChar,int32_t nEndChar)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 
SetSel(const CPVT_WordPlace & begin,const CPVT_WordPlace & end)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 
GetSel(int32_t & nStartChar,int32_t & nEndChar) const946 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 
GetCaret() const966 int32_t CFX_Edit::GetCaret() const {
967   if (m_pVT->IsValid())
968     return m_pVT->WordPlaceToWordIndex(m_wpCaret);
969 
970   return -1;
971 }
972 
GetCaretWordPlace() const973 CPVT_WordPlace CFX_Edit::GetCaretWordPlace() const {
974   return m_wpCaret;
975 }
976 
GetText() const977 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 
GetRangeText(const CPVT_WordRange & range) const1012 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 
GetSelText() const1052 CFX_WideString CFX_Edit::GetSelText() const {
1053   return GetRangeText(m_SelState.ConvertToWordRange());
1054 }
1055 
GetTotalWords() const1056 int32_t CFX_Edit::GetTotalWords() const {
1057   return m_pVT->GetTotalWords();
1058 }
1059 
GetTotalLines() const1060 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 
GetSelectWordRange() const1072 CPVT_WordRange CFX_Edit::GetSelectWordRange() const {
1073   return m_SelState.ConvertToWordRange();
1074 }
1075 
CombineWordRange(const CPVT_WordRange & wr1,const CPVT_WordRange & wr2)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 
IsRichText() const1095 FX_BOOL CFX_Edit::IsRichText() const {
1096   return m_pVT->IsRichText();
1097 }
1098 
SetRichText(FX_BOOL bRichText,FX_BOOL bPaint)1099 void CFX_Edit::SetRichText(FX_BOOL bRichText, FX_BOOL bPaint) {
1100   m_pVT->SetRichText(bRichText);
1101   if (bPaint)
1102     Paint();
1103 }
1104 
SetRichFontIndex(int32_t nFontIndex)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 
SetRichFontSize(FX_FLOAT fFontSize)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 
SetRichTextColor(FX_COLORREF dwColor)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 
SetRichTextScript(int32_t nScriptType)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 
SetRichTextBold(FX_BOOL bBold)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 
SetRichTextItalic(FX_BOOL bItalic)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 
SetRichTextUnderline(FX_BOOL bUnderline)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 
SetRichTextCrossout(FX_BOOL bCrossout)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 
SetRichTextCharSpace(FX_FLOAT fCharSpace)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 
SetRichTextHorzScale(int32_t nHorzScale)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 
SetRichTextLineLeading(FX_FLOAT fLineLeading)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 
SetRichTextLineIndent(FX_FLOAT fLineIndent)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 
SetRichTextAlignment(int32_t nAlignment)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 
SetRichTextProps(EDIT_PROPS_E eProps,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
PaintSetProps(EDIT_PROPS_E eProps,const CPVT_WordRange & wr)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 
SetSecProps(EDIT_PROPS_E eProps,const CPVT_WordPlace & place,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,const CPVT_WordRange & wr,FX_BOOL bAddUndo)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 
SetWordProps(EDIT_PROPS_E eProps,const CPVT_WordPlace & place,const CPVT_WordProps * pWordProps,const CPVT_WordRange & wr,FX_BOOL bAddUndo)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 
SetText(const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
InsertWord(FX_WORD word,int32_t charset,const CPVT_WordProps * pWordProps)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 
InsertReturn(const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)1598 FX_BOOL CFX_Edit::InsertReturn(const CPVT_SecProps* pSecProps,
1599                                const CPVT_WordProps* pWordProps) {
1600   return InsertReturn(pSecProps, pWordProps, TRUE, TRUE);
1601 }
1602 
Backspace()1603 FX_BOOL CFX_Edit::Backspace() {
1604   return Backspace(TRUE, TRUE);
1605 }
1606 
Delete()1607 FX_BOOL CFX_Edit::Delete() {
1608   return Delete(TRUE, TRUE);
1609 }
1610 
Clear()1611 FX_BOOL CFX_Edit::Clear() {
1612   return Clear(TRUE, TRUE);
1613 }
1614 
InsertText(const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
GetFontSize() const1622 FX_FLOAT CFX_Edit::GetFontSize() const {
1623   return m_pVT->GetFontSize();
1624 }
1625 
GetPasswordChar() const1626 FX_WORD CFX_Edit::GetPasswordChar() const {
1627   return m_pVT->GetPasswordChar();
1628 }
1629 
GetCharArray() const1630 int32_t CFX_Edit::GetCharArray() const {
1631   return m_pVT->GetCharArray();
1632 }
1633 
GetPlateRect() const1634 CPDF_Rect CFX_Edit::GetPlateRect() const {
1635   return m_pVT->GetPlateRect();
1636 }
1637 
GetContentRect() const1638 CPDF_Rect CFX_Edit::GetContentRect() const {
1639   return VTToEdit(m_pVT->GetContentRect());
1640 }
1641 
GetHorzScale() const1642 int32_t CFX_Edit::GetHorzScale() const {
1643   return m_pVT->GetHorzScale();
1644 }
1645 
GetCharSpace() const1646 FX_FLOAT CFX_Edit::GetCharSpace() const {
1647   return m_pVT->GetCharSpace();
1648 }
1649 
GetWholeWordRange() const1650 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 
GetVisibleWordRange() const1657 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 
SearchWordPlace(const CPDF_Point & point) const1675 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 
Paint()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 
RearrangeAll()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 
RearrangePart(const CPVT_WordRange & range)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 
SetContentChanged()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 
SelectAll()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 
SelectNone()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 
IsSelected() const1750 FX_BOOL CFX_Edit::IsSelected() const {
1751   return m_SelState.IsExist();
1752 }
1753 
VTToEdit(const CPDF_Point & point) const1754 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 
EditToVT(const CPDF_Point & point) const1776 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 
VTToEdit(const CPDF_Rect & rect) const1798 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 
EditToVT(const CPDF_Rect & rect) const1805 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 
SetScrollInfo()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 
SetScrollPosX(FX_FLOAT fx)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 
SetScrollPosY(FX_FLOAT fy)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 
SetScrollPos(const CPDF_Point & point)1871 void CFX_Edit::SetScrollPos(const CPDF_Point& point) {
1872   SetScrollPosX(point.x);
1873   SetScrollPosY(point.y);
1874   SetScrollLimit();
1875   SetCaretInfo();
1876 }
1877 
GetScrollPos() const1878 CPDF_Point CFX_Edit::GetScrollPos() const {
1879   return m_ptScrollPos;
1880 }
1881 
SetScrollLimit()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 
ScrollToCaret()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 
Refresh(REFRESH_PLAN_E ePlan,const CPVT_WordRange * pRange1,const CPVT_WordRange * pRange2)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 
RefreshPushLineRects(const CPVT_WordRange & wr)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 
RefreshPushRandomRects(const CPVT_WordRange & wr)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 
RefreshWordRange(const CPVT_WordRange & wr)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 
SetCaret(const CPVT_WordPlace & place)2118 void CFX_Edit::SetCaret(const CPVT_WordPlace& place) {
2119   m_wpOldCaret = m_wpCaret;
2120   m_wpCaret = place;
2121 }
2122 
SetCaretInfo()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 
SetCaretChange()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 
SetCaret(int32_t nPos)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 
OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)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 
OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl)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 
OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl)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 
SetText(const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,FX_BOOL bAddUndo,FX_BOOL bPaint)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 
InsertWord(FX_WORD word,int32_t charset,const CPVT_WordProps * pWordProps,FX_BOOL bAddUndo,FX_BOOL bPaint)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 
InsertReturn(const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,FX_BOOL bAddUndo,FX_BOOL bPaint)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 
Backspace(FX_BOOL bAddUndo,FX_BOOL bPaint)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 
Delete(FX_BOOL bAddUndo,FX_BOOL bPaint)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 
Empty()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 
Clear(FX_BOOL bAddUndo,FX_BOOL bPaint)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 
InsertText(const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps,FX_BOOL bAddUndo,FX_BOOL bPaint)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 
PaintInsertText(const CPVT_WordPlace & wpOld,const CPVT_WordPlace & wpNew)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 
Redo()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 
Undo()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 
SetCaretOrigin()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 
WordPlaceToWordIndex(const CPVT_WordPlace & place) const2831 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 
WordIndexToWordPlace(int32_t index) const2838 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 
IsTextFull() const2845 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 
IsTextOverflow() const2854 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 
GetLineBeginPlace(const CPVT_WordPlace & place) const2871 CPVT_WordPlace CFX_Edit::GetLineBeginPlace(const CPVT_WordPlace& place) const {
2872   return m_pVT->GetLineBeginPlace(place);
2873 }
2874 
GetLineEndPlace(const CPVT_WordPlace & place) const2875 CPVT_WordPlace CFX_Edit::GetLineEndPlace(const CPVT_WordPlace& place) const {
2876   return m_pVT->GetLineEndPlace(place);
2877 }
2878 
GetSectionBeginPlace(const CPVT_WordPlace & place) const2879 CPVT_WordPlace CFX_Edit::GetSectionBeginPlace(
2880     const CPVT_WordPlace& place) const {
2881   return m_pVT->GetSectionBeginPlace(place);
2882 }
2883 
GetSectionEndPlace(const CPVT_WordPlace & place) const2884 CPVT_WordPlace CFX_Edit::GetSectionEndPlace(const CPVT_WordPlace& place) const {
2885   return m_pVT->GetSectionEndPlace(place);
2886 }
2887 
CanUndo() const2888 FX_BOOL CFX_Edit::CanUndo() const {
2889   if (m_bEnableUndo) {
2890     return m_Undo.CanUndo();
2891   }
2892 
2893   return FALSE;
2894 }
2895 
CanRedo() const2896 FX_BOOL CFX_Edit::CanRedo() const {
2897   if (m_bEnableUndo) {
2898     return m_Undo.CanRedo();
2899   }
2900 
2901   return FALSE;
2902 }
2903 
IsModified() const2904 FX_BOOL CFX_Edit::IsModified() const {
2905   if (m_bEnableUndo) {
2906     return m_Undo.IsModified();
2907   }
2908 
2909   return FALSE;
2910 }
2911 
EnableRefresh(FX_BOOL bRefresh)2912 void CFX_Edit::EnableRefresh(FX_BOOL bRefresh) {
2913   m_bEnableRefresh = bRefresh;
2914 }
2915 
EnableUndo(FX_BOOL bUndo)2916 void CFX_Edit::EnableUndo(FX_BOOL bUndo) {
2917   m_bEnableUndo = bUndo;
2918 }
2919 
EnableNotify(FX_BOOL bNotify)2920 void CFX_Edit::EnableNotify(FX_BOOL bNotify) {
2921   m_bNotify = bNotify;
2922 }
2923 
EnableOprNotify(FX_BOOL bNotify)2924 void CFX_Edit::EnableOprNotify(FX_BOOL bNotify) {
2925   m_bOprNotify = bNotify;
2926 }
2927 
GetLineTop(const CPVT_WordPlace & place) const2928 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 
GetLineBottom(const CPVT_WordPlace & place) const2944 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 
DoInsertText(const CPVT_WordPlace & place,const FX_WCHAR * text,int32_t charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)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 
GetCharSetFromUnicode(FX_WORD word,int32_t nOldCharset)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 
BeginGroupUndo(const CFX_WideString & sTitle)3002 void CFX_Edit::BeginGroupUndo(const CFX_WideString& sTitle) {
3003   ASSERT(!m_pGroupUndoItem);
3004 
3005   m_pGroupUndoItem = new CFX_Edit_GroupUndoItem(sTitle);
3006 }
3007 
EndGroupUndo()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 
AddEditUndoItem(CFX_Edit_UndoItem * pEditUndoItem)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 
AddUndoItem(IFX_Edit_UndoItem * pUndoItem)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