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/pwl/cpwl_edit_impl.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <sstream>
12 #include <utility>
13
14 #include "core/fpdfapi/font/cpdf_font.h"
15 #include "core/fpdfapi/page/cpdf_pageobject.h"
16 #include "core/fpdfapi/page/cpdf_pageobjectholder.h"
17 #include "core/fpdfapi/page/cpdf_pathobject.h"
18 #include "core/fpdfapi/page/cpdf_textobject.h"
19 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
20 #include "core/fpdfapi/render/cpdf_renderoptions.h"
21 #include "core/fpdfapi/render/cpdf_textrenderer.h"
22 #include "core/fpdfdoc/cpvt_word.h"
23 #include "core/fpdfdoc/ipvt_fontmap.h"
24 #include "core/fxcrt/autorestorer.h"
25 #include "core/fxcrt/fx_codepage.h"
26 #include "core/fxge/cfx_graphstatedata.h"
27 #include "core/fxge/cfx_pathdata.h"
28 #include "core/fxge/cfx_renderdevice.h"
29 #include "fpdfsdk/cfx_systemhandler.h"
30 #include "fpdfsdk/pwl/cpwl_edit.h"
31 #include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
32 #include "fpdfsdk/pwl/cpwl_scroll_bar.h"
33 #include "third_party/base/ptr_util.h"
34 #include "third_party/base/stl_util.h"
35
36 namespace {
37
38 const int kEditUndoMaxItems = 10000;
39
DrawTextString(CFX_RenderDevice * pDevice,const CFX_PointF & pt,CPDF_Font * pFont,float fFontSize,const CFX_Matrix & mtUser2Device,const ByteString & str,FX_ARGB crTextFill,int32_t nHorzScale)40 void DrawTextString(CFX_RenderDevice* pDevice,
41 const CFX_PointF& pt,
42 CPDF_Font* pFont,
43 float fFontSize,
44 const CFX_Matrix& mtUser2Device,
45 const ByteString& str,
46 FX_ARGB crTextFill,
47 int32_t nHorzScale) {
48 if (!pFont)
49 return;
50
51 CFX_PointF pos = mtUser2Device.Transform(pt);
52 CFX_Matrix mt;
53 if (nHorzScale == 100) {
54 mt = mtUser2Device;
55 } else {
56 mt = CFX_Matrix(nHorzScale / 100.0f, 0, 0, 1, 0, 0);
57 mt.Concat(mtUser2Device);
58 }
59
60 CPDF_RenderOptions ro;
61 ro.SetFlags(RENDER_CLEARTYPE);
62
63 ro.SetColorMode(CPDF_RenderOptions::kNormal);
64 CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize,
65 &mt, str, crTextFill, nullptr, &ro);
66 }
67
68 } // namespace
69
CPWL_EditImpl_Iterator(CPWL_EditImpl * pEdit,CPDF_VariableText::Iterator * pVTIterator)70 CPWL_EditImpl_Iterator::CPWL_EditImpl_Iterator(
71 CPWL_EditImpl* pEdit,
72 CPDF_VariableText::Iterator* pVTIterator)
73 : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {}
74
~CPWL_EditImpl_Iterator()75 CPWL_EditImpl_Iterator::~CPWL_EditImpl_Iterator() {}
76
NextWord()77 bool CPWL_EditImpl_Iterator::NextWord() {
78 return m_pVTIterator->NextWord();
79 }
80
PrevWord()81 bool CPWL_EditImpl_Iterator::PrevWord() {
82 return m_pVTIterator->PrevWord();
83 }
84
GetWord(CPVT_Word & word) const85 bool CPWL_EditImpl_Iterator::GetWord(CPVT_Word& word) const {
86 ASSERT(m_pEdit);
87
88 if (m_pVTIterator->GetWord(word)) {
89 word.ptWord = m_pEdit->VTToEdit(word.ptWord);
90 return true;
91 }
92 return false;
93 }
94
GetLine(CPVT_Line & line) const95 bool CPWL_EditImpl_Iterator::GetLine(CPVT_Line& line) const {
96 ASSERT(m_pEdit);
97
98 if (m_pVTIterator->GetLine(line)) {
99 line.ptLine = m_pEdit->VTToEdit(line.ptLine);
100 return true;
101 }
102 return false;
103 }
104
SetAt(int32_t nWordIndex)105 void CPWL_EditImpl_Iterator::SetAt(int32_t nWordIndex) {
106 m_pVTIterator->SetAt(nWordIndex);
107 }
108
SetAt(const CPVT_WordPlace & place)109 void CPWL_EditImpl_Iterator::SetAt(const CPVT_WordPlace& place) {
110 m_pVTIterator->SetAt(place);
111 }
112
GetAt() const113 const CPVT_WordPlace& CPWL_EditImpl_Iterator::GetAt() const {
114 return m_pVTIterator->GetWordPlace();
115 }
116
CPWL_EditImpl_Provider(IPVT_FontMap * pFontMap)117 CPWL_EditImpl_Provider::CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap)
118 : CPDF_VariableText::Provider(pFontMap), m_pFontMap(pFontMap) {
119 ASSERT(m_pFontMap);
120 }
121
~CPWL_EditImpl_Provider()122 CPWL_EditImpl_Provider::~CPWL_EditImpl_Provider() {}
123
GetFontMap() const124 IPVT_FontMap* CPWL_EditImpl_Provider::GetFontMap() const {
125 return m_pFontMap;
126 }
127
GetCharWidth(int32_t nFontIndex,uint16_t word)128 int32_t CPWL_EditImpl_Provider::GetCharWidth(int32_t nFontIndex,
129 uint16_t word) {
130 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
131 uint32_t charcode = word;
132
133 if (pPDFFont->IsUnicodeCompatible())
134 charcode = pPDFFont->CharCodeFromUnicode(word);
135 else
136 charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word);
137
138 if (charcode != CPDF_Font::kInvalidCharCode)
139 return pPDFFont->GetCharWidthF(charcode);
140 }
141
142 return 0;
143 }
144
GetTypeAscent(int32_t nFontIndex)145 int32_t CPWL_EditImpl_Provider::GetTypeAscent(int32_t nFontIndex) {
146 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
147 return pPDFFont->GetTypeAscent();
148
149 return 0;
150 }
151
GetTypeDescent(int32_t nFontIndex)152 int32_t CPWL_EditImpl_Provider::GetTypeDescent(int32_t nFontIndex) {
153 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
154 return pPDFFont->GetTypeDescent();
155
156 return 0;
157 }
158
GetWordFontIndex(uint16_t word,int32_t charset,int32_t nFontIndex)159 int32_t CPWL_EditImpl_Provider::GetWordFontIndex(uint16_t word,
160 int32_t charset,
161 int32_t nFontIndex) {
162 return m_pFontMap->GetWordFontIndex(word, charset, nFontIndex);
163 }
164
GetDefaultFontIndex()165 int32_t CPWL_EditImpl_Provider::GetDefaultFontIndex() {
166 return 0;
167 }
168
IsLatinWord(uint16_t word)169 bool CPWL_EditImpl_Provider::IsLatinWord(uint16_t word) {
170 return FX_EDIT_ISLATINWORD(word);
171 }
172
CPWL_EditImpl_Refresh()173 CPWL_EditImpl_Refresh::CPWL_EditImpl_Refresh() {}
174
~CPWL_EditImpl_Refresh()175 CPWL_EditImpl_Refresh::~CPWL_EditImpl_Refresh() {}
176
BeginRefresh()177 void CPWL_EditImpl_Refresh::BeginRefresh() {
178 m_RefreshRects.clear();
179 m_OldLineRects = std::move(m_NewLineRects);
180 }
181
Push(const CPVT_WordRange & linerange,const CFX_FloatRect & rect)182 void CPWL_EditImpl_Refresh::Push(const CPVT_WordRange& linerange,
183 const CFX_FloatRect& rect) {
184 m_NewLineRects.emplace_back(CPWL_EditImpl_LineRect(linerange, rect));
185 }
186
NoAnalyse()187 void CPWL_EditImpl_Refresh::NoAnalyse() {
188 for (const auto& lineRect : m_OldLineRects)
189 Add(lineRect.m_rcLine);
190
191 for (const auto& lineRect : m_NewLineRects)
192 Add(lineRect.m_rcLine);
193 }
194
GetRefreshRects()195 std::vector<CFX_FloatRect>* CPWL_EditImpl_Refresh::GetRefreshRects() {
196 return &m_RefreshRects;
197 }
198
EndRefresh()199 void CPWL_EditImpl_Refresh::EndRefresh() {
200 m_RefreshRects.clear();
201 }
202
Add(const CFX_FloatRect & new_rect)203 void CPWL_EditImpl_Refresh::Add(const CFX_FloatRect& new_rect) {
204 // Check for overlapped area.
205 for (const auto& rect : m_RefreshRects) {
206 if (rect.Contains(new_rect))
207 return;
208 }
209 m_RefreshRects.emplace_back(CFX_FloatRect(new_rect));
210 }
211
CPWL_EditImpl_Undo()212 CPWL_EditImpl_Undo::CPWL_EditImpl_Undo()
213 : m_nCurUndoPos(0), m_bWorking(false) {}
214
~CPWL_EditImpl_Undo()215 CPWL_EditImpl_Undo::~CPWL_EditImpl_Undo() {}
216
CanUndo() const217 bool CPWL_EditImpl_Undo::CanUndo() const {
218 return m_nCurUndoPos > 0;
219 }
220
Undo()221 void CPWL_EditImpl_Undo::Undo() {
222 m_bWorking = true;
223 if (CanUndo()) {
224 m_UndoItemStack[m_nCurUndoPos - 1]->Undo();
225 m_nCurUndoPos--;
226 }
227 m_bWorking = false;
228 }
229
CanRedo() const230 bool CPWL_EditImpl_Undo::CanRedo() const {
231 return m_nCurUndoPos < m_UndoItemStack.size();
232 }
233
Redo()234 void CPWL_EditImpl_Undo::Redo() {
235 m_bWorking = true;
236 if (CanRedo()) {
237 m_UndoItemStack[m_nCurUndoPos]->Redo();
238 m_nCurUndoPos++;
239 }
240 m_bWorking = false;
241 }
242
AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem)243 void CPWL_EditImpl_Undo::AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem) {
244 ASSERT(!m_bWorking);
245 ASSERT(pItem);
246 if (CanRedo())
247 RemoveTails();
248
249 if (m_UndoItemStack.size() >= kEditUndoMaxItems)
250 RemoveHeads();
251
252 m_UndoItemStack.push_back(std::move(pItem));
253 m_nCurUndoPos = m_UndoItemStack.size();
254 }
255
RemoveHeads()256 void CPWL_EditImpl_Undo::RemoveHeads() {
257 ASSERT(m_UndoItemStack.size() > 1);
258 m_UndoItemStack.pop_front();
259 }
260
RemoveTails()261 void CPWL_EditImpl_Undo::RemoveTails() {
262 while (CanRedo())
263 m_UndoItemStack.pop_back();
264 }
265
CFXEU_InsertWord(CPWL_EditImpl * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,uint16_t word,int32_t charset)266 CFXEU_InsertWord::CFXEU_InsertWord(CPWL_EditImpl* pEdit,
267 const CPVT_WordPlace& wpOldPlace,
268 const CPVT_WordPlace& wpNewPlace,
269 uint16_t word,
270 int32_t charset)
271 : m_pEdit(pEdit),
272 m_wpOld(wpOldPlace),
273 m_wpNew(wpNewPlace),
274 m_Word(word),
275 m_nCharset(charset) {
276 ASSERT(m_pEdit);
277 }
278
~CFXEU_InsertWord()279 CFXEU_InsertWord::~CFXEU_InsertWord() {}
280
Redo()281 void CFXEU_InsertWord::Redo() {
282 m_pEdit->SelectNone();
283 m_pEdit->SetCaret(m_wpOld);
284 m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
285 }
286
Undo()287 void CFXEU_InsertWord::Undo() {
288 m_pEdit->SelectNone();
289 m_pEdit->SetCaret(m_wpNew);
290 m_pEdit->Backspace(false, true);
291 }
292
CFXEU_InsertReturn(CPWL_EditImpl * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace)293 CFXEU_InsertReturn::CFXEU_InsertReturn(CPWL_EditImpl* pEdit,
294 const CPVT_WordPlace& wpOldPlace,
295 const CPVT_WordPlace& wpNewPlace)
296 : m_pEdit(pEdit), m_wpOld(wpOldPlace), m_wpNew(wpNewPlace) {
297 ASSERT(m_pEdit);
298 }
299
~CFXEU_InsertReturn()300 CFXEU_InsertReturn::~CFXEU_InsertReturn() {}
301
Redo()302 void CFXEU_InsertReturn::Redo() {
303 m_pEdit->SelectNone();
304 m_pEdit->SetCaret(m_wpOld);
305 m_pEdit->InsertReturn(false, true);
306 }
307
Undo()308 void CFXEU_InsertReturn::Undo() {
309 m_pEdit->SelectNone();
310 m_pEdit->SetCaret(m_wpNew);
311 m_pEdit->Backspace(false, true);
312 }
313
CFXEU_Backspace(CPWL_EditImpl * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,uint16_t word,int32_t charset)314 CFXEU_Backspace::CFXEU_Backspace(CPWL_EditImpl* pEdit,
315 const CPVT_WordPlace& wpOldPlace,
316 const CPVT_WordPlace& wpNewPlace,
317 uint16_t word,
318 int32_t charset)
319 : m_pEdit(pEdit),
320 m_wpOld(wpOldPlace),
321 m_wpNew(wpNewPlace),
322 m_Word(word),
323 m_nCharset(charset) {
324 ASSERT(m_pEdit);
325 }
326
~CFXEU_Backspace()327 CFXEU_Backspace::~CFXEU_Backspace() {}
328
Redo()329 void CFXEU_Backspace::Redo() {
330 m_pEdit->SelectNone();
331 m_pEdit->SetCaret(m_wpOld);
332 m_pEdit->Backspace(false, true);
333 }
334
Undo()335 void CFXEU_Backspace::Undo() {
336 m_pEdit->SelectNone();
337 m_pEdit->SetCaret(m_wpNew);
338 if (m_wpNew.nSecIndex != m_wpOld.nSecIndex)
339 m_pEdit->InsertReturn(false, true);
340 else
341 m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
342 }
343
CFXEU_Delete(CPWL_EditImpl * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,uint16_t word,int32_t charset,bool bSecEnd)344 CFXEU_Delete::CFXEU_Delete(CPWL_EditImpl* pEdit,
345 const CPVT_WordPlace& wpOldPlace,
346 const CPVT_WordPlace& wpNewPlace,
347 uint16_t word,
348 int32_t charset,
349 bool bSecEnd)
350 : m_pEdit(pEdit),
351 m_wpOld(wpOldPlace),
352 m_wpNew(wpNewPlace),
353 m_Word(word),
354 m_nCharset(charset),
355 m_bSecEnd(bSecEnd) {
356 ASSERT(m_pEdit);
357 }
358
~CFXEU_Delete()359 CFXEU_Delete::~CFXEU_Delete() {}
360
Redo()361 void CFXEU_Delete::Redo() {
362 m_pEdit->SelectNone();
363 m_pEdit->SetCaret(m_wpOld);
364 m_pEdit->Delete(false, true);
365 }
366
Undo()367 void CFXEU_Delete::Undo() {
368 m_pEdit->SelectNone();
369 m_pEdit->SetCaret(m_wpNew);
370 if (m_bSecEnd)
371 m_pEdit->InsertReturn(false, true);
372 else
373 m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
374 }
375
CFXEU_Clear(CPWL_EditImpl * pEdit,const CPVT_WordRange & wrSel,const WideString & swText)376 CFXEU_Clear::CFXEU_Clear(CPWL_EditImpl* pEdit,
377 const CPVT_WordRange& wrSel,
378 const WideString& swText)
379 : m_pEdit(pEdit), m_wrSel(wrSel), m_swText(swText) {
380 ASSERT(m_pEdit);
381 }
382
~CFXEU_Clear()383 CFXEU_Clear::~CFXEU_Clear() {}
384
Redo()385 void CFXEU_Clear::Redo() {
386 m_pEdit->SelectNone();
387 m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos);
388 m_pEdit->Clear(false, true);
389 }
390
Undo()391 void CFXEU_Clear::Undo() {
392 m_pEdit->SelectNone();
393 m_pEdit->SetCaret(m_wrSel.BeginPos);
394 m_pEdit->InsertText(m_swText, FX_CHARSET_Default, false, true);
395 m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos);
396 }
397
CFXEU_InsertText(CPWL_EditImpl * pEdit,const CPVT_WordPlace & wpOldPlace,const CPVT_WordPlace & wpNewPlace,const WideString & swText,int32_t charset)398 CFXEU_InsertText::CFXEU_InsertText(CPWL_EditImpl* pEdit,
399 const CPVT_WordPlace& wpOldPlace,
400 const CPVT_WordPlace& wpNewPlace,
401 const WideString& swText,
402 int32_t charset)
403 : m_pEdit(pEdit),
404 m_wpOld(wpOldPlace),
405 m_wpNew(wpNewPlace),
406 m_swText(swText),
407 m_nCharset(charset) {
408 ASSERT(m_pEdit);
409 }
410
~CFXEU_InsertText()411 CFXEU_InsertText::~CFXEU_InsertText() {}
412
Redo()413 void CFXEU_InsertText::Redo() {
414 m_pEdit->SelectNone();
415 m_pEdit->SetCaret(m_wpOld);
416 m_pEdit->InsertText(m_swText, m_nCharset, false, true);
417 }
418
Undo()419 void CFXEU_InsertText::Undo() {
420 m_pEdit->SelectNone();
421 m_pEdit->SetSelection(m_wpOld, m_wpNew);
422 m_pEdit->Clear(false, true);
423 }
424
425 // static
DrawEdit(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device,CPWL_EditImpl * pEdit,FX_COLORREF crTextFill,const CFX_FloatRect & rcClip,const CFX_PointF & ptOffset,const CPVT_WordRange * pRange,CFX_SystemHandler * pSystemHandler,CFFL_FormFiller * pFFLData)426 void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice,
427 const CFX_Matrix& mtUser2Device,
428 CPWL_EditImpl* pEdit,
429 FX_COLORREF crTextFill,
430 const CFX_FloatRect& rcClip,
431 const CFX_PointF& ptOffset,
432 const CPVT_WordRange* pRange,
433 CFX_SystemHandler* pSystemHandler,
434 CFFL_FormFiller* pFFLData) {
435 const bool bContinuous =
436 pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f;
437 uint16_t SubWord = pEdit->GetPasswordChar();
438 float fFontSize = pEdit->GetFontSize();
439 CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
440 int32_t nHorzScale = pEdit->GetHorzScale();
441
442 FX_COLORREF crCurFill = crTextFill;
443 FX_COLORREF crOldFill = crCurFill;
444
445 bool bSelect = false;
446 static const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
447 static const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);
448
449 std::ostringstream sTextBuf;
450 int32_t nFontIndex = -1;
451 CFX_PointF ptBT;
452 CFX_RenderDevice::StateRestorer restorer(pDevice);
453 if (!rcClip.IsEmpty())
454 pDevice->SetClip_Rect(mtUser2Device.TransformRect(rcClip).ToFxRect());
455
456 CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator();
457 IPVT_FontMap* pFontMap = pEdit->GetFontMap();
458 if (!pFontMap)
459 return;
460
461 if (pRange)
462 pIterator->SetAt(pRange->BeginPos);
463 else
464 pIterator->SetAt(0);
465
466 CPVT_WordPlace oldplace;
467 while (pIterator->NextWord()) {
468 CPVT_WordPlace place = pIterator->GetAt();
469 if (pRange && place > pRange->EndPos)
470 break;
471
472 if (!wrSelect.IsEmpty()) {
473 bSelect = place > wrSelect.BeginPos && place <= wrSelect.EndPos;
474 crCurFill = bSelect ? crWhite : crTextFill;
475 }
476 if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
477 crCurFill = crTextFill;
478 crOldFill = crCurFill;
479 }
480 CPVT_Word word;
481 if (pIterator->GetWord(word)) {
482 if (bSelect) {
483 CPVT_Line line;
484 pIterator->GetLine(line);
485
486 if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
487 CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent,
488 word.ptWord.x + word.fWidth,
489 line.ptLine.y + line.fLineAscent);
490 rc.Intersect(rcClip);
491 pSystemHandler->OutputSelectedRect(pFFLData, rc);
492 } else {
493 CFX_PathData pathSelBK;
494 pathSelBK.AppendRect(word.ptWord.x, line.ptLine.y + line.fLineDescent,
495 word.ptWord.x + word.fWidth,
496 line.ptLine.y + line.fLineAscent);
497
498 pDevice->DrawPath(&pathSelBK, &mtUser2Device, nullptr, crSelBK, 0,
499 FXFILL_WINDING);
500 }
501 }
502
503 if (bContinuous) {
504 if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
505 crOldFill != crCurFill) {
506 if (sTextBuf.tellp() > 0) {
507 DrawTextString(
508 pDevice, CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
509 pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device,
510 ByteString(sTextBuf), crOldFill, nHorzScale);
511
512 sTextBuf.str("");
513 }
514 nFontIndex = word.nFontIndex;
515 ptBT = word.ptWord;
516 crOldFill = crCurFill;
517 }
518
519 sTextBuf << pEdit->GetPDFWordString(word.nFontIndex, word.Word,
520 SubWord);
521 } else {
522 DrawTextString(
523 pDevice,
524 CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y),
525 pFontMap->GetPDFFont(word.nFontIndex), fFontSize, mtUser2Device,
526 pEdit->GetPDFWordString(word.nFontIndex, word.Word, SubWord),
527 crCurFill, nHorzScale);
528 }
529 oldplace = place;
530 }
531 }
532
533 if (sTextBuf.tellp() > 0) {
534 DrawTextString(pDevice,
535 CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
536 pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device,
537 ByteString(sTextBuf), crOldFill, nHorzScale);
538 }
539 }
540
CPWL_EditImpl()541 CPWL_EditImpl::CPWL_EditImpl()
542 : m_pVT(pdfium::MakeUnique<CPDF_VariableText>()),
543 m_bEnableScroll(false),
544 m_nAlignment(0),
545 m_bNotifyFlag(false),
546 m_bEnableOverflow(false),
547 m_bEnableRefresh(true),
548 m_bEnableUndo(true) {}
549
~CPWL_EditImpl()550 CPWL_EditImpl::~CPWL_EditImpl() {}
551
Initialize()552 void CPWL_EditImpl::Initialize() {
553 m_pVT->Initialize();
554 SetCaret(m_pVT->GetBeginWordPlace());
555 SetCaretOrigin();
556 }
557
SetFontMap(IPVT_FontMap * pFontMap)558 void CPWL_EditImpl::SetFontMap(IPVT_FontMap* pFontMap) {
559 m_pVTProvider = pdfium::MakeUnique<CPWL_EditImpl_Provider>(pFontMap);
560 m_pVT->SetProvider(m_pVTProvider.get());
561 }
562
SetNotify(CPWL_EditCtrl * pNotify)563 void CPWL_EditImpl::SetNotify(CPWL_EditCtrl* pNotify) {
564 m_pNotify = pNotify;
565 }
566
SetOperationNotify(CPWL_Edit * pOperationNotify)567 void CPWL_EditImpl::SetOperationNotify(CPWL_Edit* pOperationNotify) {
568 m_pOperationNotify = pOperationNotify;
569 }
570
GetIterator()571 CPWL_EditImpl_Iterator* CPWL_EditImpl::GetIterator() {
572 if (!m_pIterator) {
573 m_pIterator =
574 pdfium::MakeUnique<CPWL_EditImpl_Iterator>(this, m_pVT->GetIterator());
575 }
576 return m_pIterator.get();
577 }
578
GetFontMap()579 IPVT_FontMap* CPWL_EditImpl::GetFontMap() {
580 return m_pVTProvider ? m_pVTProvider->GetFontMap() : nullptr;
581 }
582
SetPlateRect(const CFX_FloatRect & rect)583 void CPWL_EditImpl::SetPlateRect(const CFX_FloatRect& rect) {
584 m_pVT->SetPlateRect(rect);
585 m_ptScrollPos = CFX_PointF(rect.left, rect.top);
586 Paint();
587 }
588
SetAlignmentH(int32_t nFormat,bool bPaint)589 void CPWL_EditImpl::SetAlignmentH(int32_t nFormat, bool bPaint) {
590 m_pVT->SetAlignment(nFormat);
591 if (bPaint)
592 Paint();
593 }
594
SetAlignmentV(int32_t nFormat,bool bPaint)595 void CPWL_EditImpl::SetAlignmentV(int32_t nFormat, bool bPaint) {
596 m_nAlignment = nFormat;
597 if (bPaint)
598 Paint();
599 }
600
SetPasswordChar(uint16_t wSubWord,bool bPaint)601 void CPWL_EditImpl::SetPasswordChar(uint16_t wSubWord, bool bPaint) {
602 m_pVT->SetPasswordChar(wSubWord);
603 if (bPaint)
604 Paint();
605 }
606
SetLimitChar(int32_t nLimitChar)607 void CPWL_EditImpl::SetLimitChar(int32_t nLimitChar) {
608 m_pVT->SetLimitChar(nLimitChar);
609 Paint();
610 }
611
SetCharArray(int32_t nCharArray)612 void CPWL_EditImpl::SetCharArray(int32_t nCharArray) {
613 m_pVT->SetCharArray(nCharArray);
614 Paint();
615 }
616
SetCharSpace(float fCharSpace)617 void CPWL_EditImpl::SetCharSpace(float fCharSpace) {
618 m_pVT->SetCharSpace(fCharSpace);
619 Paint();
620 }
621
SetMultiLine(bool bMultiLine,bool bPaint)622 void CPWL_EditImpl::SetMultiLine(bool bMultiLine, bool bPaint) {
623 m_pVT->SetMultiLine(bMultiLine);
624 if (bPaint)
625 Paint();
626 }
627
SetAutoReturn(bool bAuto,bool bPaint)628 void CPWL_EditImpl::SetAutoReturn(bool bAuto, bool bPaint) {
629 m_pVT->SetAutoReturn(bAuto);
630 if (bPaint)
631 Paint();
632 }
633
SetAutoFontSize(bool bAuto,bool bPaint)634 void CPWL_EditImpl::SetAutoFontSize(bool bAuto, bool bPaint) {
635 m_pVT->SetAutoFontSize(bAuto);
636 if (bPaint)
637 Paint();
638 }
639
SetFontSize(float fFontSize)640 void CPWL_EditImpl::SetFontSize(float fFontSize) {
641 m_pVT->SetFontSize(fFontSize);
642 Paint();
643 }
644
SetAutoScroll(bool bAuto,bool bPaint)645 void CPWL_EditImpl::SetAutoScroll(bool bAuto, bool bPaint) {
646 m_bEnableScroll = bAuto;
647 if (bPaint)
648 Paint();
649 }
650
SetTextOverflow(bool bAllowed,bool bPaint)651 void CPWL_EditImpl::SetTextOverflow(bool bAllowed, bool bPaint) {
652 m_bEnableOverflow = bAllowed;
653 if (bPaint)
654 Paint();
655 }
656
SetSelection(int32_t nStartChar,int32_t nEndChar)657 void CPWL_EditImpl::SetSelection(int32_t nStartChar, int32_t nEndChar) {
658 if (m_pVT->IsValid()) {
659 if (nStartChar == 0 && nEndChar < 0) {
660 SelectAll();
661 } else if (nStartChar < 0) {
662 SelectNone();
663 } else {
664 if (nStartChar < nEndChar) {
665 SetSelection(m_pVT->WordIndexToWordPlace(nStartChar),
666 m_pVT->WordIndexToWordPlace(nEndChar));
667 } else {
668 SetSelection(m_pVT->WordIndexToWordPlace(nEndChar),
669 m_pVT->WordIndexToWordPlace(nStartChar));
670 }
671 }
672 }
673 }
674
SetSelection(const CPVT_WordPlace & begin,const CPVT_WordPlace & end)675 void CPWL_EditImpl::SetSelection(const CPVT_WordPlace& begin,
676 const CPVT_WordPlace& end) {
677 if (!m_pVT->IsValid())
678 return;
679
680 SelectNone();
681 m_SelState.Set(begin, end);
682 SetCaret(m_SelState.EndPos);
683 ScrollToCaret();
684 if (!m_SelState.IsEmpty())
685 Refresh();
686 SetCaretInfo();
687 }
688
GetSelection(int32_t & nStartChar,int32_t & nEndChar) const689 void CPWL_EditImpl::GetSelection(int32_t& nStartChar, int32_t& nEndChar) const {
690 nStartChar = -1;
691 nEndChar = -1;
692 if (!m_pVT->IsValid())
693 return;
694
695 if (m_SelState.IsEmpty()) {
696 nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
697 nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
698 return;
699 }
700 if (m_SelState.BeginPos < m_SelState.EndPos) {
701 nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
702 nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
703 return;
704 }
705 nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
706 nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
707 }
708
GetCaret() const709 int32_t CPWL_EditImpl::GetCaret() const {
710 if (m_pVT->IsValid())
711 return m_pVT->WordPlaceToWordIndex(m_wpCaret);
712
713 return -1;
714 }
715
GetCaretWordPlace() const716 CPVT_WordPlace CPWL_EditImpl::GetCaretWordPlace() const {
717 return m_wpCaret;
718 }
719
GetText() const720 WideString CPWL_EditImpl::GetText() const {
721 WideString swRet;
722 if (!m_pVT->IsValid())
723 return swRet;
724
725 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
726 pIterator->SetAt(0);
727
728 CPVT_Word wordinfo;
729 CPVT_WordPlace oldplace = pIterator->GetWordPlace();
730 while (pIterator->NextWord()) {
731 CPVT_WordPlace place = pIterator->GetWordPlace();
732 if (pIterator->GetWord(wordinfo))
733 swRet += wordinfo.Word;
734 if (oldplace.nSecIndex != place.nSecIndex)
735 swRet += L"\r\n";
736 oldplace = place;
737 }
738 return swRet;
739 }
740
GetRangeText(const CPVT_WordRange & range) const741 WideString CPWL_EditImpl::GetRangeText(const CPVT_WordRange& range) const {
742 WideString swRet;
743 if (!m_pVT->IsValid())
744 return swRet;
745
746 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
747 CPVT_WordRange wrTemp = range;
748 m_pVT->UpdateWordPlace(wrTemp.BeginPos);
749 m_pVT->UpdateWordPlace(wrTemp.EndPos);
750 pIterator->SetAt(wrTemp.BeginPos);
751
752 CPVT_Word wordinfo;
753 CPVT_WordPlace oldplace = wrTemp.BeginPos;
754 while (pIterator->NextWord()) {
755 CPVT_WordPlace place = pIterator->GetWordPlace();
756 if (place > wrTemp.EndPos)
757 break;
758 if (pIterator->GetWord(wordinfo))
759 swRet += wordinfo.Word;
760 if (oldplace.nSecIndex != place.nSecIndex)
761 swRet += L"\r\n";
762 oldplace = place;
763 }
764 return swRet;
765 }
766
GetSelectedText() const767 WideString CPWL_EditImpl::GetSelectedText() const {
768 return GetRangeText(m_SelState.ConvertToWordRange());
769 }
770
GetTotalLines() const771 int32_t CPWL_EditImpl::GetTotalLines() const {
772 int32_t nLines = 1;
773
774 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
775 pIterator->SetAt(0);
776 while (pIterator->NextLine())
777 ++nLines;
778
779 return nLines;
780 }
781
GetSelectWordRange() const782 CPVT_WordRange CPWL_EditImpl::GetSelectWordRange() const {
783 return m_SelState.ConvertToWordRange();
784 }
785
SetText(const WideString & sText)786 void CPWL_EditImpl::SetText(const WideString& sText) {
787 Empty();
788 DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FX_CHARSET_Default);
789 Paint();
790 }
791
InsertWord(uint16_t word,int32_t charset)792 bool CPWL_EditImpl::InsertWord(uint16_t word, int32_t charset) {
793 return InsertWord(word, charset, true, true);
794 }
795
InsertReturn()796 bool CPWL_EditImpl::InsertReturn() {
797 return InsertReturn(true, true);
798 }
799
Backspace()800 bool CPWL_EditImpl::Backspace() {
801 return Backspace(true, true);
802 }
803
Delete()804 bool CPWL_EditImpl::Delete() {
805 return Delete(true, true);
806 }
807
ClearSelection()808 bool CPWL_EditImpl::ClearSelection() {
809 return Clear(true, true);
810 }
811
InsertText(const WideString & sText,int32_t charset)812 bool CPWL_EditImpl::InsertText(const WideString& sText, int32_t charset) {
813 return InsertText(sText, charset, true, true);
814 }
815
GetFontSize() const816 float CPWL_EditImpl::GetFontSize() const {
817 return m_pVT->GetFontSize();
818 }
819
GetPasswordChar() const820 uint16_t CPWL_EditImpl::GetPasswordChar() const {
821 return m_pVT->GetPasswordChar();
822 }
823
GetCharArray() const824 int32_t CPWL_EditImpl::GetCharArray() const {
825 return m_pVT->GetCharArray();
826 }
827
GetContentRect() const828 CFX_FloatRect CPWL_EditImpl::GetContentRect() const {
829 return VTToEdit(m_pVT->GetContentRect());
830 }
831
GetHorzScale() const832 int32_t CPWL_EditImpl::GetHorzScale() const {
833 return m_pVT->GetHorzScale();
834 }
835
GetCharSpace() const836 float CPWL_EditImpl::GetCharSpace() const {
837 return m_pVT->GetCharSpace();
838 }
839
GetWholeWordRange() const840 CPVT_WordRange CPWL_EditImpl::GetWholeWordRange() const {
841 if (m_pVT->IsValid())
842 return CPVT_WordRange(m_pVT->GetBeginWordPlace(), m_pVT->GetEndWordPlace());
843
844 return CPVT_WordRange();
845 }
846
GetVisibleWordRange() const847 CPVT_WordRange CPWL_EditImpl::GetVisibleWordRange() const {
848 if (m_bEnableOverflow)
849 return GetWholeWordRange();
850
851 if (m_pVT->IsValid()) {
852 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
853
854 CPVT_WordPlace place1 =
855 m_pVT->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top)));
856 CPVT_WordPlace place2 = m_pVT->SearchWordPlace(
857 EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom)));
858
859 return CPVT_WordRange(place1, place2);
860 }
861
862 return CPVT_WordRange();
863 }
864
SearchWordPlace(const CFX_PointF & point) const865 CPVT_WordPlace CPWL_EditImpl::SearchWordPlace(const CFX_PointF& point) const {
866 if (m_pVT->IsValid()) {
867 return m_pVT->SearchWordPlace(EditToVT(point));
868 }
869
870 return CPVT_WordPlace();
871 }
872
Paint()873 void CPWL_EditImpl::Paint() {
874 if (m_pVT->IsValid()) {
875 RearrangeAll();
876 ScrollToCaret();
877 Refresh();
878 SetCaretOrigin();
879 SetCaretInfo();
880 }
881 }
882
RearrangeAll()883 void CPWL_EditImpl::RearrangeAll() {
884 if (m_pVT->IsValid()) {
885 m_pVT->UpdateWordPlace(m_wpCaret);
886 m_pVT->RearrangeAll();
887 m_pVT->UpdateWordPlace(m_wpCaret);
888 SetScrollInfo();
889 SetContentChanged();
890 }
891 }
892
RearrangePart(const CPVT_WordRange & range)893 void CPWL_EditImpl::RearrangePart(const CPVT_WordRange& range) {
894 if (m_pVT->IsValid()) {
895 m_pVT->UpdateWordPlace(m_wpCaret);
896 m_pVT->RearrangePart(range);
897 m_pVT->UpdateWordPlace(m_wpCaret);
898 SetScrollInfo();
899 SetContentChanged();
900 }
901 }
902
SetContentChanged()903 void CPWL_EditImpl::SetContentChanged() {
904 if (m_pNotify) {
905 CFX_FloatRect rcContent = m_pVT->GetContentRect();
906 if (rcContent.Width() != m_rcOldContent.Width() ||
907 rcContent.Height() != m_rcOldContent.Height()) {
908 m_rcOldContent = rcContent;
909 }
910 }
911 }
912
SelectAll()913 void CPWL_EditImpl::SelectAll() {
914 if (!m_pVT->IsValid())
915 return;
916 m_SelState = CPWL_EditImpl_Select(GetWholeWordRange());
917 SetCaret(m_SelState.EndPos);
918 ScrollToCaret();
919 Refresh();
920 SetCaretInfo();
921 }
922
SelectNone()923 void CPWL_EditImpl::SelectNone() {
924 if (!m_pVT->IsValid() || m_SelState.IsEmpty())
925 return;
926
927 m_SelState.Reset();
928 Refresh();
929 }
930
IsSelected() const931 bool CPWL_EditImpl::IsSelected() const {
932 return !m_SelState.IsEmpty();
933 }
934
VTToEdit(const CFX_PointF & point) const935 CFX_PointF CPWL_EditImpl::VTToEdit(const CFX_PointF& point) const {
936 CFX_FloatRect rcContent = m_pVT->GetContentRect();
937 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
938
939 float fPadding = 0.0f;
940
941 switch (m_nAlignment) {
942 case 0:
943 fPadding = 0.0f;
944 break;
945 case 1:
946 fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
947 break;
948 case 2:
949 fPadding = rcPlate.Height() - rcContent.Height();
950 break;
951 }
952
953 return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
954 point.y - (m_ptScrollPos.y + fPadding - rcPlate.top));
955 }
956
EditToVT(const CFX_PointF & point) const957 CFX_PointF CPWL_EditImpl::EditToVT(const CFX_PointF& point) const {
958 CFX_FloatRect rcContent = m_pVT->GetContentRect();
959 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
960
961 float fPadding = 0.0f;
962
963 switch (m_nAlignment) {
964 case 0:
965 fPadding = 0.0f;
966 break;
967 case 1:
968 fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
969 break;
970 case 2:
971 fPadding = rcPlate.Height() - rcContent.Height();
972 break;
973 }
974
975 return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
976 point.y + (m_ptScrollPos.y + fPadding - rcPlate.top));
977 }
978
VTToEdit(const CFX_FloatRect & rect) const979 CFX_FloatRect CPWL_EditImpl::VTToEdit(const CFX_FloatRect& rect) const {
980 CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom));
981 CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top));
982
983 return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
984 ptRightTop.y);
985 }
986
SetScrollInfo()987 void CPWL_EditImpl::SetScrollInfo() {
988 if (!m_pNotify)
989 return;
990
991 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
992 CFX_FloatRect rcContent = m_pVT->GetContentRect();
993 if (m_bNotifyFlag)
994 return;
995
996 AutoRestorer<bool> restorer(&m_bNotifyFlag);
997 m_bNotifyFlag = true;
998
999 PWL_SCROLL_INFO Info;
1000 Info.fPlateWidth = rcPlate.top - rcPlate.bottom;
1001 Info.fContentMin = rcContent.bottom;
1002 Info.fContentMax = rcContent.top;
1003 Info.fSmallStep = rcPlate.Height() / 3;
1004 Info.fBigStep = rcPlate.Height();
1005 m_pNotify->SetScrollInfo(Info);
1006 }
1007
SetScrollPosX(float fx)1008 void CPWL_EditImpl::SetScrollPosX(float fx) {
1009 if (!m_bEnableScroll)
1010 return;
1011
1012 if (m_pVT->IsValid()) {
1013 if (!IsFloatEqual(m_ptScrollPos.x, fx)) {
1014 m_ptScrollPos.x = fx;
1015 Refresh();
1016 }
1017 }
1018 }
1019
SetScrollPosY(float fy)1020 void CPWL_EditImpl::SetScrollPosY(float fy) {
1021 if (!m_bEnableScroll)
1022 return;
1023
1024 if (m_pVT->IsValid()) {
1025 if (!IsFloatEqual(m_ptScrollPos.y, fy)) {
1026 m_ptScrollPos.y = fy;
1027 Refresh();
1028
1029 if (m_pNotify) {
1030 if (!m_bNotifyFlag) {
1031 AutoRestorer<bool> restorer(&m_bNotifyFlag);
1032 m_bNotifyFlag = true;
1033 m_pNotify->SetScrollPosition(fy);
1034 }
1035 }
1036 }
1037 }
1038 }
1039
SetScrollPos(const CFX_PointF & point)1040 void CPWL_EditImpl::SetScrollPos(const CFX_PointF& point) {
1041 SetScrollPosX(point.x);
1042 SetScrollPosY(point.y);
1043 SetScrollLimit();
1044 SetCaretInfo();
1045 }
1046
GetScrollPos() const1047 CFX_PointF CPWL_EditImpl::GetScrollPos() const {
1048 return m_ptScrollPos;
1049 }
1050
SetScrollLimit()1051 void CPWL_EditImpl::SetScrollLimit() {
1052 if (m_pVT->IsValid()) {
1053 CFX_FloatRect rcContent = m_pVT->GetContentRect();
1054 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
1055
1056 if (rcPlate.Width() > rcContent.Width()) {
1057 SetScrollPosX(rcPlate.left);
1058 } else {
1059 if (IsFloatSmaller(m_ptScrollPos.x, rcContent.left)) {
1060 SetScrollPosX(rcContent.left);
1061 } else if (IsFloatBigger(m_ptScrollPos.x,
1062 rcContent.right - rcPlate.Width())) {
1063 SetScrollPosX(rcContent.right - rcPlate.Width());
1064 }
1065 }
1066
1067 if (rcPlate.Height() > rcContent.Height()) {
1068 SetScrollPosY(rcPlate.top);
1069 } else {
1070 if (IsFloatSmaller(m_ptScrollPos.y,
1071 rcContent.bottom + rcPlate.Height())) {
1072 SetScrollPosY(rcContent.bottom + rcPlate.Height());
1073 } else if (IsFloatBigger(m_ptScrollPos.y, rcContent.top)) {
1074 SetScrollPosY(rcContent.top);
1075 }
1076 }
1077 }
1078 }
1079
ScrollToCaret()1080 void CPWL_EditImpl::ScrollToCaret() {
1081 SetScrollLimit();
1082
1083 if (!m_pVT->IsValid())
1084 return;
1085
1086 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1087 pIterator->SetAt(m_wpCaret);
1088
1089 CFX_PointF ptHead;
1090 CFX_PointF ptFoot;
1091 CPVT_Word word;
1092 CPVT_Line line;
1093 if (pIterator->GetWord(word)) {
1094 ptHead.x = word.ptWord.x + word.fWidth;
1095 ptHead.y = word.ptWord.y + word.fAscent;
1096 ptFoot.x = word.ptWord.x + word.fWidth;
1097 ptFoot.y = word.ptWord.y + word.fDescent;
1098 } else if (pIterator->GetLine(line)) {
1099 ptHead.x = line.ptLine.x;
1100 ptHead.y = line.ptLine.y + line.fLineAscent;
1101 ptFoot.x = line.ptLine.x;
1102 ptFoot.y = line.ptLine.y + line.fLineDescent;
1103 }
1104
1105 CFX_PointF ptHeadEdit = VTToEdit(ptHead);
1106 CFX_PointF ptFootEdit = VTToEdit(ptFoot);
1107 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
1108 if (!IsFloatEqual(rcPlate.left, rcPlate.right)) {
1109 if (IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
1110 IsFloatEqual(ptHeadEdit.x, rcPlate.left)) {
1111 SetScrollPosX(ptHead.x);
1112 } else if (IsFloatBigger(ptHeadEdit.x, rcPlate.right)) {
1113 SetScrollPosX(ptHead.x - rcPlate.Width());
1114 }
1115 }
1116
1117 if (!IsFloatEqual(rcPlate.top, rcPlate.bottom)) {
1118 if (IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
1119 IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) {
1120 if (IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) {
1121 SetScrollPosY(ptFoot.y + rcPlate.Height());
1122 }
1123 } else if (IsFloatBigger(ptHeadEdit.y, rcPlate.top)) {
1124 if (IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) {
1125 SetScrollPosY(ptHead.y);
1126 }
1127 }
1128 }
1129 }
1130
Refresh()1131 void CPWL_EditImpl::Refresh() {
1132 if (m_bEnableRefresh && m_pVT->IsValid()) {
1133 m_Refresh.BeginRefresh();
1134 RefreshPushLineRects(GetVisibleWordRange());
1135
1136 m_Refresh.NoAnalyse();
1137 m_ptRefreshScrollPos = m_ptScrollPos;
1138
1139 if (m_pNotify) {
1140 if (!m_bNotifyFlag) {
1141 AutoRestorer<bool> restorer(&m_bNotifyFlag);
1142 m_bNotifyFlag = true;
1143 if (std::vector<CFX_FloatRect>* pRects = m_Refresh.GetRefreshRects()) {
1144 for (auto& rect : *pRects)
1145 m_pNotify->InvalidateRect(&rect);
1146 }
1147 }
1148 }
1149
1150 m_Refresh.EndRefresh();
1151 }
1152 }
1153
RefreshPushLineRects(const CPVT_WordRange & wr)1154 void CPWL_EditImpl::RefreshPushLineRects(const CPVT_WordRange& wr) {
1155 if (!m_pVT->IsValid())
1156 return;
1157
1158 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1159 CPVT_WordPlace wpBegin = wr.BeginPos;
1160 m_pVT->UpdateWordPlace(wpBegin);
1161 CPVT_WordPlace wpEnd = wr.EndPos;
1162 m_pVT->UpdateWordPlace(wpEnd);
1163 pIterator->SetAt(wpBegin);
1164
1165 CPVT_Line lineinfo;
1166 do {
1167 if (!pIterator->GetLine(lineinfo))
1168 break;
1169 if (lineinfo.lineplace.LineCmp(wpEnd) > 0)
1170 break;
1171
1172 CFX_FloatRect rcLine(lineinfo.ptLine.x,
1173 lineinfo.ptLine.y + lineinfo.fLineDescent,
1174 lineinfo.ptLine.x + lineinfo.fLineWidth,
1175 lineinfo.ptLine.y + lineinfo.fLineAscent);
1176
1177 m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd),
1178 VTToEdit(rcLine));
1179 } while (pIterator->NextLine());
1180 }
1181
RefreshWordRange(const CPVT_WordRange & wr)1182 void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) {
1183 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1184 CPVT_WordRange wrTemp = wr;
1185
1186 m_pVT->UpdateWordPlace(wrTemp.BeginPos);
1187 m_pVT->UpdateWordPlace(wrTemp.EndPos);
1188 pIterator->SetAt(wrTemp.BeginPos);
1189
1190 CPVT_Word wordinfo;
1191 CPVT_Line lineinfo;
1192 CPVT_WordPlace place;
1193
1194 while (pIterator->NextWord()) {
1195 place = pIterator->GetWordPlace();
1196 if (place > wrTemp.EndPos)
1197 break;
1198
1199 pIterator->GetWord(wordinfo);
1200 pIterator->GetLine(lineinfo);
1201 if (place.LineCmp(wrTemp.BeginPos) == 0 ||
1202 place.LineCmp(wrTemp.EndPos) == 0) {
1203 CFX_FloatRect rcWord(wordinfo.ptWord.x,
1204 lineinfo.ptLine.y + lineinfo.fLineDescent,
1205 wordinfo.ptWord.x + wordinfo.fWidth,
1206 lineinfo.ptLine.y + lineinfo.fLineAscent);
1207
1208 if (m_pNotify) {
1209 if (!m_bNotifyFlag) {
1210 AutoRestorer<bool> restorer(&m_bNotifyFlag);
1211 m_bNotifyFlag = true;
1212 CFX_FloatRect rcRefresh = VTToEdit(rcWord);
1213 m_pNotify->InvalidateRect(&rcRefresh);
1214 }
1215 }
1216 } else {
1217 CFX_FloatRect rcLine(lineinfo.ptLine.x,
1218 lineinfo.ptLine.y + lineinfo.fLineDescent,
1219 lineinfo.ptLine.x + lineinfo.fLineWidth,
1220 lineinfo.ptLine.y + lineinfo.fLineAscent);
1221
1222 if (m_pNotify) {
1223 if (!m_bNotifyFlag) {
1224 AutoRestorer<bool> restorer(&m_bNotifyFlag);
1225 m_bNotifyFlag = true;
1226 CFX_FloatRect rcRefresh = VTToEdit(rcLine);
1227 m_pNotify->InvalidateRect(&rcRefresh);
1228 }
1229 }
1230
1231 pIterator->NextLine();
1232 }
1233 }
1234 }
1235
SetCaret(const CPVT_WordPlace & place)1236 void CPWL_EditImpl::SetCaret(const CPVT_WordPlace& place) {
1237 m_wpOldCaret = m_wpCaret;
1238 m_wpCaret = place;
1239 }
1240
SetCaretInfo()1241 void CPWL_EditImpl::SetCaretInfo() {
1242 if (m_pNotify) {
1243 if (!m_bNotifyFlag) {
1244 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1245 pIterator->SetAt(m_wpCaret);
1246
1247 CFX_PointF ptHead;
1248 CFX_PointF ptFoot;
1249 CPVT_Word word;
1250 CPVT_Line line;
1251 if (pIterator->GetWord(word)) {
1252 ptHead.x = word.ptWord.x + word.fWidth;
1253 ptHead.y = word.ptWord.y + word.fAscent;
1254 ptFoot.x = word.ptWord.x + word.fWidth;
1255 ptFoot.y = word.ptWord.y + word.fDescent;
1256 } else if (pIterator->GetLine(line)) {
1257 ptHead.x = line.ptLine.x;
1258 ptHead.y = line.ptLine.y + line.fLineAscent;
1259 ptFoot.x = line.ptLine.x;
1260 ptFoot.y = line.ptLine.y + line.fLineDescent;
1261 }
1262
1263 AutoRestorer<bool> restorer(&m_bNotifyFlag);
1264 m_bNotifyFlag = true;
1265 m_pNotify->SetCaret(m_SelState.IsEmpty(), VTToEdit(ptHead),
1266 VTToEdit(ptFoot));
1267 }
1268 }
1269 }
1270
OnMouseDown(const CFX_PointF & point,bool bShift,bool bCtrl)1271 void CPWL_EditImpl::OnMouseDown(const CFX_PointF& point,
1272 bool bShift,
1273 bool bCtrl) {
1274 if (!m_pVT->IsValid())
1275 return;
1276
1277 SelectNone();
1278 SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
1279 m_SelState.Set(m_wpCaret, m_wpCaret);
1280 ScrollToCaret();
1281 SetCaretOrigin();
1282 SetCaretInfo();
1283 }
1284
OnMouseMove(const CFX_PointF & point,bool bShift,bool bCtrl)1285 void CPWL_EditImpl::OnMouseMove(const CFX_PointF& point,
1286 bool bShift,
1287 bool bCtrl) {
1288 if (!m_pVT->IsValid())
1289 return;
1290
1291 SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
1292 if (m_wpCaret == m_wpOldCaret)
1293 return;
1294
1295 m_SelState.SetEndPos(m_wpCaret);
1296 ScrollToCaret();
1297 Refresh();
1298 SetCaretOrigin();
1299 SetCaretInfo();
1300 }
1301
OnVK_UP(bool bShift,bool bCtrl)1302 void CPWL_EditImpl::OnVK_UP(bool bShift, bool bCtrl) {
1303 if (!m_pVT->IsValid())
1304 return;
1305
1306 SetCaret(m_pVT->GetUpWordPlace(m_wpCaret, m_ptCaret));
1307 if (bShift) {
1308 if (m_SelState.IsEmpty())
1309 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1310 else
1311 m_SelState.SetEndPos(m_wpCaret);
1312
1313 if (m_wpOldCaret != m_wpCaret) {
1314 ScrollToCaret();
1315 Refresh();
1316 SetCaretInfo();
1317 }
1318 } else {
1319 SelectNone();
1320 ScrollToCaret();
1321 SetCaretInfo();
1322 }
1323 }
1324
OnVK_DOWN(bool bShift,bool bCtrl)1325 void CPWL_EditImpl::OnVK_DOWN(bool bShift, bool bCtrl) {
1326 if (!m_pVT->IsValid())
1327 return;
1328
1329 SetCaret(m_pVT->GetDownWordPlace(m_wpCaret, m_ptCaret));
1330 if (bShift) {
1331 if (m_SelState.IsEmpty())
1332 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1333 else
1334 m_SelState.SetEndPos(m_wpCaret);
1335
1336 if (m_wpOldCaret != m_wpCaret) {
1337 ScrollToCaret();
1338 Refresh();
1339 SetCaretInfo();
1340 }
1341 } else {
1342 SelectNone();
1343 ScrollToCaret();
1344 SetCaretInfo();
1345 }
1346 }
1347
OnVK_LEFT(bool bShift,bool bCtrl)1348 void CPWL_EditImpl::OnVK_LEFT(bool bShift, bool bCtrl) {
1349 if (!m_pVT->IsValid())
1350 return;
1351
1352 if (bShift) {
1353 if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
1354 m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) {
1355 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
1356 }
1357 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
1358 if (m_SelState.IsEmpty())
1359 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1360 else
1361 m_SelState.SetEndPos(m_wpCaret);
1362
1363 if (m_wpOldCaret != m_wpCaret) {
1364 ScrollToCaret();
1365 Refresh();
1366 SetCaretInfo();
1367 }
1368 } else {
1369 if (!m_SelState.IsEmpty()) {
1370 if (m_SelState.BeginPos < m_SelState.EndPos)
1371 SetCaret(m_SelState.BeginPos);
1372 else
1373 SetCaret(m_SelState.EndPos);
1374
1375 SelectNone();
1376 ScrollToCaret();
1377 SetCaretInfo();
1378 } else {
1379 if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
1380 m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) {
1381 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
1382 }
1383 SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
1384 ScrollToCaret();
1385 SetCaretOrigin();
1386 SetCaretInfo();
1387 }
1388 }
1389 }
1390
OnVK_RIGHT(bool bShift,bool bCtrl)1391 void CPWL_EditImpl::OnVK_RIGHT(bool bShift, bool bCtrl) {
1392 if (!m_pVT->IsValid())
1393 return;
1394
1395 if (bShift) {
1396 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
1397 if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
1398 m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
1399 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
1400
1401 if (m_SelState.IsEmpty())
1402 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1403 else
1404 m_SelState.SetEndPos(m_wpCaret);
1405
1406 if (m_wpOldCaret != m_wpCaret) {
1407 ScrollToCaret();
1408 Refresh();
1409 SetCaretInfo();
1410 }
1411 } else {
1412 if (!m_SelState.IsEmpty()) {
1413 if (m_SelState.BeginPos > m_SelState.EndPos)
1414 SetCaret(m_SelState.BeginPos);
1415 else
1416 SetCaret(m_SelState.EndPos);
1417
1418 SelectNone();
1419 ScrollToCaret();
1420 SetCaretInfo();
1421 } else {
1422 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
1423 if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
1424 m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) {
1425 SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
1426 }
1427 ScrollToCaret();
1428 SetCaretOrigin();
1429 SetCaretInfo();
1430 }
1431 }
1432 }
1433
OnVK_HOME(bool bShift,bool bCtrl)1434 void CPWL_EditImpl::OnVK_HOME(bool bShift, bool bCtrl) {
1435 if (!m_pVT->IsValid())
1436 return;
1437
1438 if (bShift) {
1439 if (bCtrl)
1440 SetCaret(m_pVT->GetBeginWordPlace());
1441 else
1442 SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
1443
1444 if (m_SelState.IsEmpty())
1445 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1446 else
1447 m_SelState.SetEndPos(m_wpCaret);
1448
1449 ScrollToCaret();
1450 Refresh();
1451 SetCaretInfo();
1452 } else {
1453 if (!m_SelState.IsEmpty()) {
1454 SetCaret(std::min(m_SelState.BeginPos, m_SelState.EndPos));
1455 SelectNone();
1456 ScrollToCaret();
1457 SetCaretInfo();
1458 } else {
1459 if (bCtrl)
1460 SetCaret(m_pVT->GetBeginWordPlace());
1461 else
1462 SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
1463
1464 ScrollToCaret();
1465 SetCaretOrigin();
1466 SetCaretInfo();
1467 }
1468 }
1469 }
1470
OnVK_END(bool bShift,bool bCtrl)1471 void CPWL_EditImpl::OnVK_END(bool bShift, bool bCtrl) {
1472 if (!m_pVT->IsValid())
1473 return;
1474
1475 if (bShift) {
1476 if (bCtrl)
1477 SetCaret(m_pVT->GetEndWordPlace());
1478 else
1479 SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
1480
1481 if (m_SelState.IsEmpty())
1482 m_SelState.Set(m_wpOldCaret, m_wpCaret);
1483 else
1484 m_SelState.SetEndPos(m_wpCaret);
1485
1486 ScrollToCaret();
1487 Refresh();
1488 SetCaretInfo();
1489 } else {
1490 if (!m_SelState.IsEmpty()) {
1491 SetCaret(std::max(m_SelState.BeginPos, m_SelState.EndPos));
1492 SelectNone();
1493 ScrollToCaret();
1494 SetCaretInfo();
1495 } else {
1496 if (bCtrl)
1497 SetCaret(m_pVT->GetEndWordPlace());
1498 else
1499 SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
1500
1501 ScrollToCaret();
1502 SetCaretOrigin();
1503 SetCaretInfo();
1504 }
1505 }
1506 }
1507
InsertWord(uint16_t word,int32_t charset,bool bAddUndo,bool bPaint)1508 bool CPWL_EditImpl::InsertWord(uint16_t word,
1509 int32_t charset,
1510 bool bAddUndo,
1511 bool bPaint) {
1512 if (IsTextOverflow() || !m_pVT->IsValid())
1513 return false;
1514
1515 m_pVT->UpdateWordPlace(m_wpCaret);
1516 SetCaret(
1517 m_pVT->InsertWord(m_wpCaret, word, GetCharSetFromUnicode(word, charset)));
1518 m_SelState.Set(m_wpCaret, m_wpCaret);
1519 if (m_wpCaret == m_wpOldCaret)
1520 return false;
1521
1522 if (bAddUndo && m_bEnableUndo) {
1523 AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertWord>(
1524 this, m_wpOldCaret, m_wpCaret, word, charset));
1525 }
1526 if (bPaint)
1527 PaintInsertText(m_wpOldCaret, m_wpCaret);
1528
1529 if (m_pOperationNotify)
1530 m_pOperationNotify->OnInsertWord(m_wpCaret, m_wpOldCaret);
1531
1532 return true;
1533 }
1534
InsertReturn(bool bAddUndo,bool bPaint)1535 bool CPWL_EditImpl::InsertReturn(bool bAddUndo, bool bPaint) {
1536 if (IsTextOverflow() || !m_pVT->IsValid())
1537 return false;
1538
1539 m_pVT->UpdateWordPlace(m_wpCaret);
1540 SetCaret(m_pVT->InsertSection(m_wpCaret));
1541 m_SelState.Set(m_wpCaret, m_wpCaret);
1542 if (m_wpCaret == m_wpOldCaret)
1543 return false;
1544
1545 if (bAddUndo && m_bEnableUndo) {
1546 AddEditUndoItem(
1547 pdfium::MakeUnique<CFXEU_InsertReturn>(this, m_wpOldCaret, m_wpCaret));
1548 }
1549 if (bPaint) {
1550 RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
1551 ScrollToCaret();
1552 Refresh();
1553 SetCaretOrigin();
1554 SetCaretInfo();
1555 }
1556 if (m_pOperationNotify)
1557 m_pOperationNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret);
1558
1559 return true;
1560 }
1561
Backspace(bool bAddUndo,bool bPaint)1562 bool CPWL_EditImpl::Backspace(bool bAddUndo, bool bPaint) {
1563 if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetBeginWordPlace())
1564 return false;
1565
1566 CPVT_Word word;
1567 if (bAddUndo) {
1568 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1569 pIterator->SetAt(m_wpCaret);
1570 pIterator->GetWord(word);
1571 }
1572 m_pVT->UpdateWordPlace(m_wpCaret);
1573 SetCaret(m_pVT->BackSpaceWord(m_wpCaret));
1574 m_SelState.Set(m_wpCaret, m_wpCaret);
1575 if (m_wpCaret == m_wpOldCaret)
1576 return false;
1577
1578 if (bAddUndo && m_bEnableUndo) {
1579 if (m_wpCaret.nSecIndex != m_wpOldCaret.nSecIndex) {
1580 AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
1581 this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset));
1582 } else {
1583 AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
1584 this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset));
1585 }
1586 }
1587 if (bPaint) {
1588 RearrangePart(CPVT_WordRange(m_wpCaret, m_wpOldCaret));
1589 ScrollToCaret();
1590 Refresh();
1591 SetCaretOrigin();
1592 SetCaretInfo();
1593 }
1594 if (m_pOperationNotify)
1595 m_pOperationNotify->OnBackSpace(m_wpCaret, m_wpOldCaret);
1596
1597 return true;
1598 }
1599
Delete(bool bAddUndo,bool bPaint)1600 bool CPWL_EditImpl::Delete(bool bAddUndo, bool bPaint) {
1601 if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetEndWordPlace())
1602 return false;
1603
1604 CPVT_Word word;
1605 if (bAddUndo) {
1606 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1607 pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret));
1608 pIterator->GetWord(word);
1609 }
1610 m_pVT->UpdateWordPlace(m_wpCaret);
1611 bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret));
1612 SetCaret(m_pVT->DeleteWord(m_wpCaret));
1613 m_SelState.Set(m_wpCaret, m_wpCaret);
1614 if (bAddUndo && m_bEnableUndo) {
1615 if (bSecEnd) {
1616 AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
1617 this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd));
1618 } else {
1619 AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
1620 this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd));
1621 }
1622 }
1623 if (bPaint) {
1624 RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
1625 ScrollToCaret();
1626 Refresh();
1627 SetCaretOrigin();
1628 SetCaretInfo();
1629 }
1630 if (m_pOperationNotify)
1631 m_pOperationNotify->OnDelete(m_wpCaret, m_wpOldCaret);
1632
1633 return true;
1634 }
1635
Empty()1636 bool CPWL_EditImpl::Empty() {
1637 if (m_pVT->IsValid()) {
1638 m_pVT->DeleteWords(GetWholeWordRange());
1639 SetCaret(m_pVT->GetBeginWordPlace());
1640
1641 return true;
1642 }
1643
1644 return false;
1645 }
1646
Clear(bool bAddUndo,bool bPaint)1647 bool CPWL_EditImpl::Clear(bool bAddUndo, bool bPaint) {
1648 if (!m_pVT->IsValid() || m_SelState.IsEmpty())
1649 return false;
1650
1651 CPVT_WordRange range = m_SelState.ConvertToWordRange();
1652 if (bAddUndo && m_bEnableUndo) {
1653 AddEditUndoItem(
1654 pdfium::MakeUnique<CFXEU_Clear>(this, range, GetSelectedText()));
1655 }
1656
1657 SelectNone();
1658 SetCaret(m_pVT->DeleteWords(range));
1659 m_SelState.Set(m_wpCaret, m_wpCaret);
1660 if (bPaint) {
1661 RearrangePart(range);
1662 ScrollToCaret();
1663 Refresh();
1664 SetCaretOrigin();
1665 SetCaretInfo();
1666 }
1667 if (m_pOperationNotify)
1668 m_pOperationNotify->OnClear(m_wpCaret, m_wpOldCaret);
1669
1670 return true;
1671 }
1672
InsertText(const WideString & sText,int32_t charset,bool bAddUndo,bool bPaint)1673 bool CPWL_EditImpl::InsertText(const WideString& sText,
1674 int32_t charset,
1675 bool bAddUndo,
1676 bool bPaint) {
1677 if (IsTextOverflow())
1678 return false;
1679
1680 m_pVT->UpdateWordPlace(m_wpCaret);
1681 SetCaret(DoInsertText(m_wpCaret, sText, charset));
1682 m_SelState.Set(m_wpCaret, m_wpCaret);
1683 if (m_wpCaret == m_wpOldCaret)
1684 return false;
1685
1686 if (bAddUndo && m_bEnableUndo) {
1687 AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertText>(
1688 this, m_wpOldCaret, m_wpCaret, sText, charset));
1689 }
1690 if (bPaint)
1691 PaintInsertText(m_wpOldCaret, m_wpCaret);
1692
1693 if (m_pOperationNotify)
1694 m_pOperationNotify->OnInsertText(m_wpCaret, m_wpOldCaret);
1695
1696 return true;
1697 }
1698
PaintInsertText(const CPVT_WordPlace & wpOld,const CPVT_WordPlace & wpNew)1699 void CPWL_EditImpl::PaintInsertText(const CPVT_WordPlace& wpOld,
1700 const CPVT_WordPlace& wpNew) {
1701 if (m_pVT->IsValid()) {
1702 RearrangePart(CPVT_WordRange(wpOld, wpNew));
1703 ScrollToCaret();
1704 Refresh();
1705 SetCaretOrigin();
1706 SetCaretInfo();
1707 }
1708 }
1709
Redo()1710 bool CPWL_EditImpl::Redo() {
1711 if (m_bEnableUndo) {
1712 if (m_Undo.CanRedo()) {
1713 m_Undo.Redo();
1714 return true;
1715 }
1716 }
1717
1718 return false;
1719 }
1720
Undo()1721 bool CPWL_EditImpl::Undo() {
1722 if (m_bEnableUndo) {
1723 if (m_Undo.CanUndo()) {
1724 m_Undo.Undo();
1725 return true;
1726 }
1727 }
1728
1729 return false;
1730 }
1731
SetCaretOrigin()1732 void CPWL_EditImpl::SetCaretOrigin() {
1733 if (!m_pVT->IsValid())
1734 return;
1735
1736 CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
1737 pIterator->SetAt(m_wpCaret);
1738 CPVT_Word word;
1739 CPVT_Line line;
1740 if (pIterator->GetWord(word)) {
1741 m_ptCaret.x = word.ptWord.x + word.fWidth;
1742 m_ptCaret.y = word.ptWord.y;
1743 } else if (pIterator->GetLine(line)) {
1744 m_ptCaret.x = line.ptLine.x;
1745 m_ptCaret.y = line.ptLine.y;
1746 }
1747 }
1748
WordIndexToWordPlace(int32_t index) const1749 CPVT_WordPlace CPWL_EditImpl::WordIndexToWordPlace(int32_t index) const {
1750 if (m_pVT->IsValid())
1751 return m_pVT->WordIndexToWordPlace(index);
1752
1753 return CPVT_WordPlace();
1754 }
1755
IsTextFull() const1756 bool CPWL_EditImpl::IsTextFull() const {
1757 int32_t nTotalWords = m_pVT->GetTotalWords();
1758 int32_t nLimitChar = m_pVT->GetLimitChar();
1759 int32_t nCharArray = m_pVT->GetCharArray();
1760
1761 return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) ||
1762 (nCharArray > 0 && nTotalWords >= nCharArray);
1763 }
1764
IsTextOverflow() const1765 bool CPWL_EditImpl::IsTextOverflow() const {
1766 if (!m_bEnableScroll && !m_bEnableOverflow) {
1767 CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
1768 CFX_FloatRect rcContent = m_pVT->GetContentRect();
1769
1770 if (m_pVT->IsMultiLine() && GetTotalLines() > 1 &&
1771 IsFloatBigger(rcContent.Height(), rcPlate.Height())) {
1772 return true;
1773 }
1774
1775 if (IsFloatBigger(rcContent.Width(), rcPlate.Width()))
1776 return true;
1777 }
1778
1779 return false;
1780 }
1781
CanUndo() const1782 bool CPWL_EditImpl::CanUndo() const {
1783 if (m_bEnableUndo) {
1784 return m_Undo.CanUndo();
1785 }
1786
1787 return false;
1788 }
1789
CanRedo() const1790 bool CPWL_EditImpl::CanRedo() const {
1791 if (m_bEnableUndo) {
1792 return m_Undo.CanRedo();
1793 }
1794
1795 return false;
1796 }
1797
EnableRefresh(bool bRefresh)1798 void CPWL_EditImpl::EnableRefresh(bool bRefresh) {
1799 m_bEnableRefresh = bRefresh;
1800 }
1801
EnableUndo(bool bUndo)1802 void CPWL_EditImpl::EnableUndo(bool bUndo) {
1803 m_bEnableUndo = bUndo;
1804 }
1805
DoInsertText(const CPVT_WordPlace & place,const WideString & sText,int32_t charset)1806 CPVT_WordPlace CPWL_EditImpl::DoInsertText(const CPVT_WordPlace& place,
1807 const WideString& sText,
1808 int32_t charset) {
1809 CPVT_WordPlace wp = place;
1810
1811 if (m_pVT->IsValid()) {
1812 for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++) {
1813 uint16_t word = sText[i];
1814 switch (word) {
1815 case 0x0D:
1816 wp = m_pVT->InsertSection(wp);
1817 if (i + 1 < sz && sText[i + 1] == 0x0A)
1818 i++;
1819 break;
1820 case 0x0A:
1821 wp = m_pVT->InsertSection(wp);
1822 break;
1823 case 0x09:
1824 word = 0x20;
1825 default:
1826 wp =
1827 m_pVT->InsertWord(wp, word, GetCharSetFromUnicode(word, charset));
1828 break;
1829 }
1830 }
1831 }
1832
1833 return wp;
1834 }
1835
GetCharSetFromUnicode(uint16_t word,int32_t nOldCharset)1836 int32_t CPWL_EditImpl::GetCharSetFromUnicode(uint16_t word,
1837 int32_t nOldCharset) {
1838 if (IPVT_FontMap* pFontMap = GetFontMap())
1839 return pFontMap->CharSetFromUnicode(word, nOldCharset);
1840 return nOldCharset;
1841 }
1842
AddEditUndoItem(std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem)1843 void CPWL_EditImpl::AddEditUndoItem(
1844 std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem) {
1845 m_Undo.AddItem(std::move(pEditUndoItem));
1846 }
1847
GetPDFWordString(int32_t nFontIndex,uint16_t Word,uint16_t SubWord)1848 ByteString CPWL_EditImpl::GetPDFWordString(int32_t nFontIndex,
1849 uint16_t Word,
1850 uint16_t SubWord) {
1851 IPVT_FontMap* pFontMap = GetFontMap();
1852 CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex);
1853 if (!pPDFFont)
1854 return ByteString();
1855
1856 ByteString sWord;
1857 if (SubWord > 0) {
1858 Word = SubWord;
1859 } else {
1860 uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible()
1861 ? pPDFFont->CharCodeFromUnicode(Word)
1862 : pFontMap->CharCodeFromUnicode(nFontIndex, Word);
1863 if (dwCharCode > 0) {
1864 pPDFFont->AppendChar(&sWord, dwCharCode);
1865 return sWord;
1866 }
1867 }
1868 pPDFFont->AppendChar(&sWord, Word);
1869 return sWord;
1870 }
1871
CPWL_EditImpl_Select()1872 CPWL_EditImpl_Select::CPWL_EditImpl_Select() {}
1873
CPWL_EditImpl_Select(const CPVT_WordRange & range)1874 CPWL_EditImpl_Select::CPWL_EditImpl_Select(const CPVT_WordRange& range) {
1875 Set(range.BeginPos, range.EndPos);
1876 }
1877
ConvertToWordRange() const1878 CPVT_WordRange CPWL_EditImpl_Select::ConvertToWordRange() const {
1879 return CPVT_WordRange(BeginPos, EndPos);
1880 }
1881
Reset()1882 void CPWL_EditImpl_Select::Reset() {
1883 BeginPos.Reset();
1884 EndPos.Reset();
1885 }
1886
Set(const CPVT_WordPlace & begin,const CPVT_WordPlace & end)1887 void CPWL_EditImpl_Select::Set(const CPVT_WordPlace& begin,
1888 const CPVT_WordPlace& end) {
1889 BeginPos = begin;
1890 EndPos = end;
1891 }
1892
SetEndPos(const CPVT_WordPlace & end)1893 void CPWL_EditImpl_Select::SetEndPos(const CPVT_WordPlace& end) {
1894 EndPos = end;
1895 }
1896
IsEmpty() const1897 bool CPWL_EditImpl_Select::IsEmpty() const {
1898 return BeginPos == EndPos;
1899 }
1900