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 "xfa/fxfa/cxfa_ffdocview.h" 8 9 #include "core/fxcrt/fx_extension.h" 10 #include "fxjs/cfxjse_engine.h" 11 #include "fxjs/xfa/cjx_object.h" 12 #include "third_party/base/ptr_util.h" 13 #include "third_party/base/stl_util.h" 14 #include "xfa/fxfa/cxfa_ffapp.h" 15 #include "xfa/fxfa/cxfa_ffbarcode.h" 16 #include "xfa/fxfa/cxfa_ffcheckbutton.h" 17 #include "xfa/fxfa/cxfa_ffdoc.h" 18 #include "xfa/fxfa/cxfa_ffdraw.h" 19 #include "xfa/fxfa/cxfa_ffexclgroup.h" 20 #include "xfa/fxfa/cxfa_fffield.h" 21 #include "xfa/fxfa/cxfa_ffimage.h" 22 #include "xfa/fxfa/cxfa_ffimageedit.h" 23 #include "xfa/fxfa/cxfa_ffpageview.h" 24 #include "xfa/fxfa/cxfa_ffpushbutton.h" 25 #include "xfa/fxfa/cxfa_ffsignature.h" 26 #include "xfa/fxfa/cxfa_ffsubform.h" 27 #include "xfa/fxfa/cxfa_fftext.h" 28 #include "xfa/fxfa/cxfa_ffwidget.h" 29 #include "xfa/fxfa/cxfa_ffwidgethandler.h" 30 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" 31 #include "xfa/fxfa/cxfa_textprovider.h" 32 #include "xfa/fxfa/cxfa_widgetacciterator.h" 33 #include "xfa/fxfa/parser/cxfa_acrobat.h" 34 #include "xfa/fxfa/parser/cxfa_binditems.h" 35 #include "xfa/fxfa/parser/cxfa_calculate.h" 36 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h" 37 #include "xfa/fxfa/parser/cxfa_pageset.h" 38 #include "xfa/fxfa/parser/cxfa_present.h" 39 #include "xfa/fxfa/parser/cxfa_subform.h" 40 #include "xfa/fxfa/parser/cxfa_validate.h" 41 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" 42 43 const XFA_AttributeEnum gs_EventActivity[] = { 44 XFA_AttributeEnum::Click, XFA_AttributeEnum::Change, 45 XFA_AttributeEnum::DocClose, XFA_AttributeEnum::DocReady, 46 XFA_AttributeEnum::Enter, XFA_AttributeEnum::Exit, 47 XFA_AttributeEnum::Full, XFA_AttributeEnum::IndexChange, 48 XFA_AttributeEnum::Initialize, XFA_AttributeEnum::MouseDown, 49 XFA_AttributeEnum::MouseEnter, XFA_AttributeEnum::MouseExit, 50 XFA_AttributeEnum::MouseUp, XFA_AttributeEnum::PostExecute, 51 XFA_AttributeEnum::PostOpen, XFA_AttributeEnum::PostPrint, 52 XFA_AttributeEnum::PostSave, XFA_AttributeEnum::PostSign, 53 XFA_AttributeEnum::PostSubmit, XFA_AttributeEnum::PreExecute, 54 XFA_AttributeEnum::PreOpen, XFA_AttributeEnum::PrePrint, 55 XFA_AttributeEnum::PreSave, XFA_AttributeEnum::PreSign, 56 XFA_AttributeEnum::PreSubmit, XFA_AttributeEnum::Ready, 57 XFA_AttributeEnum::Unknown, 58 }; 59 60 CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) 61 : m_bLayoutEvent(false), 62 m_pListFocusWidget(nullptr), 63 m_bInLayoutStatus(false), 64 m_pDoc(pDoc), 65 m_pXFADocLayout(nullptr), 66 m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None), 67 m_iLock(0) {} 68 69 CXFA_FFDocView::~CXFA_FFDocView() { 70 DestroyDocView(); 71 } 72 73 void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) { 74 RunBindItems(); 75 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true, 76 nullptr); 77 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true, 78 nullptr); 79 } 80 81 int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) { 82 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; 83 m_pDoc->GetXFADoc()->DoProtoMerge(); 84 m_pDoc->GetXFADoc()->DoDataMerge(); 85 m_pXFADocLayout = GetXFALayout(); 86 87 int32_t iStatus = m_pXFADocLayout->StartLayout(); 88 if (iStatus < 0) 89 return iStatus; 90 91 CXFA_Node* pRootItem = 92 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 93 if (!pRootItem) 94 return iStatus; 95 96 InitLayout(pRootItem); 97 InitCalculate(pRootItem); 98 InitValidate(pRootItem); 99 100 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr); 101 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; 102 return iStatus; 103 } 104 105 int32_t CXFA_FFDocView::DoLayout() { 106 int32_t iStatus = 100; 107 iStatus = m_pXFADocLayout->DoLayout(); 108 if (iStatus != 100) 109 return iStatus; 110 111 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing; 112 return iStatus; 113 } 114 115 void CXFA_FFDocView::StopLayout() { 116 CXFA_Node* pRootItem = 117 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 118 if (!pRootItem) 119 return; 120 121 CXFA_Subform* pSubformNode = 122 pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false); 123 if (!pSubformNode) 124 return; 125 126 CXFA_PageSet* pPageSetNode = 127 pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet); 128 if (!pPageSetNode) 129 return; 130 131 RunCalculateWidgets(); 132 RunValidate(); 133 134 InitLayout(pPageSetNode); 135 InitCalculate(pPageSetNode); 136 InitValidate(pPageSetNode); 137 138 ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true, 139 nullptr); 140 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, 141 nullptr); 142 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true, 143 nullptr); 144 145 RunCalculateWidgets(); 146 RunValidate(); 147 148 if (RunLayout()) { 149 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, 150 nullptr); 151 } 152 153 m_CalculateAccs.clear(); 154 if (m_pFocusAcc && !m_pFocusWidget) 155 SetFocusWidgetAcc(m_pFocusAcc.Get()); 156 157 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End; 158 } 159 160 void CXFA_FFDocView::ShowNullTestMsg() { 161 int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg); 162 CXFA_FFApp* pApp = m_pDoc->GetApp(); 163 IXFA_AppProvider* pAppProvider = pApp->GetAppProvider(); 164 if (pAppProvider && iCount) { 165 int32_t iRemain = iCount > 7 ? iCount - 7 : 0; 166 iCount -= iRemain; 167 WideString wsMsg; 168 for (int32_t i = 0; i < iCount; i++) 169 wsMsg += m_arrNullTestMsg[i] + L"\n"; 170 171 if (iRemain > 0) { 172 wsMsg += L"\n" + WideString::Format( 173 L"Message limit exceeded. Remaining %d " 174 L"validation errors not reported.", 175 iRemain); 176 } 177 pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status, 178 XFA_MB_OK); 179 } 180 m_arrNullTestMsg.clear(); 181 } 182 183 void CXFA_FFDocView::UpdateDocView() { 184 if (IsUpdateLocked()) 185 return; 186 187 LockUpdate(); 188 for (CXFA_Node* pNode : m_NewAddedNodes) { 189 InitCalculate(pNode); 190 InitValidate(pNode); 191 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr); 192 } 193 m_NewAddedNodes.clear(); 194 195 RunSubformIndexChange(); 196 RunCalculateWidgets(); 197 RunValidate(); 198 199 ShowNullTestMsg(); 200 201 if (RunLayout() && m_bLayoutEvent) 202 RunEventLayoutReady(); 203 204 m_bLayoutEvent = false; 205 m_CalculateAccs.clear(); 206 RunInvalidate(); 207 UnlockUpdate(); 208 } 209 210 int32_t CXFA_FFDocView::CountPageViews() const { 211 return m_pXFADocLayout ? m_pXFADocLayout->CountPages() : 0; 212 } 213 214 CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const { 215 if (!m_pXFADocLayout) 216 return nullptr; 217 return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex)); 218 } 219 220 CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const { 221 return m_pDoc->GetXFADoc()->GetDocLayout(); 222 } 223 224 bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) { 225 CXFA_Node* pNode = pWidgetAcc->GetNode(); 226 XFA_Element eType = pNode->GetElementType(); 227 if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) 228 return false; 229 230 pWidgetAcc->ResetData(); 231 pWidgetAcc->UpdateUIDisplay(this, nullptr); 232 CXFA_Validate* validate = pNode->GetValidateIfExists(); 233 if (!validate) 234 return true; 235 236 AddValidateWidget(pWidgetAcc); 237 validate->SetFlag(XFA_NodeFlag_NeedsInitApp, false); 238 return true; 239 } 240 241 void CXFA_FFDocView::ResetWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { 242 m_bLayoutEvent = true; 243 bool bChanged = false; 244 CXFA_Node* pFormNode = nullptr; 245 if (pWidgetAcc) { 246 bChanged = ResetSingleWidgetAccData(pWidgetAcc); 247 pFormNode = pWidgetAcc->GetNode(); 248 } else { 249 pFormNode = GetRootSubform(); 250 } 251 if (!pFormNode) 252 return; 253 254 if (pFormNode->GetElementType() != XFA_Element::Field && 255 pFormNode->GetElementType() != XFA_Element::ExclGroup) { 256 CXFA_WidgetAccIterator Iterator(pFormNode); 257 while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) { 258 bChanged |= ResetSingleWidgetAccData(pAcc); 259 if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup) 260 Iterator.SkipTree(); 261 } 262 } 263 if (bChanged) 264 m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); 265 } 266 267 int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam, 268 CXFA_WidgetAcc* pWidgetAcc) { 269 if (!pParam) 270 return XFA_EVENTERROR_Error; 271 272 if (pParam->m_eType == XFA_EVENT_Validate) { 273 WideString wsValidateStr(L"preSubmit"); 274 CXFA_Node* pConfigItem = 275 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config)); 276 if (pConfigItem) { 277 CXFA_Acrobat* pAcrobatNode = 278 pConfigItem->GetChild<CXFA_Acrobat>(0, XFA_Element::Acrobat, false); 279 CXFA_Validate* pValidateNode = 280 pAcrobatNode ? pAcrobatNode->GetChild<CXFA_Validate>( 281 0, XFA_Element::Validate, false) 282 : nullptr; 283 if (!pValidateNode) { 284 CXFA_Present* pPresentNode = 285 pConfigItem->GetChild<CXFA_Present>(0, XFA_Element::Present, false); 286 pValidateNode = pPresentNode ? pPresentNode->GetChild<CXFA_Validate>( 287 0, XFA_Element::Validate, false) 288 : nullptr; 289 } 290 if (pValidateNode) 291 wsValidateStr = pValidateNode->JSObject()->GetContent(false); 292 } 293 294 if (!wsValidateStr.Contains(L"preSubmit")) 295 return XFA_EVENTERROR_Success; 296 } 297 298 CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr; 299 if (!pNode) { 300 CXFA_Node* pRootItem = 301 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 302 if (!pRootItem) 303 return XFA_EVENTERROR_Error; 304 305 pNode = pRootItem->GetChild<CXFA_Node>(0, XFA_Element::Subform, false); 306 } 307 308 ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady, 309 true, nullptr); 310 return XFA_EVENTERROR_Success; 311 } 312 313 CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) { 314 return static_cast<CXFA_FFWidget*>(GetXFALayout()->GetLayoutItem(node)); 315 } 316 317 CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() { 318 if (!m_pWidgetHandler) 319 m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this); 320 return m_pWidgetHandler.get(); 321 } 322 323 std::unique_ptr<CXFA_WidgetAccIterator> 324 CXFA_FFDocView::CreateWidgetAccIterator() { 325 CXFA_Subform* pFormRoot = GetRootSubform(); 326 return pFormRoot ? pdfium::MakeUnique<CXFA_WidgetAccIterator>(pFormRoot) 327 : nullptr; 328 } 329 330 void CXFA_FFDocView::KillFocus() { 331 if (m_pFocusWidget && 332 (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) { 333 m_pFocusWidget->OnKillFocus(nullptr); 334 } 335 m_pFocusAcc = nullptr; 336 m_pFocusWidget = nullptr; 337 m_pOldFocusWidget = nullptr; 338 } 339 340 bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) { 341 CXFA_FFWidget* pNewFocus = hWidget; 342 if (m_pOldFocusWidget == pNewFocus) 343 return false; 344 345 CXFA_FFWidget* pOldFocus = m_pOldFocusWidget.Get(); 346 m_pOldFocusWidget = pNewFocus; 347 if (pOldFocus) { 348 if (m_pFocusWidget != m_pOldFocusWidget && 349 (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) { 350 m_pFocusWidget = pOldFocus; 351 pOldFocus->OnKillFocus(pNewFocus); 352 } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) { 353 if (!pOldFocus->IsLoaded()) 354 pOldFocus->LoadWidget(); 355 356 pOldFocus->OnSetFocus(m_pFocusWidget.Get()); 357 m_pFocusWidget = pOldFocus; 358 pOldFocus->OnKillFocus(pNewFocus); 359 } 360 } 361 if (m_pFocusWidget == m_pOldFocusWidget) 362 return false; 363 364 pNewFocus = m_pOldFocusWidget.Get(); 365 if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) { 366 m_pFocusAcc = nullptr; 367 m_pFocusWidget = nullptr; 368 m_pListFocusWidget = nullptr; 369 m_pOldFocusWidget = nullptr; 370 return false; 371 } 372 if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) { 373 if (!pNewFocus->IsLoaded()) 374 pNewFocus->LoadWidget(); 375 pNewFocus->OnSetFocus(m_pFocusWidget.Get()); 376 } 377 m_pFocusAcc = pNewFocus ? pNewFocus->GetNode()->GetWidgetAcc() : nullptr; 378 m_pFocusWidget = pNewFocus; 379 m_pOldFocusWidget = m_pFocusWidget; 380 return true; 381 } 382 383 void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { 384 CXFA_FFWidget* pNewFocus = nullptr; 385 if (pWidgetAcc) 386 pNewFocus = GetWidgetForNode(pWidgetAcc->GetNode()); 387 if (!SetFocus(pNewFocus)) 388 return; 389 390 m_pFocusAcc = pWidgetAcc; 391 if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End) 392 return; 393 394 m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc.Get(), 395 m_pFocusWidget.Get()); 396 } 397 398 void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) { 399 if (m_pFocusAcc && m_pFocusAcc->GetNode() != pWidget->GetNode()) 400 return; 401 402 m_pFocusAcc = nullptr; 403 m_pFocusWidget = nullptr; 404 m_pOldFocusWidget = nullptr; 405 } 406 407 static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView, 408 CXFA_WidgetAcc* pWidgetAcc, 409 CXFA_EventParam* pParam) { 410 if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) 411 return XFA_EVENTERROR_NotExist; 412 if (!pWidgetAcc) 413 return XFA_EVENTERROR_NotExist; 414 415 CXFA_Node* node = pWidgetAcc->GetNode(); 416 if (node && node->GetElementType() == XFA_Element::Draw) 417 return XFA_EVENTERROR_NotExist; 418 419 switch (pParam->m_eType) { 420 case XFA_EVENT_Calculate: 421 return node->ProcessCalculate(pDocView); 422 case XFA_EVENT_Validate: 423 if (pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled( 424 pDocView->GetDoc())) { 425 return node->ProcessValidate(pDocView, 0x01); 426 } 427 return XFA_EVENTERROR_Disabled; 428 case XFA_EVENT_InitCalculate: { 429 CXFA_Calculate* calc = node->GetCalculateIfExists(); 430 if (!calc) 431 return XFA_EVENTERROR_NotExist; 432 if (node->IsUserInteractive()) 433 return XFA_EVENTERROR_Disabled; 434 435 return node->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam); 436 } 437 default: 438 break; 439 } 440 441 return node->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType], 442 pParam); 443 } 444 445 int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, 446 XFA_EVENTTYPE eEventType, 447 bool bIsFormReady, 448 bool bRecursive, 449 CXFA_Node* pExclude) { 450 if (pFormNode == pExclude) 451 return XFA_EVENTERROR_NotExist; 452 453 XFA_Element elementType = pFormNode->GetElementType(); 454 if (elementType == XFA_Element::Field) { 455 if (eEventType == XFA_EVENT_IndexChange) 456 return XFA_EVENTERROR_NotExist; 457 458 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); 459 if (!pWidgetAcc) 460 return XFA_EVENTERROR_NotExist; 461 462 CXFA_EventParam eParam; 463 eParam.m_eType = eEventType; 464 eParam.m_pTarget = pWidgetAcc; 465 eParam.m_bIsFormReady = bIsFormReady; 466 return XFA_ProcessEvent(this, pWidgetAcc, &eParam); 467 } 468 469 int32_t iRet = XFA_EVENTERROR_NotExist; 470 if (bRecursive) { 471 for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode; 472 pNode = pNode->GetNextContainerSibling()) { 473 elementType = pNode->GetElementType(); 474 if (elementType != XFA_Element::Variables && 475 elementType != XFA_Element::Draw) { 476 iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady, 477 bRecursive, pExclude); 478 } 479 } 480 } 481 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc(); 482 if (!pWidgetAcc) 483 return iRet; 484 485 CXFA_EventParam eParam; 486 eParam.m_eType = eEventType; 487 eParam.m_pTarget = pWidgetAcc; 488 eParam.m_bIsFormReady = bIsFormReady; 489 iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam); 490 491 return iRet; 492 } 493 494 CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName, 495 CXFA_FFWidget* pRefWidget) { 496 CXFA_WidgetAcc* pRefAcc = 497 pRefWidget ? pRefWidget->GetNode()->GetWidgetAcc() : nullptr; 498 CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc); 499 if (!pAcc) 500 return nullptr; 501 return GetWidgetForNode(pAcc->GetNode()); 502 } 503 504 CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName( 505 const WideString& wsName, 506 CXFA_WidgetAcc* pRefWidgetAcc) { 507 WideString wsExpression; 508 uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | 509 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; 510 CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext(); 511 if (!pScriptContext) 512 return nullptr; 513 514 CXFA_Node* refNode = nullptr; 515 if (pRefWidgetAcc) { 516 refNode = pRefWidgetAcc->GetNode(); 517 wsExpression = wsName; 518 } else { 519 wsExpression = L"$form." + wsName; 520 } 521 522 XFA_RESOLVENODE_RS resolveNodeRS; 523 if (!pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(), 524 &resolveNodeRS, dwStyle, nullptr)) { 525 return nullptr; 526 } 527 528 if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { 529 CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode(); 530 if (pNode) 531 return pNode->GetWidgetAcc(); 532 } 533 return nullptr; 534 } 535 536 void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender, 537 uint32_t dwEvent) { 538 CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender); 539 m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent); 540 } 541 542 543 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget, 544 const CFX_RectF& rtInvalidate) { 545 AddInvalidateRect(pWidget->GetPageView(), rtInvalidate); 546 } 547 548 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView, 549 const CFX_RectF& rtInvalidate) { 550 if (m_mapPageInvalidate[pPageView]) { 551 m_mapPageInvalidate[pPageView]->Union(rtInvalidate); 552 return; 553 } 554 555 m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate); 556 } 557 558 void CXFA_FFDocView::RunInvalidate() { 559 for (const auto& pair : m_mapPageInvalidate) 560 m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second); 561 562 m_mapPageInvalidate.clear(); 563 } 564 565 bool CXFA_FFDocView::RunLayout() { 566 LockUpdate(); 567 m_bInLayoutStatus = true; 568 if (!m_pXFADocLayout->IncrementLayout() && 569 m_pXFADocLayout->StartLayout() < 100) { 570 m_pXFADocLayout->DoLayout(); 571 UnlockUpdate(); 572 m_bInLayoutStatus = false; 573 m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, 574 XFA_PAGEVIEWEVENT_StopLayout); 575 return true; 576 } 577 578 m_bInLayoutStatus = false; 579 m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, 580 XFA_PAGEVIEWEVENT_StopLayout); 581 UnlockUpdate(); 582 return false; 583 } 584 585 void CXFA_FFDocView::RunSubformIndexChange() { 586 for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) { 587 if (!pSubformNode->GetWidgetAcc()) 588 continue; 589 590 CXFA_EventParam eParam; 591 eParam.m_eType = XFA_EVENT_IndexChange; 592 eParam.m_pTarget = pSubformNode->GetWidgetAcc(); 593 pSubformNode->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam); 594 } 595 m_IndexChangedSubforms.clear(); 596 } 597 598 void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) { 599 m_NewAddedNodes.push_back(pNode); 600 InitLayout(pNode); 601 } 602 603 void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) { 604 ASSERT(pNode->GetElementType() == XFA_Element::Subform); 605 m_IndexChangedSubforms.push_back(pNode); 606 } 607 608 void CXFA_FFDocView::RunDocClose() { 609 CXFA_Node* pRootItem = 610 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 611 if (!pRootItem) 612 return; 613 614 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true, 615 nullptr); 616 } 617 618 void CXFA_FFDocView::DestroyDocView() { 619 ClearInvalidateList(); 620 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None; 621 m_iLock = 0; 622 m_ValidateAccs.clear(); 623 m_BindItems.clear(); 624 m_CalculateAccs.clear(); 625 } 626 627 void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { 628 CXFA_WidgetAcc* pCurrentAcc = 629 !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr; 630 if (pCurrentAcc != pWidgetAcc) 631 m_CalculateAccs.push_back(pWidgetAcc); 632 } 633 634 void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) { 635 CXFA_CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData(); 636 if (!pGlobalData) 637 return; 638 639 for (auto* pResult : pGlobalData->m_Globals) { 640 if (!pResult->HasRemovedChildren()) 641 AddCalculateWidgetAcc(pResult->GetWidgetAcc()); 642 } 643 } 644 645 size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) { 646 while (index < m_CalculateAccs.size()) { 647 CXFA_Node* node = m_CalculateAccs[index]->GetNode(); 648 649 AddCalculateNodeNotify(node); 650 size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1; 651 node->JSObject()->SetCalcRecursionCount(recurse); 652 if (recurse > 11) 653 break; 654 if (node->ProcessCalculate(this) == XFA_EVENTERROR_Success) 655 AddValidateWidget(node->GetWidgetAcc()); 656 657 index = RunCalculateRecursive(++index); 658 } 659 return index; 660 } 661 662 int32_t CXFA_FFDocView::RunCalculateWidgets() { 663 if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc.Get())) 664 return XFA_EVENTERROR_Disabled; 665 if (!m_CalculateAccs.empty()) 666 RunCalculateRecursive(0); 667 668 for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs) 669 pCurAcc->GetNode()->JSObject()->SetCalcRecursionCount(0); 670 671 m_CalculateAccs.clear(); 672 return XFA_EVENTERROR_Success; 673 } 674 675 void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) { 676 if (!pdfium::ContainsValue(m_ValidateAccs, pWidget)) 677 m_ValidateAccs.push_back(pWidget); 678 } 679 680 void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) { 681 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true, 682 nullptr); 683 } 684 685 void CXFA_FFDocView::ProcessValueChanged(CXFA_WidgetAcc* widgetAcc) { 686 AddValidateWidget(widgetAcc); 687 AddCalculateWidgetAcc(widgetAcc); 688 RunCalculateWidgets(); 689 RunValidate(); 690 } 691 692 bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) { 693 if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get())) 694 return false; 695 696 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr); 697 m_ValidateAccs.clear(); 698 return true; 699 } 700 701 bool CXFA_FFDocView::RunValidate() { 702 if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get())) 703 return false; 704 705 for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) { 706 CXFA_Node* node = pAcc->GetNode(); 707 if (!node->HasRemovedChildren()) 708 node->ProcessValidate(this, 0); 709 } 710 m_ValidateAccs.clear(); 711 return true; 712 } 713 714 bool CXFA_FFDocView::RunEventLayoutReady() { 715 CXFA_Node* pRootItem = 716 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 717 if (!pRootItem) 718 return false; 719 720 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, 721 nullptr); 722 RunLayout(); 723 return true; 724 } 725 726 void CXFA_FFDocView::RunBindItems() { 727 for (auto* item : m_BindItems) { 728 if (item->HasRemovedChildren()) 729 continue; 730 731 CXFA_Node* pWidgetNode = item->GetParent(); 732 CXFA_WidgetAcc* pAcc = pWidgetNode->GetWidgetAcc(); 733 if (!pAcc) 734 continue; 735 736 CFXJSE_Engine* pScriptContext = 737 pWidgetNode->GetDocument()->GetScriptContext(); 738 WideString wsRef = item->GetRef(); 739 uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | 740 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | 741 XFA_RESOLVENODE_ALL; 742 XFA_RESOLVENODE_RS rs; 743 pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs, 744 dwStyle, nullptr); 745 pAcc->DeleteItem(-1, false, false); 746 if (rs.dwFlags != XFA_ResolveNode_RSType_Nodes || rs.objects.empty()) 747 continue; 748 749 WideString wsValueRef = item->GetValueRef(); 750 WideString wsLabelRef = item->GetLabelRef(); 751 const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef; 752 const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$"; 753 const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$"; 754 WideString wsValue; 755 WideString wsLabel; 756 uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false); 757 for (CXFA_Object* refObject : rs.objects) { 758 CXFA_Node* refNode = refObject->AsNode(); 759 if (!refNode) 760 continue; 761 762 if (bValueUseContent) { 763 wsValue = refNode->JSObject()->GetContent(false); 764 } else { 765 CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash); 766 wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false) 767 : refNode->JSObject()->GetContent(false); 768 } 769 770 if (!bUseValue) { 771 if (bLabelUseContent) { 772 wsLabel = refNode->JSObject()->GetContent(false); 773 } else { 774 CXFA_Node* nodeLabel = 775 refNode->GetFirstChildByName(wsLabelRef.AsStringView()); 776 if (nodeLabel) 777 wsLabel = nodeLabel->JSObject()->GetContent(false); 778 } 779 } else { 780 wsLabel = wsValue; 781 } 782 pAcc->InsertItem(wsLabel, wsValue, false); 783 } 784 } 785 m_BindItems.clear(); 786 } 787 788 void CXFA_FFDocView::SetChangeMark() { 789 if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) 790 return; 791 792 m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get()); 793 } 794 795 CXFA_Subform* CXFA_FFDocView::GetRootSubform() { 796 CXFA_Node* pFormPacketNode = 797 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); 798 if (!pFormPacketNode) 799 return nullptr; 800 801 return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>( 802 XFA_Element::Subform); 803 } 804