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