• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fpdfsdk/formfiller/cffl_textfield.h"
8 
9 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
10 #include "fpdfsdk/cpdfsdk_widget.h"
11 #include "fpdfsdk/formfiller/cba_fontmap.h"
12 #include "fpdfsdk/fsdk_common.h"
13 #include "third_party/base/ptr_util.h"
14 
CFFL_TextField(CPDFSDK_FormFillEnvironment * pApp,CPDFSDK_Annot * pAnnot)15 CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp,
16                                CPDFSDK_Annot* pAnnot)
17     : CFFL_FormFiller(pApp, pAnnot) {}
18 
~CFFL_TextField()19 CFFL_TextField::~CFFL_TextField() {
20   for (const auto& it : m_Maps)
21     it.second->InvalidateFocusHandler(this);
22 
23   // See comment in cffl_formfiller.h.
24   // The font map should be stored somewhere more appropriate so it will live
25   // until the PWL_Edit is done with it. pdfium:566
26   DestroyWindows();
27 }
28 
GetCreateParam()29 PWL_CREATEPARAM CFFL_TextField::GetCreateParam() {
30   PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
31 
32   int nFlags = m_pWidget->GetFieldFlags();
33 
34   if (nFlags & FIELDFLAG_PASSWORD) {
35     cp.dwFlags |= PES_PASSWORD;
36   }
37 
38   if (nFlags & FIELDFLAG_MULTILINE) {
39     cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;
40 
41     if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
42       cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
43     }
44   } else {
45     cp.dwFlags |= PES_CENTER;
46 
47     if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
48       cp.dwFlags |= PES_AUTOSCROLL;
49     }
50   }
51 
52   if (nFlags & FIELDFLAG_COMB) {
53     cp.dwFlags |= PES_CHARARRAY;
54   }
55 
56   if (nFlags & FIELDFLAG_RICHTEXT) {
57     cp.dwFlags |= PES_RICH;
58   }
59 
60   cp.dwFlags |= PES_UNDO;
61 
62   switch (m_pWidget->GetAlignment()) {
63     default:
64     case BF_ALIGN_LEFT:
65       cp.dwFlags |= PES_LEFT;
66       break;
67     case BF_ALIGN_MIDDLE:
68       cp.dwFlags |= PES_MIDDLE;
69       break;
70     case BF_ALIGN_RIGHT:
71       cp.dwFlags |= PES_RIGHT;
72       break;
73   }
74 
75   if (!m_pFontMap) {
76     m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
77         m_pWidget, m_pFormFillEnv->GetSysHandler());
78   }
79   cp.pFontMap = m_pFontMap.get();
80   cp.pFocusHandler = this;
81 
82   return cp;
83 }
84 
NewPDFWindow(const PWL_CREATEPARAM & cp,CPDFSDK_PageView * pPageView)85 CPWL_Wnd* CFFL_TextField::NewPDFWindow(const PWL_CREATEPARAM& cp,
86                                        CPDFSDK_PageView* pPageView) {
87   CPWL_Edit* pWnd = new CPWL_Edit();
88   pWnd->AttachFFLData(this);
89   pWnd->Create(cp);
90   pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
91 
92   int32_t nMaxLen = m_pWidget->GetMaxLen();
93   CFX_WideString swValue = m_pWidget->GetValue();
94 
95   if (nMaxLen > 0) {
96     if (pWnd->HasFlag(PES_CHARARRAY)) {
97       pWnd->SetCharArray(nMaxLen);
98       pWnd->SetAlignFormatV(PEAV_CENTER);
99     } else {
100       pWnd->SetLimitChar(nMaxLen);
101     }
102   }
103 
104   pWnd->SetText(swValue);
105   return pWnd;
106 }
107 
OnChar(CPDFSDK_Annot * pAnnot,uint32_t nChar,uint32_t nFlags)108 bool CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot,
109                             uint32_t nChar,
110                             uint32_t nFlags) {
111   switch (nChar) {
112     case FWL_VKEY_Return:
113       if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)) {
114         CPDFSDK_PageView* pPageView = GetCurPageView(true);
115         ASSERT(pPageView);
116         m_bValid = !m_bValid;
117         m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
118                                    pAnnot->GetRect().ToFxRect());
119 
120         if (m_bValid) {
121           if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
122             pWnd->SetFocus();
123         } else {
124           if (CommitData(pPageView, nFlags)) {
125             DestroyPDFWindow(pPageView);
126             return true;
127           }
128           return false;
129         }
130       }
131       break;
132     case FWL_VKEY_Escape: {
133       CPDFSDK_PageView* pPageView = GetCurPageView(true);
134       ASSERT(pPageView);
135       EscapeFiller(pPageView, true);
136       return true;
137     }
138   }
139 
140   return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
141 }
142 
IsDataChanged(CPDFSDK_PageView * pPageView)143 bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
144   if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false))
145     return pEdit->GetText() != m_pWidget->GetValue();
146 
147   return false;
148 }
149 
SaveData(CPDFSDK_PageView * pPageView)150 void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) {
151   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
152     CFX_WideString sOldValue = m_pWidget->GetValue();
153     CFX_WideString sNewValue = pWnd->GetText();
154 
155     m_pWidget->SetValue(sNewValue, false);
156     m_pWidget->ResetFieldAppearance(true);
157     m_pWidget->UpdateField();
158     SetChangeMark();
159   }
160 }
161 
GetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,PDFSDK_FieldAction & fa)162 void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView,
163                                    CPDF_AAction::AActionType type,
164                                    PDFSDK_FieldAction& fa) {
165   switch (type) {
166     case CPDF_AAction::KeyStroke:
167       if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
168         fa.bFieldFull = pWnd->IsTextFull();
169 
170         fa.sValue = pWnd->GetText();
171 
172         if (fa.bFieldFull) {
173           fa.sChange = L"";
174           fa.sChangeEx = L"";
175         }
176       }
177       break;
178     case CPDF_AAction::Validate:
179       if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
180         fa.sValue = pWnd->GetText();
181       }
182       break;
183     case CPDF_AAction::LoseFocus:
184     case CPDF_AAction::GetFocus:
185       fa.sValue = m_pWidget->GetValue();
186       break;
187     default:
188       break;
189   }
190 }
191 
SetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,const PDFSDK_FieldAction & fa)192 void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView,
193                                    CPDF_AAction::AActionType type,
194                                    const PDFSDK_FieldAction& fa) {
195   switch (type) {
196     case CPDF_AAction::KeyStroke:
197       if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
198         pEdit->SetFocus();
199         pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
200         pEdit->ReplaceSel(fa.sChange);
201       }
202       break;
203     default:
204       break;
205   }
206 }
207 
IsActionDataChanged(CPDF_AAction::AActionType type,const PDFSDK_FieldAction & faOld,const PDFSDK_FieldAction & faNew)208 bool CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type,
209                                          const PDFSDK_FieldAction& faOld,
210                                          const PDFSDK_FieldAction& faNew) {
211   switch (type) {
212     case CPDF_AAction::KeyStroke:
213       return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
214              faOld.nSelStart != faNew.nSelStart ||
215              faOld.sChange != faNew.sChange;
216     default:
217       break;
218   }
219 
220   return false;
221 }
222 
SaveState(CPDFSDK_PageView * pPageView)223 void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) {
224   ASSERT(pPageView);
225 
226   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
227     pWnd->GetSel(m_State.nStart, m_State.nEnd);
228     m_State.sValue = pWnd->GetText();
229   }
230 }
231 
RestoreState(CPDFSDK_PageView * pPageView)232 void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) {
233   ASSERT(pPageView);
234 
235   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, true)) {
236     pWnd->SetText(m_State.sValue);
237     pWnd->SetSel(m_State.nStart, m_State.nEnd);
238   }
239 }
240 
ResetPDFWindow(CPDFSDK_PageView * pPageView,bool bRestoreValue)241 CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView,
242                                          bool bRestoreValue) {
243   if (bRestoreValue)
244     SaveState(pPageView);
245 
246   DestroyPDFWindow(pPageView);
247 
248   CPWL_Wnd* pRet = nullptr;
249 
250   if (bRestoreValue) {
251     RestoreState(pPageView);
252     pRet = GetPDFWindow(pPageView, false);
253   } else {
254     pRet = GetPDFWindow(pPageView, true);
255   }
256 
257   m_pWidget->UpdateField();
258 
259   return pRet;
260 }
261 
262 #ifdef PDF_ENABLE_XFA
IsFieldFull(CPDFSDK_PageView * pPageView)263 bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
264   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
265     return pWnd->IsTextFull();
266   }
267 
268   return false;
269 }
270 #endif  // PDF_ENABLE_XFA
271 
OnSetFocus(CPWL_Wnd * pWnd)272 void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd) {
273   ASSERT(m_pFormFillEnv);
274   if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
275     CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
276     pEdit->SetCharSet(FXFONT_GB2312_CHARSET);
277     pEdit->SetCodePage(936);
278 
279     pEdit->SetReadyToInput();
280     CFX_WideString wsText = pEdit->GetText();
281     int nCharacters = wsText.GetLength();
282     CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
283     unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
284     m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
285   }
286 }
287