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(¶m);
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(¶m);
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(¶m);
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(¶m);
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