clang-format all pdfium code.
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Edit.cpp
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 "../../../core/include/fxcrt/fx_safe_types.h"
8 #include "../../../core/include/fxcrt/fx_xml.h"
9 #include "../../include/pdfwindow/PDFWindow.h"
10 #include "../../include/pdfwindow/PWL_Caret.h"
11 #include "../../include/pdfwindow/PWL_Edit.h"
12 #include "../../include/pdfwindow/PWL_EditCtrl.h"
13 #include "../../include/pdfwindow/PWL_FontMap.h"
14 #include "../../include/pdfwindow/PWL_ScrollBar.h"
15 #include "../../include/pdfwindow/PWL_Utils.h"
16 #include "../../include/pdfwindow/PWL_Wnd.h"
17
18 /* ---------------------------- CPWL_Edit ------------------------------ */
19
20 CPWL_Edit::CPWL_Edit()
21     : m_pFillerNotify(NULL), m_pSpellCheck(NULL), m_bFocus(FALSE) {
22   m_pFormFiller = NULL;
23 }
24
25 CPWL_Edit::~CPWL_Edit() {
26   ASSERT(m_bFocus == FALSE);
27 }
28
29 CFX_ByteString CPWL_Edit::GetClassName() const {
30   return PWL_CLASSNAME_EDIT;
31 }
32
33 void CPWL_Edit::OnDestroy() {}
34
35 void CPWL_Edit::SetText(const FX_WCHAR* csText) {
36   CFX_WideString swText = csText;
37
38   if (HasFlag(PES_RICH)) {
39     CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
40
41     if (CXML_Element* pXML =
42             CXML_Element::Parse(sValue.c_str(), sValue.GetLength())) {
43       int32_t nCount = pXML->CountChildren();
44       FX_BOOL bFirst = TRUE;
45
46       swText.Empty();
47
48       for (int32_t i = 0; i < nCount; i++) {
49         if (CXML_Element* pSubElement = pXML->GetElement(i)) {
50           CFX_ByteString tag = pSubElement->GetTagName();
51           if (tag.EqualNoCase("p")) {
52             int nChild = pSubElement->CountChildren();
53             CFX_WideString swSection;
54             for (int32_t j = 0; j < nChild; j++) {
55               swSection += pSubElement->GetContent(j);
56             }
57
58             if (bFirst)
59               bFirst = FALSE;
60             else
61               swText += FWL_VKEY_Return;
62             swText += swSection;
63           }
64         }
65       }
66
67       delete pXML;
68     }
69   }
70
71   m_pEdit->SetText(swText.c_str());
72 }
73
74 void CPWL_Edit::RePosChildWnd() {
75   if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
76     CPDF_Rect rcWindow = m_rcOldWindow;
77     CPDF_Rect rcVScroll =
78         CPDF_Rect(rcWindow.right, rcWindow.bottom,
79                   rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top);
80     pVSB->Move(rcVScroll, TRUE, FALSE);
81   }
82
83   if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
84     m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
85         GetClientRect(), 1.0f));  //+1 for caret beside border
86
87   CPWL_EditCtrl::RePosChildWnd();
88 }
89
90 CPDF_Rect CPWL_Edit::GetClientRect() const {
91   CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
92       GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
93
94   if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
95     if (pVSB->IsVisible()) {
96       rcClient.right -= PWL_SCROLLBAR_WIDTH;
97     }
98   }
99
100   return rcClient;
101 }
102
103 void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat,
104                                 FX_BOOL bPaint /* = TRUE*/) {
105   m_pEdit->SetAlignmentH((int32_t)nFormat, bPaint);
106 }
107
108 void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat,
109                                 FX_BOOL bPaint /* = TRUE*/) {
110   m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
111 }
112
113 FX_BOOL CPWL_Edit::CanSelectAll() const {
114   return GetSelectWordRange() != m_pEdit->GetWholeWordRange();
115 }
116
117 FX_BOOL CPWL_Edit::CanClear() const {
118   return !IsReadOnly() && m_pEdit->IsSelected();
119 }
120
121 FX_BOOL CPWL_Edit::CanCopy() const {
122   return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) &&
123          m_pEdit->IsSelected();
124 }
125
126 FX_BOOL CPWL_Edit::CanCut() const {
127   return CanCopy() && !IsReadOnly();
128 }
129
130 FX_BOOL CPWL_Edit::CanPaste() const {
131   if (IsReadOnly())
132     return FALSE;
133
134   CFX_WideString swClipboard;
135   if (IFX_SystemHandler* pSH = GetSystemHandler())
136     swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
137
138   return !swClipboard.IsEmpty();
139 }
140
141 void CPWL_Edit::CopyText() {
142   if (!CanCopy())
143     return;
144
145   CFX_WideString str = m_pEdit->GetSelText();
146
147   if (IFX_SystemHandler* pSH = GetSystemHandler())
148     pSH->SetClipboardText(GetAttachedHWnd(), str);
149 }
150
151 void CPWL_Edit::PasteText() {
152   if (!CanPaste())
153     return;
154
155   CFX_WideString swClipboard;
156   if (IFX_SystemHandler* pSH = GetSystemHandler())
157     swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
158
159   if (m_pFillerNotify) {
160     FX_BOOL bRC = TRUE;
161     FX_BOOL bExit = FALSE;
162     CFX_WideString strChangeEx;
163     int nSelStart = 0;
164     int nSelEnd = 0;
165     GetSel(nSelStart, nSelEnd);
166     m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), 0, swClipboard,
167                                        strChangeEx, nSelStart, nSelEnd, TRUE,
168                                        bRC, bExit, 0);
169     if (!bRC)
170       return;
171     if (bExit)
172       return;
173   }
174
175   if (swClipboard.GetLength() > 0) {
176     Clear();
177     InsertText(swClipboard.c_str());
178   }
179
180   if (m_pFillerNotify) {
181     FX_BOOL bExit = FALSE;
182     m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit, 0);
183     if (bExit)
184       return;
185   }
186 }
187
188 void CPWL_Edit::CutText() {
189   if (!CanCut())
190     return;
191
192   CFX_WideString str = m_pEdit->GetSelText();
193
194   if (IFX_SystemHandler* pSH = GetSystemHandler())
195     pSH->SetClipboardText(GetAttachedHWnd(), str);
196
197   m_pEdit->Clear();
198 }
199
200 void CPWL_Edit::OnCreated() {
201   CPWL_EditCtrl::OnCreated();
202
203   if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
204     pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
205     pScroll->SetTransparency(255);
206   }
207
208   SetParamByFlag();
209
210   m_rcOldWindow = GetWindowRect();
211
212   m_pEdit->SetOprNotify(this);
213   m_pEdit->EnableOprNotify(TRUE);
214 }
215
216 void CPWL_Edit::SetParamByFlag() {
217   if (HasFlag(PES_RIGHT)) {
218     m_pEdit->SetAlignmentH(2, FALSE);
219   } else if (HasFlag(PES_MIDDLE)) {
220     m_pEdit->SetAlignmentH(1, FALSE);
221   } else {
222     m_pEdit->SetAlignmentH(0, FALSE);
223   }
224
225   if (HasFlag(PES_BOTTOM)) {
226     m_pEdit->SetAlignmentV(2, FALSE);
227   } else if (HasFlag(PES_CENTER)) {
228     m_pEdit->SetAlignmentV(1, FALSE);
229   } else {
230     m_pEdit->SetAlignmentV(0, FALSE);
231   }
232
233   if (HasFlag(PES_PASSWORD)) {
234     m_pEdit->SetPasswordChar('*', FALSE);
235   }
236
237   m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), FALSE);
238   m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), FALSE);
239   m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), FALSE);
240   m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), FALSE);
241   m_pEdit->EnableUndo(HasFlag(PES_UNDO));
242
243   if (HasFlag(PES_TEXTOVERFLOW)) {
244     SetClipRect(CPDF_Rect(0.0f, 0.0f, 0.0f, 0.0f));
245     m_pEdit->SetTextOverflow(TRUE, FALSE);
246   } else {
247     if (m_pEditCaret) {
248       m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
249           GetClientRect(), 1.0f));  //+1 for caret beside border
250     }
251   }
252
253   if (HasFlag(PES_SPELLCHECK)) {
254     m_pSpellCheck = GetCreationParam().pSpellCheck;
255   }
256 }
257
258 void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
259   CPWL_Wnd::GetThisAppearanceStream(sAppStream);
260
261   CPDF_Rect rcClient = GetClientRect();
262   CFX_ByteTextBuf sLine;
263
264   int32_t nCharArray = m_pEdit->GetCharArray();
265
266   if (nCharArray > 0) {
267     switch (GetBorderStyle()) {
268       case PBS_SOLID: {
269         sLine << "q\n" << GetBorderWidth() << " w\n"
270               << CPWL_Utils::GetColorAppStream(GetBorderColor(), FALSE)
271               << " 2 J 0 j\n";
272
273         for (int32_t i = 1; i < nCharArray; i++) {
274           sLine << rcClient.left +
275                        ((rcClient.right - rcClient.left) / nCharArray) * i
276                 << " " << rcClient.bottom << " m\n"
277                 << rcClient.left +
278                        ((rcClient.right - rcClient.left) / nCharArray) * i
279                 << " " << rcClient.top << " l S\n";
280         }
281
282         sLine << "Q\n";
283       } break;
284       case PBS_DASH: {
285         sLine << "q\n" << GetBorderWidth() << " w\n"
286               << CPWL_Utils::GetColorAppStream(GetBorderColor(), FALSE)
287               << " 2 J 0 j\n"
288               << "[" << GetBorderDash().nDash << " " << GetBorderDash().nGap
289               << "] " << GetBorderDash().nPhase << " d\n";
290
291         for (int32_t i = 1; i < nCharArray; i++) {
292           sLine << rcClient.left +
293                        ((rcClient.right - rcClient.left) / nCharArray) * i
294                 << " " << rcClient.bottom << " m\n"
295                 << rcClient.left +
296                        ((rcClient.right - rcClient.left) / nCharArray) * i
297                 << " " << rcClient.top << " l S\n";
298         }
299
300         sLine << "Q\n";
301       } break;
302     }
303   }
304
305   sAppStream << sLine;
306
307   CFX_ByteTextBuf sText;
308
309   CPDF_Point ptOffset = CPDF_Point(0.0f, 0.0f);
310
311   CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
312   CPVT_WordRange wrSelect = GetSelectWordRange();
313   CPVT_WordRange wrVisible =
314       (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());
315   CPVT_WordRange wrSelBefore(wrWhole.BeginPos, wrSelect.BeginPos);
316   CPVT_WordRange wrSelAfter(wrSelect.EndPos, wrWhole.EndPos);
317
318   CPVT_WordRange wrTemp =
319       CPWL_Utils::OverlapWordRange(GetSelectWordRange(), wrVisible);
320   CFX_ByteString sEditSel =
321       CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset, &wrTemp);
322
323   if (sEditSel.GetLength() > 0)
324     sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR)
325           << sEditSel;
326
327   wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelBefore);
328   CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(
329       m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
330       m_pEdit->GetPasswordChar());
331
332   if (sEditBefore.GetLength() > 0)
333     sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor())
334           << sEditBefore << "ET\n";
335
336   wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelect);
337   CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(
338       m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
339       m_pEdit->GetPasswordChar());
340
341   if (sEditMid.GetLength() > 0)
342     sText << "BT\n"
343           << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1))
344           << sEditMid << "ET\n";
345
346   wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelAfter);
347   CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(
348       m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
349       m_pEdit->GetPasswordChar());
350
351   if (sEditAfter.GetLength() > 0)
352     sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor())
353           << sEditAfter << "ET\n";
354
355   if (HasFlag(PES_SPELLCHECK)) {
356     CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(
357         m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);
358     if (sSpellCheck.GetLength() > 0)
359       sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB, 1, 0, 0),
360                                              FALSE)
361             << sSpellCheck;
362   }
363
364   if (sText.GetLength() > 0) {
365     CPDF_Rect rcClient = GetClientRect();
366     sAppStream << "q\n/Tx BMC\n";
367
368     if (!HasFlag(PES_TEXTOVERFLOW))
369       sAppStream << rcClient.left << " " << rcClient.bottom << " "
370                  << rcClient.right - rcClient.left << " "
371                  << rcClient.top - rcClient.bottom << " re W n\n";
372
373     sAppStream << sText;
374
375     sAppStream << "EMC\nQ\n";
376   }
377 }
378
379 void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice,
380                                    CPDF_Matrix* pUser2Device) {
381   CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
382
383   CPDF_Rect rcClient = GetClientRect();
384   CFX_ByteTextBuf sLine;
385
386   int32_t nCharArray = m_pEdit->GetCharArray();
387   FX_SAFE_INT32 nCharArraySafe = nCharArray;
388   nCharArraySafe -= 1;
389   nCharArraySafe *= 2;
390
391   if (nCharArray > 0 && nCharArraySafe.IsValid()) {
392     switch (GetBorderStyle()) {
393       case PBS_SOLID: {
394         CFX_GraphStateData gsd;
395         gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
396
397         CFX_PathData path;
398         path.SetPointCount(nCharArraySafe.ValueOrDie());
399
400         for (int32_t i = 0; i < nCharArray - 1; i++) {
401           path.SetPoint(
402               i * 2,
403               rcClient.left +
404                   ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
405               rcClient.bottom, FXPT_MOVETO);
406           path.SetPoint(
407               i * 2 + 1,
408               rcClient.left +
409                   ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
410               rcClient.top, FXPT_LINETO);
411         }
412         if (path.GetPointCount() > 0)
413           pDevice->DrawPath(
414               &path, pUser2Device, &gsd, 0,
415               CPWL_Utils::PWLColorToFXColor(GetBorderColor(), 255),
416               FXFILL_ALTERNATE);
417       } break;
418       case PBS_DASH: {
419         CFX_GraphStateData gsd;
420         gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
421
422         gsd.SetDashCount(2);
423         gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;
424         gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;
425         gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;
426
427         CFX_PathData path;
428         path.SetPointCount(nCharArraySafe.ValueOrDie());
429
430         for (int32_t i = 0; i < nCharArray - 1; i++) {
431           path.SetPoint(
432               i * 2,
433               rcClient.left +
434                   ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
435               rcClient.bottom, FXPT_MOVETO);
436           path.SetPoint(
437               i * 2 + 1,
438               rcClient.left +
439                   ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
440               rcClient.top, FXPT_LINETO);
441         }
442         if (path.GetPointCount() > 0)
443           pDevice->DrawPath(
444               &path, pUser2Device, &gsd, 0,
445               CPWL_Utils::PWLColorToFXColor(GetBorderColor(), 255),
446               FXFILL_ALTERNATE);
447       } break;
448     }
449   }
450
451   CPDF_Rect rcClip;
452   CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
453   CPVT_WordRange* pRange = NULL;
454
455   if (!HasFlag(PES_TEXTOVERFLOW)) {
456     rcClip = GetClientRect();
457     pRange = &wrRange;
458   }
459   IFX_SystemHandler* pSysHandler = GetSystemHandler();
460   IFX_Edit::DrawEdit(
461       pDevice, pUser2Device, m_pEdit,
462       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
463       CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(), GetTransparency()),
464       rcClip, CPDF_Point(0.0f, 0.0f), pRange, pSysHandler, m_pFormFiller);
465
466   if (HasFlag(PES_SPELLCHECK)) {
467     CPWL_Utils::DrawEditSpellCheck(pDevice, pUser2Device, m_pEdit, rcClip,
468                                    CPDF_Point(0.0f, 0.0f), pRange,
469                                    GetCreationParam().pSpellCheck);
470   }
471 }
472
473 FX_BOOL CPWL_Edit::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
474   CPWL_Wnd::OnLButtonDown(point, nFlag);
475
476   if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
477     if (m_bMouseDown)
478       InvalidateRect();
479
480     m_bMouseDown = TRUE;
481     SetCapture();
482
483     m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
484   }
485
486   return TRUE;
487 }
488
489 FX_BOOL CPWL_Edit::OnLButtonDblClk(const CPDF_Point& point, FX_DWORD nFlag) {
490   CPWL_Wnd::OnLButtonDblClk(point, nFlag);
491
492   if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
493     m_pEdit->SelectAll();
494   }
495
496   return TRUE;
497 }
498
499 #define WM_PWLEDIT_UNDO 0x01
500 #define WM_PWLEDIT_REDO 0x02
501 #define WM_PWLEDIT_CUT 0x03
502 #define WM_PWLEDIT_COPY 0x04
503 #define WM_PWLEDIT_PASTE 0x05
504 #define WM_PWLEDIT_DELETE 0x06
505 #define WM_PWLEDIT_SELECTALL 0x07
506 #define WM_PWLEDIT_SUGGEST 0x08
507
508 FX_BOOL CPWL_Edit::OnRButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
509   if (m_bMouseDown)
510     return FALSE;
511
512   CPWL_Wnd::OnRButtonUp(point, nFlag);
513
514   if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point))
515     return TRUE;
516
517   IFX_SystemHandler* pSH = GetSystemHandler();
518   if (!pSH)
519     return FALSE;
520
521   SetFocus();
522
523   CPVT_WordRange wrLatin = GetLatinWordsRange(point);
524   CFX_WideString swLatin = m_pEdit->GetRangeText(wrLatin);
525
526   FX_HMENU hPopup = pSH->CreatePopupMenu();
527   if (!hPopup)
528     return FALSE;
529
530   CFX_ByteStringArray sSuggestWords;
531   CPDF_Point ptPopup = point;
532
533   if (!IsReadOnly()) {
534     if (HasFlag(PES_SPELLCHECK) && !swLatin.IsEmpty()) {
535       if (m_pSpellCheck) {
536         CFX_ByteString sLatin = CFX_ByteString::FromUnicode(swLatin);
537
538         if (!m_pSpellCheck->CheckWord(sLatin)) {
539           m_pSpellCheck->SuggestWords(sLatin, sSuggestWords);
540
541           int32_t nSuggest = sSuggestWords.GetSize();
542
543           for (int32_t nWord = 0; nWord < nSuggest; nWord++) {
544             pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SUGGEST + nWord,
545                                 sSuggestWords[nWord].UTF8Decode());
546           }
547
548           if (nSuggest > 0)
549             pSH->AppendMenuItem(hPopup, 0, L"");
550
551           ptPopup = GetWordRightBottomPoint(wrLatin.EndPos);
552         }
553       }
554     }
555   }
556
557   IPWL_Provider* pProvider = GetProvider();
558
559   if (HasFlag(PES_UNDO)) {
560     pSH->AppendMenuItem(
561         hPopup, WM_PWLEDIT_UNDO,
562         pProvider ? pProvider->LoadPopupMenuString(0) : L"&Undo");
563     pSH->AppendMenuItem(
564         hPopup, WM_PWLEDIT_REDO,
565         pProvider ? pProvider->LoadPopupMenuString(1) : L"&Redo");
566     pSH->AppendMenuItem(hPopup, 0, L"");
567
568     if (!m_pEdit->CanUndo())
569       pSH->EnableMenuItem(hPopup, WM_PWLEDIT_UNDO, FALSE);
570     if (!m_pEdit->CanRedo())
571       pSH->EnableMenuItem(hPopup, WM_PWLEDIT_REDO, FALSE);
572   }
573
574   pSH->AppendMenuItem(hPopup, WM_PWLEDIT_CUT,
575                       pProvider ? pProvider->LoadPopupMenuString(2) : L"Cu&t");
576   pSH->AppendMenuItem(hPopup, WM_PWLEDIT_COPY,
577                       pProvider ? pProvider->LoadPopupMenuString(3) : L"&Copy");
578   pSH->AppendMenuItem(
579       hPopup, WM_PWLEDIT_PASTE,
580       pProvider ? pProvider->LoadPopupMenuString(4) : L"&Paste");
581   pSH->AppendMenuItem(
582       hPopup, WM_PWLEDIT_DELETE,
583       pProvider ? pProvider->LoadPopupMenuString(5) : L"&Delete");
584
585   CFX_WideString swText = pSH->GetClipboardText(GetAttachedHWnd());
586   if (swText.IsEmpty())
587     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
588
589   if (!m_pEdit->IsSelected()) {
590     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
591     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
592     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
593   }
594
595   if (IsReadOnly()) {
596     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
597     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
598     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
599   }
600
601   if (HasFlag(PES_PASSWORD)) {
602     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
603     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
604   }
605
606   if (HasFlag(PES_NOREAD)) {
607     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
608     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
609   }
610
611   pSH->AppendMenuItem(hPopup, 0, L"");
612   pSH->AppendMenuItem(
613       hPopup, WM_PWLEDIT_SELECTALL,
614       pProvider ? pProvider->LoadPopupMenuString(6) : L"&Select All");
615
616   if (m_pEdit->GetTotalWords() == 0) {
617     pSH->EnableMenuItem(hPopup, WM_PWLEDIT_SELECTALL, FALSE);
618   }
619
620   int32_t x, y;
621   PWLtoWnd(ptPopup, x, y);
622   pSH->ClientToScreen(GetAttachedHWnd(), x, y);
623   pSH->SetCursor(FXCT_ARROW);
624   int32_t nCmd = pSH->TrackPopupMenu(hPopup, x, y, GetAttachedHWnd());
625
626   switch (nCmd) {
627     case WM_PWLEDIT_UNDO:
628       Undo();
629       break;
630     case WM_PWLEDIT_REDO:
631       Redo();
632       break;
633     case WM_PWLEDIT_CUT:
634       CutText();
635       break;
636     case WM_PWLEDIT_COPY:
637       CopyText();
638       break;
639     case WM_PWLEDIT_PASTE:
640       PasteText();
641       break;
642     case WM_PWLEDIT_DELETE:
643       Clear();
644       break;
645     case WM_PWLEDIT_SELECTALL:
646       SelectAll();
647       break;
648     case WM_PWLEDIT_SUGGEST + 0:
649       SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
650              m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
651       ReplaceSel(sSuggestWords[0].UTF8Decode().c_str());
652       break;
653     case WM_PWLEDIT_SUGGEST + 1:
654       SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
655              m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
656       ReplaceSel(sSuggestWords[1].UTF8Decode().c_str());
657       break;
658     case WM_PWLEDIT_SUGGEST + 2:
659       SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
660              m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
661       ReplaceSel(sSuggestWords[2].UTF8Decode().c_str());
662       break;
663     case WM_PWLEDIT_SUGGEST + 3:
664       SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
665              m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
666       ReplaceSel(sSuggestWords[3].UTF8Decode().c_str());
667       break;
668     case WM_PWLEDIT_SUGGEST + 4:
669       SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
670              m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
671       ReplaceSel(sSuggestWords[4].UTF8Decode().c_str());
672       break;
673     default:
674       break;
675   }
676
677   pSH->DestroyMenu(hPopup);
678
679   return TRUE;
680 }
681
682 void CPWL_Edit::OnSetFocus() {
683   SetEditCaret(TRUE);
684
685   if (!IsReadOnly()) {
686     if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
687       pFocusHandler->OnSetFocus(this);
688   }
689
690   m_bFocus = TRUE;
691 }
692
693 void CPWL_Edit::OnKillFocus() {
694   ShowVScrollBar(FALSE);
695
696   m_pEdit->SelectNone();
697   SetCaret(FALSE, CPDF_Point(0.0f, 0.0f), CPDF_Point(0.0f, 0.0f));
698
699   SetCharSet(0);
700
701   if (!IsReadOnly()) {
702     if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
703       pFocusHandler->OnKillFocus(this);
704   }
705
706   m_bFocus = FALSE;
707 }
708
709 void CPWL_Edit::SetHorzScale(int32_t nHorzScale, FX_BOOL bPaint /* = TRUE*/) {
710   m_pEdit->SetHorzScale(nHorzScale, bPaint);
711 }
712
713 void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint /* = TRUE*/) {
714   m_pEdit->SetCharSpace(fCharSpace, bPaint);
715 }
716
717 void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading,
718                                FX_BOOL bPaint /* = TRUE*/) {
719   m_pEdit->SetLineLeading(fLineLeading, bPaint);
720 }
721
722 CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(
723     const CPDF_Point& ptOffset) const {
724   CPVT_WordRange wr = GetSelectWordRange();
725   return CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset, &wr);
726 }
727
728 CPVT_WordRange CPWL_Edit::GetSelectWordRange() const {
729   if (m_pEdit->IsSelected()) {
730     int32_t nStart = -1;
731     int32_t nEnd = -1;
732
733     m_pEdit->GetSel(nStart, nEnd);
734
735     CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
736     CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);
737
738     return CPVT_WordRange(wpStart, wpEnd);
739   }
740
741   return CPVT_WordRange();
742 }
743
744 CFX_ByteString CPWL_Edit::GetTextAppearanceStream(
745     const CPDF_Point& ptOffset) const {
746   CFX_ByteTextBuf sRet;
747   CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset);
748
749   if (sEdit.GetLength() > 0) {
750     sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit
751          << "ET\n";
752   }
753
754   return sRet.GetByteString();
755 }
756
757 CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(
758     const CPDF_Point& ptOffset) const {
759   if (m_pEditCaret)
760     return m_pEditCaret->GetCaretAppearanceStream(ptOffset);
761
762   return CFX_ByteString();
763 }
764
765 CPDF_Point CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) {
766   CPDF_Point pt(0.0f, 0.0f);
767
768   if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator()) {
769     CPVT_WordPlace wpOld = pIterator->GetAt();
770     pIterator->SetAt(wpWord);
771     CPVT_Word word;
772     if (pIterator->GetWord(word)) {
773       pt = CPDF_Point(word.ptWord.x + word.fWidth,
774                       word.ptWord.y + word.fDescent);
775     }
776
777     pIterator->SetAt(wpOld);
778   }
779
780   return pt;
781 }
782
783 FX_BOOL CPWL_Edit::IsTextFull() const {
784   return m_pEdit->IsTextFull();
785 }
786
787 FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont,
788                                              const CPDF_Rect& rcPlate,
789                                              int32_t nCharArray) {
790   if (pFont && !pFont->IsStandardFont()) {
791     FX_RECT rcBBox;
792     pFont->GetFontBBox(rcBBox);
793
794     CPDF_Rect rcCell = rcPlate;
795     FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
796     FX_FLOAT ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height();
797
798     return xdiv < ydiv ? xdiv : ydiv;
799   }
800
801   return 0.0f;
802 }
803
804 void CPWL_Edit::SetCharArray(int32_t nCharArray) {
805   if (HasFlag(PES_CHARARRAY) && nCharArray > 0) {
806     m_pEdit->SetCharArray(nCharArray);
807     m_pEdit->SetTextOverflow(TRUE);
808
809     if (HasFlag(PWS_AUTOFONTSIZE)) {
810       if (IFX_Edit_FontMap* pFontMap = GetFontMap()) {
811         FX_FLOAT fFontSize = GetCharArrayAutoFontSize(
812             pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);
813         if (fFontSize > 0.0f) {
814           m_pEdit->SetAutoFontSize(FALSE);
815           m_pEdit->SetFontSize(fFontSize);
816         }
817       }
818     }
819   }
820 }
821
822 void CPWL_Edit::SetLimitChar(int32_t nLimitChar) {
823   m_pEdit->SetLimitChar(nLimitChar);
824 }
825
826 void CPWL_Edit::ReplaceSel(const FX_WCHAR* csText) {
827   m_pEdit->Clear();
828   m_pEdit->InsertText(csText);
829 }
830
831 CPDF_Rect CPWL_Edit::GetFocusRect() const {
832   return CPDF_Rect();
833 }
834
835 void CPWL_Edit::ShowVScrollBar(FX_BOOL bShow) {
836   if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
837     if (bShow) {
838       if (!pScroll->IsVisible()) {
839         pScroll->SetVisible(TRUE);
840         CPDF_Rect rcWindow = GetWindowRect();
841         m_rcOldWindow = rcWindow;
842         rcWindow.right += PWL_SCROLLBAR_WIDTH;
843         Move(rcWindow, TRUE, TRUE);
844       }
845     } else {
846       if (pScroll->IsVisible()) {
847         pScroll->SetVisible(FALSE);
848         Move(m_rcOldWindow, TRUE, TRUE);
849       }
850     }
851   }
852 }
853
854 FX_BOOL CPWL_Edit::IsVScrollBarVisible() const {
855   if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
856     return pScroll->IsVisible();
857   }
858
859   return FALSE;
860 }
861
862 void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled) {
863   if (bEnabled)
864     AddFlag(PES_SPELLCHECK);
865   else
866     RemoveFlag(PES_SPELLCHECK);
867 }
868
869 FX_BOOL CPWL_Edit::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) {
870   if (m_bMouseDown)
871     return TRUE;
872
873   if (nChar == FWL_VKEY_Delete) {
874     if (m_pFillerNotify) {
875       FX_BOOL bRC = TRUE;
876       FX_BOOL bExit = FALSE;
877       CFX_WideString strChange;
878       CFX_WideString strChangeEx;
879
880       int nSelStart = 0;
881       int nSelEnd = 0;
882       GetSel(nSelStart, nSelEnd);
883
884       if (nSelStart == nSelEnd)
885         nSelEnd = nSelStart + 1;
886       m_pFillerNotify->OnBeforeKeyStroke(
887           TRUE, GetAttachedData(), FWL_VKEY_Delete, strChange, strChangeEx,
888           nSelStart, nSelEnd, TRUE, bRC, bExit, nFlag);
889       if (!bRC)
890         return FALSE;
891       if (bExit)
892         return FALSE;
893     }
894   }
895
896   FX_BOOL bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag);
897
898   if (nChar == FWL_VKEY_Delete) {
899     if (m_pFillerNotify) {
900       FX_BOOL bExit = FALSE;
901       m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit, nFlag);
902       if (bExit)
903         return FALSE;
904     }
905   }
906
907   // In case of implementation swallow the OnKeyDown event.
908   if (IsProceedtoOnChar(nChar, nFlag))
909     return TRUE;
910
911   return bRet;
912 }
913
914 /**
915 *In case of implementation swallow the OnKeyDown event.
916 *If the event is swallowed, implementation may do other unexpected things, which
917 *is not the control means to do.
918 */
919 FX_BOOL CPWL_Edit::IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag) {
920   FX_BOOL bCtrl = IsCTRLpressed(nFlag);
921   FX_BOOL bAlt = IsALTpressed(nFlag);
922   if (bCtrl && !bAlt) {
923     // hot keys for edit control.
924     switch (nKeyCode) {
925       case 'C':
926       case 'V':
927       case 'X':
928       case 'A':
929       case 'Z':
930         return TRUE;
931       default:
932         break;
933     }
934   }
935   // control characters.
936   switch (nKeyCode) {
937     case FWL_VKEY_Escape:
938     case FWL_VKEY_Back:
939     case FWL_VKEY_Return:
940     case FWL_VKEY_Space:
941       return TRUE;
942     default:
943       break;
944   }
945   return FALSE;
946 }
947
948 FX_BOOL CPWL_Edit::OnChar(FX_WORD nChar, FX_DWORD nFlag) {
949   if (m_bMouseDown)
950     return TRUE;
951
952   FX_BOOL bRC = TRUE;
953   FX_BOOL bExit = FALSE;
954
955   FX_BOOL bCtrl = IsCTRLpressed(nFlag);
956   if (!bCtrl) {
957     if (m_pFillerNotify) {
958       CFX_WideString swChange;
959       int32_t nKeyCode;
960
961       int nSelStart = 0;
962       int nSelEnd = 0;
963       GetSel(nSelStart, nSelEnd);
964
965       switch (nChar) {
966         case FWL_VKEY_Back:
967           nKeyCode = nChar;
968           if (nSelStart == nSelEnd)
969             nSelStart = nSelEnd - 1;
970           break;
971         case FWL_VKEY_Return:
972           nKeyCode = nChar;
973           break;
974         default:
975           nKeyCode = 0;
976           swChange += nChar;
977           break;
978       }
979
980       CFX_WideString strChangeEx;
981       m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), nKeyCode,
982                                          swChange, strChangeEx, nSelStart,
983                                          nSelEnd, TRUE, bRC, bExit, nFlag);
984     }
985   }
986
987   if (!bRC)
988     return TRUE;
989   if (bExit)
990     return FALSE;
991
992   if (IFX_Edit_FontMap* pFontMap = GetFontMap()) {
993     int32_t nOldCharSet = GetCharSet();
994     int32_t nNewCharSet = pFontMap->CharSetFromUnicode(nChar, DEFAULT_CHARSET);
995     if (nOldCharSet != nNewCharSet) {
996       SetCharSet(nNewCharSet);
997     }
998   }
999   FX_BOOL bRet = CPWL_EditCtrl::OnChar(nChar, nFlag);
1000
1001   if (!bCtrl) {
1002     if (m_pFillerNotify) {
1003       m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit, nFlag);
1004       if (bExit)
1005         return FALSE;
1006     }
1007   }
1008
1009   return bRet;
1010 }
1011
1012 FX_BOOL CPWL_Edit::OnMouseWheel(short zDelta,
1013                                 const CPDF_Point& point,
1014                                 FX_DWORD nFlag) {
1015   if (HasFlag(PES_MULTILINE)) {
1016     CPDF_Point ptScroll = GetScrollPos();
1017
1018     if (zDelta > 0) {
1019       ptScroll.y += GetFontSize();
1020     } else {
1021       ptScroll.y -= GetFontSize();
1022     }
1023     SetScrollPos(ptScroll);
1024
1025     return TRUE;
1026   }
1027
1028   return FALSE;
1029 }
1030
1031 void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place,
1032                                const CPVT_WordPlace& oldplace) {
1033   if (HasFlag(PES_SPELLCHECK)) {
1034     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1035                                                GetLatinWordsRange(place)));
1036   }
1037
1038   if (m_pEditNotify) {
1039     m_pEditNotify->OnInsertReturn(place, oldplace);
1040   }
1041 }
1042
1043 void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place,
1044                             const CPVT_WordPlace& oldplace) {
1045   if (HasFlag(PES_SPELLCHECK)) {
1046     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1047                                                GetLatinWordsRange(place)));
1048   }
1049
1050   if (m_pEditNotify) {
1051     m_pEditNotify->OnBackSpace(place, oldplace);
1052   }
1053 }
1054
1055 void CPWL_Edit::OnDelete(const CPVT_WordPlace& place,
1056                          const CPVT_WordPlace& oldplace) {
1057   if (HasFlag(PES_SPELLCHECK)) {
1058     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1059                                                GetLatinWordsRange(place)));
1060   }
1061
1062   if (m_pEditNotify) {
1063     m_pEditNotify->OnDelete(place, oldplace);
1064   }
1065 }
1066
1067 void CPWL_Edit::OnClear(const CPVT_WordPlace& place,
1068                         const CPVT_WordPlace& oldplace) {
1069   if (HasFlag(PES_SPELLCHECK)) {
1070     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1071                                                GetLatinWordsRange(place)));
1072   }
1073
1074   if (m_pEditNotify) {
1075     m_pEditNotify->OnClear(place, oldplace);
1076   }
1077 }
1078
1079 void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place,
1080                              const CPVT_WordPlace& oldplace) {
1081   if (HasFlag(PES_SPELLCHECK)) {
1082     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1083                                                GetLatinWordsRange(place)));
1084   }
1085
1086   if (m_pEditNotify) {
1087     m_pEditNotify->OnInsertWord(place, oldplace);
1088   }
1089 }
1090
1091 void CPWL_Edit::OnSetText(const CPVT_WordPlace& place,
1092                           const CPVT_WordPlace& oldplace) {}
1093
1094 void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place,
1095                              const CPVT_WordPlace& oldplace) {
1096   if (HasFlag(PES_SPELLCHECK)) {
1097     m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
1098                                                GetLatinWordsRange(place)));
1099   }
1100
1101   if (m_pEditNotify) {
1102     m_pEditNotify->OnInsertText(place, oldplace);
1103   }
1104 }
1105
1106 void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem) {
1107   if (m_pEditNotify) {
1108     m_pEditNotify->OnAddUndo(this);
1109   }
1110 }
1111
1112 CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1,
1113                                            const CPVT_WordRange& wr2) {
1114   CPVT_WordRange wrRet;
1115
1116   if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) {
1117     wrRet.BeginPos = wr1.BeginPos;
1118   } else {
1119     wrRet.BeginPos = wr2.BeginPos;
1120   }
1121
1122   if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) {
1123     wrRet.EndPos = wr2.EndPos;
1124   } else {
1125     wrRet.EndPos = wr1.EndPos;
1126   }
1127
1128   return wrRet;
1129 }
1130
1131 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const {
1132   return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);
1133 }
1134
1135 CPVT_WordRange CPWL_Edit::GetLatinWordsRange(
1136     const CPVT_WordPlace& place) const {
1137   return GetSameWordsRange(place, TRUE, FALSE);
1138 }
1139
1140 CPVT_WordRange CPWL_Edit::GetArabicWordsRange(
1141     const CPVT_WordPlace& place) const {
1142   return GetSameWordsRange(place, FALSE, TRUE);
1143 }
1144
1145 #define PWL_ISARABICWORD(word) \
1146   ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
1147
1148 CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place,
1149                                             FX_BOOL bLatin,
1150                                             FX_BOOL bArabic) const {
1151   CPVT_WordRange range;
1152
1153   if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator()) {
1154     CPVT_Word wordinfo;
1155     CPVT_WordPlace wpStart(place), wpEnd(place);
1156     pIterator->SetAt(place);
1157
1158     if (bLatin) {
1159       while (pIterator->NextWord()) {
1160         if (pIterator->GetWord(wordinfo) &&
1161             FX_EDIT_ISLATINWORD(wordinfo.Word)) {
1162           wpEnd = pIterator->GetAt();
1163           continue;
1164         } else
1165           break;
1166       };
1167     } else if (bArabic) {
1168       while (pIterator->NextWord()) {
1169         if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word)) {
1170           wpEnd = pIterator->GetAt();
1171           continue;
1172         } else
1173           break;
1174       };
1175     }
1176
1177     pIterator->SetAt(place);
1178
1179     if (bLatin) {
1180       do {
1181         if (pIterator->GetWord(wordinfo) &&
1182             FX_EDIT_ISLATINWORD(wordinfo.Word)) {
1183           continue;
1184         } else {
1185           wpStart = pIterator->GetAt();
1186           break;
1187         }
1188       } while (pIterator->PrevWord());
1189     } else if (bArabic) {
1190       do {
1191         if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word)) {
1192           continue;
1193         } else {
1194           wpStart = pIterator->GetAt();
1195           break;
1196         }
1197       } while (pIterator->PrevWord());
1198     }
1199
1200     range.Set(wpStart, wpEnd);
1201   }
1202
1203   return range;
1204 }
1205
1206 void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr) {}
1207
1208 void CPWL_Edit::GeneratePageObjects(
1209     CPDF_PageObjects* pPageObjects,
1210     const CPDF_Point& ptOffset,
1211     CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) {
1212   IFX_Edit::GeneratePageObjects(
1213       pPageObjects, m_pEdit, ptOffset, NULL,
1214       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
1215       ObjArray);
1216 }
1217
1218 void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
1219                                     const CPDF_Point& ptOffset) {
1220   CFX_ArrayTemplate<CPDF_TextObject*> ObjArray;
1221   IFX_Edit::GeneratePageObjects(
1222       pPageObjects, m_pEdit, ptOffset, NULL,
1223       CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
1224       ObjArray);
1225 }