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/include/formfiller/FFL_TextField.h"
8 
9 #include "fpdfsdk/include/formfiller/FFL_CBA_Fontmap.h"
10 #include "fpdfsdk/include/fsdk_common.h"
11 #include "fpdfsdk/include/fsdk_mgr.h"
12 
CFFL_TextField(CPDFDoc_Environment * pApp,CPDFSDK_Annot * pAnnot)13 CFFL_TextField::CFFL_TextField(CPDFDoc_Environment* pApp, CPDFSDK_Annot* pAnnot)
14     : CFFL_FormFiller(pApp, pAnnot), m_pFontMap(NULL) {
15   m_State.nStart = m_State.nEnd = 0;
16 }
17 
~CFFL_TextField()18 CFFL_TextField::~CFFL_TextField() {
19   for (const auto& it : m_Maps)
20     it.second->InvalidateFocusHandler(this);
21   delete m_pFontMap;
22 }
23 
GetCreateParam()24 PWL_CREATEPARAM CFFL_TextField::GetCreateParam() {
25   PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
26 
27   int nFlags = m_pWidget->GetFieldFlags();
28 
29   if (nFlags & FIELDFLAG_PASSWORD) {
30     cp.dwFlags |= PES_PASSWORD;
31   }
32 
33   if (!(nFlags & FIELDFLAG_DONOTSPELLCHECK)) {
34   }
35 
36   if (nFlags & FIELDFLAG_MULTILINE) {
37     cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;
38 
39     if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
40       cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
41     }
42   } else {
43     cp.dwFlags |= PES_CENTER;
44 
45     if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
46       cp.dwFlags |= PES_AUTOSCROLL;
47     }
48   }
49 
50   if (nFlags & FIELDFLAG_COMB) {
51     cp.dwFlags |= PES_CHARARRAY;
52   }
53 
54   if (nFlags & FIELDFLAG_RICHTEXT) {
55     cp.dwFlags |= PES_RICH;
56   }
57 
58   cp.dwFlags |= PES_UNDO;
59 
60   switch (m_pWidget->GetAlignment()) {
61     default:
62     case BF_ALIGN_LEFT:
63       cp.dwFlags |= PES_LEFT;
64       break;
65     case BF_ALIGN_MIDDLE:
66       cp.dwFlags |= PES_MIDDLE;
67       break;
68     case BF_ALIGN_RIGHT:
69       cp.dwFlags |= PES_RIGHT;
70       break;
71   }
72 
73   if (!m_pFontMap)
74     m_pFontMap = new CBA_FontMap(m_pWidget, m_pApp->GetSysHandler());
75   cp.pFontMap = m_pFontMap;
76   cp.pFocusHandler = this;
77 
78   return cp;
79 }
80 
NewPDFWindow(const PWL_CREATEPARAM & cp,CPDFSDK_PageView * pPageView)81 CPWL_Wnd* CFFL_TextField::NewPDFWindow(const PWL_CREATEPARAM& cp,
82                                        CPDFSDK_PageView* pPageView) {
83   CPWL_Edit* pWnd = new CPWL_Edit();
84   pWnd->AttachFFLData(this);
85   pWnd->Create(cp);
86 
87   CFFL_IFormFiller* pIFormFiller = m_pApp->GetIFormFiller();
88   pWnd->SetFillerNotify(pIFormFiller);
89 
90   int32_t nMaxLen = m_pWidget->GetMaxLen();
91   CFX_WideString swValue = m_pWidget->GetValue();
92 
93   if (nMaxLen > 0) {
94     if (pWnd->HasFlag(PES_CHARARRAY)) {
95       pWnd->SetCharArray(nMaxLen);
96       pWnd->SetAlignFormatV(PEAV_CENTER);
97     } else {
98       pWnd->SetLimitChar(nMaxLen);
99     }
100   }
101 
102   pWnd->SetText(swValue.c_str());
103   return pWnd;
104 }
105 
OnChar(CPDFSDK_Annot * pAnnot,FX_UINT nChar,FX_UINT nFlags)106 FX_BOOL CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot,
107                                FX_UINT nChar,
108                                FX_UINT nFlags) {
109   switch (nChar) {
110     case FWL_VKEY_Return:
111       if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)) {
112         CPDFSDK_PageView* pPageView = GetCurPageView();
113         ASSERT(pPageView);
114         m_bValid = !m_bValid;
115         CPDF_Rect rcAnnot = pAnnot->GetRect();
116         m_pApp->FFI_Invalidate(pAnnot->GetUnderlyingPage(), rcAnnot.left,
117                                rcAnnot.top, rcAnnot.right, rcAnnot.bottom);
118 
119         if (m_bValid) {
120           if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, TRUE))
121             pWnd->SetFocus();
122         } else {
123           if (CommitData(pPageView, nFlags)) {
124             DestroyPDFWindow(pPageView);
125             return TRUE;
126           }
127           return FALSE;
128         }
129       }
130       break;
131     case FWL_VKEY_Escape: {
132       CPDFSDK_PageView* pPageView = GetCurPageView();
133       ASSERT(pPageView);
134       EscapeFiller(pPageView, TRUE);
135       return TRUE;
136     }
137   }
138 
139   return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
140 }
141 
IsDataChanged(CPDFSDK_PageView * pPageView)142 FX_BOOL CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
143   if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
144     return pEdit->GetText() != m_pWidget->GetValue();
145 
146   return FALSE;
147 }
148 
SaveData(CPDFSDK_PageView * pPageView)149 void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) {
150   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
151     CFX_WideString sOldValue = m_pWidget->GetValue();
152     CFX_WideString sNewValue = pWnd->GetText();
153 
154     m_pWidget->SetValue(sNewValue, FALSE);
155     m_pWidget->ResetFieldAppearance(TRUE);
156     m_pWidget->UpdateField();
157     SetChangeMark();
158   }
159 }
160 
GetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,PDFSDK_FieldAction & fa)161 void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView,
162                                    CPDF_AAction::AActionType type,
163                                    PDFSDK_FieldAction& fa) {
164   switch (type) {
165     case CPDF_AAction::KeyStroke:
166       if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
167         fa.bFieldFull = pWnd->IsTextFull();
168 
169         fa.sValue = pWnd->GetText();
170 
171         if (fa.bFieldFull) {
172           fa.sChange = L"";
173           fa.sChangeEx = L"";
174         }
175       }
176       break;
177     case CPDF_AAction::Validate:
178       if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
179         fa.sValue = pWnd->GetText();
180       }
181       break;
182     case CPDF_AAction::LoseFocus:
183     case CPDF_AAction::GetFocus:
184       fa.sValue = m_pWidget->GetValue();
185       break;
186     default:
187       break;
188   }
189 }
190 
SetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,const PDFSDK_FieldAction & fa)191 void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView,
192                                    CPDF_AAction::AActionType type,
193                                    const PDFSDK_FieldAction& fa) {
194   switch (type) {
195     case CPDF_AAction::KeyStroke:
196       if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
197         pEdit->SetFocus();
198         pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
199         pEdit->ReplaceSel(fa.sChange.c_str());
200       }
201       break;
202     default:
203       break;
204   }
205 }
206 
IsActionDataChanged(CPDF_AAction::AActionType type,const PDFSDK_FieldAction & faOld,const PDFSDK_FieldAction & faNew)207 FX_BOOL CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type,
208                                             const PDFSDK_FieldAction& faOld,
209                                             const PDFSDK_FieldAction& faNew) {
210   switch (type) {
211     case CPDF_AAction::KeyStroke:
212       return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
213              faOld.nSelStart != faNew.nSelStart ||
214              faOld.sChange != faNew.sChange;
215     default:
216       break;
217   }
218 
219   return FALSE;
220 }
221 
SaveState(CPDFSDK_PageView * pPageView)222 void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) {
223   ASSERT(pPageView);
224 
225   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
226     pWnd->GetSel(m_State.nStart, m_State.nEnd);
227     m_State.sValue = pWnd->GetText();
228   }
229 }
230 
RestoreState(CPDFSDK_PageView * pPageView)231 void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) {
232   ASSERT(pPageView);
233 
234   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, TRUE)) {
235     pWnd->SetText(m_State.sValue.c_str());
236     pWnd->SetSel(m_State.nStart, m_State.nEnd);
237   }
238 }
239 
ResetPDFWindow(CPDFSDK_PageView * pPageView,FX_BOOL bRestoreValue)240 CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView,
241                                          FX_BOOL bRestoreValue) {
242   if (bRestoreValue)
243     SaveState(pPageView);
244 
245   DestroyPDFWindow(pPageView);
246 
247   CPWL_Wnd* pRet = NULL;
248 
249   if (bRestoreValue) {
250     RestoreState(pPageView);
251     pRet = GetPDFWindow(pPageView, FALSE);
252   } else {
253     pRet = GetPDFWindow(pPageView, TRUE);
254   }
255 
256   m_pWidget->UpdateField();
257 
258   return pRet;
259 }
260 
261 #ifdef PDF_ENABLE_XFA
IsFieldFull(CPDFSDK_PageView * pPageView)262 FX_BOOL CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
263   if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE)) {
264     return pWnd->IsTextFull();
265   }
266 
267   return FALSE;
268 }
269 #endif  // PDF_ENABLE_XFA
270 
OnSetFocus(CPWL_Wnd * pWnd)271 void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd) {
272   ASSERT(m_pApp);
273   if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
274     CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
275     pEdit->SetCharSet(134);
276     pEdit->SetCodePage(936);
277 
278     pEdit->SetReadyToInput();
279     CFX_WideString wsText = pEdit->GetText();
280     int nCharacters = wsText.GetLength();
281     CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
282     unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
283     m_pApp->FFI_OnSetFieldInputFocus(m_pWidget->GetFormField(), pBuffer,
284                                      nCharacters, TRUE);
285 
286     pEdit->SetEditNotify(this);
287   }
288 }
289 
OnKillFocus(CPWL_Wnd * pWnd)290 void CFFL_TextField::OnKillFocus(CPWL_Wnd* pWnd) {}
291 
OnAddUndo(CPWL_Edit * pEdit)292 void CFFL_TextField::OnAddUndo(CPWL_Edit* pEdit) {}
293