• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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_combobox.h"
8 
9 #include <utility>
10 
11 #include "constants/form_flags.h"
12 #include "core/fpdfdoc/cpdf_bafontmap.h"
13 #include "fpdfsdk/cpdfsdk_widget.h"
14 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
15 #include "fpdfsdk/formfiller/cffl_perwindowdata.h"
16 #include "fpdfsdk/pwl/cpwl_combo_box.h"
17 #include "fpdfsdk/pwl/cpwl_edit.h"
18 
CFFL_ComboBox(CFFL_InteractiveFormFiller * pFormFiller,CPDFSDK_Widget * pWidget)19 CFFL_ComboBox::CFFL_ComboBox(CFFL_InteractiveFormFiller* pFormFiller,
20                              CPDFSDK_Widget* pWidget)
21     : CFFL_TextObject(pFormFiller, pWidget) {}
22 
~CFFL_ComboBox()23 CFFL_ComboBox::~CFFL_ComboBox() {
24   // See comment in cffl_formfiller.h.
25   // The font map should be stored somewhere more appropriate so it will live
26   // until the PWL_Edit is done with it. pdfium:566
27   DestroyWindows();
28 }
29 
GetCreateParam()30 CPWL_Wnd::CreateParams CFFL_ComboBox::GetCreateParam() {
31   CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
32   if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit)
33     cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
34 
35   cp.pFontMap = GetOrCreateFontMap();
36   return cp;
37 }
38 
NewPWLWindow(const CPWL_Wnd::CreateParams & cp,std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)39 std::unique_ptr<CPWL_Wnd> CFFL_ComboBox::NewPWLWindow(
40     const CPWL_Wnd::CreateParams& cp,
41     std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData) {
42   static_cast<CFFL_PerWindowData*>(pAttachedData.get())->SetFormField(this);
43   auto pWnd = std::make_unique<CPWL_ComboBox>(cp, std::move(pAttachedData));
44   pWnd->Realize();
45 
46   int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
47   WideString swText;
48   if (nCurSel < 0)
49     swText = m_pWidget->GetValue();
50   else
51     swText = m_pWidget->GetOptionLabel(nCurSel);
52 
53   for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++)
54     pWnd->AddString(m_pWidget->GetOptionLabel(i));
55 
56   pWnd->SetSelect(nCurSel);
57   pWnd->SetText(swText);
58   return std::move(pWnd);
59 }
60 
OnChar(CPDFSDK_Widget * pWidget,uint32_t nChar,Mask<FWL_EVENTFLAG> nFlags)61 bool CFFL_ComboBox::OnChar(CPDFSDK_Widget* pWidget,
62                            uint32_t nChar,
63                            Mask<FWL_EVENTFLAG> nFlags) {
64   return CFFL_TextObject::OnChar(pWidget, nChar, nFlags);
65 }
66 
IsDataChanged(const CPDFSDK_PageView * pPageView)67 bool CFFL_ComboBox::IsDataChanged(const CPDFSDK_PageView* pPageView) {
68   auto* pWnd = GetPWLComboBox(pPageView);
69   if (!pWnd)
70     return false;
71 
72   int32_t nCurSel = pWnd->GetSelect();
73   if (!(m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit))
74     return nCurSel != m_pWidget->GetSelectedIndex(0);
75 
76   if (nCurSel >= 0)
77     return nCurSel != m_pWidget->GetSelectedIndex(0);
78 
79   return pWnd->GetText() != m_pWidget->GetValue();
80 }
81 
SaveData(const CPDFSDK_PageView * pPageView)82 void CFFL_ComboBox::SaveData(const CPDFSDK_PageView* pPageView) {
83   CPWL_ComboBox* pWnd = GetPWLComboBox(pPageView);
84   if (!pWnd)
85     return;
86 
87   WideString swText = pWnd->GetText();
88   int32_t nCurSel = pWnd->GetSelect();
89   bool bSetValue = false;
90   if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit)
91     bSetValue = (nCurSel < 0) || (swText != m_pWidget->GetOptionLabel(nCurSel));
92 
93   if (bSetValue) {
94     m_pWidget->SetValue(swText);
95   } else {
96     m_pWidget->GetSelectedIndex(0);
97     m_pWidget->SetOptionSelection(nCurSel);
98   }
99   ObservedPtr<CPDFSDK_Widget> observed_widget(m_pWidget);
100   ObservedPtr<CFFL_ComboBox> observed_this(this);
101   m_pWidget->ResetFieldAppearance();
102   if (!observed_widget)
103     return;
104 
105   m_pWidget->UpdateField();
106   if (!observed_widget || !observed_this)
107     return;
108 
109   SetChangeMark();
110 }
111 
GetActionData(const CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,CFFL_FieldAction & fa)112 void CFFL_ComboBox::GetActionData(const CPDFSDK_PageView* pPageView,
113                                   CPDF_AAction::AActionType type,
114                                   CFFL_FieldAction& fa) {
115   switch (type) {
116     case CPDF_AAction::kKeyStroke:
117       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
118         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
119           fa.bFieldFull = pEdit->IsTextFull();
120           std::tie(fa.nSelStart, fa.nSelEnd) = pEdit->GetSelection();
121           fa.sValue = pEdit->GetText();
122           fa.sChangeEx = GetSelectExportText();
123 
124           if (fa.bFieldFull) {
125             fa.sChange.clear();
126             fa.sChangeEx.clear();
127           }
128         }
129       }
130       break;
131     case CPDF_AAction::kValidate:
132       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
133         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
134           fa.sValue = pEdit->GetText();
135         }
136       }
137       break;
138     case CPDF_AAction::kLoseFocus:
139     case CPDF_AAction::kGetFocus:
140       fa.sValue = m_pWidget->GetValue();
141       break;
142     default:
143       break;
144   }
145 }
146 
SetActionData(const CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,const CFFL_FieldAction & fa)147 void CFFL_ComboBox::SetActionData(const CPDFSDK_PageView* pPageView,
148                                   CPDF_AAction::AActionType type,
149                                   const CFFL_FieldAction& fa) {
150   switch (type) {
151     case CPDF_AAction::kKeyStroke:
152       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
153         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
154           pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
155           pEdit->ReplaceSelection(fa.sChange);
156         }
157       }
158       break;
159     default:
160       break;
161   }
162 }
163 
SavePWLWindowState(const CPDFSDK_PageView * pPageView)164 void CFFL_ComboBox::SavePWLWindowState(const CPDFSDK_PageView* pPageView) {
165   CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
166   if (!pComboBox)
167     return;
168 
169   m_State.nIndex = pComboBox->GetSelect();
170 
171   CPWL_Edit* pEdit = pComboBox->GetEdit();
172   if (!pEdit)
173     return;
174 
175   std::tie(m_State.nStart, m_State.nEnd) = pEdit->GetSelection();
176   m_State.sValue = pEdit->GetText();
177 }
178 
RecreatePWLWindowFromSavedState(const CPDFSDK_PageView * pPageView)179 void CFFL_ComboBox::RecreatePWLWindowFromSavedState(
180     const CPDFSDK_PageView* pPageView) {
181   CPWL_ComboBox* pComboBox = CreateOrUpdatePWLComboBox(pPageView);
182   if (!pComboBox)
183     return;
184 
185   if (m_State.nIndex >= 0) {
186     pComboBox->SetSelect(m_State.nIndex);
187     return;
188   }
189 
190   CPWL_Edit* pEdit = pComboBox->GetEdit();
191   if (!pEdit)
192     return;
193 
194   pEdit->SetText(m_State.sValue);
195   pEdit->SetSelection(m_State.nStart, m_State.nEnd);
196 }
197 
SetIndexSelected(int index,bool selected)198 bool CFFL_ComboBox::SetIndexSelected(int index, bool selected) {
199   if (!IsValid() || !selected)
200     return false;
201 
202   if (index < 0 || index >= m_pWidget->CountOptions())
203     return false;
204 
205   CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
206   if (!pWnd)
207     return false;
208 
209   pWnd->SetSelect(index);
210   return true;
211 }
212 
IsIndexSelected(int index)213 bool CFFL_ComboBox::IsIndexSelected(int index) {
214   if (!IsValid())
215     return false;
216 
217   if (index < 0 || index >= m_pWidget->CountOptions())
218     return false;
219 
220   CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
221   return pWnd && index == pWnd->GetSelect();
222 }
223 
224 #ifdef PDF_ENABLE_XFA
IsFieldFull(const CPDFSDK_PageView * pPageView)225 bool CFFL_ComboBox::IsFieldFull(const CPDFSDK_PageView* pPageView) {
226   CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
227   if (!pComboBox)
228     return false;
229 
230   CPWL_Edit* pEdit = pComboBox->GetEdit();
231   return pEdit && pEdit->IsTextFull();
232 }
233 #endif  // PDF_ENABLE_XFA
234 
OnSetFocusForEdit(CPWL_Edit * pEdit)235 void CFFL_ComboBox::OnSetFocusForEdit(CPWL_Edit* pEdit) {
236   pEdit->SetCharSet(FX_Charset::kChineseSimplified);
237   pEdit->SetReadyToInput();
238   m_pFormFiller->OnSetFieldInputFocus(pEdit->GetText());
239 }
240 
GetSelectExportText()241 WideString CFFL_ComboBox::GetSelectExportText() {
242   CPWL_ComboBox* pComboBox = GetPWLComboBox(GetCurPageView());
243   int nExport = pComboBox ? pComboBox->GetSelect() : -1;
244   return m_pWidget->GetSelectExportText(nExport);
245 }
246 
GetPWLComboBox(const CPDFSDK_PageView * pPageView) const247 CPWL_ComboBox* CFFL_ComboBox::GetPWLComboBox(
248     const CPDFSDK_PageView* pPageView) const {
249   return static_cast<CPWL_ComboBox*>(GetPWLWindow(pPageView));
250 }
251 
CreateOrUpdatePWLComboBox(const CPDFSDK_PageView * pPageView)252 CPWL_ComboBox* CFFL_ComboBox::CreateOrUpdatePWLComboBox(
253     const CPDFSDK_PageView* pPageView) {
254   return static_cast<CPWL_ComboBox*>(CreateOrUpdatePWLWindow(pPageView));
255 }
256