Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: xfa/fwl/core/cfwl_edit.cpp

Issue 2559173002: Move xfa/fwl/core to xfa/fwl. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « xfa/fwl/core/cfwl_edit.h ('k') | xfa/fwl/core/cfwl_event.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/core/cfwl_edit.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "third_party/base/ptr_util.h"
15 #include "third_party/base/stl_util.h"
16 #include "xfa/fde/cfde_txtedtengine.h"
17 #include "xfa/fde/fde_gedevice.h"
18 #include "xfa/fde/fde_render.h"
19 #include "xfa/fde/ifde_txtedtpage.h"
20 #include "xfa/fgas/font/cfgas_gefont.h"
21 #include "xfa/fwl/core/cfwl_app.h"
22 #include "xfa/fwl/core/cfwl_caret.h"
23 #include "xfa/fwl/core/cfwl_event.h"
24 #include "xfa/fwl/core/cfwl_evtcheckword.h"
25 #include "xfa/fwl/core/cfwl_evttextchanged.h"
26 #include "xfa/fwl/core/cfwl_evtvalidate.h"
27 #include "xfa/fwl/core/cfwl_msgkey.h"
28 #include "xfa/fwl/core/cfwl_msgmouse.h"
29 #include "xfa/fwl/core/cfwl_themebackground.h"
30 #include "xfa/fwl/core/cfwl_themepart.h"
31 #include "xfa/fwl/core/cfwl_widgetmgr.h"
32 #include "xfa/fwl/core/ifwl_themeprovider.h"
33 #include "xfa/fxfa/xfa_ffdoc.h"
34 #include "xfa/fxfa/xfa_ffwidget.h"
35 #include "xfa/fxgraphics/cfx_path.h"
36
37 namespace {
38
39 const int kEditMargin = 3;
40
41 bool FX_EDIT_ISLATINWORD(FX_WCHAR c) {
42 return c == 0x2D || (c <= 0x005A && c >= 0x0041) ||
43 (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) ||
44 c == 0x0027;
45 }
46
47 void AddSquigglyPath(CFX_Path* pPathData,
48 FX_FLOAT fStartX,
49 FX_FLOAT fEndX,
50 FX_FLOAT fY,
51 FX_FLOAT fStep) {
52 pPathData->MoveTo(fStartX, fY);
53 int i = 1;
54 for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i)
55 pPathData->LineTo(fx, fY + (i & 1) * fStep);
56 }
57
58 } // namespace
59
60 CFWL_Edit::CFWL_Edit(const CFWL_App* app,
61 std::unique_ptr<CFWL_WidgetProperties> properties,
62 CFWL_Widget* pOuter)
63 : CFWL_Widget(app, std::move(properties), pOuter),
64 m_fVAlignOffset(0.0f),
65 m_fScrollOffsetX(0.0f),
66 m_fScrollOffsetY(0.0f),
67 m_bLButtonDown(false),
68 m_nSelStart(0),
69 m_nLimit(-1),
70 m_fFontSize(0),
71 m_bSetRange(false),
72 m_iMax(0xFFFFFFF),
73 m_iCurRecord(-1),
74 m_iMaxRecord(128) {
75 m_rtClient.Reset();
76 m_rtEngine.Reset();
77 m_rtStatic.Reset();
78
79 InitCaret();
80 }
81
82 CFWL_Edit::~CFWL_Edit() {
83 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
84 HideCaret(nullptr);
85 ClearRecord();
86 }
87
88 FWL_Type CFWL_Edit::GetClassID() const {
89 return FWL_Type::Edit;
90 }
91
92 CFX_RectF CFWL_Edit::GetWidgetRect() {
93 CFX_RectF rect = m_pProperties->m_rtWidget;
94 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
95 if (IsShowScrollBar(true)) {
96 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
97 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
98 rect.width += *pfWidth;
99 rect.width += kEditMargin;
100 }
101 if (IsShowScrollBar(false)) {
102 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
103 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
104 rect.height += *pfWidth;
105 rect.height += kEditMargin;
106 }
107 }
108 return rect;
109 }
110
111 CFX_RectF CFWL_Edit::GetAutosizedWidgetRect() {
112 CFX_RectF rect;
113 if (m_EdtEngine.GetTextLength() > 0) {
114 CFX_SizeF sz = CalcTextSize(
115 m_EdtEngine.GetText(0, -1), m_pProperties->m_pThemeProvider,
116 !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine));
117 rect.Set(0, 0, sz.x, sz.y);
118 }
119 InflateWidgetRect(rect);
120 return rect;
121 }
122
123 void CFWL_Edit::SetStates(uint32_t dwStates) {
124 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
125 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
126 HideCaret(nullptr);
127 }
128 CFWL_Widget::SetStates(dwStates);
129 }
130
131 void CFWL_Edit::Update() {
132 if (IsLocked())
133 return;
134 if (!m_pProperties->m_pThemeProvider)
135 m_pProperties->m_pThemeProvider = GetAvailableTheme();
136
137 Layout();
138 if (m_rtClient.IsEmpty())
139 return;
140
141 UpdateEditEngine();
142 UpdateVAlignment();
143 UpdateScroll();
144 InitCaret();
145 }
146
147 FWL_WidgetHit CFWL_Edit::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
148 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
149 if (IsShowScrollBar(true)) {
150 if (m_pVertScrollBar->GetWidgetRect().Contains(fx, fy))
151 return FWL_WidgetHit::VScrollBar;
152 }
153 if (IsShowScrollBar(false)) {
154 if (m_pHorzScrollBar->GetWidgetRect().Contains(fx, fy))
155 return FWL_WidgetHit::HScrollBar;
156 }
157 }
158 if (m_rtClient.Contains(fx, fy))
159 return FWL_WidgetHit::Edit;
160 return FWL_WidgetHit::Unknown;
161 }
162
163 void CFWL_Edit::AddSpellCheckObj(CFX_Path& PathData,
164 int32_t nStart,
165 int32_t nCount,
166 FX_FLOAT fOffSetX,
167 FX_FLOAT fOffSetY) {
168 FX_FLOAT fStartX = 0.0f;
169 FX_FLOAT fEndX = 0.0f;
170 FX_FLOAT fY = 0.0f;
171 FX_FLOAT fStep = 0.0f;
172 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
173 CFX_RectFArray rectArray;
174 CFX_RectF rectText;
175 const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams();
176 FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) *
177 txtEdtParams->fFontSize / 1000;
178 pPage->CalcRangeRectArray(nStart, nCount, rectArray);
179
180 for (int i = 0; i < rectArray.GetSize(); i++) {
181 rectText = rectArray.GetAt(i);
182 fY = rectText.top + fAsent + fOffSetY;
183 fStep = txtEdtParams->fFontSize / 16.0f;
184 fStartX = rectText.left + fOffSetX;
185 fEndX = fStartX + rectText.Width();
186 AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep);
187 }
188 }
189
190 void CFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics,
191 const CFX_Matrix* pMatrix) {
192 pGraphics->SaveGraphState();
193 if (pMatrix)
194 pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix));
195
196 CFX_Color crLine(0xFFFF0000);
197 CFWL_EvtCheckWord checkWordEvent(this);
198
199 CFX_ByteString sLatinWord;
200 CFX_Path pathSpell;
201 pathSpell.Create();
202
203 int32_t nStart = 0;
204 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
205 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
206
207 CFX_WideString wsSpell = GetText();
208 int32_t nContentLen = wsSpell.GetLength();
209 for (int i = 0; i < nContentLen; i++) {
210 if (FX_EDIT_ISLATINWORD(wsSpell[i])) {
211 if (sLatinWord.IsEmpty())
212 nStart = i;
213 sLatinWord += (FX_CHAR)wsSpell[i];
214 continue;
215 }
216 checkWordEvent.bsWord = sLatinWord;
217 checkWordEvent.bCheckWord = true;
218 DispatchEvent(&checkWordEvent);
219
220 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
221 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
222 fOffSetY);
223 }
224 sLatinWord.clear();
225 }
226
227 checkWordEvent.bsWord = sLatinWord;
228 checkWordEvent.bCheckWord = true;
229 DispatchEvent(&checkWordEvent);
230
231 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
232 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
233 fOffSetY);
234 }
235 if (!pathSpell.IsEmpty()) {
236 CFX_RectF rtClip = m_rtEngine;
237 CFX_Matrix mt;
238 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
239 if (pMatrix) {
240 pMatrix->TransformRect(rtClip);
241 mt.Concat(*pMatrix);
242 }
243 pGraphics->SetClipRect(rtClip);
244 pGraphics->SetStrokeColor(&crLine);
245 pGraphics->SetLineWidth(0);
246 pGraphics->StrokePath(&pathSpell, nullptr);
247 }
248 pGraphics->RestoreGraphState();
249 }
250
251 void CFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) {
252 if (!pGraphics)
253 return;
254 if (!m_pProperties->m_pThemeProvider)
255 return;
256 if (m_rtClient.IsEmpty())
257 return;
258
259 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
260 if (!m_pWidgetMgr->IsFormDisabled())
261 DrawTextBk(pGraphics, pTheme, pMatrix);
262 DrawContent(pGraphics, pTheme, pMatrix);
263
264 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
265 !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) {
266 DrawSpellCheck(pGraphics, pMatrix);
267 }
268 if (HasBorder())
269 DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
270 if (HasEdge())
271 DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
272 }
273
274 void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
275 if (!pThemeProvider)
276 return;
277 if (m_pHorzScrollBar)
278 m_pHorzScrollBar->SetThemeProvider(pThemeProvider);
279 if (m_pVertScrollBar)
280 m_pVertScrollBar->SetThemeProvider(pThemeProvider);
281 if (m_pCaret)
282 m_pCaret->SetThemeProvider(pThemeProvider);
283 m_pProperties->m_pThemeProvider = pThemeProvider;
284 }
285
286 void CFWL_Edit::SetText(const CFX_WideString& wsText) {
287 m_EdtEngine.SetText(wsText);
288 }
289
290 int32_t CFWL_Edit::GetTextLength() const {
291 return m_EdtEngine.GetTextLength();
292 }
293
294 CFX_WideString CFWL_Edit::GetText() const {
295 return m_EdtEngine.GetText(0, -1);
296 }
297
298 void CFWL_Edit::ClearText() {
299 m_EdtEngine.ClearText();
300 }
301
302 void CFWL_Edit::AddSelRange(int32_t nStart) {
303 m_EdtEngine.AddSelRange(nStart, -1);
304 }
305
306 int32_t CFWL_Edit::CountSelRanges() const {
307 return m_EdtEngine.CountSelRanges();
308 }
309
310 int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t* nStart) const {
311 return m_EdtEngine.GetSelRange(nIndex, nStart);
312 }
313
314 void CFWL_Edit::ClearSelections() {
315 m_EdtEngine.ClearSelection();
316 }
317
318 int32_t CFWL_Edit::GetLimit() const {
319 return m_nLimit;
320 }
321
322 void CFWL_Edit::SetLimit(int32_t nLimit) {
323 m_nLimit = nLimit;
324 m_EdtEngine.SetLimit(nLimit);
325 }
326
327 void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) {
328 m_EdtEngine.SetAliasChar(wAlias);
329 }
330
331 bool CFWL_Edit::Copy(CFX_WideString& wsCopy) {
332 int32_t nCount = m_EdtEngine.CountSelRanges();
333 if (nCount == 0)
334 return false;
335
336 wsCopy.clear();
337 int32_t nStart;
338 int32_t nLength;
339 for (int32_t i = 0; i < nCount; i++) {
340 nLength = m_EdtEngine.GetSelRange(i, &nStart);
341 wsCopy += m_EdtEngine.GetText(nStart, nLength);
342 }
343 return true;
344 }
345
346 bool CFWL_Edit::Cut(CFX_WideString& wsCut) {
347 int32_t nCount = m_EdtEngine.CountSelRanges();
348 if (nCount == 0)
349 return false;
350
351 wsCut.clear();
352 CFX_WideString wsTemp;
353 int32_t nStart, nLength;
354 for (int32_t i = 0; i < nCount; i++) {
355 nLength = m_EdtEngine.GetSelRange(i, &nStart);
356 wsTemp = m_EdtEngine.GetText(nStart, nLength);
357 wsCut += wsTemp;
358 wsTemp.clear();
359 }
360 m_EdtEngine.Delete(0);
361 return true;
362 }
363
364 bool CFWL_Edit::Paste(const CFX_WideString& wsPaste) {
365 int32_t nCaret = m_EdtEngine.GetCaretPos();
366 int32_t iError =
367 m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength());
368 if (iError < 0) {
369 ProcessInsertError(iError);
370 return false;
371 }
372 return true;
373 }
374
375 bool CFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) {
376 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
377 return true;
378 return m_EdtEngine.Redo(pRecord);
379 }
380
381 bool CFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) {
382 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
383 return true;
384 return m_EdtEngine.Undo(pRecord);
385 }
386
387 bool CFWL_Edit::Undo() {
388 if (!CanUndo())
389 return false;
390 return Undo(m_DoRecords[m_iCurRecord--].get());
391 }
392
393 bool CFWL_Edit::Redo() {
394 if (!CanRedo())
395 return false;
396 return Redo(m_DoRecords[++m_iCurRecord].get());
397 }
398
399 bool CFWL_Edit::CanUndo() {
400 return m_iCurRecord >= 0;
401 }
402
403 bool CFWL_Edit::CanRedo() {
404 return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
405 }
406
407 void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) {
408 m_pOuter = pOuter;
409 }
410
411 void CFWL_Edit::OnCaretChanged() {
412 if (m_rtEngine.IsEmpty())
413 return;
414 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
415 return;
416
417 bool bRepaintContent = UpdateOffset();
418 UpdateCaret();
419 CFX_RectF rtInvalid;
420 rtInvalid.Set(0, 0, 0, 0);
421 bool bRepaintScroll = false;
422 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
423 CFWL_ScrollBar* pScroll = UpdateScroll();
424 if (pScroll) {
425 rtInvalid = pScroll->GetWidgetRect();
426 bRepaintScroll = true;
427 }
428 }
429 if (bRepaintContent || bRepaintScroll) {
430 if (bRepaintContent)
431 rtInvalid.Union(m_rtEngine);
432 Repaint(&rtInvalid);
433 }
434 }
435
436 void CFWL_Edit::OnTextChanged(const FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) {
437 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask)
438 UpdateVAlignment();
439
440 CFX_RectF rtTemp;
441 GetClientRect(rtTemp);
442
443 CFWL_EvtTextChanged event(this);
444 event.wsPrevText = ChangeInfo.wsPrevText;
445 DispatchEvent(&event);
446
447 LayoutScrollBar();
448 Repaint(&rtTemp);
449 }
450
451 void CFWL_Edit::OnSelChanged() {
452 CFX_RectF rtTemp;
453 GetClientRect(rtTemp);
454 Repaint(&rtTemp);
455 }
456
457 bool CFWL_Edit::OnPageLoad(int32_t nPageIndex) {
458 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
459 if (!pPage)
460 return false;
461
462 pPage->LoadPage(nullptr, nullptr);
463 return true;
464 }
465
466 bool CFWL_Edit::OnPageUnload(int32_t nPageIndex) {
467 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
468 if (!pPage)
469 return false;
470
471 pPage->UnloadPage(nullptr);
472 return true;
473 }
474
475 void CFWL_Edit::OnAddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) {
476 AddDoRecord(std::move(pRecord));
477 }
478
479 bool CFWL_Edit::OnValidate(const CFX_WideString& wsText) {
480 CFWL_Widget* pDst = GetOuter();
481 if (!pDst)
482 pDst = this;
483
484 CFWL_EvtValidate event(this);
485 event.wsInsert = wsText;
486 event.bValidate = true;
487 DispatchEvent(&event);
488 return event.bValidate;
489 }
490
491 void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) {
492 m_fScrollOffsetY = fScrollOffset;
493 }
494
495 void CFWL_Edit::DrawTextBk(CFX_Graphics* pGraphics,
496 IFWL_ThemeProvider* pTheme,
497 const CFX_Matrix* pMatrix) {
498 CFWL_ThemeBackground param;
499 param.m_pWidget = this;
500 param.m_iPart = CFWL_Part::Background;
501 param.m_bStaticBackground = false;
502 param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly
503 ? CFWL_PartState_ReadOnly
504 : CFWL_PartState_Normal;
505 uint32_t dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled);
506 if (dwStates)
507 param.m_dwStates = CFWL_PartState_Disabled;
508 param.m_pGraphics = pGraphics;
509 param.m_matrix = *pMatrix;
510 param.m_rtPart = m_rtClient;
511 pTheme->DrawBackground(&param);
512
513 if (!IsShowScrollBar(true) || !IsShowScrollBar(false))
514 return;
515
516 CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect();
517
518 CFX_RectF rtStatic;
519 rtStatic.Set(m_rtClient.right() - rtScroll.height,
520 m_rtClient.bottom() - rtScroll.height, rtScroll.height,
521 rtScroll.height);
522 param.m_bStaticBackground = true;
523 param.m_bMaximize = true;
524 param.m_rtPart = rtStatic;
525 pTheme->DrawBackground(&param);
526 }
527
528 void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics,
529 IFWL_ThemeProvider* pTheme,
530 const CFX_Matrix* pMatrix) {
531 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
532 if (!pPage)
533 return;
534
535 pGraphics->SaveGraphState();
536 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
537 pGraphics->SaveGraphState();
538
539 CFX_RectF rtClip = m_rtEngine;
540 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
541 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
542 CFX_Matrix mt;
543 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
544 if (pMatrix) {
545 pMatrix->TransformRect(rtClip);
546 mt.Concat(*pMatrix);
547 }
548
549 bool bShowSel = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) ||
550 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
551 if (bShowSel) {
552 CFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(this);
553 if (pForm) {
554 bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) !=
555 FWL_WGTSTATE_Deactivated;
556 }
557 }
558
559 int32_t nSelCount = m_EdtEngine.CountSelRanges();
560 if (bShowSel && nSelCount > 0) {
561 int32_t nPageCharStart = pPage->GetCharStart();
562 int32_t nPageCharCount = pPage->GetCharCount();
563 int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1;
564 int32_t nCharCount;
565 int32_t nCharStart;
566 CFX_RectFArray rectArr;
567 int32_t i = 0;
568 for (i = 0; i < nSelCount; i++) {
569 nCharCount = m_EdtEngine.GetSelRange(i, &nCharStart);
570 int32_t nCharEnd = nCharStart + nCharCount - 1;
571 if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd)
572 continue;
573
574 int32_t nBgn = std::max(nCharStart, nPageCharStart);
575 int32_t nEnd = std::min(nCharEnd, nPageCharEnd);
576 pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1,
577 rectArr);
578 }
579
580 int32_t nCount = rectArr.GetSize();
581 CFX_Path path;
582 path.Create();
583 for (i = 0; i < nCount; i++) {
584 rectArr[i].left += fOffSetX;
585 rectArr[i].top += fOffSetY;
586 path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width,
587 rectArr[i].height);
588 }
589 pGraphics->SetClipRect(rtClip);
590
591 CFWL_ThemeBackground param;
592 param.m_pGraphics = pGraphics;
593 param.m_matrix = *pMatrix;
594 param.m_pWidget = this;
595 param.m_iPart = CFWL_Part::Background;
596 param.m_pPath = &path;
597 pTheme->DrawBackground(&param);
598 }
599
600 CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice();
601 if (!pRenderDev)
602 return;
603
604 std::unique_ptr<CFDE_RenderDevice> pRenderDevice(
605 new CFDE_RenderDevice(pRenderDev, false));
606 std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext);
607 pRenderDevice->SetClipRect(rtClip);
608 pRenderContext->StartRender(pRenderDevice.get(), pPage, mt);
609 pRenderContext->DoRender(nullptr);
610
611 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
612 pGraphics->RestoreGraphState();
613 CFX_Path path;
614 path.Create();
615 int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
616 FX_FLOAT fStep = m_rtEngine.width / iLimit;
617 FX_FLOAT fLeft = m_rtEngine.left + 1;
618 for (int32_t i = 1; i < iLimit; i++) {
619 fLeft += fStep;
620 path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom());
621 }
622
623 CFWL_ThemeBackground param;
624 param.m_pGraphics = pGraphics;
625 param.m_matrix = *pMatrix;
626 param.m_pWidget = this;
627 param.m_iPart = CFWL_Part::CombTextLine;
628 param.m_pPath = &path;
629 pTheme->DrawBackground(&param);
630 }
631 pGraphics->RestoreGraphState();
632 }
633
634 void CFWL_Edit::UpdateEditEngine() {
635 UpdateEditParams();
636 UpdateEditLayout();
637 if (m_nLimit > -1)
638 m_EdtEngine.SetLimit(m_nLimit);
639 }
640
641 void CFWL_Edit::UpdateEditParams() {
642 FDE_TXTEDTPARAMS params;
643 params.nHorzScale = 100;
644 params.fPlateWidth = m_rtEngine.width;
645 params.fPlateHeight = m_rtEngine.height;
646 if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout)
647 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL;
648 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout)
649 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical;
650 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars)
651 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial;
652 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine)
653 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve;
654 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes)
655 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes;
656 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab)
657 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab;
658 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
659 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText;
660 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight)
661 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight;
662 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate)
663 params.dwMode |= FDE_TEXTEDITMODE_Validate;
664 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password)
665 params.dwMode |= FDE_TEXTEDITMODE_Password;
666
667 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
668 case FWL_STYLEEXT_EDT_HNear: {
669 params.dwAlignment |= FDE_TEXTEDITALIGN_Left;
670 break;
671 }
672 case FWL_STYLEEXT_EDT_HCenter: {
673 params.dwAlignment |= FDE_TEXTEDITALIGN_Center;
674 break;
675 }
676 case FWL_STYLEEXT_EDT_HFar: {
677 params.dwAlignment |= FDE_TEXTEDITALIGN_Right;
678 break;
679 }
680 default:
681 break;
682 }
683 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
684 case FWL_STYLEEXT_EDT_Justified: {
685 params.dwAlignment |= FDE_TEXTEDITALIGN_Justified;
686 break;
687 }
688 case FWL_STYLEEXT_EDT_Distributed: {
689 params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed;
690 break;
691 }
692 default: {
693 params.dwAlignment |= FDE_TEXTEDITALIGN_Normal;
694 break;
695 }
696 }
697 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
698 params.dwMode |= FDE_TEXTEDITMODE_MultiLines;
699 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 &&
700 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
701 params.dwMode |=
702 FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz;
703 }
704 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
705 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) {
706 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert;
707 } else {
708 params.fPlateHeight = 0x00FFFFFF;
709 }
710 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) ==
711 0) {
712 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz;
713 }
714 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
715 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
716 params.dwMode |= FDE_TEXTEDITMODE_ReadOnly;
717 }
718
719 FX_FLOAT* pFontSize =
720 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
721 if (!pFontSize)
722 return;
723
724 m_fFontSize = *pFontSize;
725 uint32_t* pFontColor =
726 static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor));
727 if (!pFontColor)
728 return;
729
730 params.dwFontColor = *pFontColor;
731 FX_FLOAT* pLineHeight =
732 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight));
733 if (!pLineHeight)
734 return;
735
736 params.fLineSpace = *pLineHeight;
737 CFGAS_GEFont* pFont =
738 static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font));
739 if (!pFont)
740 return;
741
742 params.pFont = pFont;
743 params.fFontSize = m_fFontSize;
744 params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace);
745 if (params.nLineCount <= 0)
746 params.nLineCount = 1;
747 params.fTabWidth = params.fFontSize * 1;
748 params.bTabEquidistant = true;
749 params.wLineBreakChar = L'\n';
750 params.nCharRotation = 0;
751 params.pEventSink = this;
752 m_EdtEngine.SetEditParams(params);
753 }
754
755 void CFWL_Edit::UpdateEditLayout() {
756 if (m_EdtEngine.GetTextLength() <= 0)
757 m_EdtEngine.SetTextByStream(nullptr);
758
759 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
760 if (pPage)
761 pPage->UnloadPage(nullptr);
762
763 m_EdtEngine.StartLayout();
764 m_EdtEngine.DoLayout(nullptr);
765 m_EdtEngine.EndLayout();
766 pPage = m_EdtEngine.GetPage(0);
767 if (pPage)
768 pPage->LoadPage(nullptr, nullptr);
769 }
770
771 bool CFWL_Edit::UpdateOffset() {
772 CFX_RectF rtCaret;
773 m_EdtEngine.GetCaretRect(rtCaret);
774 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
775 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
776 rtCaret.Offset(fOffSetX, fOffSetY);
777 const CFX_RectF& rtEidt = m_rtEngine;
778 if (rtEidt.Contains(rtCaret)) {
779 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
780 if (!pPage)
781 return false;
782
783 CFX_RectF rtFDE = pPage->GetContentsBox();
784 rtFDE.Offset(fOffSetX, fOffSetY);
785 if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) {
786 m_fScrollOffsetX += rtFDE.right() - rtEidt.right();
787 m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f);
788 }
789 if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) {
790 m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom();
791 m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f);
792 }
793 return false;
794 }
795
796 FX_FLOAT offsetX = 0.0;
797 FX_FLOAT offsetY = 0.0;
798 if (rtCaret.left < rtEidt.left)
799 offsetX = rtCaret.left - rtEidt.left;
800 if (rtCaret.right() > rtEidt.right())
801 offsetX = rtCaret.right() - rtEidt.right();
802 if (rtCaret.top < rtEidt.top)
803 offsetY = rtCaret.top - rtEidt.top;
804 if (rtCaret.bottom() > rtEidt.bottom())
805 offsetY = rtCaret.bottom() - rtEidt.bottom();
806 m_fScrollOffsetX += offsetX;
807 m_fScrollOffsetY += offsetY;
808 if (m_fFontSize > m_rtEngine.height)
809 m_fScrollOffsetY = 0;
810 return true;
811 }
812
813 bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) {
814 if (pScrollBar == m_pHorzScrollBar.get())
815 m_fScrollOffsetX += fPosChanged;
816 else
817 m_fScrollOffsetY += fPosChanged;
818 return true;
819 }
820
821 void CFWL_Edit::UpdateVAlignment() {
822 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
823 if (!pPage)
824 return;
825
826 const CFX_RectF& rtFDE = pPage->GetContentsBox();
827 FX_FLOAT fOffsetY = 0.0f;
828 FX_FLOAT fSpaceAbove = 0.0f;
829 FX_FLOAT fSpaceBelow = 0.0f;
830 CFX_SizeF* pSpace = static_cast<CFX_SizeF*>(
831 GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow));
832 if (pSpace) {
833 fSpaceAbove = pSpace->x;
834 fSpaceBelow = pSpace->y;
835 }
836 if (fSpaceAbove < 0.1f)
837 fSpaceAbove = 0;
838 if (fSpaceBelow < 0.1f)
839 fSpaceBelow = 0;
840
841 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
842 fOffsetY = (m_rtEngine.height - rtFDE.height) / 2;
843 if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 &&
844 fSpaceAbove < fSpaceBelow) {
845 return;
846 }
847 fOffsetY += (fSpaceAbove - fSpaceBelow) / 2;
848 } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
849 fOffsetY = (m_rtEngine.height - rtFDE.height);
850 fOffsetY -= fSpaceBelow;
851 } else {
852 fOffsetY += fSpaceAbove;
853 }
854 m_fVAlignOffset = std::max(fOffsetY, 0.0f);
855 }
856
857 void CFWL_Edit::UpdateCaret() {
858 CFX_RectF rtFDE;
859 m_EdtEngine.GetCaretRect(rtFDE);
860
861 rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX,
862 m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);
863 CFX_RectF rtCaret;
864 rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height);
865
866 CFX_RectF rtClient;
867 GetClientRect(rtClient);
868 rtCaret.Intersect(rtClient);
869
870 if (rtCaret.left > rtClient.right()) {
871 FX_FLOAT right = rtCaret.right();
872 rtCaret.left = rtClient.right() - 1;
873 rtCaret.width = right - rtCaret.left;
874 }
875
876 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty())
877 ShowCaret(&rtCaret);
878 else
879 HideCaret(&rtCaret);
880 }
881
882 CFWL_ScrollBar* CFWL_Edit::UpdateScroll() {
883 bool bShowHorz =
884 m_pHorzScrollBar &&
885 ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
886 bool bShowVert =
887 m_pVertScrollBar &&
888 ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
889 if (!bShowHorz && !bShowVert)
890 return nullptr;
891
892 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
893 if (!pPage)
894 return nullptr;
895
896 const CFX_RectF& rtFDE = pPage->GetContentsBox();
897 CFWL_ScrollBar* pRepaint = nullptr;
898 if (bShowHorz) {
899 CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect();
900 if (rtScroll.width < rtFDE.width) {
901 m_pHorzScrollBar->LockUpdate();
902 FX_FLOAT fRange = rtFDE.width - rtScroll.width;
903 m_pHorzScrollBar->SetRange(0.0f, fRange);
904
905 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetX, 0.0f), fRange);
906 m_pHorzScrollBar->SetPos(fPos);
907 m_pHorzScrollBar->SetTrackPos(fPos);
908 m_pHorzScrollBar->SetPageSize(rtScroll.width);
909 m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
910 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
911 m_pHorzScrollBar->UnlockUpdate();
912 m_pHorzScrollBar->Update();
913 pRepaint = m_pHorzScrollBar.get();
914 } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
915 m_pHorzScrollBar->LockUpdate();
916 m_pHorzScrollBar->SetRange(0, -1);
917 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled);
918 m_pHorzScrollBar->UnlockUpdate();
919 m_pHorzScrollBar->Update();
920 pRepaint = m_pHorzScrollBar.get();
921 }
922 }
923
924 if (bShowVert) {
925 CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect();
926 if (rtScroll.height < rtFDE.height) {
927 m_pVertScrollBar->LockUpdate();
928 FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace;
929 FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep);
930
931 m_pVertScrollBar->SetRange(0.0f, fRange);
932 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange);
933 m_pVertScrollBar->SetPos(fPos);
934 m_pVertScrollBar->SetTrackPos(fPos);
935 m_pVertScrollBar->SetPageSize(rtScroll.height);
936 m_pVertScrollBar->SetStepSize(fStep);
937 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
938 m_pVertScrollBar->UnlockUpdate();
939 m_pVertScrollBar->Update();
940 pRepaint = m_pVertScrollBar.get();
941 } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
942 m_pVertScrollBar->LockUpdate();
943 m_pVertScrollBar->SetRange(0, -1);
944 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled);
945 m_pVertScrollBar->UnlockUpdate();
946 m_pVertScrollBar->Update();
947 pRepaint = m_pVertScrollBar.get();
948 }
949 }
950 return pRepaint;
951 }
952
953 bool CFWL_Edit::IsShowScrollBar(bool bVert) {
954 bool bShow =
955 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
956 ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
957 FWL_WGTSTATE_Focused
958 : true;
959 if (bVert) {
960 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
961 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
962 IsContentHeightOverflow();
963 }
964 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) &&
965 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
966 }
967
968 bool CFWL_Edit::IsContentHeightOverflow() {
969 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
970 if (!pPage)
971 return false;
972 return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f;
973 }
974
975 int32_t CFWL_Edit::AddDoRecord(std::unique_ptr<IFDE_TxtEdtDoRecord> pRecord) {
976 int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords);
977 if (m_iCurRecord == nCount - 1) {
978 if (nCount == m_iMaxRecord) {
979 m_DoRecords.pop_front();
980 m_iCurRecord--;
981 }
982 } else {
983 m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1,
984 m_DoRecords.end());
985 }
986
987 m_DoRecords.push_back(std::move(pRecord));
988 m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
989 return m_iCurRecord;
990 }
991
992 void CFWL_Edit::Layout() {
993 GetClientRect(m_rtClient);
994 m_rtEngine = m_rtClient;
995 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
996 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
997 if (!pfWidth)
998 return;
999
1000 FX_FLOAT fWidth = *pfWidth;
1001 if (!m_pOuter) {
1002 CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
1003 GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
1004 if (pUIMargin) {
1005 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
1006 pUIMargin->height);
1007 }
1008 } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) {
1009 CFWL_ThemePart part;
1010 part.m_pWidget = m_pOuter;
1011 CFX_RectF* pUIMargin =
1012 static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity(
1013 &part, CFWL_WidgetCapacity::UIMargin));
1014 if (pUIMargin) {
1015 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
1016 pUIMargin->height);
1017 }
1018 }
1019
1020 bool bShowVertScrollbar = IsShowScrollBar(true);
1021 bool bShowHorzScrollbar = IsShowScrollBar(false);
1022 if (bShowVertScrollbar) {
1023 InitVerticalScrollBar();
1024
1025 CFX_RectF rtVertScr;
1026 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1027 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
1028 m_rtClient.height);
1029 } else {
1030 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
1031 m_rtClient.height);
1032 if (bShowHorzScrollbar)
1033 rtVertScr.height -= fWidth;
1034 m_rtEngine.width -= fWidth;
1035 }
1036
1037 m_pVertScrollBar->SetWidgetRect(rtVertScr);
1038 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
1039 m_pVertScrollBar->Update();
1040 } else if (m_pVertScrollBar) {
1041 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible);
1042 }
1043
1044 if (bShowHorzScrollbar) {
1045 InitHorizontalScrollBar();
1046
1047 CFX_RectF rtHoriScr;
1048 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1049 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
1050 m_rtClient.width, fWidth);
1051 } else {
1052 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
1053 m_rtClient.width, fWidth);
1054 if (bShowVertScrollbar)
1055 rtHoriScr.width -= fWidth;
1056 m_rtEngine.height -= fWidth;
1057 }
1058 m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
1059 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
1060 m_pHorzScrollBar->Update();
1061 } else if (m_pHorzScrollBar) {
1062 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible);
1063 }
1064 }
1065
1066 void CFWL_Edit::LayoutScrollBar() {
1067 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
1068 0) {
1069 return;
1070 }
1071
1072 FX_FLOAT* pfWidth = nullptr;
1073 bool bShowVertScrollbar = IsShowScrollBar(true);
1074 bool bShowHorzScrollbar = IsShowScrollBar(false);
1075 if (bShowVertScrollbar) {
1076 if (!m_pVertScrollBar) {
1077 pfWidth = static_cast<FX_FLOAT*>(
1078 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
1079 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
1080 InitVerticalScrollBar();
1081 CFX_RectF rtVertScr;
1082 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1083 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
1084 m_rtClient.height);
1085 } else {
1086 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
1087 m_rtClient.height);
1088 if (bShowHorzScrollbar)
1089 rtVertScr.height -= fWidth;
1090 }
1091 m_pVertScrollBar->SetWidgetRect(rtVertScr);
1092 m_pVertScrollBar->Update();
1093 }
1094 m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
1095 } else if (m_pVertScrollBar) {
1096 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible);
1097 }
1098
1099 if (bShowHorzScrollbar) {
1100 if (!m_pHorzScrollBar) {
1101 if (!pfWidth) {
1102 pfWidth = static_cast<FX_FLOAT*>(
1103 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
1104 }
1105
1106 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
1107 InitHorizontalScrollBar();
1108 CFX_RectF rtHoriScr;
1109 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
1110 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
1111 m_rtClient.width, fWidth);
1112 } else {
1113 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
1114 m_rtClient.width, fWidth);
1115 if (bShowVertScrollbar)
1116 rtHoriScr.width -= (fWidth);
1117 }
1118 m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
1119 m_pHorzScrollBar->Update();
1120 }
1121 m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
1122 } else if (m_pHorzScrollBar) {
1123 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible);
1124 }
1125 if (bShowVertScrollbar || bShowHorzScrollbar)
1126 UpdateScroll();
1127 }
1128
1129 void CFWL_Edit::DeviceToEngine(CFX_PointF& pt) {
1130 pt.x += m_fScrollOffsetX - m_rtEngine.left;
1131 pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset;
1132 }
1133
1134 void CFWL_Edit::InitVerticalScrollBar() {
1135 if (m_pVertScrollBar)
1136 return;
1137
1138 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
1139 prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Vert;
1140 prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
1141 prop->m_pParent = this;
1142 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
1143 m_pVertScrollBar =
1144 pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this);
1145 }
1146
1147 void CFWL_Edit::InitHorizontalScrollBar() {
1148 if (m_pHorzScrollBar)
1149 return;
1150
1151 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
1152 prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Horz;
1153 prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
1154 prop->m_pParent = this;
1155 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
1156 m_pHorzScrollBar =
1157 pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp, std::move(prop), this);
1158 }
1159
1160 void CFWL_Edit::ShowCaret(CFX_RectF* pRect) {
1161 if (m_pCaret) {
1162 m_pCaret->ShowCaret();
1163 if (!pRect->IsEmpty())
1164 m_pCaret->SetWidgetRect(*pRect);
1165 Repaint(&m_rtEngine);
1166 return;
1167 }
1168
1169 CFWL_Widget* pOuter = this;
1170 pRect->Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
1171 while (pOuter->GetOuter()) {
1172 pOuter = pOuter->GetOuter();
1173
1174 CFX_RectF rtOuter = pOuter->GetWidgetRect();
1175 pRect->Offset(rtOuter.left, rtOuter.top);
1176 }
1177
1178 CXFA_FFWidget* pXFAWidget =
1179 static_cast<CXFA_FFWidget*>(pOuter->GetLayoutItem());
1180 if (!pXFAWidget)
1181 return;
1182
1183 IXFA_DocEnvironment* pDocEnvironment =
1184 pXFAWidget->GetDoc()->GetDocEnvironment();
1185 if (!pDocEnvironment)
1186 return;
1187
1188 CFX_Matrix mt;
1189 pXFAWidget->GetRotateMatrix(mt);
1190
1191 CFX_RectF rt(*pRect);
1192 mt.TransformRect(rt);
1193 pDocEnvironment->DisplayCaret(pXFAWidget, true, &rt);
1194 }
1195
1196 void CFWL_Edit::HideCaret(CFX_RectF* pRect) {
1197 if (m_pCaret) {
1198 m_pCaret->HideCaret();
1199 Repaint(&m_rtEngine);
1200 return;
1201 }
1202
1203 CFWL_Widget* pOuter = this;
1204 while (pOuter->GetOuter())
1205 pOuter = pOuter->GetOuter();
1206
1207 CXFA_FFWidget* pXFAWidget =
1208 static_cast<CXFA_FFWidget*>(pOuter->GetLayoutItem());
1209 if (!pXFAWidget)
1210 return;
1211
1212 IXFA_DocEnvironment* pDocEnvironment =
1213 pXFAWidget->GetDoc()->GetDocEnvironment();
1214 if (!pDocEnvironment)
1215 return;
1216
1217 pDocEnvironment->DisplayCaret(pXFAWidget, false, pRect);
1218 }
1219
1220 bool CFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) {
1221 if (!m_bSetRange)
1222 return true;
1223
1224 CFX_WideString wsText = m_EdtEngine.GetText(0, -1);
1225 if (wsText.IsEmpty()) {
1226 if (cNum == L'0')
1227 return false;
1228 return true;
1229 }
1230
1231 int32_t caretPos = m_EdtEngine.GetCaretPos();
1232 if (CountSelRanges() == 0) {
1233 if (cNum == L'0' && caretPos == 0)
1234 return false;
1235
1236 int32_t nLen = wsText.GetLength();
1237 CFX_WideString l = wsText.Mid(0, caretPos);
1238 CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos);
1239 CFX_WideString wsNew = l + cNum + r;
1240 if (wsNew.GetInteger() <= m_iMax)
1241 return true;
1242 return false;
1243 }
1244
1245 if (wsText.GetInteger() <= m_iMax)
1246 return true;
1247 return false;
1248 }
1249
1250 void CFWL_Edit::InitCaret() {
1251 if (!m_pCaret) {
1252 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) {
1253 m_pCaret = pdfium::MakeUnique<CFWL_Caret>(
1254 m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this);
1255 m_pCaret->SetParent(this);
1256 m_pCaret->SetStates(m_pProperties->m_dwStates);
1257 }
1258 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) ==
1259 0) {
1260 m_pCaret.reset();
1261 }
1262 }
1263
1264 void CFWL_Edit::ClearRecord() {
1265 m_iCurRecord = -1;
1266 m_DoRecords.clear();
1267 }
1268
1269 void CFWL_Edit::ProcessInsertError(int32_t iError) {
1270 if (iError != -2)
1271 return;
1272
1273 CFWL_Event textFullEvent(CFWL_Event::Type::TextFull, this);
1274 DispatchEvent(&textFullEvent);
1275 }
1276
1277 void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) {
1278 if (!pMessage)
1279 return;
1280
1281 switch (pMessage->GetType()) {
1282 case CFWL_Message::Type::SetFocus:
1283 OnFocusChanged(pMessage, true);
1284 break;
1285 case CFWL_Message::Type::KillFocus:
1286 OnFocusChanged(pMessage, false);
1287 break;
1288 case CFWL_Message::Type::Mouse: {
1289 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
1290 switch (pMsg->m_dwCmd) {
1291 case FWL_MouseCommand::LeftButtonDown:
1292 OnLButtonDown(pMsg);
1293 break;
1294 case FWL_MouseCommand::LeftButtonUp:
1295 OnLButtonUp(pMsg);
1296 break;
1297 case FWL_MouseCommand::LeftButtonDblClk:
1298 OnButtonDblClk(pMsg);
1299 break;
1300 case FWL_MouseCommand::Move:
1301 OnMouseMove(pMsg);
1302 break;
1303 case FWL_MouseCommand::RightButtonDown:
1304 DoButtonDown(pMsg);
1305 break;
1306 default:
1307 break;
1308 }
1309 break;
1310 }
1311 case CFWL_Message::Type::Key: {
1312 CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
1313 if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
1314 OnKeyDown(pKey);
1315 else if (pKey->m_dwCmd == FWL_KeyCommand::Char)
1316 OnChar(pKey);
1317 break;
1318 }
1319 default:
1320 break;
1321 }
1322 CFWL_Widget::OnProcessMessage(pMessage);
1323 }
1324
1325 void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) {
1326 if (!pEvent)
1327 return;
1328 if (pEvent->GetType() != CFWL_Event::Type::Scroll)
1329 return;
1330
1331 CFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
1332 if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
1333 (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
1334 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
1335 OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
1336 pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
1337 }
1338 }
1339
1340 void CFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics,
1341 const CFX_Matrix* pMatrix) {
1342 DrawWidget(pGraphics, pMatrix);
1343 }
1344
1345 void CFWL_Edit::DoButtonDown(CFWL_MsgMouse* pMsg) {
1346 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
1347 SetFocus(true);
1348
1349 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
1350 if (!pPage)
1351 return;
1352
1353 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1354 DeviceToEngine(pt);
1355 bool bBefore = true;
1356 int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
1357 if (nIndex < 0)
1358 nIndex = 0;
1359
1360 m_EdtEngine.SetCaretPos(nIndex, bBefore);
1361 }
1362
1363 void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
1364 uint32_t dwStyleEx = GetStylesEx();
1365 bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret);
1366 if (bSet) {
1367 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
1368
1369 UpdateVAlignment();
1370 UpdateOffset();
1371 UpdateCaret();
1372 } else if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
1373 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
1374 HideCaret(nullptr);
1375 if ((dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) {
1376 int32_t nSel = CountSelRanges();
1377 if (nSel > 0) {
1378 ClearSelections();
1379 bRepaint = true;
1380 }
1381 m_EdtEngine.SetCaretPos(0, true);
1382 UpdateOffset();
1383 }
1384 ClearRecord();
1385 }
1386
1387 LayoutScrollBar();
1388 if (!bRepaint)
1389 return;
1390
1391 CFX_RectF rtInvalidate;
1392 rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
1393 m_pProperties->m_rtWidget.height);
1394 Repaint(&rtInvalidate);
1395 }
1396
1397 void CFWL_Edit::OnLButtonDown(CFWL_MsgMouse* pMsg) {
1398 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
1399 return;
1400
1401 m_bLButtonDown = true;
1402 SetGrab(true);
1403 DoButtonDown(pMsg);
1404 int32_t nIndex = m_EdtEngine.GetCaretPos();
1405 bool bRepaint = false;
1406 if (m_EdtEngine.CountSelRanges() > 0) {
1407 m_EdtEngine.ClearSelection();
1408 bRepaint = true;
1409 }
1410
1411 if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) {
1412 int32_t iStart = std::min(m_nSelStart, nIndex);
1413 int32_t iEnd = std::max(m_nSelStart, nIndex);
1414 m_EdtEngine.AddSelRange(iStart, iEnd - iStart);
1415 bRepaint = true;
1416 } else {
1417 m_nSelStart = nIndex;
1418 }
1419 if (bRepaint)
1420 Repaint(&m_rtEngine);
1421 }
1422
1423 void CFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) {
1424 m_bLButtonDown = false;
1425 SetGrab(false);
1426 }
1427
1428 void CFWL_Edit::OnButtonDblClk(CFWL_MsgMouse* pMsg) {
1429 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
1430 if (!pPage)
1431 return;
1432
1433 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1434 DeviceToEngine(pt);
1435 int32_t nCount = 0;
1436 int32_t nIndex = pPage->SelectWord(pt, nCount);
1437 if (nIndex < 0)
1438 return;
1439
1440 m_EdtEngine.AddSelRange(nIndex, nCount);
1441 m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false);
1442 Repaint(&m_rtEngine);
1443 }
1444
1445 void CFWL_Edit::OnMouseMove(CFWL_MsgMouse* pMsg) {
1446 if (m_nSelStart == -1 || !m_bLButtonDown)
1447 return;
1448
1449 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
1450 if (!pPage)
1451 return;
1452
1453 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
1454 DeviceToEngine(pt);
1455 bool bBefore = true;
1456 int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
1457 m_EdtEngine.SetCaretPos(nIndex, bBefore);
1458 nIndex = m_EdtEngine.GetCaretPos();
1459 m_EdtEngine.ClearSelection();
1460
1461 if (nIndex == m_nSelStart)
1462 return;
1463
1464 int32_t nLen = m_EdtEngine.GetTextLength();
1465 if (m_nSelStart >= nLen)
1466 m_nSelStart = nLen;
1467
1468 m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex),
1469 FXSYS_abs(nIndex - m_nSelStart));
1470 }
1471
1472 void CFWL_Edit::OnKeyDown(CFWL_MsgKey* pMsg) {
1473 FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone;
1474 bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
1475 bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);
1476 uint32_t dwKeyCode = pMsg->m_dwKeyCode;
1477 switch (dwKeyCode) {
1478 case FWL_VKEY_Left: {
1479 MoveCaret = MC_Left;
1480 break;
1481 }
1482 case FWL_VKEY_Right: {
1483 MoveCaret = MC_Right;
1484 break;
1485 }
1486 case FWL_VKEY_Up: {
1487 MoveCaret = MC_Up;
1488 break;
1489 }
1490 case FWL_VKEY_Down: {
1491 MoveCaret = MC_Down;
1492 break;
1493 }
1494 case FWL_VKEY_Home: {
1495 MoveCaret = bCtrl ? MC_Home : MC_LineStart;
1496 break;
1497 }
1498 case FWL_VKEY_End: {
1499 MoveCaret = bCtrl ? MC_End : MC_LineEnd;
1500 break;
1501 }
1502 case FWL_VKEY_Insert:
1503 break;
1504 case FWL_VKEY_Delete: {
1505 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
1506 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
1507 break;
1508 }
1509 int32_t nCaret = m_EdtEngine.GetCaretPos();
1510 #if (_FX_OS_ == _FX_MACOSX_)
1511 m_EdtEngine.Delete(nCaret, true);
1512 #else
1513 m_EdtEngine.Delete(nCaret);
1514 #endif
1515 break;
1516 }
1517 case FWL_VKEY_F2:
1518 case FWL_VKEY_Tab:
1519 default:
1520 break;
1521 }
1522 if (MoveCaret != MC_MoveNone)
1523 m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl);
1524 }
1525
1526 void CFWL_Edit::OnChar(CFWL_MsgKey* pMsg) {
1527 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
1528 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
1529 return;
1530 }
1531
1532 int32_t iError = 0;
1533 FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode);
1534 int32_t nCaret = m_EdtEngine.GetCaretPos();
1535 switch (c) {
1536 case FWL_VKEY_Back:
1537 m_EdtEngine.Delete(nCaret, true);
1538 break;
1539 case FWL_VKEY_NewLine:
1540 case FWL_VKEY_Escape:
1541 break;
1542 case FWL_VKEY_Tab: {
1543 iError = m_EdtEngine.Insert(nCaret, L"\t", 1);
1544 break;
1545 }
1546 case FWL_VKEY_Return: {
1547 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) {
1548 iError = m_EdtEngine.Insert(nCaret, L"\n", 1);
1549 }
1550 break;
1551 }
1552 default: {
1553 if (!m_pWidgetMgr->IsFormDisabled()) {
1554 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) {
1555 if (((pMsg->m_dwKeyCode < FWL_VKEY_0) &&
1556 (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) ||
1557 pMsg->m_dwKeyCode > FWL_VKEY_9) {
1558 break;
1559 }
1560 if (!ValidateNumberChar(c))
1561 break;
1562 }
1563 }
1564 #if (_FX_OS_ == _FX_MACOSX_)
1565 if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
1566 #else
1567 if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
1568 #endif
1569 {
1570 break;
1571 }
1572 iError = m_EdtEngine.Insert(nCaret, &c, 1);
1573 break;
1574 }
1575 }
1576 if (iError < 0)
1577 ProcessInsertError(iError);
1578 }
1579
1580 bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar,
1581 CFWL_EvtScroll::Code dwCode,
1582 FX_FLOAT fPos) {
1583 CFX_SizeF fs;
1584 pScrollBar->GetRange(&fs.x, &fs.y);
1585 FX_FLOAT iCurPos = pScrollBar->GetPos();
1586 FX_FLOAT fStep = pScrollBar->GetStepSize();
1587 switch (dwCode) {
1588 case CFWL_EvtScroll::Code::Min: {
1589 fPos = fs.x;
1590 break;
1591 }
1592 case CFWL_EvtScroll::Code::Max: {
1593 fPos = fs.y;
1594 break;
1595 }
1596 case CFWL_EvtScroll::Code::StepBackward: {
1597 fPos -= fStep;
1598 if (fPos < fs.x + fStep / 2) {
1599 fPos = fs.x;
1600 }
1601 break;
1602 }
1603 case CFWL_EvtScroll::Code::StepForward: {
1604 fPos += fStep;
1605 if (fPos > fs.y - fStep / 2) {
1606 fPos = fs.y;
1607 }
1608 break;
1609 }
1610 case CFWL_EvtScroll::Code::PageBackward: {
1611 fPos -= pScrollBar->GetPageSize();
1612 if (fPos < fs.x) {
1613 fPos = fs.x;
1614 }
1615 break;
1616 }
1617 case CFWL_EvtScroll::Code::PageForward: {
1618 fPos += pScrollBar->GetPageSize();
1619 if (fPos > fs.y) {
1620 fPos = fs.y;
1621 }
1622 break;
1623 }
1624 case CFWL_EvtScroll::Code::Pos:
1625 case CFWL_EvtScroll::Code::TrackPos:
1626 case CFWL_EvtScroll::Code::None:
1627 break;
1628 case CFWL_EvtScroll::Code::EndScroll:
1629 return false;
1630 }
1631 if (iCurPos == fPos)
1632 return true;
1633
1634 pScrollBar->SetPos(fPos);
1635 pScrollBar->SetTrackPos(fPos);
1636 UpdateOffset(pScrollBar, fPos - iCurPos);
1637 UpdateCaret();
1638
1639 CFX_RectF rect = GetWidgetRect();
1640 CFX_RectF rtInvalidate;
1641 rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2);
1642 Repaint(&rtInvalidate);
1643 return true;
1644 }
OLDNEW
« no previous file with comments | « xfa/fwl/core/cfwl_edit.h ('k') | xfa/fwl/core/cfwl_event.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698