• 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 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   ObservedPtr<CFFL_ComboBox> observed_this(this);
84   CPWL_ComboBox* pWnd = observed_this->GetPWLComboBox(pPageView);
85   if (!pWnd) {
86     return;
87   }
88   WideString swText = pWnd->GetText();
89   int32_t nCurSel = pWnd->GetSelect();
90   bool bSetValue = false;
91   ObservedPtr<CPDFSDK_Widget> observed_widget(observed_this->m_pWidget);
92   if (observed_widget->GetFieldFlags() & pdfium::form_flags::kChoiceEdit) {
93     bSetValue =
94         (nCurSel < 0) || (swText != observed_widget->GetOptionLabel(nCurSel));
95   }
96   if (bSetValue) {
97     observed_widget->SetValue(swText);
98   } else {
99     observed_widget->GetSelectedIndex(0);
100     observed_widget->SetOptionSelection(nCurSel);
101   }
102   if (!observed_widget) {
103     return;
104   }
105   observed_widget->ResetFieldAppearance();
106   if (!observed_widget) {
107     return;
108   }
109   observed_widget->UpdateField();
110   if (!observed_widget || !observed_this) {
111     return;
112   }
113   observed_this->SetChangeMark();
114 }
115 
GetActionData(const CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,CFFL_FieldAction & fa)116 void CFFL_ComboBox::GetActionData(const CPDFSDK_PageView* pPageView,
117                                   CPDF_AAction::AActionType type,
118                                   CFFL_FieldAction& fa) {
119   switch (type) {
120     case CPDF_AAction::kKeyStroke:
121       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
122         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
123           fa.bFieldFull = pEdit->IsTextFull();
124           std::tie(fa.nSelStart, fa.nSelEnd) = pEdit->GetSelection();
125           fa.sValue = pEdit->GetText();
126           fa.sChangeEx = GetSelectExportText();
127 
128           if (fa.bFieldFull) {
129             fa.sChange.clear();
130             fa.sChangeEx.clear();
131           }
132         }
133       }
134       break;
135     case CPDF_AAction::kValidate:
136       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
137         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
138           fa.sValue = pEdit->GetText();
139         }
140       }
141       break;
142     case CPDF_AAction::kLoseFocus:
143     case CPDF_AAction::kGetFocus:
144       fa.sValue = m_pWidget->GetValue();
145       break;
146     default:
147       break;
148   }
149 }
150 
SetActionData(const CPDFSDK_PageView * pPageView,CPDF_AAction::AActionType type,const CFFL_FieldAction & fa)151 void CFFL_ComboBox::SetActionData(const CPDFSDK_PageView* pPageView,
152                                   CPDF_AAction::AActionType type,
153                                   const CFFL_FieldAction& fa) {
154   switch (type) {
155     case CPDF_AAction::kKeyStroke:
156       if (CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView)) {
157         if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
158           pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
159           pEdit->ReplaceSelection(fa.sChange);
160         }
161       }
162       break;
163     default:
164       break;
165   }
166 }
167 
SavePWLWindowState(const CPDFSDK_PageView * pPageView)168 void CFFL_ComboBox::SavePWLWindowState(const CPDFSDK_PageView* pPageView) {
169   CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
170   if (!pComboBox)
171     return;
172 
173   m_State.nIndex = pComboBox->GetSelect();
174 
175   CPWL_Edit* pEdit = pComboBox->GetEdit();
176   if (!pEdit)
177     return;
178 
179   std::tie(m_State.nStart, m_State.nEnd) = pEdit->GetSelection();
180   m_State.sValue = pEdit->GetText();
181 }
182 
RecreatePWLWindowFromSavedState(const CPDFSDK_PageView * pPageView)183 void CFFL_ComboBox::RecreatePWLWindowFromSavedState(
184     const CPDFSDK_PageView* pPageView) {
185   CPWL_ComboBox* pComboBox = CreateOrUpdatePWLComboBox(pPageView);
186   if (!pComboBox)
187     return;
188 
189   if (m_State.nIndex >= 0) {
190     pComboBox->SetSelect(m_State.nIndex);
191     return;
192   }
193 
194   CPWL_Edit* pEdit = pComboBox->GetEdit();
195   if (!pEdit)
196     return;
197 
198   pEdit->SetText(m_State.sValue);
199   pEdit->SetSelection(m_State.nStart, m_State.nEnd);
200 }
201 
SetIndexSelected(int index,bool selected)202 bool CFFL_ComboBox::SetIndexSelected(int index, bool selected) {
203   if (!IsValid() || !selected)
204     return false;
205 
206   if (index < 0 || index >= m_pWidget->CountOptions())
207     return false;
208 
209   CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
210   if (!pWnd)
211     return false;
212 
213   pWnd->SetSelect(index);
214   return true;
215 }
216 
IsIndexSelected(int index)217 bool CFFL_ComboBox::IsIndexSelected(int index) {
218   if (!IsValid())
219     return false;
220 
221   if (index < 0 || index >= m_pWidget->CountOptions())
222     return false;
223 
224   CPWL_ComboBox* pWnd = GetPWLComboBox(GetCurPageView());
225   return pWnd && index == pWnd->GetSelect();
226 }
227 
228 #ifdef PDF_ENABLE_XFA
IsFieldFull(const CPDFSDK_PageView * pPageView)229 bool CFFL_ComboBox::IsFieldFull(const CPDFSDK_PageView* pPageView) {
230   CPWL_ComboBox* pComboBox = GetPWLComboBox(pPageView);
231   if (!pComboBox)
232     return false;
233 
234   CPWL_Edit* pEdit = pComboBox->GetEdit();
235   return pEdit && pEdit->IsTextFull();
236 }
237 #endif  // PDF_ENABLE_XFA
238 
OnSetFocusForEdit(CPWL_Edit * pEdit)239 void CFFL_ComboBox::OnSetFocusForEdit(CPWL_Edit* pEdit) {
240   pEdit->SetCharSet(FX_Charset::kChineseSimplified);
241   pEdit->SetReadyToInput();
242   m_pFormFiller->OnSetFieldInputFocus(pEdit->GetText());
243 }
244 
GetSelectExportText()245 WideString CFFL_ComboBox::GetSelectExportText() {
246   CPWL_ComboBox* pComboBox = GetPWLComboBox(GetCurPageView());
247   int nExport = pComboBox ? pComboBox->GetSelect() : -1;
248   return m_pWidget->GetSelectExportText(nExport);
249 }
250 
GetPWLComboBox(const CPDFSDK_PageView * pPageView) const251 CPWL_ComboBox* CFFL_ComboBox::GetPWLComboBox(
252     const CPDFSDK_PageView* pPageView) const {
253   return static_cast<CPWL_ComboBox*>(GetPWLWindow(pPageView));
254 }
255 
CreateOrUpdatePWLComboBox(const CPDFSDK_PageView * pPageView)256 CPWL_ComboBox* CFFL_ComboBox::CreateOrUpdatePWLComboBox(
257     const CPDFSDK_PageView* pPageView) {
258   return static_cast<CPWL_ComboBox*>(CreateOrUpdatePWLWindow(pPageView));
259 }
260