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/src/foxitlib.h" 8 #include "xfa/src/fxfa/src/common/xfa_common.h" 9 #include "xfa_fwladapter.h" 10 #include "xfa_ffpageview.h" 11 #include "xfa_ffwidget.h" 12 #include "xfa_ffdoc.h" 13 #include "xfa_ffdocview.h" 14 #include "xfa_fffield.h" 15 #include "xfa_ffpushbutton.h" 16 #include "xfa_ffcheckbutton.h" 17 #include "xfa_ffchoicelist.h" 18 #include "xfa_ffimageedit.h" 19 #include "xfa_fftextedit.h" 20 CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea) 21 : CXFA_ContainerLayoutItem(pPageArea), 22 m_pDocView(pDocView), 23 m_bLoaded(FALSE) {} 24 CXFA_FFPageView::~CXFA_FFPageView() {} 25 IXFA_DocView* CXFA_FFPageView::GetDocView() { 26 return m_pDocView; 27 } 28 int32_t CXFA_FFPageView::GetPageViewIndex() { 29 return GetPageIndex(); 30 } 31 void CXFA_FFPageView::GetPageViewRect(CFX_RectF& rtPage) { 32 CFX_SizeF sz; 33 GetPageSize(sz); 34 rtPage.Set(0, 0, sz); 35 } 36 void CXFA_FFPageView::GetDisplayMatrix(CFX_Matrix& mt, 37 const CFX_Rect& rtDisp, 38 int32_t iRotate) { 39 CFX_SizeF sz; 40 GetPageSize(sz); 41 CFX_RectF fdePage; 42 fdePage.Set(0, 0, sz.x, sz.y); 43 FDE_GetPageMatrix(mt, fdePage, rtDisp, iRotate, 0); 44 } 45 int32_t CXFA_FFPageView::LoadPageView(IFX_Pause* pPause) { 46 if (m_bLoaded) { 47 return 100; 48 } 49 m_bLoaded = TRUE; 50 return 100; 51 } 52 void CXFA_FFPageView::UnloadPageView() { 53 if (!m_bLoaded) { 54 return; 55 } 56 } 57 FX_BOOL CXFA_FFPageView::IsPageViewLoaded() { 58 return m_bLoaded; 59 } 60 IXFA_Widget* CXFA_FFPageView::GetWidgetByPos(FX_FLOAT fx, FX_FLOAT fy) { 61 if (!m_bLoaded) { 62 return nullptr; 63 } 64 IXFA_WidgetIterator* pIterator = CreateWidgetIterator(); 65 CXFA_FFWidget* pWidget = nullptr; 66 while ((pWidget = static_cast<CXFA_FFWidget*>(pIterator->MoveToNext()))) { 67 if (!(pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible)) { 68 continue; 69 } 70 CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc(); 71 int32_t type = pAcc->GetClassID(); 72 if (type != XFA_ELEMENT_Field && type != XFA_ELEMENT_Draw) { 73 continue; 74 } 75 FX_FLOAT fWidgetx = fx; 76 FX_FLOAT fWidgety = fy; 77 pWidget->Rotate2Normal(fWidgetx, fWidgety); 78 FX_DWORD dwFlag = pWidget->OnHitTest(fWidgetx, fWidgety); 79 if ((FWL_WGTHITTEST_Client == dwFlag || 80 FWL_WGTHITTEST_HyperLink == dwFlag)) { 81 break; 82 } 83 } 84 pIterator->Release(); 85 return pWidget; 86 } 87 IXFA_WidgetIterator* CXFA_FFPageView::CreateWidgetIterator( 88 FX_DWORD dwTraverseWay, 89 FX_DWORD dwWidgetFilter) { 90 switch (dwTraverseWay) { 91 case XFA_TRAVERSEWAY_Tranvalse: 92 return new CXFA_FFTabOrderPageWidgetIterator(this, dwWidgetFilter); 93 case XFA_TRAVERSEWAY_Form: 94 return new CXFA_FFPageWidgetIterator(this, dwWidgetFilter); 95 } 96 return NULL; 97 } 98 static FX_BOOL XFA_PageWidgetFilter(CXFA_FFWidget* pWidget, 99 FX_DWORD dwFilter, 100 FX_BOOL bTraversal, 101 FX_BOOL bIgnorerelevant) { 102 CXFA_WidgetAcc* pWidgetAcc = pWidget->GetDataAcc(); 103 FX_DWORD dwType = dwFilter & XFA_WIDGETFILTER_AllType; 104 if ((dwType == XFA_WIDGETFILTER_Field) && 105 (pWidgetAcc->GetClassID() != XFA_ELEMENT_Field)) { 106 return FALSE; 107 } 108 FX_DWORD dwStatus = pWidget->GetStatus(); 109 if (bTraversal && (dwStatus & XFA_WIDGETSTATUS_Disabled)) { 110 return FALSE; 111 } 112 if (bIgnorerelevant) { 113 return (dwStatus & XFA_WIDGETFILTER_Visible) != 0; 114 } 115 dwFilter &= (XFA_WIDGETFILTER_Visible | XFA_WIDGETFILTER_Viewable | 116 XFA_WIDGETFILTER_Printable); 117 return (dwFilter & dwStatus) == dwFilter; 118 } 119 CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(CXFA_FFPageView* pPageView, 120 FX_DWORD dwFilter) { 121 m_pPageView = pPageView; 122 m_dwFilter = dwFilter; 123 m_sIterator.Init(pPageView); 124 m_bIgnorerelevant = ((CXFA_FFDoc*)m_pPageView->GetDocView()->GetDoc()) 125 ->GetXFADoc() 126 ->GetCurVersionMode() < XFA_VERSION_205; 127 } 128 CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {} 129 void CXFA_FFPageWidgetIterator::Reset() { 130 m_sIterator.Reset(); 131 } 132 IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToFirst() { 133 m_sIterator.Reset(); 134 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem; 135 pLayoutItem = m_sIterator.MoveToNext()) { 136 if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) { 137 return hWidget; 138 } 139 } 140 return NULL; 141 } 142 IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToLast() { 143 m_sIterator.SetCurrent(NULL); 144 return MoveToPrevious(); 145 } 146 IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToNext() { 147 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem; 148 pLayoutItem = m_sIterator.MoveToNext()) { 149 if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) { 150 return hWidget; 151 } 152 } 153 return NULL; 154 } 155 IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToPrevious() { 156 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem; 157 pLayoutItem = m_sIterator.MoveToPrev()) { 158 if (IXFA_Widget* hWidget = GetWidget(pLayoutItem)) { 159 return hWidget; 160 } 161 } 162 return NULL; 163 } 164 IXFA_Widget* CXFA_FFPageWidgetIterator::GetCurrentWidget() { 165 CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); 166 return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : NULL; 167 } 168 FX_BOOL CXFA_FFPageWidgetIterator::SetCurrentWidget(IXFA_Widget* hWidget) { 169 CXFA_FFWidget* pWidget = static_cast<CXFA_FFWidget*>(hWidget); 170 return pWidget && m_sIterator.SetCurrent(pWidget); 171 } 172 IXFA_Widget* CXFA_FFPageWidgetIterator::GetWidget( 173 CXFA_LayoutItem* pLayoutItem) { 174 if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) { 175 if (!XFA_PageWidgetFilter(pWidget, m_dwFilter, FALSE, m_bIgnorerelevant)) { 176 return NULL; 177 } 178 if (!pWidget->IsLoaded() && 179 (pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible) != 0) { 180 pWidget->LoadWidget(); 181 } 182 return pWidget; 183 } 184 return NULL; 185 } 186 CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator( 187 CXFA_FFPageView* pPageView, 188 FX_DWORD dwFilter) 189 : m_pPageView(pPageView), m_dwFilter(dwFilter), m_iCurWidget(-1) { 190 m_bIgnorerelevant = ((CXFA_FFDoc*)m_pPageView->GetDocView()->GetDoc()) 191 ->GetXFADoc() 192 ->GetCurVersionMode() < XFA_VERSION_205; 193 Reset(); 194 } 195 CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {} 196 void CXFA_FFTabOrderPageWidgetIterator::Release() { 197 delete this; 198 } 199 void CXFA_FFTabOrderPageWidgetIterator::Reset() { 200 CreateTabOrderWidgetArray(); 201 m_iCurWidget = -1; 202 } 203 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() { 204 if (m_TabOrderWidgetArray.GetSize() > 0) { 205 for (int32_t i = 0; i < m_TabOrderWidgetArray.GetSize(); i++) { 206 if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, 207 m_bIgnorerelevant)) { 208 m_iCurWidget = i; 209 return m_TabOrderWidgetArray[m_iCurWidget]; 210 } 211 } 212 } 213 return NULL; 214 } 215 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() { 216 if (m_TabOrderWidgetArray.GetSize() > 0) { 217 for (int32_t i = m_TabOrderWidgetArray.GetSize() - 1; i >= 0; i--) { 218 if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, 219 m_bIgnorerelevant)) { 220 m_iCurWidget = i; 221 return m_TabOrderWidgetArray[m_iCurWidget]; 222 } 223 } 224 } 225 return NULL; 226 } 227 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() { 228 for (int32_t i = m_iCurWidget + 1; i < m_TabOrderWidgetArray.GetSize(); i++) { 229 if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, 230 m_bIgnorerelevant)) { 231 m_iCurWidget = i; 232 return m_TabOrderWidgetArray[m_iCurWidget]; 233 } 234 } 235 m_iCurWidget = -1; 236 return NULL; 237 } 238 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() { 239 for (int32_t i = m_iCurWidget - 1; i >= 0; i--) { 240 if (XFA_PageWidgetFilter(m_TabOrderWidgetArray[i], m_dwFilter, TRUE, 241 m_bIgnorerelevant)) { 242 m_iCurWidget = i; 243 return m_TabOrderWidgetArray[m_iCurWidget]; 244 } 245 } 246 m_iCurWidget = -1; 247 return NULL; 248 } 249 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() { 250 if (m_iCurWidget >= 0) { 251 return m_TabOrderWidgetArray[m_iCurWidget]; 252 } 253 return NULL; 254 } 255 FX_BOOL CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget( 256 IXFA_Widget* hWidget) { 257 int32_t iWidgetIndex = 258 m_TabOrderWidgetArray.Find(static_cast<CXFA_FFWidget*>(hWidget)); 259 if (iWidgetIndex >= 0) { 260 m_iCurWidget = iWidgetIndex; 261 return TRUE; 262 } 263 return FALSE; 264 } 265 CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget( 266 CXFA_FFWidget* pWidget) { 267 CXFA_WidgetAcc* pAcc = pWidget->GetDataAcc(); 268 CXFA_Node* pTraversal = pAcc->GetNode()->GetChild(0, XFA_ELEMENT_Traversal); 269 if (pTraversal != NULL) { 270 CXFA_Node* pTraverse = pTraversal->GetChild(0, XFA_ELEMENT_Traverse); 271 if (pTraverse != NULL) { 272 CFX_WideString wsTraverseWidgetName; 273 if (pTraverse->GetAttribute(XFA_ATTRIBUTE_Ref, wsTraverseWidgetName)) { 274 return FindWidgetByName(wsTraverseWidgetName, pWidget); 275 } 276 } 277 } 278 return NULL; 279 } 280 CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName( 281 const CFX_WideStringC& wsWidgetName, 282 CXFA_FFWidget* pRefWidget) { 283 return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget); 284 } 285 void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() { 286 m_TabOrderWidgetArray.RemoveAll(); 287 CXFA_WidgetArray SpaceOrderWidgetArray; 288 CreateSpaceOrderWidgetArray(SpaceOrderWidgetArray); 289 int32_t nWidgetCount = SpaceOrderWidgetArray.GetSize(); 290 if (nWidgetCount < 1) { 291 return; 292 } 293 CXFA_FFWidget* hWidget = SpaceOrderWidgetArray[0]; 294 for (; m_TabOrderWidgetArray.GetSize() < nWidgetCount;) { 295 if (m_TabOrderWidgetArray.Find(hWidget) < 0) { 296 m_TabOrderWidgetArray.Add(hWidget); 297 CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc(); 298 if (pWidgetAcc->GetUIType() == XFA_ELEMENT_ExclGroup) { 299 int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget) + 1; 300 while (TRUE) { 301 CXFA_FFWidget* pRadio = 302 SpaceOrderWidgetArray[(iWidgetIndex) % nWidgetCount]; 303 if (pRadio->GetDataAcc()->GetExclGroup() != pWidgetAcc) { 304 break; 305 } 306 if (m_TabOrderWidgetArray.Find(hWidget) < 0) { 307 m_TabOrderWidgetArray.Add(pRadio); 308 } 309 iWidgetIndex++; 310 } 311 } 312 if (CXFA_FFWidget* hTraverseWidget = GetTraverseWidget(hWidget)) { 313 hWidget = hTraverseWidget; 314 continue; 315 } 316 } 317 int32_t iWidgetIndex = SpaceOrderWidgetArray.Find(hWidget); 318 hWidget = SpaceOrderWidgetArray[(iWidgetIndex + 1) % nWidgetCount]; 319 } 320 } 321 static int32_t XFA_TabOrderWidgetComparator(const void* phWidget1, 322 const void* phWidget2) { 323 CXFA_FFWidget* pWidget1 = (*(CXFA_TabParam**)phWidget1)->m_pWidget; 324 CXFA_FFWidget* pWidget2 = (*(CXFA_TabParam**)phWidget2)->m_pWidget; 325 CFX_RectF rt1, rt2; 326 pWidget1->GetWidgetRect(rt1); 327 pWidget2->GetWidgetRect(rt2); 328 FX_FLOAT x1 = rt1.left, y1 = rt1.top, x2 = rt2.left, y2 = rt2.top; 329 if (y1 < y2 || (y1 - y2 < XFA_FLOAT_PERCISION && x1 < x2)) { 330 return -1; 331 } 332 return 1; 333 } 334 void CXFA_FFTabOrderPageWidgetIterator::OrderContainer( 335 CXFA_LayoutItemIterator* sIterator, 336 CXFA_LayoutItem* pContainerItem, 337 CXFA_TabParam* pContainer, 338 FX_BOOL& bCurrentItem, 339 FX_BOOL& bContentArea, 340 FX_BOOL bMarsterPage) { 341 CFX_PtrArray tabParams; 342 CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext(); 343 while (pSearchItem) { 344 if (!pSearchItem->IsContentLayoutItem()) { 345 bContentArea = TRUE; 346 pSearchItem = sIterator->MoveToNext(); 347 continue; 348 } 349 if (bMarsterPage && bContentArea) { 350 break; 351 } 352 if (bMarsterPage || bContentArea) { 353 CXFA_FFWidget* hWidget = GetWidget(pSearchItem); 354 if (!hWidget) { 355 pSearchItem = sIterator->MoveToNext(); 356 continue; 357 } 358 if (pContainerItem && (pSearchItem->GetParent() != pContainerItem)) { 359 bCurrentItem = TRUE; 360 break; 361 } 362 CXFA_TabParam* pParam = new CXFA_TabParam; 363 pParam->m_pWidget = hWidget; 364 tabParams.Add(pParam); 365 if (XFA_IsLayoutElement(pSearchItem->GetFormNode()->GetClassID(), TRUE)) { 366 OrderContainer(sIterator, pSearchItem, pParam, bCurrentItem, 367 bContentArea, bMarsterPage); 368 } 369 } 370 if (bCurrentItem) { 371 pSearchItem = sIterator->GetCurrent(); 372 bCurrentItem = FALSE; 373 } else { 374 pSearchItem = sIterator->MoveToNext(); 375 } 376 } 377 int32_t iChildren = tabParams.GetSize(); 378 if (iChildren > 1) { 379 FXSYS_qsort(tabParams.GetData(), iChildren, sizeof(void*), 380 XFA_TabOrderWidgetComparator); 381 } 382 for (int32_t iStart = 0; iStart < iChildren; iStart++) { 383 CXFA_TabParam* pParam = (CXFA_TabParam*)tabParams[iStart]; 384 pContainer->m_Children.Add(pParam->m_pWidget); 385 if (pParam->m_Children.GetSize() > 0) { 386 pContainer->m_Children.Append(pParam->m_Children); 387 } 388 delete pParam; 389 } 390 tabParams.RemoveAll(); 391 } 392 void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray( 393 CXFA_WidgetArray& WidgetArray) { 394 CXFA_LayoutItemIterator sIterator; 395 sIterator.Init(m_pPageView); 396 CXFA_TabParam* pParam = new CXFA_TabParam; 397 FX_BOOL bCurrentItem = FALSE; 398 FX_BOOL bContentArea = FALSE; 399 OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea); 400 if (pParam->m_Children.GetSize() > 0) { 401 WidgetArray.Append(pParam->m_Children); 402 } 403 sIterator.Reset(); 404 bCurrentItem = FALSE; 405 bContentArea = FALSE; 406 pParam->m_Children.RemoveAll(); 407 OrderContainer(&sIterator, NULL, pParam, bCurrentItem, bContentArea, TRUE); 408 if (pParam->m_Children.GetSize() > 0) { 409 WidgetArray.Append(pParam->m_Children); 410 } 411 delete pParam; 412 } 413 CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetWidget( 414 CXFA_LayoutItem* pLayoutItem) { 415 if (CXFA_FFWidget* pWidget = XFA_GetWidgetFromLayoutItem(pLayoutItem)) { 416 if (!pWidget->IsLoaded() && 417 (pWidget->GetStatus() & XFA_WIDGETSTATUS_Visible)) { 418 pWidget->LoadWidget(); 419 } 420 return pWidget; 421 } 422 return NULL; 423 } 424