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"
CXFA_FFPageView(CXFA_FFDocView * pDocView,CXFA_Node * pPageArea)20 CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea)
21     : CXFA_ContainerLayoutItem(pPageArea),
22       m_pDocView(pDocView),
23       m_bLoaded(FALSE) {}
~CXFA_FFPageView()24 CXFA_FFPageView::~CXFA_FFPageView() {}
GetDocView()25 IXFA_DocView* CXFA_FFPageView::GetDocView() {
26   return m_pDocView;
27 }
GetPageViewIndex()28 int32_t CXFA_FFPageView::GetPageViewIndex() {
29   return GetPageIndex();
30 }
GetPageViewRect(CFX_RectF & rtPage)31 void CXFA_FFPageView::GetPageViewRect(CFX_RectF& rtPage) {
32   CFX_SizeF sz;
33   GetPageSize(sz);
34   rtPage.Set(0, 0, sz);
35 }
GetDisplayMatrix(CFX_Matrix & mt,const CFX_Rect & rtDisp,int32_t iRotate)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 }
LoadPageView(IFX_Pause * pPause)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 }
UnloadPageView()52 void CXFA_FFPageView::UnloadPageView() {
53   if (!m_bLoaded) {
54     return;
55   }
56 }
IsPageViewLoaded()57 FX_BOOL CXFA_FFPageView::IsPageViewLoaded() {
58   return m_bLoaded;
59 }
GetWidgetByPos(FX_FLOAT fx,FX_FLOAT fy)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 }
CreateWidgetIterator(FX_DWORD dwTraverseWay,FX_DWORD dwWidgetFilter)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 }
XFA_PageWidgetFilter(CXFA_FFWidget * pWidget,FX_DWORD dwFilter,FX_BOOL bTraversal,FX_BOOL bIgnorerelevant)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 }
CXFA_FFPageWidgetIterator(CXFA_FFPageView * pPageView,FX_DWORD dwFilter)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 }
~CXFA_FFPageWidgetIterator()128 CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() {}
Reset()129 void CXFA_FFPageWidgetIterator::Reset() {
130   m_sIterator.Reset();
131 }
MoveToFirst()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 }
MoveToLast()142 IXFA_Widget* CXFA_FFPageWidgetIterator::MoveToLast() {
143   m_sIterator.SetCurrent(NULL);
144   return MoveToPrevious();
145 }
MoveToNext()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 }
MoveToPrevious()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 }
GetCurrentWidget()164 IXFA_Widget* CXFA_FFPageWidgetIterator::GetCurrentWidget() {
165   CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent();
166   return pLayoutItem ? XFA_GetWidgetFromLayoutItem(pLayoutItem) : NULL;
167 }
SetCurrentWidget(IXFA_Widget * hWidget)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 }
GetWidget(CXFA_LayoutItem * pLayoutItem)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 }
CXFA_FFTabOrderPageWidgetIterator(CXFA_FFPageView * pPageView,FX_DWORD dwFilter)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 }
~CXFA_FFTabOrderPageWidgetIterator()195 CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() {}
Release()196 void CXFA_FFTabOrderPageWidgetIterator::Release() {
197   delete this;
198 }
Reset()199 void CXFA_FFTabOrderPageWidgetIterator::Reset() {
200   CreateTabOrderWidgetArray();
201   m_iCurWidget = -1;
202 }
MoveToFirst()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 }
MoveToLast()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 }
MoveToNext()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 }
MoveToPrevious()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 }
GetCurrentWidget()249 IXFA_Widget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() {
250   if (m_iCurWidget >= 0) {
251     return m_TabOrderWidgetArray[m_iCurWidget];
252   }
253   return NULL;
254 }
SetCurrentWidget(IXFA_Widget * hWidget)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 }
GetTraverseWidget(CXFA_FFWidget * pWidget)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 }
FindWidgetByName(const CFX_WideStringC & wsWidgetName,CXFA_FFWidget * pRefWidget)280 CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName(
281     const CFX_WideStringC& wsWidgetName,
282     CXFA_FFWidget* pRefWidget) {
283   return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget);
284 }
CreateTabOrderWidgetArray()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 }
XFA_TabOrderWidgetComparator(const void * phWidget1,const void * phWidget2)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 }
OrderContainer(CXFA_LayoutItemIterator * sIterator,CXFA_LayoutItem * pContainerItem,CXFA_TabParam * pContainer,FX_BOOL & bCurrentItem,FX_BOOL & bContentArea,FX_BOOL bMarsterPage)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 }
CreateSpaceOrderWidgetArray(CXFA_WidgetArray & WidgetArray)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 }
GetWidget(CXFA_LayoutItem * pLayoutItem)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