blob: 7887593b15f8231404a672c0950920979b0760fa [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairedbb3192016-03-21 09:08:24 -04007#include "fpdfsdk/formfiller/cffl_combobox.h"
Lei Zhangc2fb35f2016-01-05 16:46:58 -08008
dsinclair735606d2016-10-05 15:47:02 -07009#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
dsinclair114e46a2016-09-29 17:18:21 -070010#include "fpdfsdk/cpdfsdk_widget.h"
Dan Sinclairedbb3192016-03-21 09:08:24 -040011#include "fpdfsdk/formfiller/cba_fontmap.h"
12#include "fpdfsdk/formfiller/cffl_formfiller.h"
dsinclairb94d7c92016-09-21 12:07:00 -070013#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
dsinclair114e46a2016-09-29 17:18:21 -070014#include "fpdfsdk/fsdk_common.h"
dan sinclair89e904b2016-03-23 19:29:15 -040015#include "fpdfsdk/pdfwindow/PWL_ComboBox.h"
Tom Sepezfe91c6c2017-05-16 15:33:20 -070016#include "third_party/base/ptr_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070017
dsinclair735606d2016-10-05 15:47:02 -070018CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp,
19 CPDFSDK_Annot* pAnnot)
Tom Sepezfe91c6c2017-05-16 15:33:20 -070020 : CFFL_FormFiller(pApp, pAnnot) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070021 m_State.nIndex = 0;
22 m_State.nStart = 0;
23 m_State.nEnd = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070024}
25
Nico Weber9d8ec5a2015-08-04 13:00:21 -070026CFFL_ComboBox::~CFFL_ComboBox() {
Lei Zhangab5537d2016-01-06 14:58:14 -080027 for (const auto& it : m_Maps)
28 it.second->InvalidateFocusHandler(this);
dsinclair28a4a242016-08-22 13:36:02 -070029
30 // See comment in cffl_formfiller.h.
31 // The font map should be stored somewhere more appropriate so it will live
32 // until the PWL_Edit is done with it. pdfium:566
33 DestroyWindows();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070034}
35
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() {
37 PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
Tom Sepezfe91c6c2017-05-16 15:33:20 -070038 if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070039 cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070040
Tom Sepezd0409af2017-05-25 15:53:57 -070041 if (!m_pFontMap) {
42 m_pFontMap =
43 pdfium::MakeUnique<CBA_FontMap>(m_pWidget.Get(), GetSystemHandler());
44 }
Tom Sepezfe91c6c2017-05-16 15:33:20 -070045 cp.pFontMap = m_pFontMap.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046 cp.pFocusHandler = this;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 return cp;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070048}
49
Nico Weber9d8ec5a2015-08-04 13:00:21 -070050CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
51 CPDFSDK_PageView* pPageView) {
52 CPWL_ComboBox* pWnd = new CPWL_ComboBox();
53 pWnd->AttachFFLData(this);
54 pWnd->Create(cp);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070055
dsinclair8779fa82016-10-12 12:05:44 -070056 CFFL_InteractiveFormFiller* pFormFiller =
57 m_pFormFillEnv->GetInteractiveFormFiller();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 pWnd->SetFillerNotify(pFormFiller);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070059
Nico Weber9d8ec5a2015-08-04 13:00:21 -070060 int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
61 CFX_WideString swText;
62 if (nCurSel < 0)
63 swText = m_pWidget->GetValue();
64 else
65 swText = m_pWidget->GetOptionLabel(nCurSel);
Tom Sepez4f7bc042015-04-27 12:06:58 -070066
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 for (int32_t i = 0, sz = m_pWidget->CountOptions(); i < sz; i++) {
tsepez067990c2016-09-13 06:46:40 -070068 pWnd->AddString(m_pWidget->GetOptionLabel(i));
Nico Weber9d8ec5a2015-08-04 13:00:21 -070069 }
Tom Sepez4f7bc042015-04-27 12:06:58 -070070
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071 pWnd->SetSelect(nCurSel);
tsepez067990c2016-09-13 06:46:40 -070072 pWnd->SetText(swText);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073 return pWnd;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070074}
75
tsepez4cf55152016-11-02 14:37:54 -070076bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot,
77 uint32_t nChar,
78 uint32_t nFlags) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079 return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080}
81
tsepez4cf55152016-11-02 14:37:54 -070082bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
83 CPWL_ComboBox* pWnd = (CPWL_ComboBox*)GetPDFWindow(pPageView, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070084 if (!pWnd)
tsepez4cf55152016-11-02 14:37:54 -070085 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070086
Nico Weber9d8ec5a2015-08-04 13:00:21 -070087 int32_t nCurSel = pWnd->GetSelect();
88 if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT))
89 return nCurSel != m_pWidget->GetSelectedIndex(0);
90
91 if (nCurSel >= 0)
92 return nCurSel != m_pWidget->GetSelectedIndex(0);
93
94 return pWnd->GetText() != m_pWidget->GetValue();
95}
96
97void CFFL_ComboBox::SaveData(CPDFSDK_PageView* pPageView) {
Lei Zhangc2fb35f2016-01-05 16:46:58 -080098 CPWL_ComboBox* pWnd =
tsepez4cf55152016-11-02 14:37:54 -070099 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false));
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800100 if (!pWnd)
101 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700102
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800103 CFX_WideString swText = pWnd->GetText();
104 int32_t nCurSel = pWnd->GetSelect();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700105
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800106 bool bSetValue = false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800108 if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
109 bSetValue = (nCurSel < 0) || (swText != m_pWidget->GetOptionLabel(nCurSel));
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700110
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800111 if (bSetValue) {
tsepez4cf55152016-11-02 14:37:54 -0700112 m_pWidget->SetValue(swText, false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800113 } else {
114 m_pWidget->GetSelectedIndex(0);
tsepez4cf55152016-11-02 14:37:54 -0700115 m_pWidget->SetOptionSelection(nCurSel, true, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700116 }
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800117
tsepez4cf55152016-11-02 14:37:54 -0700118 m_pWidget->ResetFieldAppearance(true);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800119 m_pWidget->UpdateField();
120 SetChangeMark();
121
122 m_pWidget->GetPDFPage();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700123}
124
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700125void CFFL_ComboBox::GetActionData(CPDFSDK_PageView* pPageView,
126 CPDF_AAction::AActionType type,
127 PDFSDK_FieldAction& fa) {
128 switch (type) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700129 case CPDF_AAction::KeyStroke:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700130 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700131 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
Tom Sepezb4f00292015-11-23 09:13:33 -0800132 if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133 fa.bFieldFull = pEdit->IsTextFull();
134 int nSelStart = 0;
135 int nSelEnd = 0;
136 pEdit->GetSel(nSelStart, nSelEnd);
137 fa.nSelEnd = nSelEnd;
138 fa.nSelStart = nSelStart;
139 fa.sValue = pEdit->GetText();
140 fa.sChangeEx = GetSelectExportText();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700141
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700142 if (fa.bFieldFull) {
143 fa.sChange = L"";
144 fa.sChangeEx = L"";
145 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700146 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 }
148 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700149 case CPDF_AAction::Validate:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700150 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700151 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
Tom Sepezb4f00292015-11-23 09:13:33 -0800152 if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700153 fa.sValue = pEdit->GetText();
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700154 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 }
156 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700157 case CPDF_AAction::LoseFocus:
158 case CPDF_AAction::GetFocus:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 fa.sValue = m_pWidget->GetValue();
160 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700161 default:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 break;
163 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700164}
165
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166void CFFL_ComboBox::SetActionData(CPDFSDK_PageView* pPageView,
167 CPDF_AAction::AActionType type,
168 const PDFSDK_FieldAction& fa) {
169 switch (type) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700170 case CPDF_AAction::KeyStroke:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700172 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
Tom Sepezb4f00292015-11-23 09:13:33 -0800173 if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
tsepez067990c2016-09-13 06:46:40 -0700175 pEdit->ReplaceSel(fa.sChange);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700176 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 }
178 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700179 default:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180 break;
181 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182}
183
tsepez4cf55152016-11-02 14:37:54 -0700184bool CFFL_ComboBox::IsActionDataChanged(CPDF_AAction::AActionType type,
185 const PDFSDK_FieldAction& faOld,
186 const PDFSDK_FieldAction& faNew) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 switch (type) {
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700188 case CPDF_AAction::KeyStroke:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700189 return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) ||
190 faOld.nSelStart != faNew.nSelStart ||
191 faOld.sChange != faNew.sChange;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700192 default:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 break;
194 }
195
tsepez4cf55152016-11-02 14:37:54 -0700196 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197}
198
199void CFFL_ComboBox::SaveState(CPDFSDK_PageView* pPageView) {
Lei Zhang96660d62015-12-14 18:27:25 -0800200 ASSERT(pPageView);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700201
202 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700203 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 m_State.nIndex = pComboBox->GetSelect();
205
Tom Sepezb4f00292015-11-23 09:13:33 -0800206 if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 pEdit->GetSel(m_State.nStart, m_State.nEnd);
208 m_State.sValue = pEdit->GetText();
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700209 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700210 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700211}
212
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700213void CFFL_ComboBox::RestoreState(CPDFSDK_PageView* pPageView) {
Lei Zhang96660d62015-12-14 18:27:25 -0800214 ASSERT(pPageView);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700215
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700217 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, true))) {
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800218 if (m_State.nIndex >= 0) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700219 pComboBox->SetSelect(m_State.nIndex);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800220 } else {
Tom Sepezb4f00292015-11-23 09:13:33 -0800221 if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
tsepez067990c2016-09-13 06:46:40 -0700222 pEdit->SetText(m_State.sValue);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223 pEdit->SetSel(m_State.nStart, m_State.nEnd);
224 }
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700225 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700227}
228
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700229CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
tsepez4cf55152016-11-02 14:37:54 -0700230 bool bRestoreValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 if (bRestoreValue)
232 SaveState(pPageView);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700233
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234 DestroyPDFWindow(pPageView);
235
thestig1cd352e2016-06-07 17:53:06 -0700236 CPWL_Wnd* pRet = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700237
238 if (bRestoreValue) {
239 RestoreState(pPageView);
tsepez4cf55152016-11-02 14:37:54 -0700240 pRet = GetPDFWindow(pPageView, false);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800241 } else {
tsepez4cf55152016-11-02 14:37:54 -0700242 pRet = GetPDFWindow(pPageView, true);
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800243 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700244
245 m_pWidget->UpdateField();
246
247 return pRet;
248}
249
Tom Sepez51da0932015-11-25 16:05:49 -0800250#ifdef PDF_ENABLE_XFA
tsepez4cf55152016-11-02 14:37:54 -0700251bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700252 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700253 static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
Tom Sepezb4f00292015-11-23 09:13:33 -0800254 if (CPWL_Edit* pEdit = pComboBox->GetEdit())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255 return pEdit->IsTextFull();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 }
tsepez4cf55152016-11-02 14:37:54 -0700257 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700258}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800259#endif // PDF_ENABLE_XFA
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700260
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) {
dsinclair8779fa82016-10-12 12:05:44 -0700262 ASSERT(m_pFormFillEnv);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700263
Lei Zhanga8c2b912017-03-22 17:41:02 -0700264 if (pWnd->GetClassName() != PWL_CLASSNAME_EDIT)
265 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266
Lei Zhanga8c2b912017-03-22 17:41:02 -0700267 CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
Dan Sinclairf51a02a2017-04-19 12:46:53 -0400268 pEdit->SetCharSet(FX_CHARSET_ChineseSimplified);
Lei Zhanga8c2b912017-03-22 17:41:02 -0700269 pEdit->SetReadyToInput();
270
271 CFX_WideString wsText = pEdit->GetText();
272 int nCharacters = wsText.GetLength();
273 CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
274 auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
275 m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276}
277
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278CFX_WideString CFFL_ComboBox::GetSelectExportText() {
279 CFX_WideString swRet;
280
281 int nExport = -1;
dsinclair461eeaf2016-07-27 07:40:05 -0700282 CPDFSDK_PageView* pPageView = GetCurPageView(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 if (CPWL_ComboBox* pComboBox =
tsepez4cf55152016-11-02 14:37:54 -0700284 (CPWL_ComboBox*)GetPDFWindow(pPageView, false)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700285 nExport = pComboBox->GetSelect();
286 }
287
288 if (nExport >= 0) {
289 if (CPDF_FormField* pFormField = m_pWidget->GetFormField()) {
290 swRet = pFormField->GetOptionValue(nExport);
291 if (swRet.IsEmpty())
292 swRet = pFormField->GetOptionLabel(nExport);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700293 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700294 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700295
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 return swRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700297}