• 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_Widget * pWidget)15 CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp,
16                                CPDFSDK_Widget* pWidget)
17     : CFFL_TextObject(pApp, pWidget) {}
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 CPWL_Wnd::CreateParams CFFL_TextField::GetCreateParam() {
30   CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
31   int nFlags = m_pWidget->GetFieldFlags();
32   if (nFlags & FIELDFLAG_PASSWORD)
33     cp.dwFlags |= PES_PASSWORD;
34 
35   if (nFlags & FIELDFLAG_MULTILINE) {
36     cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;
37     if (!(nFlags & FIELDFLAG_DONOTSCROLL))
38       cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
39   } else {
40     cp.dwFlags |= PES_CENTER;
41     if (!(nFlags & FIELDFLAG_DONOTSCROLL))
42       cp.dwFlags |= PES_AUTOSCROLL;
43   }
44 
45   if (nFlags & FIELDFLAG_COMB)
46     cp.dwFlags |= PES_CHARARRAY;
47 
48   if (nFlags & FIELDFLAG_RICHTEXT)
49     cp.dwFlags |= PES_RICH;
50 
51   cp.dwFlags |= PES_UNDO;
52 
53   switch (m_pWidget->GetAlignment()) {
54     default:
55     case BF_ALIGN_LEFT:
56       cp.dwFlags |= PES_LEFT;
57       break;
58     case BF_ALIGN_MIDDLE:
59       cp.dwFlags |= PES_MIDDLE;
60       break;
61     case BF_ALIGN_RIGHT:
62       cp.dwFlags |= PES_RIGHT;
63       break;
64   }
65   cp.pFontMap = MaybeCreateFontMap();
66   cp.pFocusHandler = this;
67   return cp;
68 }
69 
NewPDFWindow(const CPWL_Wnd::CreateParams & cp)70 CPWL_Wnd* CFFL_TextField::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
71   auto* pWnd = new CPWL_Edit();
72   pWnd->AttachFFLData(this);
73   pWnd->Create(cp);
74   pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
75 
76   int32_t nMaxLen = m_pWidget->GetMaxLen();
77   WideString swValue = m_pWidget->GetValue();
78 
79   if (nMaxLen > 0) {
80     if (pWnd->HasFlag(PES_CHARARRAY)) {
81       pWnd->SetCharArray(nMaxLen);
82       pWnd->SetAlignFormatV(PEAV_CENTER);
83     } else {
84       pWnd->SetLimitChar(nMaxLen);
85     }
86   }
87 
88   pWnd->SetText(swValue);
89   return pWnd;
90 }
91 
OnChar(CPDFSDK_Annot * pAnnot,uint32_t nChar,uint32_t nFlags)92 bool CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot,
93                             uint32_t nChar,
94                             uint32_t nFlags) {
95   switch (nChar) {
96     case FWL_VKEY_Return: {
97       if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)
98         break;
99 
100       CPDFSDK_PageView* pPageView = GetCurPageView(true);
101       ASSERT(pPageView);
102       m_bValid = !m_bValid;
103       m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
104                                  pAnnot->GetRect().GetOuterRect());
105 
106       if (m_bValid) {
107         if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
108           pWnd->SetFocus();
109         break;
110       }
111 
112       if (!CommitData(pPageView, nFlags))
113         return false;
114 
115       DestroyPDFWindow(pPageView);
116       return true;
117     }
118     case FWL_VKEY_Escape: {
119       CPDFSDK_PageView* pPageView = GetCurPageView(true);
120       ASSERT(pPageView);
121       EscapeFiller(pPageView, true);
122       return true;
123     }
124   }
125 
126   return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
127 }
128 
IsDataChanged(CPDFSDK_PageView * pPageView)129 bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
130   CPWL_Edit* pEdit = GetEdit(pPageView, false);
131   return pEdit && pEdit->GetText() != m_pWidget->GetValue();
132 }
133 
SaveData(CPDFSDK_PageView * pPageView)134 void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) {
135   CPWL_Edit* pWnd = GetEdit(pPageView, false);
136   if (!pWnd)
137     return;
138 
139   WideString sOldValue = m_pWidget->GetValue();
140   WideString sNewValue = pWnd->GetText();
141 
142   CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
143   CFFL_TextField::ObservedPtr observed_this(this);
144 
145   m_pWidget->SetValue(sNewValue, false);
146   if (!observed_widget)
147     return;
148   m_pWidget->ResetFieldAppearance(true);
149   if (!observed_widget)
150     return;
151   m_pWidget->UpdateField();
152   if (!observed_widget || !observed_this)
153     return;
154   SetChangeMark();
155 }
156 
GetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,PDFSDK_FieldAction & fa)157 void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView,
158                                    CPDF_AAction::AActionType type,
159                                    PDFSDK_FieldAction& fa) {
160   switch (type) {
161     case CPDF_AAction::KeyStroke:
162       if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
163         fa.bFieldFull = pWnd->IsTextFull();
164 
165         fa.sValue = pWnd->GetText();
166 
167         if (fa.bFieldFull) {
168           fa.sChange = L"";
169           fa.sChangeEx = L"";
170         }
171       }
172       break;
173     case CPDF_AAction::Validate:
174       if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
175         fa.sValue = pWnd->GetText();
176       }
177       break;
178     case CPDF_AAction::LoseFocus:
179     case CPDF_AAction::GetFocus:
180       fa.sValue = m_pWidget->GetValue();
181       break;
182     default:
183       break;
184   }
185 }
186 
SetActionData(CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,const PDFSDK_FieldAction & fa)187 void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView,
188                                    CPDF_AAction::AActionType type,
189                                    const PDFSDK_FieldAction& fa) {
190   switch (type) {
191     case CPDF_AAction::KeyStroke:
192       if (CPWL_Edit* pEdit = GetEdit(pPageView, false)) {
193         pEdit->SetFocus();
194         pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
195         pEdit->ReplaceSel(fa.sChange);
196       }
197       break;
198     default:
199       break;
200   }
201 }
202 
IsActionDataChanged(CPDF_AAction::AActionType type,const PDFSDK_FieldAction & faOld,const PDFSDK_FieldAction & faNew)203 bool CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type,
204                                          const PDFSDK_FieldAction& faOld,
205                                          const PDFSDK_FieldAction& faNew) {
206   switch (type) {
207     case CPDF_AAction::KeyStroke:
208       return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
209              faOld.nSelStart != faNew.nSelStart ||
210              faOld.sChange != faNew.sChange;
211     default:
212       break;
213   }
214 
215   return false;
216 }
217 
SaveState(CPDFSDK_PageView * pPageView)218 void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) {
219   ASSERT(pPageView);
220 
221   CPWL_Edit* pWnd = GetEdit(pPageView, false);
222   if (!pWnd)
223     return;
224 
225   pWnd->GetSelection(m_State.nStart, m_State.nEnd);
226   m_State.sValue = pWnd->GetText();
227 }
228 
RestoreState(CPDFSDK_PageView * pPageView)229 void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) {
230   ASSERT(pPageView);
231 
232   CPWL_Edit* pWnd = GetEdit(pPageView, true);
233   if (!pWnd)
234     return;
235 
236   pWnd->SetText(m_State.sValue);
237   pWnd->SetSelection(m_State.nStart, m_State.nEnd);
238 }
239 
240 #ifdef PDF_ENABLE_XFA
IsFieldFull(CPDFSDK_PageView * pPageView)241 bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
242   CPWL_Edit* pWnd = GetEdit(pPageView, false);
243   return pWnd && pWnd->IsTextFull();
244 }
245 #endif  // PDF_ENABLE_XFA
246 
OnSetFocus(CPWL_Edit * pEdit)247 void CFFL_TextField::OnSetFocus(CPWL_Edit* pEdit) {
248   pEdit->SetCharSet(FX_CHARSET_ChineseSimplified);
249   pEdit->SetReadyToInput();
250 
251   WideString wsText = pEdit->GetText();
252   int nCharacters = wsText.GetLength();
253   ByteString bsUTFText = wsText.UTF16LE_Encode();
254   auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
255   m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
256 }
257 
GetEdit(CPDFSDK_PageView * pPageView,bool bNew)258 CPWL_Edit* CFFL_TextField::GetEdit(CPDFSDK_PageView* pPageView, bool bNew) {
259   return static_cast<CPWL_Edit*>(GetPDFWindow(pPageView, bNew));
260 }
261