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