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_interactiveformfiller.h" 8 9 #include "core/fpdfapi/page/cpdf_page.h" 10 #include "core/fpdfapi/parser/cpdf_document.h" 11 #include "core/fxcrt/autorestorer.h" 12 #include "core/fxge/cfx_graphstatedata.h" 13 #include "core/fxge/cfx_pathdata.h" 14 #include "core/fxge/cfx_renderdevice.h" 15 #include "fpdfsdk/cpdfsdk_formfillenvironment.h" 16 #include "fpdfsdk/cpdfsdk_interform.h" 17 #include "fpdfsdk/cpdfsdk_pageview.h" 18 #include "fpdfsdk/cpdfsdk_widget.h" 19 #include "fpdfsdk/formfiller/cffl_checkbox.h" 20 #include "fpdfsdk/formfiller/cffl_combobox.h" 21 #include "fpdfsdk/formfiller/cffl_formfiller.h" 22 #include "fpdfsdk/formfiller/cffl_listbox.h" 23 #include "fpdfsdk/formfiller/cffl_pushbutton.h" 24 #include "fpdfsdk/formfiller/cffl_radiobutton.h" 25 #include "fpdfsdk/formfiller/cffl_textfield.h" 26 #include "third_party/base/stl_util.h" 27 28 CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller( 29 CPDFSDK_FormFillEnvironment* pFormFillEnv) 30 : m_pFormFillEnv(pFormFillEnv), m_bNotifying(false) {} 31 32 CFFL_InteractiveFormFiller::~CFFL_InteractiveFormFiller() {} 33 34 bool CFFL_InteractiveFormFiller::Annot_HitTest(CPDFSDK_PageView* pPageView, 35 CPDFSDK_Annot* pAnnot, 36 const CFX_PointF& point) { 37 return pAnnot->GetRect().Contains(point); 38 } 39 40 FX_RECT CFFL_InteractiveFormFiller::GetViewBBox(CPDFSDK_PageView* pPageView, 41 CPDFSDK_Annot* pAnnot) { 42 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) 43 return pFormFiller->GetViewBBox(pPageView, pAnnot); 44 45 ASSERT(pPageView); 46 47 CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot(); 48 CFX_FloatRect rcWin = pPDFAnnot->GetRect(); 49 if (!rcWin.IsEmpty()) { 50 rcWin.Inflate(1, 1); 51 rcWin.Normalize(); 52 } 53 return rcWin.GetOuterRect(); 54 } 55 56 void CFFL_InteractiveFormFiller::OnDraw(CPDFSDK_PageView* pPageView, 57 CPDFSDK_Annot* pAnnot, 58 CFX_RenderDevice* pDevice, 59 CFX_Matrix* pUser2Device) { 60 ASSERT(pPageView); 61 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot); 62 if (!IsVisible(pWidget)) 63 return; 64 65 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); 66 if (pFormFiller && pFormFiller->IsValid()) { 67 pFormFiller->OnDraw(pPageView, pAnnot, pDevice, *pUser2Device); 68 pAnnot->GetPDFPage(); 69 70 if (m_pFormFillEnv->GetFocusAnnot() != pAnnot) 71 return; 72 73 CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView); 74 if (rcFocus.IsEmpty()) 75 return; 76 77 CFX_PathData path; 78 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::MoveTo, 79 false); 80 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom), 81 FXPT_TYPE::LineTo, false); 82 path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom), 83 FXPT_TYPE::LineTo, false); 84 path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top), FXPT_TYPE::LineTo, 85 false); 86 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::LineTo, 87 false); 88 89 CFX_GraphStateData gsd; 90 gsd.SetDashCount(1); 91 gsd.m_DashArray[0] = 1.0f; 92 gsd.m_DashPhase = 0; 93 gsd.m_LineWidth = 1.0f; 94 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), 95 FXFILL_ALTERNATE); 96 return; 97 } 98 99 pFormFiller = GetFormFiller(pAnnot, false); 100 if (pFormFiller) { 101 pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, *pUser2Device); 102 } else { 103 pWidget->DrawAppearance(pDevice, *pUser2Device, CPDF_Annot::Normal, 104 nullptr); 105 } 106 107 if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget)) 108 pWidget->DrawShadow(pDevice, pPageView); 109 } 110 111 void CFFL_InteractiveFormFiller::OnDelete(CPDFSDK_Annot* pAnnot) { 112 UnRegisterFormFiller(pAnnot); 113 } 114 115 void CFFL_InteractiveFormFiller::OnMouseEnter( 116 CPDFSDK_PageView* pPageView, 117 CPDFSDK_Annot::ObservedPtr* pAnnot, 118 uint32_t nFlag) { 119 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 120 if (!m_bNotifying) { 121 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 122 if (pWidget->GetAAction(CPDF_AAction::CursorEnter).GetDict()) { 123 m_bNotifying = true; 124 125 uint32_t nValueAge = pWidget->GetValueAge(); 126 pWidget->ClearAppModified(); 127 ASSERT(pPageView); 128 129 PDFSDK_FieldAction fa; 130 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 131 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 132 pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView); 133 m_bNotifying = false; 134 if (!(*pAnnot)) 135 return; 136 137 if (pWidget->IsAppModified()) { 138 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { 139 pFormFiller->ResetPDFWindow(pPageView, 140 pWidget->GetValueAge() == nValueAge); 141 } 142 } 143 } 144 } 145 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true)) 146 pFormFiller->OnMouseEnter(pPageView, pAnnot->Get()); 147 } 148 149 void CFFL_InteractiveFormFiller::OnMouseExit(CPDFSDK_PageView* pPageView, 150 CPDFSDK_Annot::ObservedPtr* pAnnot, 151 uint32_t nFlag) { 152 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 153 if (!m_bNotifying) { 154 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 155 if (pWidget->GetAAction(CPDF_AAction::CursorExit).GetDict()) { 156 m_bNotifying = true; 157 158 uint32_t nValueAge = pWidget->GetValueAge(); 159 pWidget->ClearAppModified(); 160 ASSERT(pPageView); 161 162 PDFSDK_FieldAction fa; 163 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 164 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 165 pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView); 166 m_bNotifying = false; 167 if (!(*pAnnot)) 168 return; 169 170 if (pWidget->IsAppModified()) { 171 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { 172 pFormFiller->ResetPDFWindow(pPageView, 173 nValueAge == pWidget->GetValueAge()); 174 } 175 } 176 } 177 } 178 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false)) 179 pFormFiller->OnMouseExit(pPageView, pAnnot->Get()); 180 } 181 182 bool CFFL_InteractiveFormFiller::OnLButtonDown( 183 CPDFSDK_PageView* pPageView, 184 CPDFSDK_Annot::ObservedPtr* pAnnot, 185 uint32_t nFlags, 186 const CFX_PointF& point) { 187 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 188 if (!m_bNotifying) { 189 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 190 if (Annot_HitTest(pPageView, pAnnot->Get(), point) && 191 pWidget->GetAAction(CPDF_AAction::ButtonDown).GetDict()) { 192 m_bNotifying = true; 193 194 uint32_t nValueAge = pWidget->GetValueAge(); 195 pWidget->ClearAppModified(); 196 ASSERT(pPageView); 197 198 PDFSDK_FieldAction fa; 199 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlags); 200 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlags); 201 pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView); 202 m_bNotifying = false; 203 if (!(*pAnnot)) 204 return true; 205 206 if (!IsValidAnnot(pPageView, pAnnot->Get())) 207 return true; 208 209 if (pWidget->IsAppModified()) { 210 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) { 211 pFormFiller->ResetPDFWindow(pPageView, 212 nValueAge == pWidget->GetValueAge()); 213 } 214 } 215 } 216 } 217 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 218 return pFormFiller && 219 pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point); 220 } 221 222 bool CFFL_InteractiveFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView, 223 CPDFSDK_Annot::ObservedPtr* pAnnot, 224 uint32_t nFlags, 225 const CFX_PointF& point) { 226 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 227 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 228 229 bool bSetFocus; 230 switch (pWidget->GetFieldType()) { 231 case FormFieldType::kPushButton: 232 case FormFieldType::kCheckBox: 233 case FormFieldType::kRadioButton: { 234 FX_RECT bbox = GetViewBBox(pPageView, pAnnot->Get()); 235 bSetFocus = 236 bbox.Contains(static_cast<int>(point.x), static_cast<int>(point.y)); 237 break; 238 } 239 default: 240 bSetFocus = true; 241 break; 242 } 243 if (bSetFocus) 244 m_pFormFillEnv->SetFocusAnnot(pAnnot); 245 246 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 247 bool bRet = pFormFiller && 248 pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point); 249 if (m_pFormFillEnv->GetFocusAnnot() != pAnnot->Get()) 250 return bRet; 251 if (OnButtonUp(pAnnot, pPageView, nFlags) || !pAnnot) 252 return true; 253 #ifdef PDF_ENABLE_XFA 254 if (OnClick(pAnnot, pPageView, nFlags) || !pAnnot) 255 return true; 256 #endif // PDF_ENABLE_XFA 257 return bRet; 258 } 259 260 bool CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot, 261 CPDFSDK_PageView* pPageView, 262 uint32_t nFlag) { 263 if (m_bNotifying) 264 return false; 265 266 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 267 if (!pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict()) 268 return false; 269 270 m_bNotifying = true; 271 272 uint32_t nAge = pWidget->GetAppearanceAge(); 273 uint32_t nValueAge = pWidget->GetValueAge(); 274 ASSERT(pPageView); 275 276 PDFSDK_FieldAction fa; 277 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 278 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 279 pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView); 280 m_bNotifying = false; 281 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) 282 return true; 283 if (nAge == pWidget->GetAppearanceAge()) 284 return false; 285 286 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); 287 if (pFormFiller) 288 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); 289 return true; 290 } 291 292 bool CFFL_InteractiveFormFiller::OnLButtonDblClk( 293 CPDFSDK_PageView* pPageView, 294 CPDFSDK_Annot::ObservedPtr* pAnnot, 295 uint32_t nFlags, 296 const CFX_PointF& point) { 297 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 298 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 299 return pFormFiller && 300 pFormFiller->OnLButtonDblClk(pPageView, pAnnot->Get(), nFlags, point); 301 } 302 303 bool CFFL_InteractiveFormFiller::OnMouseMove(CPDFSDK_PageView* pPageView, 304 CPDFSDK_Annot::ObservedPtr* pAnnot, 305 uint32_t nFlags, 306 const CFX_PointF& point) { 307 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 308 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true); 309 return pFormFiller && 310 pFormFiller->OnMouseMove(pPageView, pAnnot->Get(), nFlags, point); 311 } 312 313 bool CFFL_InteractiveFormFiller::OnMouseWheel( 314 CPDFSDK_PageView* pPageView, 315 CPDFSDK_Annot::ObservedPtr* pAnnot, 316 uint32_t nFlags, 317 short zDelta, 318 const CFX_PointF& point) { 319 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 320 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 321 return pFormFiller && 322 pFormFiller->OnMouseWheel(pPageView, pAnnot->Get(), nFlags, zDelta, 323 point); 324 } 325 326 bool CFFL_InteractiveFormFiller::OnRButtonDown( 327 CPDFSDK_PageView* pPageView, 328 CPDFSDK_Annot::ObservedPtr* pAnnot, 329 uint32_t nFlags, 330 const CFX_PointF& point) { 331 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 332 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 333 return pFormFiller && 334 pFormFiller->OnRButtonDown(pPageView, pAnnot->Get(), nFlags, point); 335 } 336 337 bool CFFL_InteractiveFormFiller::OnRButtonUp(CPDFSDK_PageView* pPageView, 338 CPDFSDK_Annot::ObservedPtr* pAnnot, 339 uint32_t nFlags, 340 const CFX_PointF& point) { 341 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 342 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 343 return pFormFiller && 344 pFormFiller->OnRButtonUp(pPageView, pAnnot->Get(), nFlags, point); 345 } 346 347 bool CFFL_InteractiveFormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot, 348 uint32_t nKeyCode, 349 uint32_t nFlags) { 350 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 351 352 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); 353 return pFormFiller && pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags); 354 } 355 356 bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Annot* pAnnot, 357 uint32_t nChar, 358 uint32_t nFlags) { 359 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 360 if (nChar == FWL_VKEY_Tab) 361 return true; 362 363 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); 364 return pFormFiller && pFormFiller->OnChar(pAnnot, nChar, nFlags); 365 } 366 367 bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, 368 uint32_t nFlag) { 369 if (!(*pAnnot)) 370 return false; 371 372 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 373 if (!m_bNotifying) { 374 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 375 if (pWidget->GetAAction(CPDF_AAction::GetFocus).GetDict()) { 376 m_bNotifying = true; 377 378 uint32_t nValueAge = pWidget->GetValueAge(); 379 pWidget->ClearAppModified(); 380 381 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, true); 382 if (!pFormFiller) 383 return false; 384 385 CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); 386 ASSERT(pPageView); 387 388 PDFSDK_FieldAction fa; 389 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 390 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 391 pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa); 392 pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView); 393 m_bNotifying = false; 394 if (!(*pAnnot)) 395 return false; 396 397 if (pWidget->IsAppModified()) { 398 if (CFFL_FormFiller* pFiller = GetFormFiller(pWidget, false)) { 399 pFiller->ResetPDFWindow(pPageView, 400 nValueAge == pWidget->GetValueAge()); 401 } 402 } 403 } 404 } 405 406 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true)) 407 pFormFiller->SetFocusForAnnot(pAnnot->Get(), nFlag); 408 409 return true; 410 } 411 412 bool CFFL_InteractiveFormFiller::OnKillFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, 413 uint32_t nFlag) { 414 if (!(*pAnnot)) 415 return false; 416 417 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 418 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false); 419 if (!pFormFiller) 420 return true; 421 422 pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag); 423 if (!(*pAnnot)) 424 return false; 425 426 if (m_bNotifying) 427 return true; 428 429 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 430 if (!pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict()) 431 return true; 432 433 m_bNotifying = true; 434 pWidget->ClearAppModified(); 435 436 CPDFSDK_PageView* pPageView = pWidget->GetPageView(); 437 ASSERT(pPageView); 438 439 PDFSDK_FieldAction fa; 440 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 441 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 442 pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa); 443 pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView); 444 m_bNotifying = false; 445 return !!(*pAnnot); 446 } 447 448 bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) { 449 return pWidget->IsVisible(); 450 } 451 452 bool CFFL_InteractiveFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) { 453 int nFieldFlags = pWidget->GetFieldFlags(); 454 return (nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY; 455 } 456 457 bool CFFL_InteractiveFormFiller::IsFillingAllowed(CPDFSDK_Widget* pWidget) { 458 if (pWidget->GetFieldType() == FormFieldType::kPushButton) 459 return false; 460 461 CPDF_Page* pPage = pWidget->GetPDFPage(); 462 uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions(); 463 return (dwPermissions & FPDFPERM_FILL_FORM) || 464 (dwPermissions & FPDFPERM_ANNOT_FORM) || 465 (dwPermissions & FPDFPERM_MODIFY); 466 } 467 468 CFFL_FormFiller* CFFL_InteractiveFormFiller::GetFormFiller( 469 CPDFSDK_Annot* pAnnot, 470 bool bRegister) { 471 auto it = m_Maps.find(pAnnot); 472 if (it != m_Maps.end()) 473 return it->second.get(); 474 475 if (!bRegister) 476 return nullptr; 477 478 // TODO(thestig): How do we know |pAnnot| is a CPDFSDK_Widget? 479 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot); 480 FormFieldType fieldType = pWidget->GetFieldType(); 481 CFFL_FormFiller* pFormFiller; 482 switch (fieldType) { 483 case FormFieldType::kPushButton: 484 pFormFiller = new CFFL_PushButton(m_pFormFillEnv.Get(), pWidget); 485 break; 486 case FormFieldType::kCheckBox: 487 pFormFiller = new CFFL_CheckBox(m_pFormFillEnv.Get(), pWidget); 488 break; 489 case FormFieldType::kRadioButton: 490 pFormFiller = new CFFL_RadioButton(m_pFormFillEnv.Get(), pWidget); 491 break; 492 case FormFieldType::kTextField: 493 pFormFiller = new CFFL_TextField(m_pFormFillEnv.Get(), pWidget); 494 break; 495 case FormFieldType::kListBox: 496 pFormFiller = new CFFL_ListBox(m_pFormFillEnv.Get(), pWidget); 497 break; 498 case FormFieldType::kComboBox: 499 pFormFiller = new CFFL_ComboBox(m_pFormFillEnv.Get(), pWidget); 500 break; 501 case FormFieldType::kUnknown: 502 default: 503 pFormFiller = nullptr; 504 break; 505 } 506 507 if (!pFormFiller) 508 return nullptr; 509 510 m_Maps[pAnnot].reset(pFormFiller); 511 return pFormFiller; 512 } 513 514 WideString CFFL_InteractiveFormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) { 515 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 516 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); 517 return pFormFiller ? pFormFiller->GetSelectedText(pAnnot) : WideString(); 518 } 519 520 void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, 521 const WideString& text) { 522 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); 523 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); 524 if (!pFormFiller) 525 return; 526 527 pFormFiller->ReplaceSelection(pAnnot, text); 528 } 529 530 void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) { 531 auto it = m_Maps.find(pAnnot); 532 if (it == m_Maps.end()) 533 return; 534 535 m_Maps.erase(it); 536 } 537 538 void CFFL_InteractiveFormFiller::QueryWherePopup( 539 CPWL_Wnd::PrivateData* pAttached, 540 float fPopupMin, 541 float fPopupMax, 542 bool* bBottom, 543 float* fPopupRet) { 544 auto* pData = static_cast<CFFL_PrivateData*>(pAttached); 545 CPDFSDK_Widget* pWidget = pData->pWidget; 546 CPDF_Page* pPage = pWidget->GetPDFPage(); 547 548 CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0); 549 rcPageView.Normalize(); 550 551 CFX_FloatRect rcAnnot = pWidget->GetRect(); 552 float fTop = 0.0f; 553 float fBottom = 0.0f; 554 switch (pWidget->GetRotate() / 90) { 555 default: 556 case 0: 557 fTop = rcPageView.top - rcAnnot.top; 558 fBottom = rcAnnot.bottom - rcPageView.bottom; 559 break; 560 case 1: 561 fTop = rcAnnot.left - rcPageView.left; 562 fBottom = rcPageView.right - rcAnnot.right; 563 break; 564 case 2: 565 fTop = rcAnnot.bottom - rcPageView.bottom; 566 fBottom = rcPageView.top - rcAnnot.top; 567 break; 568 case 3: 569 fTop = rcPageView.right - rcAnnot.right; 570 fBottom = rcAnnot.left - rcPageView.left; 571 break; 572 } 573 574 constexpr float kMaxListBoxHeight = 140; 575 const float fMaxListBoxHeight = 576 pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax); 577 578 if (fBottom > fMaxListBoxHeight) { 579 *fPopupRet = fMaxListBoxHeight; 580 *bBottom = true; 581 return; 582 } 583 584 if (fTop > fMaxListBoxHeight) { 585 *fPopupRet = fMaxListBoxHeight; 586 *bBottom = false; 587 return; 588 } 589 590 if (fTop > fBottom) { 591 *fPopupRet = fTop; 592 *bBottom = false; 593 } else { 594 *fPopupRet = fBottom; 595 *bBottom = true; 596 } 597 } 598 599 bool CFFL_InteractiveFormFiller::OnKeyStrokeCommit( 600 CPDFSDK_Annot::ObservedPtr* pAnnot, 601 CPDFSDK_PageView* pPageView, 602 uint32_t nFlag) { 603 if (m_bNotifying) 604 return true; 605 606 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 607 if (!pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) 608 return true; 609 610 ASSERT(pPageView); 611 m_bNotifying = true; 612 pWidget->ClearAppModified(); 613 614 PDFSDK_FieldAction fa; 615 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 616 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 617 fa.bWillCommit = true; 618 fa.bKeyDown = true; 619 fa.bRC = true; 620 621 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); 622 pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa); 623 pFormFiller->SaveState(pPageView); 624 pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView); 625 if (!(*pAnnot)) 626 return true; 627 628 m_bNotifying = false; 629 return fa.bRC; 630 } 631 632 bool CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot, 633 CPDFSDK_PageView* pPageView, 634 uint32_t nFlag) { 635 if (m_bNotifying) 636 return true; 637 638 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 639 if (!pWidget->GetAAction(CPDF_AAction::Validate).GetDict()) 640 return true; 641 642 ASSERT(pPageView); 643 m_bNotifying = true; 644 pWidget->ClearAppModified(); 645 646 PDFSDK_FieldAction fa; 647 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 648 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 649 fa.bKeyDown = true; 650 fa.bRC = true; 651 652 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false); 653 pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa); 654 pFormFiller->SaveState(pPageView); 655 pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView); 656 if (!(*pAnnot)) 657 return true; 658 659 m_bNotifying = false; 660 return fa.bRC; 661 } 662 663 void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot, 664 CPDFSDK_PageView* pPageView, 665 uint32_t nFlag) { 666 if (m_bNotifying) 667 return; 668 669 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 670 if (pWidget) { 671 CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm(); 672 pInterForm->OnCalculate(pWidget->GetFormField()); 673 } 674 m_bNotifying = false; 675 } 676 677 void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot, 678 CPDFSDK_PageView* pPageView, 679 uint32_t nFlag) { 680 if (m_bNotifying) 681 return; 682 683 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 684 ASSERT(pWidget); 685 CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm(); 686 687 bool bFormatted = false; 688 WideString sValue = pInterForm->OnFormat(pWidget->GetFormField(), bFormatted); 689 if (!(*pAnnot)) 690 return; 691 692 if (bFormatted) { 693 pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true); 694 pInterForm->UpdateField(pWidget->GetFormField()); 695 } 696 697 m_bNotifying = false; 698 } 699 700 #ifdef PDF_ENABLE_XFA 701 bool CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot, 702 CPDFSDK_PageView* pPageView, 703 uint32_t nFlag) { 704 if (m_bNotifying) 705 return false; 706 707 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 708 if (!pWidget->HasXFAAAction(PDFSDK_XFA_Click)) 709 return false; 710 711 m_bNotifying = true; 712 uint32_t nAge = pWidget->GetAppearanceAge(); 713 uint32_t nValueAge = pWidget->GetValueAge(); 714 715 PDFSDK_FieldAction fa; 716 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 717 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 718 719 pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView); 720 m_bNotifying = false; 721 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) 722 return true; 723 if (nAge == pWidget->GetAppearanceAge()) 724 return false; 725 726 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) 727 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); 728 return false; 729 } 730 731 bool CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot, 732 CPDFSDK_PageView* pPageView, 733 uint32_t nFlag) { 734 if (m_bNotifying) 735 return false; 736 737 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 738 if (!pWidget->HasXFAAAction(PDFSDK_XFA_Full)) 739 return false; 740 741 m_bNotifying = true; 742 uint32_t nAge = pWidget->GetAppearanceAge(); 743 uint32_t nValueAge = pWidget->GetValueAge(); 744 745 PDFSDK_FieldAction fa; 746 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 747 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 748 749 pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView); 750 m_bNotifying = false; 751 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) 752 return true; 753 if (nAge == pWidget->GetAppearanceAge()) 754 return false; 755 756 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) 757 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); 758 759 return true; 760 } 761 762 bool CFFL_InteractiveFormFiller::OnPopupPreOpen( 763 CPWL_Wnd::PrivateData* pAttached, 764 uint32_t nFlag) { 765 auto* pData = static_cast<CFFL_PrivateData*>(pAttached); 766 ASSERT(pData); 767 ASSERT(pData->pWidget); 768 769 CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget); 770 return OnPreOpen(&pObserved, pData->pPageView, nFlag) || !pObserved; 771 } 772 773 bool CFFL_InteractiveFormFiller::OnPopupPostOpen( 774 CPWL_Wnd::PrivateData* pAttached, 775 uint32_t nFlag) { 776 auto* pData = static_cast<CFFL_PrivateData*>(pAttached); 777 ASSERT(pData); 778 ASSERT(pData->pWidget); 779 780 CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget); 781 return OnPostOpen(&pObserved, pData->pPageView, nFlag) || !pObserved; 782 } 783 784 bool CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, 785 CPDFSDK_PageView* pPageView, 786 uint32_t nFlag) { 787 if (m_bNotifying) 788 return false; 789 790 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 791 if (!pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) 792 return false; 793 794 m_bNotifying = true; 795 uint32_t nAge = pWidget->GetAppearanceAge(); 796 uint32_t nValueAge = pWidget->GetValueAge(); 797 798 PDFSDK_FieldAction fa; 799 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 800 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 801 802 pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView); 803 m_bNotifying = false; 804 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) 805 return true; 806 if (nAge == pWidget->GetAppearanceAge()) 807 return false; 808 809 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) 810 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); 811 812 return true; 813 } 814 815 bool CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot, 816 CPDFSDK_PageView* pPageView, 817 uint32_t nFlag) { 818 if (m_bNotifying) 819 return false; 820 821 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get()); 822 if (!pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) 823 return false; 824 825 m_bNotifying = true; 826 uint32_t nAge = pWidget->GetAppearanceAge(); 827 uint32_t nValueAge = pWidget->GetValueAge(); 828 829 PDFSDK_FieldAction fa; 830 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 831 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 832 833 pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView); 834 m_bNotifying = false; 835 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) 836 return true; 837 if (nAge == pWidget->GetAppearanceAge()) 838 return false; 839 840 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) 841 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge()); 842 843 return true; 844 } 845 #endif // PDF_ENABLE_XFA 846 847 bool CFFL_InteractiveFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView, 848 CPDFSDK_Annot* pAnnot) { 849 return pPageView && pPageView->IsValidAnnot(pAnnot->GetPDFAnnot()); 850 } 851 852 std::pair<bool, bool> CFFL_InteractiveFormFiller::OnBeforeKeyStroke( 853 CPWL_Wnd::PrivateData* pAttached, 854 WideString& strChange, 855 const WideString& strChangeEx, 856 int nSelStart, 857 int nSelEnd, 858 bool bKeyDown, 859 uint32_t nFlag) { 860 // Copy the private data since the window owning it may not survive. 861 CFFL_PrivateData privateData = *static_cast<CFFL_PrivateData*>(pAttached); 862 ASSERT(privateData.pWidget); 863 864 CFFL_FormFiller* pFormFiller = GetFormFiller(privateData.pWidget, false); 865 866 #ifdef PDF_ENABLE_XFA 867 if (pFormFiller->IsFieldFull(privateData.pPageView)) { 868 CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget); 869 if (OnFull(&pObserved, privateData.pPageView, nFlag) || !pObserved) 870 return {true, true}; 871 } 872 #endif // PDF_ENABLE_XFA 873 874 if (m_bNotifying || 875 !privateData.pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) { 876 return {true, false}; 877 } 878 879 AutoRestorer<bool> restorer(&m_bNotifying); 880 m_bNotifying = true; 881 882 uint32_t nAge = privateData.pWidget->GetAppearanceAge(); 883 uint32_t nValueAge = privateData.pWidget->GetValueAge(); 884 CPDFSDK_FormFillEnvironment* pFormFillEnv = 885 privateData.pPageView->GetFormFillEnv(); 886 887 PDFSDK_FieldAction fa; 888 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag); 889 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag); 890 fa.sChange = strChange; 891 fa.sChangeEx = strChangeEx; 892 fa.bKeyDown = bKeyDown; 893 fa.bWillCommit = false; 894 fa.bRC = true; 895 fa.nSelStart = nSelStart; 896 fa.nSelEnd = nSelEnd; 897 pFormFiller->GetActionData(privateData.pPageView, CPDF_AAction::KeyStroke, 898 fa); 899 pFormFiller->SaveState(privateData.pPageView); 900 901 CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget); 902 bool action_status = privateData.pWidget->OnAAction( 903 CPDF_AAction::KeyStroke, fa, privateData.pPageView); 904 905 if (!pObserved || !IsValidAnnot(privateData.pPageView, privateData.pWidget)) 906 return {true, true}; 907 908 if (!action_status) 909 return {true, false}; 910 911 bool bExit = false; 912 if (nAge != privateData.pWidget->GetAppearanceAge()) { 913 CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow( 914 privateData.pPageView, nValueAge == privateData.pWidget->GetValueAge()); 915 if (!pWnd) 916 return {true, true}; 917 privateData = *static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()); 918 bExit = true; 919 } 920 if (fa.bRC) { 921 pFormFiller->SetActionData(privateData.pPageView, CPDF_AAction::KeyStroke, 922 fa); 923 } else { 924 pFormFiller->RestoreState(privateData.pPageView); 925 } 926 if (pFormFillEnv->GetFocusAnnot() == privateData.pWidget) 927 return {false, bExit}; 928 929 pFormFiller->CommitData(privateData.pPageView, nFlag); 930 return {false, true}; 931 } 932