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 "xfa/fwl/basewidget/fwl_editimp.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <vector>
12 
13 #include "third_party/base/stl_util.h"
14 #include "xfa/fde/cfde_txtedtengine.h"
15 #include "xfa/fde/fde_gedevice.h"
16 #include "xfa/fde/fde_render.h"
17 #include "xfa/fde/ifde_txtedtpage.h"
18 #include "xfa/fgas/font/fgas_gefont.h"
19 #include "xfa/fwl/basewidget/fwl_caretimp.h"
20 #include "xfa/fwl/basewidget/fwl_comboboximp.h"
21 #include "xfa/fwl/basewidget/fwl_scrollbarimp.h"
22 #include "xfa/fwl/basewidget/ifwl_caret.h"
23 #include "xfa/fwl/core/cfwl_message.h"
24 #include "xfa/fwl/core/cfwl_themebackground.h"
25 #include "xfa/fwl/core/cfwl_themepart.h"
26 #include "xfa/fwl/core/cfwl_widgetmgr.h"
27 #include "xfa/fwl/core/fwl_appimp.h"
28 #include "xfa/fwl/core/fwl_noteimp.h"
29 #include "xfa/fwl/core/fwl_widgetimp.h"
30 #include "xfa/fwl/core/ifwl_themeprovider.h"
31 #include "xfa/fxfa/include/xfa_ffdoc.h"
32 #include "xfa/fxfa/include/xfa_ffwidget.h"
33 #include "xfa/fxgraphics/cfx_path.h"
34 
35 namespace {
36 
37 const int kEditMargin = 3;
38 
FX_EDIT_ISLATINWORD(FX_WCHAR c)39 bool FX_EDIT_ISLATINWORD(FX_WCHAR c) {
40   return c == 0x2D || (c <= 0x005A && c >= 0x0041) ||
41          (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) ||
42          c == 0x0027;
43 }
44 
AddSquigglyPath(CFX_Path * pPathData,FX_FLOAT fStartX,FX_FLOAT fEndX,FX_FLOAT fY,FX_FLOAT fStep)45 void AddSquigglyPath(CFX_Path* pPathData,
46                      FX_FLOAT fStartX,
47                      FX_FLOAT fEndX,
48                      FX_FLOAT fY,
49                      FX_FLOAT fStep) {
50   pPathData->MoveTo(fStartX, fY);
51   int i = 1;
52   for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i) {
53     pPathData->LineTo(fx, fY + (i & 1) * fStep);
54   }
55 }
56 
57 }  // namespace
58 
59 // static
Create(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)60 IFWL_Edit* IFWL_Edit::Create(const CFWL_WidgetImpProperties& properties,
61                              IFWL_Widget* pOuter) {
62   IFWL_Edit* pEdit = new IFWL_Edit;
63   CFWL_EditImp* pEditImpl = new CFWL_EditImp(properties, pOuter);
64   pEdit->SetImpl(pEditImpl);
65   pEditImpl->SetInterface(pEdit);
66   return pEdit;
67 }
68 // static
CreateComboEdit(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)69 IFWL_Edit* IFWL_Edit::CreateComboEdit(
70     const CFWL_WidgetImpProperties& properties,
71     IFWL_Widget* pOuter) {
72   IFWL_Edit* pEdit = new IFWL_Edit;
73   CFWL_EditImp* pComboEditImpl = new CFWL_ComboEditImp(properties, pOuter);
74   pEdit->SetImpl(pComboEditImpl);
75   pComboEditImpl->SetInterface(pEdit);
76   return pEdit;
77 }
IFWL_Edit()78 IFWL_Edit::IFWL_Edit() {}
SetText(const CFX_WideString & wsText)79 FWL_Error IFWL_Edit::SetText(const CFX_WideString& wsText) {
80   return static_cast<CFWL_EditImp*>(GetImpl())->SetText(wsText);
81 }
GetTextLength() const82 int32_t IFWL_Edit::GetTextLength() const {
83   return static_cast<CFWL_EditImp*>(GetImpl())->GetTextLength();
84 }
GetText(CFX_WideString & wsText,int32_t nStart,int32_t nCount) const85 FWL_Error IFWL_Edit::GetText(CFX_WideString& wsText,
86                              int32_t nStart,
87                              int32_t nCount) const {
88   return static_cast<CFWL_EditImp*>(GetImpl())->GetText(wsText, nStart, nCount);
89 }
ClearText()90 FWL_Error IFWL_Edit::ClearText() {
91   return static_cast<CFWL_EditImp*>(GetImpl())->ClearText();
92 }
GetCaretPos() const93 int32_t IFWL_Edit::GetCaretPos() const {
94   return static_cast<CFWL_EditImp*>(GetImpl())->GetCaretPos();
95 }
SetCaretPos(int32_t nIndex,FX_BOOL bBefore)96 int32_t IFWL_Edit::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) {
97   return static_cast<CFWL_EditImp*>(GetImpl())->SetCaretPos(nIndex, bBefore);
98 }
AddSelRange(int32_t nStart,int32_t nCount)99 FWL_Error IFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) {
100   return static_cast<CFWL_EditImp*>(GetImpl())->AddSelRange(nStart, nCount);
101 }
CountSelRanges()102 int32_t IFWL_Edit::CountSelRanges() {
103   return static_cast<CFWL_EditImp*>(GetImpl())->CountSelRanges();
104 }
GetSelRange(int32_t nIndex,int32_t & nStart)105 int32_t IFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) {
106   return static_cast<CFWL_EditImp*>(GetImpl())->GetSelRange(nIndex, nStart);
107 }
ClearSelections()108 FWL_Error IFWL_Edit::ClearSelections() {
109   return static_cast<CFWL_EditImp*>(GetImpl())->ClearSelections();
110 }
GetLimit()111 int32_t IFWL_Edit::GetLimit() {
112   return static_cast<CFWL_EditImp*>(GetImpl())->GetLimit();
113 }
SetLimit(int32_t nLimit)114 FWL_Error IFWL_Edit::SetLimit(int32_t nLimit) {
115   return static_cast<CFWL_EditImp*>(GetImpl())->SetLimit(nLimit);
116 }
SetAliasChar(FX_WCHAR wAlias)117 FWL_Error IFWL_Edit::SetAliasChar(FX_WCHAR wAlias) {
118   return static_cast<CFWL_EditImp*>(GetImpl())->SetAliasChar(wAlias);
119 }
Insert(int32_t nStart,const FX_WCHAR * lpText,int32_t nLen)120 FWL_Error IFWL_Edit::Insert(int32_t nStart,
121                             const FX_WCHAR* lpText,
122                             int32_t nLen) {
123   return static_cast<CFWL_EditImp*>(GetImpl())->Insert(nStart, lpText, nLen);
124 }
DeleteSelections()125 FWL_Error IFWL_Edit::DeleteSelections() {
126   return static_cast<CFWL_EditImp*>(GetImpl())->DeleteSelections();
127 }
DeleteRange(int32_t nStart,int32_t nCount)128 FWL_Error IFWL_Edit::DeleteRange(int32_t nStart, int32_t nCount) {
129   return static_cast<CFWL_EditImp*>(GetImpl())->DeleteRange(nStart, nCount);
130 }
Replace(int32_t nStart,int32_t nLen,const CFX_WideStringC & wsReplace)131 FWL_Error IFWL_Edit::Replace(int32_t nStart,
132                              int32_t nLen,
133                              const CFX_WideStringC& wsReplace) {
134   return static_cast<CFWL_EditImp*>(GetImpl())
135       ->Replace(nStart, nLen, wsReplace);
136 }
DoClipboard(int32_t iCmd)137 FWL_Error IFWL_Edit::DoClipboard(int32_t iCmd) {
138   return static_cast<CFWL_EditImp*>(GetImpl())->DoClipboard(iCmd);
139 }
Copy(CFX_WideString & wsCopy)140 FX_BOOL IFWL_Edit::Copy(CFX_WideString& wsCopy) {
141   return static_cast<CFWL_EditImp*>(GetImpl())->Copy(wsCopy);
142 }
Cut(CFX_WideString & wsCut)143 FX_BOOL IFWL_Edit::Cut(CFX_WideString& wsCut) {
144   return static_cast<CFWL_EditImp*>(GetImpl())->Cut(wsCut);
145 }
Paste(const CFX_WideString & wsPaste)146 FX_BOOL IFWL_Edit::Paste(const CFX_WideString& wsPaste) {
147   return static_cast<CFWL_EditImp*>(GetImpl())->Paste(wsPaste);
148 }
Delete()149 FX_BOOL IFWL_Edit::Delete() {
150   return static_cast<CFWL_EditImp*>(GetImpl())->Delete();
151 }
Redo(const IFDE_TxtEdtDoRecord * pRecord)152 FX_BOOL IFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) {
153   return static_cast<CFWL_EditImp*>(GetImpl())->Redo(pRecord);
154 }
Undo(const IFDE_TxtEdtDoRecord * pRecord)155 FX_BOOL IFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) {
156   return static_cast<CFWL_EditImp*>(GetImpl())->Undo(pRecord);
157 }
Undo()158 FX_BOOL IFWL_Edit::Undo() {
159   return static_cast<CFWL_EditImp*>(GetImpl())->Undo();
160 }
Redo()161 FX_BOOL IFWL_Edit::Redo() {
162   return static_cast<CFWL_EditImp*>(GetImpl())->Redo();
163 }
CanUndo()164 FX_BOOL IFWL_Edit::CanUndo() {
165   return static_cast<CFWL_EditImp*>(GetImpl())->CanUndo();
166 }
CanRedo()167 FX_BOOL IFWL_Edit::CanRedo() {
168   return static_cast<CFWL_EditImp*>(GetImpl())->CanRedo();
169 }
SetTabWidth(FX_FLOAT fTabWidth,FX_BOOL bEquidistant)170 FWL_Error IFWL_Edit::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
171   return static_cast<CFWL_EditImp*>(GetImpl())
172       ->SetTabWidth(fTabWidth, bEquidistant);
173 }
SetOuter(IFWL_Widget * pOuter)174 FWL_Error IFWL_Edit::SetOuter(IFWL_Widget* pOuter) {
175   return static_cast<CFWL_EditImp*>(GetImpl())->SetOuter(pOuter);
176 }
SetNumberRange(int32_t iMin,int32_t iMax)177 FWL_Error IFWL_Edit::SetNumberRange(int32_t iMin, int32_t iMax) {
178   return static_cast<CFWL_EditImp*>(GetImpl())->SetNumberRange(iMin, iMax);
179 }
SetBackColor(uint32_t dwColor)180 FWL_Error IFWL_Edit::SetBackColor(uint32_t dwColor) {
181   return static_cast<CFWL_EditImp*>(GetImpl())->SetBackgroundColor(dwColor);
182 }
SetFont(const CFX_WideString & wsFont,FX_FLOAT fSize)183 FWL_Error IFWL_Edit::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) {
184   return static_cast<CFWL_EditImp*>(GetImpl())->SetFont(wsFont, fSize);
185 }
SetScrollOffset(FX_FLOAT fScrollOffset)186 void IFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) {
187   return static_cast<CFWL_EditImp*>(GetImpl())->SetScrollOffset(fScrollOffset);
188 }
GetSuggestWords(CFX_PointF pointf,std::vector<CFX_ByteString> & sSuggest)189 FX_BOOL IFWL_Edit::GetSuggestWords(CFX_PointF pointf,
190                                    std::vector<CFX_ByteString>& sSuggest) {
191   return static_cast<CFWL_EditImp*>(GetImpl())
192       ->GetSuggestWords(pointf, sSuggest);
193 }
ReplaceSpellCheckWord(CFX_PointF pointf,const CFX_ByteStringC & bsReplace)194 FX_BOOL IFWL_Edit::ReplaceSpellCheckWord(CFX_PointF pointf,
195                                          const CFX_ByteStringC& bsReplace) {
196   return static_cast<CFWL_EditImp*>(GetImpl())
197       ->ReplaceSpellCheckWord(pointf, bsReplace);
198 }
199 
CFWL_EditImp(const CFWL_WidgetImpProperties & properties,IFWL_Widget * pOuter)200 CFWL_EditImp::CFWL_EditImp(const CFWL_WidgetImpProperties& properties,
201                            IFWL_Widget* pOuter)
202     : CFWL_WidgetImp(properties, pOuter),
203       m_fVAlignOffset(0.0f),
204       m_fScrollOffsetX(0.0f),
205       m_fScrollOffsetY(0.0f),
206       m_pEdtEngine(nullptr),
207       m_bLButtonDown(FALSE),
208       m_nSelStart(0),
209       m_nLimit(-1),
210       m_fSpaceAbove(0),
211       m_fSpaceBelow(0),
212       m_fFontSize(0),
213       m_bSetRange(FALSE),
214       m_iMin(-1),
215       m_iMax(0xFFFFFFF),
216       m_backColor(0),
217       m_updateBackColor(FALSE),
218       m_iCurRecord(-1),
219       m_iMaxRecord(128) {
220   m_rtClient.Reset();
221   m_rtEngine.Reset();
222   m_rtStatic.Reset();
223 }
224 
~CFWL_EditImp()225 CFWL_EditImp::~CFWL_EditImp() {
226   delete m_pEdtEngine;
227   ClearRecord();
228 }
229 
GetClassName(CFX_WideString & wsClass) const230 FWL_Error CFWL_EditImp::GetClassName(CFX_WideString& wsClass) const {
231   wsClass = FWL_CLASS_Edit;
232   return FWL_Error::Succeeded;
233 }
234 
GetClassID() const235 FWL_Type CFWL_EditImp::GetClassID() const {
236   return FWL_Type::Edit;
237 }
238 
Initialize()239 FWL_Error CFWL_EditImp::Initialize() {
240   if (CFWL_WidgetImp::Initialize() != FWL_Error::Succeeded)
241     return FWL_Error::Indefinite;
242   if (!m_pDelegate)
243     m_pDelegate = new CFWL_EditImpDelegate(this);
244 
245   InitCaret();
246   if (!m_pEdtEngine)
247     InitEngine();
248 
249   return FWL_Error::Succeeded;
250 }
251 
Finalize()252 FWL_Error CFWL_EditImp::Finalize() {
253   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
254     ShowCaret(FALSE);
255   }
256   if (m_pHorzScrollBar) {
257     m_pHorzScrollBar->Finalize();
258   }
259   if (m_pVertScrollBar) {
260     m_pVertScrollBar->Finalize();
261   }
262   delete m_pDelegate;
263   m_pDelegate = nullptr;
264   return CFWL_WidgetImp::Finalize();
265 }
GetWidgetRect(CFX_RectF & rect,FX_BOOL bAutoSize)266 FWL_Error CFWL_EditImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
267   if (bAutoSize) {
268     rect.Set(0, 0, 0, 0);
269     if (m_pEdtEngine) {
270       int32_t iTextLen = m_pEdtEngine->GetTextLength();
271       if (iTextLen > 0) {
272         CFX_WideString wsText;
273         m_pEdtEngine->GetText(wsText, 0);
274         CFX_SizeF sz = CalcTextSize(
275             wsText, m_pProperties->m_pThemeProvider,
276             m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
277         rect.Set(0, 0, sz.x, sz.y);
278       }
279     }
280     CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
281   } else {
282     rect = m_pProperties->m_rtWidget;
283     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
284       if (IsShowScrollBar(TRUE)) {
285         FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
286             GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
287         rect.width += *pfWidth;
288         rect.width += kEditMargin;
289       }
290       if (IsShowScrollBar(FALSE)) {
291         FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
292             GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
293         rect.height += *pfWidth;
294         rect.height += kEditMargin;
295       }
296     }
297   }
298   return FWL_Error::Succeeded;
299 }
300 
SetStates(uint32_t dwStates,FX_BOOL bSet)301 void CFWL_EditImp::SetStates(uint32_t dwStates, FX_BOOL bSet) {
302   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
303       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
304     ShowCaret(FALSE);
305   }
306   CFWL_WidgetImp::SetStates(dwStates, bSet);
307 }
308 
SetWidgetRect(const CFX_RectF & rect)309 FWL_Error CFWL_EditImp::SetWidgetRect(const CFX_RectF& rect) {
310   return CFWL_WidgetImp::SetWidgetRect(rect);
311 }
Update()312 FWL_Error CFWL_EditImp::Update() {
313   if (IsLocked()) {
314     return FWL_Error::Indefinite;
315   }
316   if (!m_pProperties->m_pThemeProvider) {
317     m_pProperties->m_pThemeProvider = GetAvailableTheme();
318   }
319   Layout();
320   if (m_rtClient.IsEmpty()) {
321     return FWL_Error::Indefinite;
322   }
323   UpdateEditEngine();
324   UpdateVAlignment();
325   UpdateScroll();
326   InitCaret();
327   return FWL_Error::Succeeded;
328 }
329 
HitTest(FX_FLOAT fx,FX_FLOAT fy)330 FWL_WidgetHit CFWL_EditImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
331   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
332     if (IsShowScrollBar(TRUE)) {
333       CFX_RectF rect;
334       m_pVertScrollBar->GetWidgetRect(rect);
335       if (rect.Contains(fx, fy))
336         return FWL_WidgetHit::VScrollBar;
337     }
338     if (IsShowScrollBar(FALSE)) {
339       CFX_RectF rect;
340       m_pHorzScrollBar->GetWidgetRect(rect);
341       if (rect.Contains(fx, fy))
342         return FWL_WidgetHit::HScrollBar;
343     }
344   }
345   if (m_rtClient.Contains(fx, fy))
346     return FWL_WidgetHit::Edit;
347   return FWL_WidgetHit::Unknown;
348 }
349 
AddSpellCheckObj(CFX_Path & PathData,int32_t nStart,int32_t nCount,FX_FLOAT fOffSetX,FX_FLOAT fOffSetY)350 void CFWL_EditImp::AddSpellCheckObj(CFX_Path& PathData,
351                                     int32_t nStart,
352                                     int32_t nCount,
353                                     FX_FLOAT fOffSetX,
354                                     FX_FLOAT fOffSetY) {
355   FX_FLOAT fStartX = 0.0f;
356   FX_FLOAT fEndX = 0.0f;
357   FX_FLOAT fY = 0.0f;
358   FX_FLOAT fStep = 0.0f;
359   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
360   CFX_RectFArray rectArray;
361   CFX_RectF rectText;
362   const FDE_TXTEDTPARAMS* txtEdtParams = m_pEdtEngine->GetEditParams();
363   FX_FLOAT fAsent = (FX_FLOAT)txtEdtParams->pFont->GetAscent() *
364                     txtEdtParams->fFontSize / 1000;
365   pPage->CalcRangeRectArray(nStart, nCount, rectArray);
366   for (int i = 0; i < rectArray.GetSize(); i++) {
367     rectText = rectArray.GetAt(i);
368     fY = rectText.top + fAsent + fOffSetY;
369     fStep = txtEdtParams->fFontSize / 16.0f;
370     fStartX = rectText.left + fOffSetX;
371     fEndX = fStartX + rectText.Width();
372     AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep);
373   }
374 }
GetWordAtPoint(CFX_PointF pointf,int32_t & nCount)375 int32_t CFWL_EditImp::GetWordAtPoint(CFX_PointF pointf, int32_t& nCount) {
376   return 0;
377 }
GetSuggestWords(CFX_PointF pointf,std::vector<CFX_ByteString> & sSuggest)378 FX_BOOL CFWL_EditImp::GetSuggestWords(CFX_PointF pointf,
379                                       std::vector<CFX_ByteString>& sSuggest) {
380   int32_t nWordCount = 0;
381   int32_t nWordStart = GetWordAtPoint(pointf, nWordCount);
382   if (nWordCount < 1) {
383     return FALSE;
384   }
385   CFX_WideString wsSpell;
386   GetText(wsSpell, nWordStart, nWordCount);
387   CFX_ByteString sLatinWord;
388   for (int i = 0; i < nWordCount; i++) {
389     if (!FX_EDIT_ISLATINWORD(wsSpell[i])) {
390       break;
391     }
392     sLatinWord += (FX_CHAR)wsSpell[i];
393   }
394   if (sLatinWord.IsEmpty()) {
395     return FALSE;
396   }
397   CFWL_EvtEdtCheckWord checkWordEvent;
398   checkWordEvent.m_pSrcTarget = m_pInterface;
399   checkWordEvent.bsWord = sLatinWord;
400   checkWordEvent.bCheckWord = TRUE;
401   DispatchEvent(&checkWordEvent);
402   if (checkWordEvent.bCheckWord) {
403     return FALSE;
404   }
405   CFWL_EvtEdtGetSuggestWords suggestWordsEvent;
406   suggestWordsEvent.m_pSrcTarget = m_pInterface;
407   suggestWordsEvent.bsWord = sLatinWord;
408   suggestWordsEvent.bsArraySuggestWords = sSuggest;
409   suggestWordsEvent.bSuggestWords = FALSE;
410   DispatchEvent(&checkWordEvent);
411   return suggestWordsEvent.bSuggestWords;
412 }
ReplaceSpellCheckWord(CFX_PointF pointf,const CFX_ByteStringC & bsReplace)413 FX_BOOL CFWL_EditImp::ReplaceSpellCheckWord(CFX_PointF pointf,
414                                             const CFX_ByteStringC& bsReplace) {
415   int32_t nWordCount = 0;
416   int32_t nWordStart = GetWordAtPoint(pointf, nWordCount);
417   if (nWordCount < 1) {
418     return FALSE;
419   }
420   CFX_WideString wsSpell;
421   GetText(wsSpell, nWordStart, nWordCount);
422   for (int i = 0; i < nWordCount; i++) {
423     if (!FX_EDIT_ISLATINWORD(wsSpell[i])) {
424       nWordCount = i;
425       break;
426     }
427   }
428   int32_t nDestLen = bsReplace.GetLength();
429   CFX_WideString wsDest;
430   FX_WCHAR* pBuffer = wsDest.GetBuffer(nDestLen);
431   for (int32_t i = 0; i < nDestLen; i++) {
432     pBuffer[i] = bsReplace[i];
433   }
434   wsDest.ReleaseBuffer(nDestLen);
435   Replace(nWordStart, nWordCount, wsDest.AsStringC());
436   return TRUE;
437 }
DrawSpellCheck(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)438 void CFWL_EditImp::DrawSpellCheck(CFX_Graphics* pGraphics,
439                                   const CFX_Matrix* pMatrix) {
440   pGraphics->SaveGraphState();
441   if (pMatrix) {
442     pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix));
443   }
444   FX_ARGB cr = 0xFFFF0000;
445   CFX_Color crLine(cr);
446   CFWL_EvtEdtCheckWord checkWordEvent;
447   checkWordEvent.m_pSrcTarget = m_pInterface;
448   CFX_ByteString sLatinWord;
449   CFX_Path pathSpell;
450   pathSpell.Create();
451   int32_t nStart = 0;
452   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
453   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
454   CFX_WideString wsSpell;
455   GetText(wsSpell);
456   int32_t nContentLen = wsSpell.GetLength();
457   for (int i = 0; i < nContentLen; i++) {
458     if (FX_EDIT_ISLATINWORD(wsSpell[i])) {
459       if (sLatinWord.IsEmpty()) {
460         nStart = i;
461       }
462       sLatinWord += (FX_CHAR)wsSpell[i];
463     } else {
464       checkWordEvent.bsWord = sLatinWord;
465       checkWordEvent.bCheckWord = TRUE;
466       DispatchEvent(&checkWordEvent);
467       if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
468         AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
469                          fOffSetY);
470       }
471       sLatinWord.clear();
472     }
473   }
474   checkWordEvent.bsWord = sLatinWord;
475   checkWordEvent.bCheckWord = TRUE;
476   DispatchEvent(&checkWordEvent);
477   if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
478     AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
479                      fOffSetY);
480   }
481   if (!pathSpell.IsEmpty()) {
482     CFX_RectF rtClip = m_rtEngine;
483     CFX_Matrix mt;
484     mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
485     if (pMatrix) {
486       pMatrix->TransformRect(rtClip);
487       mt.Concat(*pMatrix);
488     }
489     pGraphics->SetClipRect(rtClip);
490     pGraphics->SetStrokeColor(&crLine);
491     pGraphics->SetLineWidth(0);
492     pGraphics->StrokePath(&pathSpell, nullptr);
493   }
494   pGraphics->RestoreGraphState();
495 }
DrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)496 FWL_Error CFWL_EditImp::DrawWidget(CFX_Graphics* pGraphics,
497                                    const CFX_Matrix* pMatrix) {
498   if (!pGraphics)
499     return FWL_Error::Indefinite;
500   if (!m_pProperties->m_pThemeProvider)
501     return FWL_Error::Indefinite;
502   if (m_rtClient.IsEmpty()) {
503     return FWL_Error::Indefinite;
504   }
505   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
506   if (!m_pWidgetMgr->IsFormDisabled()) {
507     DrawTextBk(pGraphics, pTheme, pMatrix);
508   }
509   if (m_pEdtEngine) {
510     DrawContent(pGraphics, pTheme, pMatrix);
511   }
512   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
513       !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) {
514     DrawSpellCheck(pGraphics, pMatrix);
515   }
516   if (HasBorder()) {
517     DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
518   }
519   if (HasEdge()) {
520     DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
521   }
522   return FWL_Error::Succeeded;
523 }
SetThemeProvider(IFWL_ThemeProvider * pThemeProvider)524 FWL_Error CFWL_EditImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
525   if (!pThemeProvider)
526     return FWL_Error::Indefinite;
527   if (m_pHorzScrollBar) {
528     m_pHorzScrollBar->SetThemeProvider(pThemeProvider);
529   }
530   if (m_pVertScrollBar) {
531     m_pVertScrollBar->SetThemeProvider(pThemeProvider);
532   }
533   if (m_pCaret) {
534     m_pCaret->SetThemeProvider(pThemeProvider);
535   }
536   m_pProperties->m_pThemeProvider = pThemeProvider;
537   return FWL_Error::Succeeded;
538 }
539 
SetText(const CFX_WideString & wsText)540 FWL_Error CFWL_EditImp::SetText(const CFX_WideString& wsText) {
541   m_pEdtEngine->SetText(wsText);
542   return FWL_Error::Succeeded;
543 }
544 
GetTextLength() const545 int32_t CFWL_EditImp::GetTextLength() const {
546   if (!m_pEdtEngine)
547     return -1;
548   return m_pEdtEngine->GetTextLength();
549 }
550 
GetText(CFX_WideString & wsText,int32_t nStart,int32_t nCount) const551 FWL_Error CFWL_EditImp::GetText(CFX_WideString& wsText,
552                                 int32_t nStart,
553                                 int32_t nCount) const {
554   if (!m_pEdtEngine)
555     return FWL_Error::Indefinite;
556 
557   m_pEdtEngine->GetText(wsText, nStart, nCount);
558   return FWL_Error::Succeeded;
559 }
560 
ClearText()561 FWL_Error CFWL_EditImp::ClearText() {
562   if (!m_pEdtEngine)
563     return FWL_Error::Indefinite;
564 
565   m_pEdtEngine->ClearText();
566   return FWL_Error::Succeeded;
567 }
568 
GetCaretPos() const569 int32_t CFWL_EditImp::GetCaretPos() const {
570   if (!m_pEdtEngine)
571     return -1;
572   return m_pEdtEngine->GetCaretPos();
573 }
574 
SetCaretPos(int32_t nIndex,FX_BOOL bBefore)575 int32_t CFWL_EditImp::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) {
576   if (!m_pEdtEngine)
577     return -1;
578   return m_pEdtEngine->SetCaretPos(nIndex, bBefore);
579 }
580 
AddSelRange(int32_t nStart,int32_t nCount)581 FWL_Error CFWL_EditImp::AddSelRange(int32_t nStart, int32_t nCount) {
582   if (!m_pEdtEngine)
583     return FWL_Error::Indefinite;
584 
585   m_pEdtEngine->AddSelRange(nStart, nCount);
586   return FWL_Error::Succeeded;
587 }
588 
CountSelRanges()589 int32_t CFWL_EditImp::CountSelRanges() {
590   if (!m_pEdtEngine)
591     return 0;
592   return m_pEdtEngine->CountSelRanges();
593 }
594 
GetSelRange(int32_t nIndex,int32_t & nStart)595 int32_t CFWL_EditImp::GetSelRange(int32_t nIndex, int32_t& nStart) {
596   if (!m_pEdtEngine)
597     return -1;
598   return m_pEdtEngine->GetSelRange(nIndex, nStart);
599 }
600 
ClearSelections()601 FWL_Error CFWL_EditImp::ClearSelections() {
602   if (!m_pEdtEngine)
603     return FWL_Error::Indefinite;
604 
605   m_pEdtEngine->ClearSelection();
606   return FWL_Error::Succeeded;
607 }
608 
GetLimit()609 int32_t CFWL_EditImp::GetLimit() {
610   return m_nLimit;
611 }
612 
SetLimit(int32_t nLimit)613 FWL_Error CFWL_EditImp::SetLimit(int32_t nLimit) {
614   m_nLimit = nLimit;
615   if (!m_pEdtEngine)
616     return FWL_Error::Indefinite;
617 
618   m_pEdtEngine->SetLimit(nLimit);
619   return FWL_Error::Succeeded;
620 }
621 
SetAliasChar(FX_WCHAR wAlias)622 FWL_Error CFWL_EditImp::SetAliasChar(FX_WCHAR wAlias) {
623   if (!m_pEdtEngine)
624     return FWL_Error::Indefinite;
625 
626   m_pEdtEngine->SetAliasChar(wAlias);
627   return FWL_Error::Succeeded;
628 }
629 
Insert(int32_t nStart,const FX_WCHAR * lpText,int32_t nLen)630 FWL_Error CFWL_EditImp::Insert(int32_t nStart,
631                                const FX_WCHAR* lpText,
632                                int32_t nLen) {
633   if (!m_pEdtEngine)
634     return FWL_Error::Indefinite;
635 
636   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
637       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
638     return FWL_Error::Indefinite;
639   }
640   m_pEdtEngine->Insert(nStart, lpText, nLen);
641   return FWL_Error::Succeeded;
642 }
643 
DeleteSelections()644 FWL_Error CFWL_EditImp::DeleteSelections() {
645   if (!m_pEdtEngine)
646     return FWL_Error::Indefinite;
647 
648   int32_t iCount = m_pEdtEngine->CountSelRanges();
649   if (iCount > 0)
650     m_pEdtEngine->Delete(-1);
651   return FWL_Error::Succeeded;
652 }
653 
DeleteRange(int32_t nStart,int32_t nCount)654 FWL_Error CFWL_EditImp::DeleteRange(int32_t nStart, int32_t nCount) {
655   if (!m_pEdtEngine)
656     return FWL_Error::Indefinite;
657 
658   m_pEdtEngine->DeleteRange(nStart, nCount);
659   return FWL_Error::Succeeded;
660 }
661 
Replace(int32_t nStart,int32_t nLen,const CFX_WideStringC & wsReplace)662 FWL_Error CFWL_EditImp::Replace(int32_t nStart,
663                                 int32_t nLen,
664                                 const CFX_WideStringC& wsReplace) {
665   if (!m_pEdtEngine)
666     return FWL_Error::Indefinite;
667 
668   m_pEdtEngine->Replace(nStart, nLen, CFX_WideString(wsReplace));
669   return FWL_Error::Succeeded;
670 }
671 
DoClipboard(int32_t iCmd)672 FWL_Error CFWL_EditImp::DoClipboard(int32_t iCmd) {
673   if (!m_pEdtEngine)
674     return FWL_Error::Indefinite;
675 
676   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
677       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
678     return FWL_Error::Succeeded;
679   }
680   return FWL_Error::Indefinite;
681 }
682 
Copy(CFX_WideString & wsCopy)683 FX_BOOL CFWL_EditImp::Copy(CFX_WideString& wsCopy) {
684   if (!m_pEdtEngine)
685     return FALSE;
686 
687   int32_t nCount = m_pEdtEngine->CountSelRanges();
688   if (nCount == 0)
689     return FALSE;
690 
691   wsCopy.clear();
692   CFX_WideString wsTemp;
693   int32_t nStart, nLength;
694   for (int32_t i = 0; i < nCount; i++) {
695     nLength = m_pEdtEngine->GetSelRange(i, nStart);
696     m_pEdtEngine->GetText(wsTemp, nStart, nLength);
697     wsCopy += wsTemp;
698     wsTemp.clear();
699   }
700   return TRUE;
701 }
702 
Cut(CFX_WideString & wsCut)703 FX_BOOL CFWL_EditImp::Cut(CFX_WideString& wsCut) {
704   if (!m_pEdtEngine)
705     return FALSE;
706 
707   int32_t nCount = m_pEdtEngine->CountSelRanges();
708   if (nCount == 0)
709     return FALSE;
710 
711   wsCut.clear();
712   CFX_WideString wsTemp;
713   int32_t nStart, nLength;
714   for (int32_t i = 0; i < nCount; i++) {
715     nLength = m_pEdtEngine->GetSelRange(i, nStart);
716     m_pEdtEngine->GetText(wsTemp, nStart, nLength);
717     wsCut += wsTemp;
718     wsTemp.clear();
719   }
720   m_pEdtEngine->Delete(0);
721   return TRUE;
722 }
723 
Paste(const CFX_WideString & wsPaste)724 FX_BOOL CFWL_EditImp::Paste(const CFX_WideString& wsPaste) {
725   if (!m_pEdtEngine)
726     return FALSE;
727 
728   int32_t nCaret = m_pEdtEngine->GetCaretPos();
729   int32_t iError =
730       m_pEdtEngine->Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength());
731   if (iError < 0) {
732     ProcessInsertError(iError);
733     return FALSE;
734   }
735   return TRUE;
736 }
737 
Delete()738 FX_BOOL CFWL_EditImp::Delete() {
739   if (!m_pEdtEngine)
740     return FALSE;
741 
742   int32_t nCount = m_pEdtEngine->CountSelRanges();
743   if (nCount < 1)
744     return FALSE;
745 
746   m_pEdtEngine->Delete(0);
747   return TRUE;
748 }
749 
Redo(const IFDE_TxtEdtDoRecord * pRecord)750 FX_BOOL CFWL_EditImp::Redo(const IFDE_TxtEdtDoRecord* pRecord) {
751   if (!m_pEdtEngine)
752     return FALSE;
753   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
754     return TRUE;
755   return m_pEdtEngine->Redo(pRecord);
756 }
757 
Undo(const IFDE_TxtEdtDoRecord * pRecord)758 FX_BOOL CFWL_EditImp::Undo(const IFDE_TxtEdtDoRecord* pRecord) {
759   if (!m_pEdtEngine)
760     return FALSE;
761   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
762     return TRUE;
763   return m_pEdtEngine->Undo(pRecord);
764 }
765 
Undo()766 FX_BOOL CFWL_EditImp::Undo() {
767   if (!CanUndo())
768     return FALSE;
769   return Undo(m_DoRecords[m_iCurRecord--].get());
770 }
771 
Redo()772 FX_BOOL CFWL_EditImp::Redo() {
773   if (!CanRedo())
774     return FALSE;
775   return Redo(m_DoRecords[++m_iCurRecord].get());
776 }
777 
CanUndo()778 FX_BOOL CFWL_EditImp::CanUndo() {
779   return m_iCurRecord >= 0;
780 }
781 
CanRedo()782 FX_BOOL CFWL_EditImp::CanRedo() {
783   return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
784 }
785 
SetTabWidth(FX_FLOAT fTabWidth,FX_BOOL bEquidistant)786 FWL_Error CFWL_EditImp::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
787   if (!m_pEdtEngine)
788     return FWL_Error::Indefinite;
789 
790   FDE_TXTEDTPARAMS* pParams = m_pEdtEngine->GetEditParams();
791   pParams->fTabWidth = fTabWidth;
792   pParams->bTabEquidistant = bEquidistant;
793   return FWL_Error::Succeeded;
794 }
795 
SetOuter(IFWL_Widget * pOuter)796 FWL_Error CFWL_EditImp::SetOuter(IFWL_Widget* pOuter) {
797   m_pOuter = pOuter;
798   return FWL_Error::Succeeded;
799 }
800 
SetNumberRange(int32_t iMin,int32_t iMax)801 FWL_Error CFWL_EditImp::SetNumberRange(int32_t iMin, int32_t iMax) {
802   m_iMin = iMin;
803   m_iMax = iMax;
804   m_bSetRange = TRUE;
805   return FWL_Error::Succeeded;
806 }
807 
On_CaretChanged(CFDE_TxtEdtEngine * pEdit,int32_t nPage,FX_BOOL bVisible)808 void CFWL_EditImp::On_CaretChanged(CFDE_TxtEdtEngine* pEdit,
809                                    int32_t nPage,
810                                    FX_BOOL bVisible) {
811   if (m_rtEngine.IsEmpty())
812     return;
813   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
814     return;
815 
816   FX_BOOL bRepaintContent = UpdateOffset();
817   UpdateCaret();
818   CFX_RectF rtInvalid;
819   rtInvalid.Set(0, 0, 0, 0);
820   FX_BOOL bRepaintScroll = FALSE;
821   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
822     IFWL_ScrollBar* pScroll = UpdateScroll();
823     if (pScroll) {
824       pScroll->GetWidgetRect(rtInvalid);
825       bRepaintScroll = TRUE;
826     }
827   }
828   if (bRepaintContent || bRepaintScroll) {
829     if (bRepaintContent) {
830       rtInvalid.Union(m_rtEngine);
831     }
832     Repaint(&rtInvalid);
833   }
834 }
835 
On_TextChanged(CFDE_TxtEdtEngine * pEdit,FDE_TXTEDT_TEXTCHANGE_INFO & ChangeInfo)836 void CFWL_EditImp::On_TextChanged(CFDE_TxtEdtEngine* pEdit,
837                                   FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) {
838   uint32_t dwStyleEx = m_pProperties->m_dwStyleExes;
839   if (dwStyleEx & FWL_STYLEEXT_EDT_VAlignMask)
840     UpdateVAlignment();
841 
842   IFDE_TxtEdtPage* page = m_pEdtEngine->GetPage(0);
843   FX_FLOAT fContentWidth = page->GetContentsBox().width;
844   FX_FLOAT fContentHeight = page->GetContentsBox().height;
845   CFX_RectF rtTemp;
846   GetClientRect(rtTemp);
847   FX_BOOL bHSelfAdaption =
848       m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption;
849   FX_BOOL bVSelfAdaption =
850       m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption;
851   FX_BOOL bNeedUpdate = FALSE;
852   if (bHSelfAdaption || bVSelfAdaption) {
853     CFWL_EvtEdtPreSelfAdaption evt;
854     evt.m_pSrcTarget = m_pInterface;
855     evt.bHSelfAdaption = TRUE;
856     evt.bVSelfAdaption = TRUE;
857     FX_FLOAT fWidth;
858     FX_FLOAT fHight;
859     fWidth = bHSelfAdaption ? fContentWidth : m_pProperties->m_rtWidget.width;
860     fHight = bVSelfAdaption ? fContentHeight : m_pProperties->m_rtWidget.height;
861     evt.rtAfterChange.Set(0, 0, fWidth, fHight);
862     DispatchEvent(&evt);
863     if (!evt.bHSelfAdaption) {
864       ModifyStylesEx(
865           0, FWL_STYLEEXT_EDT_HSelfAdaption | FWL_STYLEEXT_EDT_AutoHScroll);
866     }
867     if (!evt.bVSelfAdaption) {
868       ModifyStylesEx(
869           0, FWL_STYLEEXT_EDT_VSelfAdaption | FWL_STYLEEXT_EDT_AutoVScroll);
870     }
871     bNeedUpdate = (bHSelfAdaption && !evt.bHSelfAdaption) ||
872                   (bVSelfAdaption && !evt.bVSelfAdaption);
873   }
874   FX_FLOAT fContentWidth1 = fContentWidth;
875   FX_FLOAT fContentHeight1 = fContentHeight;
876   if (bNeedUpdate) {
877     UpdateEditParams();
878     UpdateEditLayout();
879     IFDE_TxtEdtPage* page1 = m_pEdtEngine->GetPage(0);
880     fContentWidth1 = page1->GetContentsBox().width;
881     fContentHeight1 = page1->GetContentsBox().height;
882   }
883   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption) {
884     rtTemp.width = std::max(m_pProperties->m_rtWidget.width, fContentWidth1);
885     m_pProperties->m_rtWidget.width = fContentWidth1;
886   }
887   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption) {
888     rtTemp.height = std::max(m_pProperties->m_rtWidget.height, fContentHeight1);
889     m_pProperties->m_rtWidget.height = fContentHeight1;
890   }
891   CFWL_EvtEdtTextChanged event;
892   event.m_pSrcTarget = m_pInterface;
893   event.nChangeType = ChangeInfo.nChangeType;
894   event.wsInsert = ChangeInfo.wsInsert;
895   event.wsDelete = ChangeInfo.wsDelete;
896   event.wsPrevText = ChangeInfo.wsPrevText;
897   DispatchEvent(&event);
898   LayoutScrollBar();
899   Repaint(&rtTemp);
900 }
On_SelChanged(CFDE_TxtEdtEngine * pEdit)901 void CFWL_EditImp::On_SelChanged(CFDE_TxtEdtEngine* pEdit) {
902   CFX_RectF rtTemp;
903   GetClientRect(rtTemp);
904   Repaint(&rtTemp);
905 }
On_PageLoad(CFDE_TxtEdtEngine * pEdit,int32_t nPageIndex,int32_t nPurpose)906 FX_BOOL CFWL_EditImp::On_PageLoad(CFDE_TxtEdtEngine* pEdit,
907                                   int32_t nPageIndex,
908                                   int32_t nPurpose) {
909   CFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine;
910   IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex);
911   if (!pPage)
912     return FALSE;
913   pPage->LoadPage(nullptr, nullptr);
914   return TRUE;
915 }
On_PageUnload(CFDE_TxtEdtEngine * pEdit,int32_t nPageIndex,int32_t nPurpose)916 FX_BOOL CFWL_EditImp::On_PageUnload(CFDE_TxtEdtEngine* pEdit,
917                                     int32_t nPageIndex,
918                                     int32_t nPurpose) {
919   CFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine;
920   IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex);
921   if (!pPage)
922     return FALSE;
923   pPage->UnloadPage(nullptr);
924   return TRUE;
925 }
926 
On_AddDoRecord(CFDE_TxtEdtEngine * pEdit,IFDE_TxtEdtDoRecord * pRecord)927 void CFWL_EditImp::On_AddDoRecord(CFDE_TxtEdtEngine* pEdit,
928                                   IFDE_TxtEdtDoRecord* pRecord) {
929   AddDoRecord(pRecord);
930 }
931 
On_Validate(CFDE_TxtEdtEngine * pEdit,CFX_WideString & wsText)932 FX_BOOL CFWL_EditImp::On_Validate(CFDE_TxtEdtEngine* pEdit,
933                                   CFX_WideString& wsText) {
934   IFWL_Widget* pDst = GetOuter();
935   if (!pDst) {
936     pDst = m_pInterface;
937   }
938   CFWL_EvtEdtValidate event;
939   event.pDstWidget = pDst;
940   event.m_pSrcTarget = m_pInterface;
941   event.wsInsert = wsText;
942   event.bValidate = TRUE;
943   DispatchEvent(&event);
944   return event.bValidate;
945 }
SetBackgroundColor(uint32_t color)946 FWL_Error CFWL_EditImp::SetBackgroundColor(uint32_t color) {
947   m_backColor = color;
948   m_updateBackColor = TRUE;
949   return FWL_Error::Succeeded;
950 }
SetFont(const CFX_WideString & wsFont,FX_FLOAT fSize)951 FWL_Error CFWL_EditImp::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) {
952   m_wsFont = wsFont;
953   m_fFontSize = fSize;
954   return FWL_Error::Succeeded;
955 }
SetScrollOffset(FX_FLOAT fScrollOffset)956 void CFWL_EditImp::SetScrollOffset(FX_FLOAT fScrollOffset) {
957   m_fScrollOffsetY = fScrollOffset;
958 }
DrawTextBk(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)959 void CFWL_EditImp::DrawTextBk(CFX_Graphics* pGraphics,
960                               IFWL_ThemeProvider* pTheme,
961                               const CFX_Matrix* pMatrix) {
962   CFWL_ThemeBackground param;
963   param.m_pWidget = m_pInterface;
964   param.m_iPart = CFWL_Part::Background;
965   param.m_bStaticBackground = false;
966   param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly
967                          ? CFWL_PartState_ReadOnly
968                          : CFWL_PartState_Normal;
969   uint32_t dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled);
970   if (dwStates) {
971     param.m_dwStates = CFWL_PartState_Disabled;
972   }
973   param.m_pGraphics = pGraphics;
974   param.m_matrix = *pMatrix;
975   param.m_rtPart = m_rtClient;
976   pTheme->DrawBackground(&param);
977   if (!IsShowScrollBar(TRUE) || !IsShowScrollBar(FALSE)) {
978     return;
979   }
980   CFX_RectF rtScorll;
981   m_pHorzScrollBar->GetWidgetRect(rtScorll);
982   CFX_RectF rtStatic;
983   rtStatic.Set(m_rtClient.right() - rtScorll.height,
984                m_rtClient.bottom() - rtScorll.height, rtScorll.height,
985                rtScorll.height);
986   param.m_bStaticBackground = true;
987   param.m_bMaximize = true;
988   param.m_rtPart = rtStatic;
989   pTheme->DrawBackground(&param);
990 }
DrawContent(CFX_Graphics * pGraphics,IFWL_ThemeProvider * pTheme,const CFX_Matrix * pMatrix)991 void CFWL_EditImp::DrawContent(CFX_Graphics* pGraphics,
992                                IFWL_ThemeProvider* pTheme,
993                                const CFX_Matrix* pMatrix) {
994   if (!m_pEdtEngine)
995     return;
996   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
997   if (!pPage)
998     return;
999   pGraphics->SaveGraphState();
1000   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
1001     pGraphics->SaveGraphState();
1002   }
1003   CFX_RectF rtClip = m_rtEngine;
1004   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
1005   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
1006   CFX_Matrix mt;
1007   mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
1008   if (pMatrix) {
1009     pMatrix->TransformRect(rtClip);
1010     mt.Concat(*pMatrix);
1011   }
1012   FX_BOOL bShowSel =
1013       (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) ||
1014       (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
1015   if (bShowSel) {
1016     IFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(m_pInterface);
1017     if (pForm) {
1018       bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) !=
1019                  FWL_WGTSTATE_Deactivated;
1020     }
1021   }
1022   int32_t nSelCount = m_pEdtEngine->CountSelRanges();
1023   if (bShowSel && nSelCount > 0) {
1024     int32_t nPageCharStart = pPage->GetCharStart();
1025     int32_t nPageCharCount = pPage->GetCharCount();
1026     int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1;
1027     int32_t nCharCount;
1028     int32_t nCharStart;
1029     CFX_RectFArray rectArr;
1030     int32_t i = 0;
1031     for (i = 0; i < nSelCount; i++) {
1032       nCharCount = m_pEdtEngine->GetSelRange(i, nCharStart);
1033       int32_t nCharEnd = nCharStart + nCharCount - 1;
1034       if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) {
1035         continue;
1036       }
1037       int32_t nBgn = std::max(nCharStart, nPageCharStart);
1038       int32_t nEnd = std::min(nCharEnd, nPageCharEnd);
1039       pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1,
1040                                 rectArr);
1041     }
1042     int32_t nCount = rectArr.GetSize();
1043     CFX_Path path;
1044     path.Create();
1045     for (i = 0; i < nCount; i++) {
1046       rectArr[i].left += fOffSetX;
1047       rectArr[i].top += fOffSetY;
1048       path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width,
1049                         rectArr[i].height);
1050     }
1051     pGraphics->SetClipRect(rtClip);
1052     CFWL_ThemeBackground param;
1053     param.m_pGraphics = pGraphics;
1054     param.m_matrix = *pMatrix;
1055     param.m_pWidget = m_pInterface;
1056     param.m_iPart = CFWL_Part::Background;
1057     param.m_pPath = &path;
1058     pTheme->DrawBackground(&param);
1059   }
1060   CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice();
1061   if (!pRenderDev)
1062     return;
1063 
1064   std::unique_ptr<CFDE_RenderDevice> pRenderDevice(
1065       new CFDE_RenderDevice(pRenderDev, FALSE));
1066   std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext);
1067   pRenderDevice->SetClipRect(rtClip);
1068   pRenderContext->StartRender(pRenderDevice.get(), pPage, mt);
1069   pRenderContext->DoRender(nullptr);
1070   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
1071     pGraphics->RestoreGraphState();
1072     CFX_Path path;
1073     path.Create();
1074     int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
1075     FX_FLOAT fStep = m_rtEngine.width / iLimit;
1076     FX_FLOAT fLeft = m_rtEngine.left + 1;
1077     for (int32_t i = 1; i < iLimit; i++) {
1078       fLeft += fStep;
1079       path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom());
1080     }
1081     CFWL_ThemeBackground param;
1082     param.m_pGraphics = pGraphics;
1083     param.m_matrix = *pMatrix;
1084     param.m_pWidget = m_pInterface;
1085     param.m_iPart = CFWL_Part::CombTextLine;
1086     param.m_pPath = &path;
1087     pTheme->DrawBackground(&param);
1088   }
1089   pGraphics->RestoreGraphState();
1090 }
1091 
UpdateEditEngine()1092 void CFWL_EditImp::UpdateEditEngine() {
1093   UpdateEditParams();
1094   UpdateEditLayout();
1095   if (m_nLimit > -1) {
1096     m_pEdtEngine->SetLimit(m_nLimit);
1097   }
1098 }
UpdateEditParams()1099 void CFWL_EditImp::UpdateEditParams() {
1100   FDE_TXTEDTPARAMS params;
1101   params.nHorzScale = 100;
1102   params.fPlateWidth = m_rtEngine.width;
1103   params.fPlateHeight = m_rtEngine.height;
1104   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout) {
1105     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL;
1106   }
1107   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout) {
1108     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical;
1109   }
1110   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars) {
1111     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial;
1112   }
1113   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine) {
1114     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve;
1115   }
1116   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes) {
1117     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes;
1118   }
1119   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab) {
1120     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab;
1121   }
1122   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
1123     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText;
1124   }
1125   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) {
1126     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight;
1127   }
1128   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) {
1129     params.dwMode |= FDE_TEXTEDITMODE_Validate;
1130   }
1131   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) {
1132     params.dwMode |= FDE_TEXTEDITMODE_Password;
1133   }
1134   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
1135     case FWL_STYLEEXT_EDT_HNear: {
1136       params.dwAlignment |= FDE_TEXTEDITALIGN_Left;
1137       break;
1138     }
1139     case FWL_STYLEEXT_EDT_HCenter: {
1140       params.dwAlignment |= FDE_TEXTEDITALIGN_Center;
1141       break;
1142     }
1143     case FWL_STYLEEXT_EDT_HFar: {
1144       params.dwAlignment |= FDE_TEXTEDITALIGN_Right;
1145       break;
1146     }
1147     default: {}
1148   }
1149   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
1150     case FWL_STYLEEXT_EDT_Justified: {
1151       params.dwAlignment |= FDE_TEXTEDITALIGN_Justified;
1152       break;
1153     }
1154     case FWL_STYLEEXT_EDT_Distributed: {
1155       params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed;
1156       break;
1157     }
1158     default: { params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; }
1159   }
1160   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
1161     params.dwMode |= FDE_TEXTEDITMODE_MultiLines;
1162     if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 &&
1163         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
1164       params.dwMode |=
1165           FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz;
1166     }
1167     if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
1168         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) {
1169       params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert;
1170     } else {
1171       params.fPlateHeight = 0x00FFFFFF;
1172     }
1173   } else {
1174     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
1175       params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz;
1176     }
1177   }
1178   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
1179       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
1180     params.dwMode |= FDE_TEXTEDITMODE_ReadOnly;
1181   }
1182   FX_FLOAT* pFontSize =
1183       static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
1184   if (!pFontSize)
1185     return;
1186   m_fFontSize = *pFontSize;
1187   uint32_t* pFontColor =
1188       static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor));
1189   if (!pFontColor)
1190     return;
1191   params.dwFontColor = *pFontColor;
1192   FX_FLOAT* pLineHeight =
1193       static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight));
1194   if (!pLineHeight)
1195     return;
1196   params.fLineSpace = *pLineHeight;
1197   CFGAS_GEFont* pFont =
1198       static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font));
1199   if (!pFont)
1200     return;
1201   params.pFont = pFont;
1202   params.fFontSize = m_fFontSize;
1203   params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace);
1204   if (params.nLineCount <= 0) {
1205     params.nLineCount = 1;
1206   }
1207   params.fTabWidth = params.fFontSize * 1;
1208   params.bTabEquidistant = TRUE;
1209   params.wLineBreakChar = L'\n';
1210   params.nCharRotation = 0;
1211   params.pEventSink = this;
1212   m_pEdtEngine->SetEditParams(params);
1213 }
1214 
UpdateEditLayout()1215 void CFWL_EditImp::UpdateEditLayout() {
1216   if (m_pEdtEngine->GetTextLength() <= 0)
1217     m_pEdtEngine->SetTextByStream(nullptr);
1218 
1219   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
1220   if (pPage)
1221     pPage->UnloadPage(nullptr);
1222 
1223   m_pEdtEngine->StartLayout();
1224   m_pEdtEngine->DoLayout(nullptr);
1225   m_pEdtEngine->EndLayout();
1226   pPage = m_pEdtEngine->GetPage(0);
1227   if (pPage)
1228     pPage->LoadPage(nullptr, nullptr);
1229 }
1230 
UpdateOffset()1231 FX_BOOL CFWL_EditImp::UpdateOffset() {
1232   CFX_RectF rtCaret;
1233   m_pEdtEngine->GetCaretRect(rtCaret);
1234   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
1235   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
1236   rtCaret.Offset(fOffSetX, fOffSetY);
1237   const CFX_RectF& rtEidt = m_rtEngine;
1238   if (rtEidt.Contains(rtCaret)) {
1239     IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
1240     if (!pPage)
1241       return FALSE;
1242 
1243     CFX_RectF rtFDE = pPage->GetContentsBox();
1244     rtFDE.Offset(fOffSetX, fOffSetY);
1245     if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) {
1246       m_fScrollOffsetX += rtFDE.right() - rtEidt.right();
1247       m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f);
1248     }
1249     if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) {
1250       m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom();
1251       m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f);
1252     }
1253     return FALSE;
1254   }
1255 
1256   FX_FLOAT offsetX = 0.0;
1257   FX_FLOAT offsetY = 0.0;
1258   if (rtCaret.left < rtEidt.left)
1259     offsetX = rtCaret.left - rtEidt.left;
1260   if (rtCaret.right() > rtEidt.right())
1261     offsetX = rtCaret.right() - rtEidt.right();
1262   if (rtCaret.top < rtEidt.top)
1263     offsetY = rtCaret.top - rtEidt.top;
1264   if (rtCaret.bottom() > rtEidt.bottom())
1265     offsetY = rtCaret.bottom() - rtEidt.bottom();
1266   if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption))
1267     m_fScrollOffsetX += offsetX;
1268   if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption))
1269     m_fScrollOffsetY += offsetY;
1270   if (m_fFontSize > m_rtEngine.height)
1271     m_fScrollOffsetY = 0;
1272   return TRUE;
1273 }
1274 
UpdateOffset(IFWL_ScrollBar * pScrollBar,FX_FLOAT fPosChanged)1275 FX_BOOL CFWL_EditImp::UpdateOffset(IFWL_ScrollBar* pScrollBar,
1276                                    FX_FLOAT fPosChanged) {
1277   if (pScrollBar == m_pHorzScrollBar.get())
1278     m_fScrollOffsetX += fPosChanged;
1279   else
1280     m_fScrollOffsetY += fPosChanged;
1281   return TRUE;
1282 }
1283 
UpdateVAlignment()1284 void CFWL_EditImp::UpdateVAlignment() {
1285   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
1286   if (!pPage)
1287     return;
1288   const CFX_RectF& rtFDE = pPage->GetContentsBox();
1289   FX_FLOAT fOffsetY = 0.0f;
1290   FX_FLOAT fSpaceAbove = 0.0f;
1291   FX_FLOAT fSpaceBelow = 0.0f;
1292   CFX_SizeF* pSpace = static_cast<CFX_SizeF*>(
1293       GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow));
1294   if (pSpace) {
1295     fSpaceAbove = pSpace->x;
1296     fSpaceBelow = pSpace->y;
1297   }
1298   if (fSpaceAbove < 0.1f) {
1299     fSpaceAbove = 0;
1300   }
1301   if (fSpaceBelow < 0.1f) {
1302     fSpaceBelow = 0;
1303   }
1304   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
1305     fOffsetY = (m_rtEngine.height - rtFDE.height) / 2;
1306     if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 &&
1307         fSpaceAbove < fSpaceBelow) {
1308       return;
1309     }
1310     fOffsetY += (fSpaceAbove - fSpaceBelow) / 2;
1311   } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
1312     fOffsetY = (m_rtEngine.height - rtFDE.height);
1313     fOffsetY -= fSpaceBelow;
1314   } else {
1315     fOffsetY += fSpaceAbove;
1316   }
1317   m_fVAlignOffset = fOffsetY;
1318   if (m_fVAlignOffset < 0) {
1319     m_fVAlignOffset = 0;
1320   }
1321 }
UpdateCaret()1322 void CFWL_EditImp::UpdateCaret() {
1323   CFX_RectF rtFDE;
1324   m_pEdtEngine->GetCaretRect(rtFDE);
1325   rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX,
1326                m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);
1327   CFX_RectF rtCaret;
1328   rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height);
1329   CFX_RectF temp = rtCaret;
1330   CFX_RectF rtClient;
1331   GetClientRect(rtClient);
1332   rtCaret.Intersect(rtClient);
1333   if (rtCaret.left > rtClient.right()) {
1334     FX_FLOAT right = rtCaret.right();
1335     rtCaret.left = rtClient.right() - 1;
1336     rtCaret.width = right - rtCaret.left;
1337   }
1338   FX_BOOL bIntersect = !rtCaret.IsEmpty();
1339   FX_BOOL bShow = TRUE;
1340   FX_BOOL bShowWhole = FALSE;
1341   if (!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) || !bIntersect) {
1342     bShow = FALSE;
1343   }
1344   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption &&
1345       temp.right() > m_rtEngine.right()) {
1346     bShowWhole = TRUE;
1347   }
1348   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption &&
1349       temp.bottom() > m_rtEngine.bottom()) {
1350     bShowWhole = TRUE;
1351   } else {
1352     bShow = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && bIntersect);
1353   }
1354   if (bShowWhole) {
1355     rtCaret = temp;
1356   }
1357   ShowCaret(bShow, &rtCaret);
1358 }
UpdateScroll()1359 IFWL_ScrollBar* CFWL_EditImp::UpdateScroll() {
1360   FX_BOOL bShowHorz =
1361       m_pHorzScrollBar &&
1362       ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
1363   FX_BOOL bShowVert =
1364       m_pVertScrollBar &&
1365       ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
1366   if (!bShowHorz && !bShowVert) {
1367     return nullptr;
1368   }
1369   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
1370   if (!pPage)
1371     return nullptr;
1372   const CFX_RectF& rtFDE = pPage->GetContentsBox();
1373   IFWL_ScrollBar* pRepaint = nullptr;
1374   if (bShowHorz) {
1375     CFX_RectF rtScroll;
1376     m_pHorzScrollBar->GetWidgetRect(rtScroll);
1377     if (rtScroll.width < rtFDE.width) {
1378       m_pHorzScrollBar->LockUpdate();
1379       FX_FLOAT fRange = rtFDE.width - rtScroll.width;
1380       m_pHorzScrollBar->SetRange(0.0f, fRange);
1381       FX_FLOAT fPos = m_fScrollOffsetX;
1382       if (fPos < 0.0f) {
1383         fPos = 0.0f;
1384       }
1385       if (fPos > fRange) {
1386         fPos = fRange;
1387       }
1388       m_pHorzScrollBar->SetPos(fPos);
1389       m_pHorzScrollBar->SetTrackPos(fPos);
1390       m_pHorzScrollBar->SetPageSize(rtScroll.width);
1391       m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
1392       m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE);
1393       m_pHorzScrollBar->UnlockUpdate();
1394       m_pHorzScrollBar->Update();
1395       pRepaint = m_pHorzScrollBar.get();
1396     } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
1397       m_pHorzScrollBar->LockUpdate();
1398       m_pHorzScrollBar->SetRange(0, -1);
1399       m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE);
1400       m_pHorzScrollBar->UnlockUpdate();
1401       m_pHorzScrollBar->Update();
1402       pRepaint = m_pHorzScrollBar.get();
1403     }
1404   }
1405   if (bShowVert) {
1406     CFX_RectF rtScroll;
1407     m_pVertScrollBar->GetWidgetRect(rtScroll);
1408     if (rtScroll.height < rtFDE.height) {
1409       m_pVertScrollBar->LockUpdate();
1410       FX_FLOAT fStep = m_pEdtEngine->GetEditParams()->fLineSpace;
1411       FX_FLOAT fRange = rtFDE.height - m_rtEngine.height;
1412       if (fRange < fStep) {
1413         fRange = fStep;
1414       }
1415       m_pVertScrollBar->SetRange(0.0f, fRange);
1416       FX_FLOAT fPos = m_fScrollOffsetY;
1417       if (fPos < 0.0f) {
1418         fPos = 0.0f;
1419       }
1420       if (fPos > fRange) {
1421         fPos = fRange;
1422       }
1423       m_pVertScrollBar->SetPos(fPos);
1424       m_pVertScrollBar->SetTrackPos(fPos);
1425       m_pVertScrollBar->SetPageSize(rtScroll.height);
1426       m_pVertScrollBar->SetStepSize(fStep);
1427       m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE);
1428       m_pVertScrollBar->UnlockUpdate();
1429       m_pVertScrollBar->Update();
1430       pRepaint = m_pVertScrollBar.get();
1431     } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
1432       m_pVertScrollBar->LockUpdate();
1433       m_pVertScrollBar->SetRange(0, -1);
1434       m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE);
1435       m_pVertScrollBar->UnlockUpdate();
1436       m_pVertScrollBar->Update();
1437       pRepaint = m_pVertScrollBar.get();
1438     }
1439   }
1440   return pRepaint;
1441 }
IsShowScrollBar(FX_BOOL bVert)1442 FX_BOOL CFWL_EditImp::IsShowScrollBar(FX_BOOL bVert) {
1443   FX_BOOL bShow =
1444       (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
1445           ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
1446                 FWL_WGTSTATE_Focused
1447           : TRUE;
1448   if (bVert) {
1449     return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
1450            (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
1451            IsContentHeightOverflow();
1452   }
1453   return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) &&
1454          (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
1455 }
IsContentHeightOverflow()1456 FX_BOOL CFWL_EditImp::IsContentHeightOverflow() {
1457   if (!m_pEdtEngine)
1458     return FALSE;
1459   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
1460   if (!pPage)
1461     return FALSE;
1462   return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f;
1463 }
AddDoRecord(IFDE_TxtEdtDoRecord * pRecord)1464 int32_t CFWL_EditImp::AddDoRecord(IFDE_TxtEdtDoRecord* pRecord) {
1465   int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords);
1466   if (m_iCurRecord == nCount - 1) {
1467     if (nCount == m_iMaxRecord) {
1468       m_DoRecords.pop_front();
1469       m_iCurRecord--;
1470     }
1471   } else {
1472     m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1,
1473                       m_DoRecords.end());
1474   }
1475 
1476   m_DoRecords.push_back(std::unique_ptr<IFDE_TxtEdtDoRecord>(pRecord));
1477   m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
1478   return m_iCurRecord;
1479 }
Layout()1480 void CFWL_EditImp::Layout() {
1481   GetClientRect(m_rtClient);
1482   m_rtEngine = m_rtClient;
1483   FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
1484       GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
1485   if (!pfWidth)
1486     return;
1487   FX_FLOAT fWidth = *pfWidth;
1488   if (!m_pOuter) {
1489     CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
1490         GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
1491     if (pUIMargin) {
1492       m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
1493                          pUIMargin->height);
1494     }
1495   } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) {
1496     CFWL_ThemePart part;
1497     part.m_pWidget = m_pOuter;
1498     CFX_RectF* pUIMargin =
1499         static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity(
1500             &part, CFWL_WidgetCapacity::UIMargin));
1501     if (pUIMargin) {
1502       m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
1503                          pUIMargin->height);
1504     }
1505   }
1506   FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE);
1507   FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE);
1508   if (bShowVertScrollbar) {
1509     InitScrollBar();
1510     CFX_RectF rtVertScr;
1511     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1512       rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
1513                     m_rtClient.height);
1514     } else {
1515       rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
1516                     m_rtClient.height);
1517       if (bShowHorzScrollbar) {
1518         rtVertScr.height -= fWidth;
1519       }
1520       m_rtEngine.width -= fWidth;
1521     }
1522     m_pVertScrollBar->SetWidgetRect(rtVertScr);
1523     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
1524     m_pVertScrollBar->Update();
1525   } else if (m_pVertScrollBar) {
1526     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
1527   }
1528   if (bShowHorzScrollbar) {
1529     InitScrollBar(FALSE);
1530     CFX_RectF rtHoriScr;
1531     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1532       rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
1533                     m_rtClient.width, fWidth);
1534     } else {
1535       rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
1536                     m_rtClient.width, fWidth);
1537       if (bShowVertScrollbar) {
1538         rtHoriScr.width -= fWidth;
1539       }
1540       m_rtEngine.height -= fWidth;
1541     }
1542     m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
1543     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
1544     m_pHorzScrollBar->Update();
1545   } else if (m_pHorzScrollBar) {
1546     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
1547   }
1548 }
LayoutScrollBar()1549 void CFWL_EditImp::LayoutScrollBar() {
1550   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
1551       0) {
1552     return;
1553   }
1554   FX_FLOAT* pfWidth = nullptr;
1555   FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE);
1556   FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE);
1557   if (bShowVertScrollbar) {
1558     if (!m_pVertScrollBar) {
1559       pfWidth = static_cast<FX_FLOAT*>(
1560           GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
1561       FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
1562       InitScrollBar();
1563       CFX_RectF rtVertScr;
1564       if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1565         rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
1566                       m_rtClient.height);
1567       } else {
1568         rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
1569                       m_rtClient.height);
1570         if (bShowHorzScrollbar) {
1571           rtVertScr.height -= fWidth;
1572         }
1573       }
1574       m_pVertScrollBar->SetWidgetRect(rtVertScr);
1575       m_pVertScrollBar->Update();
1576     }
1577     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
1578   } else if (m_pVertScrollBar) {
1579     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
1580   }
1581   if (bShowHorzScrollbar) {
1582     if (!m_pHorzScrollBar) {
1583       if (!pfWidth) {
1584         pfWidth = static_cast<FX_FLOAT*>(
1585             GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
1586       }
1587       FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
1588       InitScrollBar(FALSE);
1589       CFX_RectF rtHoriScr;
1590       if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1591         rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
1592                       m_rtClient.width, fWidth);
1593       } else {
1594         rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
1595                       m_rtClient.width, fWidth);
1596         if (bShowVertScrollbar) {
1597           rtHoriScr.width -= (fWidth);
1598         }
1599       }
1600       m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
1601       m_pHorzScrollBar->Update();
1602     }
1603     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
1604   } else if (m_pHorzScrollBar) {
1605     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
1606   }
1607   if (bShowVertScrollbar || bShowHorzScrollbar) {
1608     UpdateScroll();
1609   }
1610 }
1611 
DeviceToEngine(CFX_PointF & pt)1612 void CFWL_EditImp::DeviceToEngine(CFX_PointF& pt) {
1613   pt.x += m_fScrollOffsetX - m_rtEngine.left;
1614   pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset;
1615 }
1616 
InitScrollBar(FX_BOOL bVert)1617 void CFWL_EditImp::InitScrollBar(FX_BOOL bVert) {
1618   if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) {
1619     return;
1620   }
1621   CFWL_WidgetImpProperties prop;
1622   prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
1623   prop.m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
1624   prop.m_pParent = m_pInterface;
1625   prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
1626   IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface);
1627   pScrollBar->Initialize();
1628   (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar);
1629 }
1630 
InitEngine()1631 void CFWL_EditImp::InitEngine() {
1632   if (!m_pEdtEngine)
1633     m_pEdtEngine = new CFDE_TxtEdtEngine;
1634 }
1635 
FWL_ShowCaret(IFWL_Widget * pWidget,FX_BOOL bVisible,const CFX_RectF * pRtAnchor)1636 FX_BOOL FWL_ShowCaret(IFWL_Widget* pWidget,
1637                       FX_BOOL bVisible,
1638                       const CFX_RectF* pRtAnchor) {
1639   CXFA_FFWidget* pXFAWidget =
1640       static_cast<CXFA_FFWidget*>(pWidget->GetLayoutItem());
1641   if (!pXFAWidget)
1642     return FALSE;
1643 
1644   IXFA_DocProvider* pDocProvider = pXFAWidget->GetDoc()->GetDocProvider();
1645   if (!pDocProvider)
1646     return FALSE;
1647 
1648   if (bVisible) {
1649     CFX_Matrix mt;
1650     pXFAWidget->GetRotateMatrix(mt);
1651     CFX_RectF rt(*pRtAnchor);
1652     mt.TransformRect(rt);
1653     pDocProvider->DisplayCaret(pXFAWidget, bVisible, &rt);
1654     return TRUE;
1655   }
1656   pDocProvider->DisplayCaret(pXFAWidget, bVisible, pRtAnchor);
1657   return TRUE;
1658 }
1659 
ShowCaret(FX_BOOL bVisible,CFX_RectF * pRect)1660 void CFWL_EditImp::ShowCaret(FX_BOOL bVisible, CFX_RectF* pRect) {
1661   if (m_pCaret) {
1662     m_pCaret->ShowCaret(bVisible);
1663     if (bVisible && !pRect->IsEmpty()) {
1664       m_pCaret->SetWidgetRect(*pRect);
1665     }
1666     Repaint(&m_rtEngine);
1667   } else {
1668     IFWL_Widget* pOuter = m_pInterface;
1669     if (bVisible) {
1670       pRect->Offset(m_pProperties->m_rtWidget.left,
1671                     m_pProperties->m_rtWidget.top);
1672     }
1673     while (pOuter->GetOuter()) {
1674       pOuter = pOuter->GetOuter();
1675       if (bVisible) {
1676         CFX_RectF rtOuter;
1677         pOuter->GetWidgetRect(rtOuter);
1678         pRect->Offset(rtOuter.left, rtOuter.top);
1679       }
1680     }
1681     FWL_ShowCaret(pOuter, bVisible, pRect);
1682   }
1683 }
ValidateNumberChar(FX_WCHAR cNum)1684 FX_BOOL CFWL_EditImp::ValidateNumberChar(FX_WCHAR cNum) {
1685   if (!m_pEdtEngine) {
1686     return FALSE;
1687   }
1688   if (!m_bSetRange) {
1689     return TRUE;
1690   }
1691   CFX_WideString wsOld, wsText;
1692   m_pEdtEngine->GetText(wsText, 0);
1693   if (wsText.IsEmpty()) {
1694     if (cNum == L'0') {
1695       return FALSE;
1696     }
1697     return TRUE;
1698   }
1699   int32_t caretPos = m_pEdtEngine->GetCaretPos();
1700   int32_t iSel = CountSelRanges();
1701   if (iSel == 0) {
1702     if (cNum == L'0' && caretPos == 0) {
1703       return FALSE;
1704     }
1705     int32_t nLen = wsText.GetLength();
1706     CFX_WideString l = wsText.Mid(0, caretPos);
1707     CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos);
1708     CFX_WideString wsNew = l + cNum + r;
1709     if (wsNew.GetInteger() <= m_iMax) {
1710       return TRUE;
1711     }
1712   } else {
1713     if (wsText.GetInteger() <= m_iMax) {
1714       return TRUE;
1715     }
1716   }
1717   return FALSE;
1718 }
InitCaret()1719 void CFWL_EditImp::InitCaret() {
1720   if (!m_pCaret) {
1721     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) {
1722       CFWL_WidgetImpProperties prop;
1723       m_pCaret.reset(IFWL_Caret::Create(prop, m_pInterface));
1724       m_pCaret->Initialize();
1725       m_pCaret->SetParent(m_pInterface);
1726       m_pCaret->SetStates(m_pProperties->m_dwStates);
1727     }
1728   } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) ==
1729              0) {
1730     m_pCaret.reset();
1731   }
1732 }
1733 
ClearRecord()1734 void CFWL_EditImp::ClearRecord() {
1735   m_iCurRecord = -1;
1736   m_DoRecords.clear();
1737 }
1738 
ProcessInsertError(int32_t iError)1739 void CFWL_EditImp::ProcessInsertError(int32_t iError) {
1740   switch (iError) {
1741     case -2: {
1742       CFWL_EvtEdtTextFull textFullEvent;
1743       textFullEvent.m_pSrcTarget = m_pInterface;
1744       DispatchEvent(&textFullEvent);
1745       break;
1746     }
1747     default: {}
1748   }
1749 }
1750 
CFWL_EditImpDelegate(CFWL_EditImp * pOwner)1751 CFWL_EditImpDelegate::CFWL_EditImpDelegate(CFWL_EditImp* pOwner)
1752     : m_pOwner(pOwner) {}
1753 
OnProcessMessage(CFWL_Message * pMessage)1754 void CFWL_EditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
1755   if (!pMessage)
1756     return;
1757 
1758   CFWL_MessageType dwMsgCode = pMessage->GetClassID();
1759   switch (dwMsgCode) {
1760     case CFWL_MessageType::Activate: {
1761       DoActivate(static_cast<CFWL_MsgActivate*>(pMessage));
1762       break;
1763     }
1764     case CFWL_MessageType::Deactivate: {
1765       DoDeactivate(static_cast<CFWL_MsgDeactivate*>(pMessage));
1766       break;
1767     }
1768     case CFWL_MessageType::SetFocus:
1769     case CFWL_MessageType::KillFocus: {
1770       OnFocusChanged(pMessage, dwMsgCode == CFWL_MessageType::SetFocus);
1771       break;
1772     }
1773     case CFWL_MessageType::Mouse: {
1774       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
1775       switch (pMsg->m_dwCmd) {
1776         case FWL_MouseCommand::LeftButtonDown: {
1777           OnLButtonDown(pMsg);
1778           break;
1779         }
1780         case FWL_MouseCommand::LeftButtonUp: {
1781           OnLButtonUp(pMsg);
1782           break;
1783         }
1784         case FWL_MouseCommand::LeftButtonDblClk: {
1785           OnButtonDblClk(pMsg);
1786           break;
1787         }
1788         case FWL_MouseCommand::Move: {
1789           OnMouseMove(pMsg);
1790           break;
1791         }
1792         case FWL_MouseCommand::RightButtonDown: {
1793           DoButtonDown(pMsg);
1794           break;
1795         }
1796         default:
1797           break;
1798       }
1799       break;
1800     }
1801     case CFWL_MessageType::Key: {
1802       CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
1803       if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
1804         OnKeyDown(pKey);
1805       else if (pKey->m_dwCmd == FWL_KeyCommand::Char)
1806         OnChar(pKey);
1807       break;
1808     }
1809     default: {
1810       break;
1811     }
1812   }
1813   CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
1814 }
1815 
OnProcessEvent(CFWL_Event * pEvent)1816 void CFWL_EditImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
1817   if (!pEvent)
1818     return;
1819   if (pEvent->GetClassID() != CFWL_EventType::Scroll)
1820     return;
1821 
1822   IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
1823   if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() &&
1824        m_pOwner->m_pVertScrollBar) ||
1825       (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() &&
1826        m_pOwner->m_pHorzScrollBar)) {
1827     CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
1828     OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget),
1829              pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
1830   }
1831 }
1832 
OnDrawWidget(CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)1833 void CFWL_EditImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
1834                                         const CFX_Matrix* pMatrix) {
1835   m_pOwner->DrawWidget(pGraphics, pMatrix);
1836 }
1837 
DoActivate(CFWL_MsgActivate * pMsg)1838 void CFWL_EditImpDelegate::DoActivate(CFWL_MsgActivate* pMsg) {
1839   m_pOwner->m_pProperties->m_dwStates |= ~FWL_WGTSTATE_Deactivated;
1840   m_pOwner->Repaint(&m_pOwner->m_rtClient);
1841 }
DoDeactivate(CFWL_MsgDeactivate * pMsg)1842 void CFWL_EditImpDelegate::DoDeactivate(CFWL_MsgDeactivate* pMsg) {
1843   m_pOwner->m_pProperties->m_dwStates &= FWL_WGTSTATE_Deactivated;
1844   m_pOwner->Repaint(&m_pOwner->m_rtClient);
1845 }
DoButtonDown(CFWL_MsgMouse * pMsg)1846 void CFWL_EditImpDelegate::DoButtonDown(CFWL_MsgMouse* pMsg) {
1847   if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
1848     m_pOwner->SetFocus(TRUE);
1849   }
1850   if (!m_pOwner->m_pEdtEngine) {
1851     m_pOwner->UpdateEditEngine();
1852   }
1853   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
1854   if (!pPage)
1855     return;
1856   CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1857   m_pOwner->DeviceToEngine(pt);
1858   FX_BOOL bBefore = TRUE;
1859   int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
1860   if (nIndex < 0) {
1861     nIndex = 0;
1862   }
1863   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore);
1864 }
OnFocusChanged(CFWL_Message * pMsg,FX_BOOL bSet)1865 void CFWL_EditImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) {
1866   uint32_t dwStyleEx = m_pOwner->GetStylesEx();
1867   bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret);
1868   if (bSet) {
1869     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
1870     if (!m_pOwner->m_pEdtEngine) {
1871       m_pOwner->UpdateEditEngine();
1872     }
1873     m_pOwner->UpdateVAlignment();
1874     m_pOwner->UpdateOffset();
1875     m_pOwner->UpdateCaret();
1876   } else if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
1877     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
1878     m_pOwner->ShowCaret(FALSE);
1879     if (m_pOwner->m_pEdtEngine &&
1880         (dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) {
1881       int32_t nSel = m_pOwner->CountSelRanges();
1882       if (nSel > 0) {
1883         m_pOwner->ClearSelections();
1884         bRepaint = TRUE;
1885       }
1886       m_pOwner->SetCaretPos(0);
1887       m_pOwner->UpdateOffset();
1888     }
1889     m_pOwner->ClearRecord();
1890   }
1891   m_pOwner->LayoutScrollBar();
1892   if (bRepaint) {
1893     CFX_RectF rtInvalidate;
1894     rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width,
1895                      m_pOwner->m_pProperties->m_rtWidget.height);
1896     m_pOwner->Repaint(&rtInvalidate);
1897   }
1898 }
OnLButtonDown(CFWL_MsgMouse * pMsg)1899 void CFWL_EditImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
1900   DoCursor(pMsg);
1901   if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
1902     return;
1903   }
1904   m_pOwner->m_bLButtonDown = TRUE;
1905   m_pOwner->SetGrab(TRUE);
1906   DoButtonDown(pMsg);
1907   int32_t nIndex = m_pOwner->m_pEdtEngine->GetCaretPos();
1908   FX_BOOL bRepaint = FALSE;
1909   int32_t iCount = m_pOwner->m_pEdtEngine->CountSelRanges();
1910   if (iCount > 0) {
1911     m_pOwner->m_pEdtEngine->ClearSelection();
1912     bRepaint = TRUE;
1913   }
1914   FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift;
1915   if (bShift && m_pOwner->m_nSelStart != nIndex) {
1916     int32_t iStart = std::min(m_pOwner->m_nSelStart, nIndex);
1917     int32_t iEnd = std::max(m_pOwner->m_nSelStart, nIndex);
1918     m_pOwner->m_pEdtEngine->AddSelRange(iStart, iEnd - iStart);
1919     bRepaint = TRUE;
1920   } else {
1921     m_pOwner->m_nSelStart = nIndex;
1922   }
1923   if (bRepaint) {
1924     m_pOwner->Repaint(&m_pOwner->m_rtEngine);
1925   }
1926 }
OnLButtonUp(CFWL_MsgMouse * pMsg)1927 void CFWL_EditImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
1928   DoCursor(pMsg);
1929   m_pOwner->m_bLButtonDown = FALSE;
1930   m_pOwner->SetGrab(FALSE);
1931 }
OnButtonDblClk(CFWL_MsgMouse * pMsg)1932 void CFWL_EditImpDelegate::OnButtonDblClk(CFWL_MsgMouse* pMsg) {
1933   if (!m_pOwner->m_pEdtEngine)
1934     return;
1935   DoCursor(pMsg);
1936   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
1937   if (!pPage)
1938     return;
1939   CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1940   m_pOwner->DeviceToEngine(pt);
1941   int32_t nCount = 0;
1942   int32_t nIndex = pPage->SelectWord(pt, nCount);
1943   if (nIndex < 0) {
1944     return;
1945   }
1946   m_pOwner->m_pEdtEngine->AddSelRange(nIndex, nCount);
1947   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex + nCount - 1, FALSE);
1948   m_pOwner->Repaint(&m_pOwner->m_rtEngine);
1949 }
OnMouseMove(CFWL_MsgMouse * pMsg)1950 void CFWL_EditImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
1951   if (!m_pOwner->m_pEdtEngine)
1952     return;
1953   DoCursor(pMsg);
1954   if (m_pOwner->m_nSelStart == -1 || !m_pOwner->m_bLButtonDown) {
1955     return;
1956   }
1957   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
1958   if (!pPage)
1959     return;
1960   CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1961   m_pOwner->DeviceToEngine(pt);
1962   FX_BOOL bBefore = TRUE;
1963   int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
1964   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore);
1965   nIndex = m_pOwner->m_pEdtEngine->GetCaretPos();
1966   m_pOwner->m_pEdtEngine->ClearSelection();
1967   if (nIndex != m_pOwner->m_nSelStart) {
1968     int32_t nLen = m_pOwner->m_pEdtEngine->GetTextLength();
1969     if (m_pOwner->m_nSelStart >= nLen) {
1970       m_pOwner->m_nSelStart = nLen;
1971     }
1972     m_pOwner->m_pEdtEngine->AddSelRange(
1973         std::min(m_pOwner->m_nSelStart, nIndex),
1974         FXSYS_abs(nIndex - m_pOwner->m_nSelStart));
1975   }
1976 }
OnKeyDown(CFWL_MsgKey * pMsg)1977 void CFWL_EditImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) {
1978   if (!m_pOwner->m_pEdtEngine)
1979     return;
1980   FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone;
1981   FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift;
1982   FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl;
1983   uint32_t dwKeyCode = pMsg->m_dwKeyCode;
1984   switch (dwKeyCode) {
1985     case FWL_VKEY_Left: {
1986       MoveCaret = MC_Left;
1987       break;
1988     }
1989     case FWL_VKEY_Right: {
1990       MoveCaret = MC_Right;
1991       break;
1992     }
1993     case FWL_VKEY_Up: {
1994       MoveCaret = MC_Up;
1995       break;
1996     }
1997     case FWL_VKEY_Down: {
1998       MoveCaret = MC_Down;
1999       break;
2000     }
2001     case FWL_VKEY_Home: {
2002       if (bCtrl) {
2003         MoveCaret = MC_Home;
2004       } else {
2005         MoveCaret = MC_LineStart;
2006       }
2007       break;
2008     }
2009     case FWL_VKEY_End: {
2010       if (bCtrl) {
2011         MoveCaret = MC_End;
2012       } else {
2013         MoveCaret = MC_LineEnd;
2014       }
2015       break;
2016     }
2017     case FWL_VKEY_Insert: {
2018       break;
2019     }
2020     case FWL_VKEY_Delete: {
2021       if ((m_pOwner->m_pProperties->m_dwStyleExes &
2022            FWL_STYLEEXT_EDT_ReadOnly) ||
2023           (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
2024         break;
2025       }
2026       int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos();
2027 #if (_FX_OS_ == _FX_MACOSX_)
2028       m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE);
2029 #else
2030       m_pOwner->m_pEdtEngine->Delete(nCaret);
2031 #endif
2032       break;
2033     }
2034     case FWL_VKEY_F2: {
2035       break;
2036     }
2037     case FWL_VKEY_Tab: {
2038       m_pOwner->DispatchKeyEvent(pMsg);
2039       break;
2040     }
2041     default: {
2042 #if (_FX_OS_ == _FX_MACOSX_)
2043       if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) {
2044 #else
2045       if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) {
2046 #endif
2047         if (dwKeyCode == 0x43 || dwKeyCode == 0x63) {
2048           m_pOwner->DoClipboard(1);
2049           return;
2050         }
2051         if (dwKeyCode == 0x58 || dwKeyCode == 0x78) {
2052           m_pOwner->DoClipboard(2);
2053           return;
2054         }
2055         if (dwKeyCode == 0x56 || dwKeyCode == 0x76) {
2056           m_pOwner->DoClipboard(3);
2057           return;
2058         }
2059       }
2060     }
2061   }
2062   if (MoveCaret != MC_MoveNone) {
2063     m_pOwner->m_pEdtEngine->MoveCaretPos(MoveCaret, bShift, bCtrl);
2064   }
2065 }
2066 void CFWL_EditImpDelegate::OnChar(CFWL_MsgKey* pMsg) {
2067   if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
2068       (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
2069     return;
2070   }
2071   if (!m_pOwner->m_pEdtEngine)
2072     return;
2073   int32_t iError = 0;
2074   FX_WCHAR c = (FX_WCHAR)pMsg->m_dwKeyCode;
2075   int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos();
2076   switch (c) {
2077     case FWL_VKEY_Back: {
2078       m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE);
2079       break;
2080     }
2081     case 0x0A: {
2082       break;
2083     }
2084     case FWL_VKEY_Escape: {
2085       break;
2086     }
2087     case FWL_VKEY_Tab: {
2088       iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\t", 1);
2089       break;
2090     }
2091     case FWL_VKEY_Return: {
2092       if (m_pOwner->m_pProperties->m_dwStyleExes &
2093           FWL_STYLEEXT_EDT_WantReturn) {
2094         iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\n", 1);
2095       }
2096       break;
2097     }
2098     default: {
2099       if (!m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
2100         if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) {
2101           if (((pMsg->m_dwKeyCode < FWL_VKEY_0) &&
2102                (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) ||
2103               pMsg->m_dwKeyCode > FWL_VKEY_9) {
2104             break;
2105           }
2106           if (!m_pOwner->ValidateNumberChar(c)) {
2107             break;
2108           }
2109         }
2110       }
2111 #if (_FX_OS_ == _FX_MACOSX_)
2112       if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
2113 #else
2114       if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
2115 #endif
2116       {
2117         break;
2118       }
2119       iError = m_pOwner->m_pEdtEngine->Insert(nCaret, &c, 1);
2120       break;
2121     }
2122   }
2123   if (iError < 0) {
2124     m_pOwner->ProcessInsertError(iError);
2125   }
2126 }
2127 FX_BOOL CFWL_EditImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar,
2128                                        uint32_t dwCode,
2129                                        FX_FLOAT fPos) {
2130   CFX_SizeF fs;
2131   pScrollBar->GetRange(fs.x, fs.y);
2132   FX_FLOAT iCurPos = pScrollBar->GetPos();
2133   FX_FLOAT fStep = pScrollBar->GetStepSize();
2134   switch (dwCode) {
2135     case FWL_SCBCODE_Min: {
2136       fPos = fs.x;
2137       break;
2138     }
2139     case FWL_SCBCODE_Max: {
2140       fPos = fs.y;
2141       break;
2142     }
2143     case FWL_SCBCODE_StepBackward: {
2144       fPos -= fStep;
2145       if (fPos < fs.x + fStep / 2) {
2146         fPos = fs.x;
2147       }
2148       break;
2149     }
2150     case FWL_SCBCODE_StepForward: {
2151       fPos += fStep;
2152       if (fPos > fs.y - fStep / 2) {
2153         fPos = fs.y;
2154       }
2155       break;
2156     }
2157     case FWL_SCBCODE_PageBackward: {
2158       fPos -= pScrollBar->GetPageSize();
2159       if (fPos < fs.x) {
2160         fPos = fs.x;
2161       }
2162       break;
2163     }
2164     case FWL_SCBCODE_PageForward: {
2165       fPos += pScrollBar->GetPageSize();
2166       if (fPos > fs.y) {
2167         fPos = fs.y;
2168       }
2169       break;
2170     }
2171     case FWL_SCBCODE_Pos:
2172     case FWL_SCBCODE_TrackPos: {
2173       break;
2174     }
2175     case FWL_SCBCODE_EndScroll: {
2176       return FALSE;
2177     }
2178     default: {}
2179   }
2180   if (iCurPos != fPos) {
2181     pScrollBar->SetPos(fPos);
2182     pScrollBar->SetTrackPos(fPos);
2183     m_pOwner->UpdateOffset(pScrollBar, fPos - iCurPos);
2184     if (m_pOwner->m_pEdtEngine) {
2185       m_pOwner->UpdateCaret();
2186     }
2187     CFX_RectF rect;
2188     m_pOwner->GetWidgetRect(rect);
2189     CFX_RectF rtInvalidate;
2190     rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2);
2191     m_pOwner->Repaint(&rtInvalidate);
2192   }
2193   return TRUE;
2194 }
2195 void CFWL_EditImpDelegate::DoCursor(CFWL_MsgMouse* pMsg) {}
2196