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