Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxfa / src / parser / xfa_layout_pagemgr_new.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "../common/xfa_utils.h"\r
9 #include "../common/xfa_object.h"\r
10 #include "../common/xfa_document.h"\r
11 #include "../common/xfa_parser.h"\r
12 #include "../common/xfa_script.h"\r
13 #include "../common/xfa_docdata.h"\r
14 #include "../common/xfa_doclayout.h"\r
15 #include "../common/xfa_debug.h"\r
16 #include "../common/xfa_localemgr.h"\r
17 #include "../common/xfa_fm2jsapi.h"\r
18 #include "xfa_debug_parser.h"\r
19 #include "xfa_document_datamerger_imp.h"\r
20 #include "xfa_document_layout_imp.h"\r
21 #include "xfa_layout_itemlayout.h"\r
22 #include "xfa_layout_pagemgr_new.h"\r
23 #include "xfa_layout_appadapter.h"\r
24 CXFA_LayoutPageMgr::CXFA_LayoutPageMgr(CXFA_LayoutProcessor* pLayoutProcessor)\r
25     : m_pLayoutProcessor(pLayoutProcessor)\r
26     , m_pTemplatePageSetRoot(NULL)\r
27     , m_pPageSetLayoutItemRoot(NULL)\r
28     , m_pCurrentContainerRecord(NULL)\r
29     , m_nCurPageCount(0)\r
30     , m_pCurPageArea(NULL)\r
31     , m_ePageSetMode(XFA_ATTRIBUTEENUM_OrderedOccurrence)\r
32     , m_nAvailPages(0)\r
33     , m_pPageSetCurRoot(NULL)\r
34     , m_bCreateOverFlowPage(FALSE)\r
35 {\r
36 }\r
37 CXFA_LayoutPageMgr::~CXFA_LayoutPageMgr()\r
38 {\r
39     ClearData();\r
40     CXFA_LayoutItemImpl *pLayoutItem = GetRootLayoutItem();\r
41     CXFA_LayoutItemImpl *pNextLayout = NULL;\r
42     for(; pLayoutItem; pLayoutItem = pNextLayout) {\r
43         pNextLayout = pLayoutItem->m_pNextSibling;\r
44         XFA_ReleaseLayoutItem(pLayoutItem);\r
45     }\r
46 }\r
47 FX_BOOL CXFA_LayoutPageMgr::InitLayoutPage(CXFA_Node* pFormNode)\r
48 {\r
49     PrepareLayout();\r
50     CXFA_Node* pTemplateNode = pFormNode->GetTemplateNode();\r
51     if (!pTemplateNode) {\r
52         return FALSE;\r
53     }\r
54     m_pTemplatePageSetRoot = pTemplateNode->GetProperty(0, XFA_ELEMENT_PageSet);\r
55     ASSERT(m_pTemplatePageSetRoot);\r
56     if (m_pPageSetLayoutItemRoot) {\r
57         m_pPageSetLayoutItemRoot->m_pParent = NULL;\r
58         m_pPageSetLayoutItemRoot->m_pFirstChild = NULL;\r
59         m_pPageSetLayoutItemRoot->m_pNextSibling = NULL;\r
60         m_pPageSetLayoutItemRoot->m_pFormNode = m_pTemplatePageSetRoot;\r
61     } else {\r
62         m_pPageSetLayoutItemRoot = FX_NEW CXFA_ContainerLayoutItemImpl(m_pTemplatePageSetRoot);\r
63     }\r
64     m_pPageSetCurRoot = m_pPageSetLayoutItemRoot;\r
65     m_pTemplatePageSetRoot->SetUserData(XFA_LAYOUTITEMKEY, (FX_LPVOID)m_pPageSetLayoutItemRoot);\r
66     XFA_ATTRIBUTEENUM eRelation = m_pTemplatePageSetRoot->GetEnum(XFA_ATTRIBUTE_Relation);\r
67     if(eRelation != XFA_ATTRIBUTEENUM_Unknown) {\r
68         m_ePageSetMode = eRelation;\r
69     }\r
70     InitPageSetMap();\r
71     CXFA_Node* pPageArea = NULL;\r
72     FX_INT32 iCount = 0;\r
73     for (pPageArea = m_pTemplatePageSetRoot->GetNodeItem(XFA_NODEITEM_FirstChild); pPageArea; pPageArea = pPageArea->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
74         if (pPageArea->GetClassID() == XFA_ELEMENT_PageArea) {\r
75             iCount++;\r
76             if (pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea)) {\r
77                 return TRUE;\r
78             }\r
79         }\r
80     }\r
81     if (iCount > 0) {\r
82         return FALSE;\r
83     }\r
84     CXFA_Document* pDocument = pTemplateNode->GetDocument();\r
85     IXFA_ObjFactory* pObjFactory = pDocument->GetParser()->GetFactory();\r
86     pPageArea = m_pTemplatePageSetRoot->GetChild(0, XFA_ELEMENT_PageArea);\r
87     if (!pPageArea) {\r
88         pPageArea = pObjFactory->CreateNode(m_pTemplatePageSetRoot->GetPacketID(), XFA_ELEMENT_PageArea);\r
89         if(!pPageArea) {\r
90             return FALSE;\r
91         }\r
92         m_pTemplatePageSetRoot->InsertChild(pPageArea, NULL);\r
93         pPageArea->SetFlag(XFA_NODEFLAG_Initialized);\r
94     }\r
95     CXFA_Node* pContentArea = pPageArea->GetChild(0, XFA_ELEMENT_ContentArea);\r
96     if (!pContentArea) {\r
97         pContentArea = pObjFactory->CreateNode(pPageArea->GetPacketID(), XFA_ELEMENT_ContentArea);\r
98         if(!pContentArea) {\r
99             return FALSE;\r
100         }\r
101         pPageArea->InsertChild(pContentArea, NULL);\r
102         pContentArea->SetFlag(XFA_NODEFLAG_Initialized);\r
103         pContentArea->SetMeasure(XFA_ATTRIBUTE_X, CXFA_Measurement(0.25f, XFA_UNIT_In));\r
104         pContentArea->SetMeasure(XFA_ATTRIBUTE_Y, CXFA_Measurement(0.25f, XFA_UNIT_In));\r
105         pContentArea->SetMeasure(XFA_ATTRIBUTE_W, CXFA_Measurement(8.0f, XFA_UNIT_In));\r
106         pContentArea->SetMeasure(XFA_ATTRIBUTE_H, CXFA_Measurement(10.5f, XFA_UNIT_In));\r
107     }\r
108     CXFA_Node* pMedium  = pPageArea->GetChild(0, XFA_ELEMENT_Medium);\r
109     if (!pMedium) {\r
110         pMedium = pObjFactory->CreateNode(pPageArea->GetPacketID(), XFA_ELEMENT_Medium);\r
111         if(!pContentArea) {\r
112             return FALSE;\r
113         }\r
114         pPageArea->InsertChild(pMedium, NULL);\r
115         pMedium->SetFlag(XFA_NODEFLAG_Initialized);\r
116         pMedium->SetMeasure(XFA_ATTRIBUTE_Short, CXFA_Measurement(8.5f, XFA_UNIT_In));\r
117         pMedium->SetMeasure(XFA_ATTRIBUTE_Long, CXFA_Measurement(11.0f, XFA_UNIT_In));\r
118     }\r
119     return TRUE;\r
120 }\r
121 FX_BOOL CXFA_LayoutPageMgr::PrepareFirstPage(CXFA_Node* pRootSubform)\r
122 {\r
123     FX_BOOL bProBreakBefore = FALSE;\r
124     CXFA_Node* pBreakBeforeNode = NULL;\r
125     while (pRootSubform) {\r
126         for(CXFA_Node* pBreakNode = pRootSubform->GetNodeItem(XFA_NODEITEM_FirstChild); pBreakNode; pBreakNode = pBreakNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
127             XFA_ELEMENT eType = pBreakNode->GetClassID();\r
128             if (eType == XFA_ELEMENT_BreakBefore || (eType == XFA_ELEMENT_Break && pBreakNode->GetEnum(XFA_ATTRIBUTE_Before) != XFA_ATTRIBUTEENUM_Auto)) {\r
129                 bProBreakBefore = TRUE;\r
130                 pBreakBeforeNode = pBreakNode;\r
131                 break;\r
132             }\r
133         }\r
134         if (bProBreakBefore) {\r
135             break;\r
136         }\r
137         bProBreakBefore = TRUE;\r
138         pRootSubform = pRootSubform->GetFirstChildByClass(XFA_ELEMENT_Subform);\r
139         while (pRootSubform && !XFA_ItemLayoutProcessor_IsTakingSpace(pRootSubform)) {\r
140             pRootSubform = pRootSubform->GetNextSameClassSibling(XFA_ELEMENT_Subform);\r
141         }\r
142     }\r
143     CXFA_Node* pLeader, *pTrailer;\r
144     if (pBreakBeforeNode && ExecuteBreakBeforeOrAfter(pBreakBeforeNode, TRUE, pLeader, pTrailer)) {\r
145         m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition();\r
146         return TRUE;\r
147     }\r
148     return AppendNewPage(TRUE);\r
149 }\r
150 FX_BOOL  CXFA_LayoutPageMgr::AppendNewPage(FX_BOOL bFirstTemPage)\r
151 {\r
152     if(m_pCurrentContainerRecord != m_rgProposedContainerRecord.GetTailPosition()) {\r
153         return TRUE;\r
154     }\r
155     CXFA_Node* pPageNode = GetNextAvailPageArea(NULL);\r
156     if (!pPageNode) {\r
157         return FALSE;\r
158     }\r
159     if (bFirstTemPage && m_pCurrentContainerRecord == NULL) {\r
160         m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetHeadPosition();\r
161     }\r
162     return !bFirstTemPage || m_pCurrentContainerRecord != NULL;\r
163 }\r
164 static void XFA_LayoutItemMgr_ReorderLayoutItemToTail(CXFA_ContainerLayoutItemImpl* pLayoutItem)\r
165 {\r
166     CXFA_ContainerLayoutItemImpl* pParentLayoutItem = (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pParent;\r
167     if(!pParentLayoutItem) {\r
168         return;\r
169     }\r
170     CXFA_LayoutItemImpl* pNext = pLayoutItem->m_pNextSibling;\r
171     pParentLayoutItem->RemoveChild(pLayoutItem);\r
172     pParentLayoutItem->AddChild(pLayoutItem);\r
173 }\r
174 static void XFA_LayoutItemMgr_RemoveLayoutItem(CXFA_ContainerLayoutItemImpl* pLayoutItem)\r
175 {\r
176     CXFA_ContainerLayoutItemImpl* pParentLayoutItem = (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pParent;\r
177     if(!pParentLayoutItem) {\r
178         return;\r
179     }\r
180     CXFA_LayoutItemImpl* pNext = pLayoutItem->m_pNextSibling;\r
181     pParentLayoutItem->RemoveChild(pLayoutItem);\r
182 }\r
183 void CXFA_LayoutPageMgr::RemoveLayoutRecord(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord)\r
184 {\r
185     if(!pNewRecord || !pPrevRecord) {\r
186         return;\r
187     }\r
188     if(pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) {\r
189         XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageSet);\r
190         return;\r
191     }\r
192     if(pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) {\r
193         XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurPageArea);\r
194         return;\r
195     }\r
196     if(pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) {\r
197         XFA_LayoutItemMgr_RemoveLayoutItem(pNewRecord->pCurContentArea);\r
198         return;\r
199     }\r
200 }\r
201 void CXFA_LayoutPageMgr::ReorderPendingLayoutRecordToTail(CXFA_ContainerRecord* pNewRecord, CXFA_ContainerRecord* pPrevRecord)\r
202 {\r
203     if(!pNewRecord || !pPrevRecord) {\r
204         return;\r
205     }\r
206     if(pNewRecord->pCurPageSet != pPrevRecord->pCurPageSet) {\r
207         XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageSet);\r
208         return;\r
209     }\r
210     if(pNewRecord->pCurPageArea != pPrevRecord->pCurPageArea) {\r
211         XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurPageArea);\r
212         return;\r
213     }\r
214     if(pNewRecord->pCurContentArea != pPrevRecord->pCurContentArea) {\r
215         XFA_LayoutItemMgr_ReorderLayoutItemToTail(pNewRecord->pCurContentArea);\r
216         return;\r
217     }\r
218 }\r
219 void CXFA_LayoutPageMgr::SubmitContentItem(CXFA_ContentLayoutItemImpl* pContentLayoutItem, XFA_ItemLayoutProcessorResult eStatus)\r
220 {\r
221     if(pContentLayoutItem) {\r
222         GetCurrentContainerRecord()->pCurContentArea->AddChild(pContentLayoutItem);\r
223         m_bCreateOverFlowPage = FALSE;\r
224     }\r
225     if(eStatus != XFA_ItemLayoutProcessorResult_Done) {\r
226         if(eStatus == XFA_ItemLayoutProcessorResult_PageFullBreak && m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetTailPosition()) {\r
227             AppendNewPage();\r
228         }\r
229         m_pCurrentContainerRecord = m_rgProposedContainerRecord.GetTailPosition();\r
230         m_pCurPageArea = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode;\r
231     }\r
232 }\r
233 FX_FLOAT CXFA_LayoutPageMgr::GetAvailHeight()\r
234 {\r
235     FX_FLOAT fAvailHeight = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);\r
236     if (fAvailHeight < XFA_LAYOUT_FLOAT_PERCISION) {\r
237         if (m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetHeadPosition()) {\r
238             fAvailHeight = 0;\r
239         } else {\r
240             fAvailHeight = XFA_LAYOUT_FLOAT_MAX;\r
241         }\r
242     }\r
243     return fAvailHeight;\r
244 }\r
245 static CXFA_Node* XFA_ResolveBreakTarget(CXFA_Node* pPageSetRoot, FX_BOOL bNewExprStyle, CFX_WideStringC& wsTargetExpr)\r
246 {\r
247     CXFA_Document* pDocument = pPageSetRoot->GetDocument();\r
248     if(wsTargetExpr.IsEmpty()) {\r
249         return NULL;\r
250     }\r
251     CFX_WideString wsTargetAll = wsTargetExpr;\r
252     wsTargetAll.TrimLeft();\r
253     wsTargetAll.TrimRight();\r
254     FX_INT32 iSpliteIndex = 0;\r
255     FX_BOOL bTargetAllFind = TRUE;\r
256     while(iSpliteIndex != -1) {\r
257         CFX_WideString wsTargetExpr;\r
258         FX_INT32 iSpliteNextIndex = 0;\r
259         if(!bTargetAllFind) {\r
260             iSpliteNextIndex = wsTargetAll.Find(' ', iSpliteIndex);\r
261             wsTargetExpr = wsTargetAll.Mid(iSpliteIndex, iSpliteNextIndex - iSpliteIndex);\r
262         } else {\r
263             wsTargetExpr = wsTargetAll;\r
264         }\r
265         if(wsTargetExpr.IsEmpty()) {\r
266             return NULL;\r
267         }\r
268         bTargetAllFind = FALSE;\r
269         if(wsTargetExpr.GetAt(0) == '#') {\r
270             CXFA_Node *pNode = pDocument->GetNodeByID((CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Template), wsTargetExpr.Mid(1));\r
271             if(pNode) {\r
272                 return pNode;\r
273             }\r
274         } else if(bNewExprStyle) {\r
275             CFX_WideString wsProcessedTarget =  wsTargetExpr;\r
276             if(wsTargetExpr.Left(4) == FX_WSTRC(L"som(") && wsTargetExpr.Right(1) == FX_WSTRC(L")")) {\r
277                 wsProcessedTarget = wsTargetExpr.Mid(4, wsTargetExpr.GetLength() - 5);\r
278             }\r
279             XFA_RESOLVENODE_RS rs;\r
280             FX_INT32 iCount = pDocument->GetScriptContext()->ResolveObjects(pPageSetRoot, wsProcessedTarget, rs, XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent);\r
281             if(iCount > 0 && rs.nodes[0]->IsNode()) {\r
282                 return (CXFA_Node*)rs.nodes[0];\r
283             }\r
284         }\r
285         iSpliteIndex = iSpliteNextIndex;\r
286     }\r
287     return NULL;\r
288 }\r
289 \r
290 FX_BOOL XFA_LayoutPageMgr_RunBreakTestScript(CXFA_Node* pTestScript)\r
291 {\r
292     CFX_WideString wsExpression;\r
293     pTestScript->TryContent(wsExpression);\r
294     if(wsExpression.IsEmpty()) {\r
295         return TRUE;\r
296     }\r
297     return pTestScript->GetDocument()->GetParser()->GetNotify()->RunScript(pTestScript, pTestScript->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode));\r
298 }\r
299 CXFA_ContainerRecord* CXFA_LayoutPageMgr::CreateContainerRecord(CXFA_Node* pPageNode, FX_BOOL bCreateNew)\r
300 {\r
301     CXFA_ContainerRecord* pNewRecord = FX_NEW CXFA_ContainerRecord();\r
302     if(m_pCurrentContainerRecord) {\r
303         if(!IsPageSetRootOrderedOccurrence() || pPageNode == NULL) {\r
304             *pNewRecord = *GetCurrentContainerRecord();\r
305             m_rgProposedContainerRecord.AddTail(pNewRecord);\r
306             return pNewRecord;\r
307         }\r
308         CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent);\r
309         if(!bCreateNew) {\r
310             if(pPageSet == m_pTemplatePageSetRoot) {\r
311                 pNewRecord->pCurPageSet = m_pPageSetCurRoot;\r
312             } else {\r
313                 CXFA_ContainerLayoutItemImpl* pParentLayoutItem = (CXFA_ContainerLayoutItemImpl*)pPageSet->GetUserData(XFA_LAYOUTITEMKEY);\r
314                 if(pParentLayoutItem == NULL) {\r
315                     pParentLayoutItem = m_pPageSetCurRoot;\r
316                 }\r
317                 pNewRecord->pCurPageSet = pParentLayoutItem;\r
318             }\r
319         } else {\r
320             CXFA_ContainerLayoutItemImpl* pParentPageSetLayout = NULL;\r
321             if(pPageSet == GetCurrentContainerRecord()->pCurPageSet->m_pFormNode) {\r
322                 pParentPageSetLayout = (CXFA_ContainerLayoutItemImpl*)GetCurrentContainerRecord()->pCurPageSet->m_pParent;\r
323             } else {\r
324                 pParentPageSetLayout = (CXFA_ContainerLayoutItemImpl*)pPageSet->GetNodeItem(XFA_NODEITEM_Parent)->GetUserData(XFA_LAYOUTITEMKEY);\r
325             }\r
326             CXFA_ContainerLayoutItemImpl* pPageSetLayoutItem = FX_NEW CXFA_ContainerLayoutItemImpl(pPageSet);\r
327             pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (FX_LPVOID)pPageSetLayoutItem);\r
328             if(pParentPageSetLayout == NULL) {\r
329                 CXFA_ContainerLayoutItemImpl* pPrePageSet = m_pPageSetLayoutItemRoot;\r
330                 while(pPrePageSet->m_pNextSibling) {\r
331                     pPrePageSet = (CXFA_ContainerLayoutItemImpl*)pPrePageSet->m_pNextSibling;\r
332                 }\r
333                 pPrePageSet->m_pNextSibling = pPageSetLayoutItem;\r
334                 m_pPageSetCurRoot = pPageSetLayoutItem;\r
335             } else {\r
336                 pParentPageSetLayout->AddChild(pPageSetLayoutItem);\r
337             }\r
338             pNewRecord->pCurPageSet = pPageSetLayoutItem;\r
339         }\r
340     } else {\r
341         if(pPageNode) {\r
342             CXFA_Node* pPageSet = pPageNode->GetNodeItem(XFA_NODEITEM_Parent);\r
343             if(pPageSet == m_pTemplatePageSetRoot) {\r
344                 pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot;\r
345             } else {\r
346                 CXFA_ContainerLayoutItemImpl* pPageSetLayoutItem = FX_NEW CXFA_ContainerLayoutItemImpl(pPageSet);\r
347                 pPageSet->SetUserData(XFA_LAYOUTITEMKEY, (FX_LPVOID)pPageSetLayoutItem);\r
348                 m_pPageSetLayoutItemRoot->AddChild(pPageSetLayoutItem);\r
349                 pNewRecord->pCurPageSet = pPageSetLayoutItem;\r
350             }\r
351         } else {\r
352             pNewRecord->pCurPageSet = m_pPageSetLayoutItemRoot;\r
353         }\r
354     }\r
355     m_rgProposedContainerRecord.AddTail(pNewRecord);\r
356     return pNewRecord;\r
357 }\r
358 void CXFA_LayoutPageMgr::AddPageAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pNewPageArea)\r
359 {\r
360     CXFA_ContainerLayoutItemImpl* pNewPageAreaLayoutItem = NULL;\r
361     if (m_PageArray.GetSize() > m_nAvailPages) {\r
362         CXFA_ContainerLayoutItemImpl* pContainerItem = m_PageArray[m_nAvailPages];\r
363         pContainerItem->m_pFormNode = pNewPageArea;\r
364         m_nAvailPages++;\r
365         pNewPageAreaLayoutItem = pContainerItem;\r
366     } else {\r
367         IXFA_Notify* pNotify = pNewPageArea->GetDocument()->GetParser()->GetNotify();\r
368         CXFA_ContainerLayoutItemImpl* pContainerItem = (CXFA_ContainerLayoutItemImpl*)pNotify->OnCreateLayoutItem(pNewPageArea);\r
369         m_PageArray.Add(pContainerItem);\r
370         m_nAvailPages++;\r
371         pNotify->OnPageEvent((IXFA_LayoutPage*)pContainerItem, XFA_PAGEEVENT_PageAdded, (FX_LPVOID)(FX_UINTPTR)m_nAvailPages);\r
372         pNewPageAreaLayoutItem = pContainerItem;\r
373     }\r
374     pNewRecord->pCurPageSet->AddChild(pNewPageAreaLayoutItem);\r
375     pNewRecord->pCurPageArea = pNewPageAreaLayoutItem;\r
376     pNewRecord->pCurContentArea = NULL;\r
377 }\r
378 void CXFA_LayoutPageMgr::AddContentAreaLayoutItem(CXFA_ContainerRecord* pNewRecord, CXFA_Node* pContentArea)\r
379 {\r
380     if(pContentArea == NULL) {\r
381         pNewRecord->pCurContentArea = NULL;\r
382         return;\r
383     }\r
384     CXFA_ContainerLayoutItemImpl* pNewContentAreaLayoutItem = FX_NEW CXFA_ContainerLayoutItemImpl(pContentArea);\r
385     ASSERT(pNewRecord->pCurPageArea);\r
386     pNewRecord->pCurPageArea->AddChild(pNewContentAreaLayoutItem);\r
387     pNewRecord->pCurContentArea = pNewContentAreaLayoutItem;\r
388 }\r
389 class CXFA_TraverseStrategy_PageSetContainerLayoutItem\r
390 {\r
391 public:\r
392     static inline CXFA_ContainerLayoutItemImpl* GetFirstChild(CXFA_ContainerLayoutItemImpl* pLayoutItem)\r
393     {\r
394         if(pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
395             CXFA_ContainerLayoutItemImpl* pChildItem = (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pFirstChild;\r
396             while(pChildItem && pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) {\r
397                 pChildItem = (CXFA_ContainerLayoutItemImpl*)pChildItem->m_pNextSibling;\r
398             }\r
399             return pChildItem;\r
400         }\r
401         return NULL;\r
402     }\r
403     static inline CXFA_ContainerLayoutItemImpl* GetNextSibling(CXFA_ContainerLayoutItemImpl* pLayoutItem)\r
404     {\r
405         CXFA_ContainerLayoutItemImpl* pChildItem = (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pNextSibling;\r
406         while(pChildItem && pChildItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageSet) {\r
407             pChildItem = (CXFA_ContainerLayoutItemImpl*)pChildItem->m_pNextSibling;\r
408         }\r
409         return pChildItem;\r
410     }\r
411     static inline CXFA_ContainerLayoutItemImpl* GetParent(CXFA_ContainerLayoutItemImpl* pLayoutItem)\r
412     {\r
413         return (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pParent;\r
414     }\r
415 };\r
416 void CXFA_LayoutPageMgr::FinishPaginatedPageSets()\r
417 {\r
418     CXFA_ContainerLayoutItemImpl* pRootPageSetLayoutItem = m_pPageSetLayoutItemRoot;\r
419     for (; pRootPageSetLayoutItem; pRootPageSetLayoutItem = (CXFA_ContainerLayoutItemImpl*)pRootPageSetLayoutItem->m_pNextSibling) {\r
420         CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItemImpl, CXFA_TraverseStrategy_PageSetContainerLayoutItem> sIterator(pRootPageSetLayoutItem);\r
421         for(CXFA_ContainerLayoutItemImpl *pPageSetLayoutItem = sIterator.GetCurrent(); pPageSetLayoutItem; pPageSetLayoutItem = sIterator.MoveToNext()) {\r
422             XFA_ATTRIBUTEENUM ePageRelation = pPageSetLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Relation);\r
423             switch(ePageRelation) {\r
424                 case XFA_ATTRIBUTEENUM_OrderedOccurrence:\r
425                 default: {\r
426                         ProcessLastPageSet();\r
427                     }\r
428                     break;\r
429                 case XFA_ATTRIBUTEENUM_SimplexPaginated:\r
430                 case XFA_ATTRIBUTEENUM_DuplexPaginated: {\r
431                         CXFA_LayoutItemImpl* pLastPageAreaLayoutItem = NULL;\r
432                         FX_INT32 nPageAreaCount = 0;\r
433                         for(CXFA_LayoutItemImpl* pPageAreaLayoutItem = pPageSetLayoutItem->m_pFirstChild; pPageAreaLayoutItem; pPageAreaLayoutItem = pPageAreaLayoutItem->m_pNextSibling) {\r
434                             if(pPageAreaLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {\r
435                                 continue;\r
436                             }\r
437                             nPageAreaCount++;\r
438                             pLastPageAreaLayoutItem = pPageAreaLayoutItem;\r
439                         }\r
440                         if(!pLastPageAreaLayoutItem) {\r
441                             break;\r
442                         }\r
443                         if (!FindPageAreaFromPageSet_SimplexDuplex(pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE, TRUE, nPageAreaCount == 1 ? XFA_ATTRIBUTEENUM_Only : XFA_ATTRIBUTEENUM_Last)\r
444                                 && (nPageAreaCount == 1 && !FindPageAreaFromPageSet_SimplexDuplex(pPageSetLayoutItem->m_pFormNode, NULL, NULL, NULL, TRUE, TRUE, XFA_ATTRIBUTEENUM_Last))) {\r
445                             break;\r
446                         }\r
447                         CXFA_Node *pNode = m_pCurPageArea;\r
448                         XFA_ATTRIBUTEENUM eCurChoice = pNode->GetEnum(XFA_ATTRIBUTE_PagePosition);\r
449                         if(eCurChoice == XFA_ATTRIBUTEENUM_Last) {\r
450                             XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any;\r
451                             pNode->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven);\r
452                             XFA_ATTRIBUTEENUM eLastChoice = pLastPageAreaLayoutItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_PagePosition);\r
453                             if (eLastChoice == XFA_ATTRIBUTEENUM_First && (ePageRelation == XFA_ATTRIBUTEENUM_SimplexPaginated || eOddOrEven != XFA_ATTRIBUTEENUM_Odd)) {\r
454                                 CXFA_ContainerRecord* pRecord = CreateContainerRecord();\r
455                                 AddPageAreaLayoutItem(pRecord, pNode);\r
456                                 break;;\r
457                             }\r
458                         }\r
459                         FX_BOOL bUsable = TRUE;\r
460                         CFX_ArrayTemplate<FX_FLOAT> rgUsedHeights;\r
461                         for(CXFA_LayoutItemImpl* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild; pChildLayoutItem; pChildLayoutItem = pChildLayoutItem->m_pNextSibling) {\r
462                             if(pChildLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_ContentArea) {\r
463                                 continue;\r
464                             }\r
465                             FX_FLOAT fUsedHeight = 0;\r
466                             for(CXFA_LayoutItemImpl* pContentChildLayoutItem = pChildLayoutItem->m_pFirstChild; pContentChildLayoutItem; pContentChildLayoutItem = pContentChildLayoutItem->m_pNextSibling) {\r
467                                 if(!pContentChildLayoutItem->IsContentLayoutItem()) {\r
468                                     continue;\r
469                                 }\r
470                                 fUsedHeight += ((CXFA_ContentLayoutItemImpl*)pContentChildLayoutItem)->m_sSize.y;\r
471                             }\r
472                             rgUsedHeights.Add(fUsedHeight);\r
473                         }\r
474                         FX_INT32 iCurContentAreaIndex = -1;\r
475                         for(CXFA_Node* pContentAreaNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild); pContentAreaNode; pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
476                             if(pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) {\r
477                                 continue;\r
478                             }\r
479                             iCurContentAreaIndex++;\r
480                             if(rgUsedHeights[iCurContentAreaIndex] > pContentAreaNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt) + XFA_LAYOUT_FLOAT_PERCISION) {\r
481                                 bUsable = FALSE;\r
482                                 break;\r
483                             }\r
484                         }\r
485                         if(bUsable) {\r
486                             CXFA_LayoutItemImpl* pChildLayoutItem = pLastPageAreaLayoutItem->m_pFirstChild;\r
487                             CXFA_Node* pContentAreaNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);\r
488                             pLastPageAreaLayoutItem->m_pFormNode = pNode;\r
489                             while(pChildLayoutItem && pContentAreaNode) {\r
490                                 if(pChildLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_ContentArea) {\r
491                                     pChildLayoutItem = pChildLayoutItem->m_pNextSibling;\r
492                                     continue;\r
493                                 }\r
494                                 if(pContentAreaNode->GetClassID() != XFA_ELEMENT_ContentArea) {\r
495                                     pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling);\r
496                                     continue;\r
497                                 }\r
498                                 pChildLayoutItem->m_pFormNode = pContentAreaNode;\r
499                                 pChildLayoutItem = pChildLayoutItem->m_pNextSibling;\r
500                                 pContentAreaNode = pContentAreaNode->GetNodeItem(XFA_NODEITEM_NextSibling);\r
501                             }\r
502                         } else if(pNode->GetEnum(XFA_ATTRIBUTE_PagePosition) == XFA_ATTRIBUTEENUM_Last) {\r
503                             CXFA_ContainerRecord* pRecord = CreateContainerRecord();\r
504                             AddPageAreaLayoutItem(pRecord, pNode);\r
505                         }\r
506                     }\r
507                     break;\r
508             }\r
509         }\r
510     }\r
511 }\r
512 FX_INT32 CXFA_LayoutPageMgr::GetPageCount() const\r
513 {\r
514     return m_PageArray.GetSize();\r
515 }\r
516 IXFA_LayoutPage* CXFA_LayoutPageMgr::GetPage(FX_INT32 index) const\r
517 {\r
518     if (m_PageArray.GetSize() > index) {\r
519         return (IXFA_LayoutPage*)m_PageArray[index];\r
520     }\r
521     return NULL;\r
522 }\r
523 FX_INT32 CXFA_LayoutPageMgr::GetPageIndex(IXFA_LayoutPage* pPage) const\r
524 {\r
525     return m_PageArray.Find((CXFA_ContainerLayoutItemImpl*)pPage);\r
526 }\r
527 FX_BOOL CXFA_LayoutPageMgr::RunBreak(XFA_ELEMENT eBreakType, XFA_ATTRIBUTEENUM eTargetType, CXFA_Node* pTarget, FX_BOOL bStartNew)\r
528 {\r
529     FX_BOOL bRet = FALSE;\r
530     switch(eTargetType) {\r
531         case XFA_ATTRIBUTEENUM_ContentArea:\r
532             if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_ContentArea) {\r
533                 pTarget = NULL;\r
534             }\r
535             if (!pTarget || !m_pCurrentContainerRecord || pTarget != GetCurrentContainerRecord()->pCurContentArea->m_pFormNode || bStartNew) {\r
536                 CXFA_Node* pPageArea = NULL;\r
537                 if(pTarget) {\r
538                     pPageArea = pTarget->GetNodeItem(XFA_NODEITEM_Parent);\r
539                 }\r
540                 pPageArea = GetNextAvailPageArea(pPageArea, pTarget);\r
541                 bRet = pPageArea != NULL;\r
542             }\r
543             break;\r
544         case XFA_ATTRIBUTEENUM_PageArea:\r
545             if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {\r
546                 pTarget = NULL;\r
547             }\r
548             if (!pTarget || !m_pCurrentContainerRecord || pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode || bStartNew) {\r
549                 CXFA_Node* pPageArea = GetNextAvailPageArea(pTarget, NULL, TRUE);\r
550                 bRet = pPageArea != NULL;\r
551             }\r
552             break;\r
553         case XFA_ATTRIBUTEENUM_PageOdd:\r
554             if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {\r
555                 pTarget = NULL;\r
556             }\r
557             if (m_nAvailPages % 2 != 1 || !m_pCurrentContainerRecord || (pTarget && pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode) || bStartNew) {\r
558                 if(m_nAvailPages % 2 == 1) {\r
559                 }\r
560             }\r
561             break;\r
562         case XFA_ATTRIBUTEENUM_PageEven:\r
563             if (pTarget && pTarget->GetClassID() != XFA_ELEMENT_PageArea) {\r
564                 pTarget = NULL;\r
565             }\r
566             if (m_nAvailPages % 2 != 0 || !m_pCurrentContainerRecord || (pTarget && pTarget != GetCurrentContainerRecord()->pCurPageArea->m_pFormNode)  || bStartNew) {\r
567                 if(m_nAvailPages % 2 == 0) {\r
568                 }\r
569             }\r
570             break;\r
571         case XFA_ATTRIBUTEENUM_Auto:\r
572         default:\r
573             break;;\r
574     }\r
575     return bRet;\r
576 }\r
577 FX_BOOL CXFA_LayoutPageMgr::ExecuteBreakBeforeOrAfter(CXFA_Node* pCurNode, FX_BOOL bBefore, CXFA_Node* &pBreakLeaderTemplate, CXFA_Node* &pBreakTrailerTemplate)\r
578 {\r
579     XFA_ELEMENT eType = pCurNode->GetClassID();\r
580     switch(eType) {\r
581         case XFA_ELEMENT_BreakBefore:\r
582         case XFA_ELEMENT_BreakAfter: {\r
583                 CFX_WideStringC wsBreakLeader, wsBreakTrailer;\r
584                 CXFA_Node* pFormNode = pCurNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
585                 CXFA_Node *pContainer = pFormNode->GetTemplateNode();\r
586                 FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0;\r
587                 CXFA_Node *pScript = pCurNode->GetFirstChildByClass(XFA_ELEMENT_Script);\r
588                 if(pScript && !XFA_LayoutPageMgr_RunBreakTestScript(pScript)) {\r
589                     return FALSE;\r
590                 }\r
591                 CFX_WideStringC wsTarget = pCurNode->GetCData(XFA_ATTRIBUTE_Target);\r
592                 CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget);\r
593                 wsBreakTrailer = pCurNode->GetCData(XFA_ATTRIBUTE_Trailer);\r
594                 wsBreakLeader = pCurNode->GetCData(XFA_ATTRIBUTE_Leader);\r
595                 pBreakLeaderTemplate  = XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakLeader);\r
596                 pBreakTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsBreakTrailer);\r
597                 if(RunBreak(eType, pCurNode->GetEnum(XFA_ATTRIBUTE_TargetType), pTarget, bStartNew)) {\r
598                     return TRUE;\r
599                 } else {\r
600                     if(m_rgProposedContainerRecord.GetCount() > 0 && m_pCurrentContainerRecord == m_rgProposedContainerRecord.GetHeadPosition()\r
601                             && eType == XFA_ELEMENT_BreakBefore) {\r
602                         CXFA_Node* pParentNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
603                         if(!pParentNode || pFormNode != pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild, XFA_OBJECTTYPE_ContainerNode)) {\r
604                             break;\r
605                         }\r
606                         pParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);\r
607                         if(!pParentNode || pParentNode->GetClassID() != XFA_ELEMENT_Form) {\r
608                             break;\r
609                         }\r
610                         return TRUE;\r
611                     }\r
612                 }\r
613             }\r
614             break;\r
615         case XFA_ELEMENT_Break: {\r
616                 FX_BOOL bStartNew = pCurNode->GetInteger(XFA_ATTRIBUTE_StartNew) != 0;\r
617                 CFX_WideStringC wsTarget = pCurNode->GetCData(bBefore ? XFA_ATTRIBUTE_BeforeTarget : XFA_ATTRIBUTE_AfterTarget);\r
618                 CXFA_Node* pTarget = XFA_ResolveBreakTarget(m_pTemplatePageSetRoot, TRUE, wsTarget);\r
619                 if(RunBreak(bBefore ? XFA_ELEMENT_BreakBefore : XFA_ELEMENT_BreakAfter, pCurNode->GetEnum(bBefore ? XFA_ATTRIBUTE_Before : XFA_ATTRIBUTE_After), pTarget, bStartNew)) {\r
620                     return TRUE;\r
621                 }\r
622             }\r
623             break;\r
624         default:\r
625             break;\r
626     }\r
627     return FALSE;\r
628 }\r
629 static void XFA_SetLayoutGeneratedNodeFlag(CXFA_Node* pNode)\r
630 {\r
631     pNode->SetFlag(XFA_NODEFLAG_LayoutGeneratedNode, TRUE, FALSE);\r
632     pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE, FALSE);\r
633 }\r
634 FX_BOOL CXFA_LayoutPageMgr::ProcessBreakBeforeOrAfter(CXFA_Node* pBreakNode, FX_BOOL bBefore, CXFA_Node* &pBreakLeaderNode, CXFA_Node* &pBreakTrailerNode, FX_BOOL& bCreatePage)\r
635 {\r
636     CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL;\r
637     CXFA_Node *pFormNode = pBreakNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
638     if(XFA_ItemLayoutProcessor_IsTakingSpace(pFormNode)) {\r
639         bCreatePage = ExecuteBreakBeforeOrAfter(pBreakNode, bBefore, pLeaderTemplate, pTrailerTemplate);\r
640         CXFA_Document* pDocument = pBreakNode->GetDocument();\r
641         CXFA_Node* pDataScope = NULL;\r
642         pFormNode = pFormNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
643         if(pLeaderTemplate) {\r
644             if(!pDataScope) {\r
645                 pDataScope = XFA_DataMerge_FindDataScope(pFormNode);\r
646             }\r
647             pBreakLeaderNode = pDocument->DataMerge_CopyContainer(pLeaderTemplate, pFormNode, pDataScope, TRUE);\r
648             pDocument->DataMerge_UpdateBindingRelations(pBreakLeaderNode);\r
649             XFA_SetLayoutGeneratedNodeFlag(pBreakLeaderNode);\r
650         }\r
651         if(pTrailerTemplate) {\r
652             if(!pDataScope) {\r
653                 pDataScope = XFA_DataMerge_FindDataScope(pFormNode);\r
654             }\r
655             pBreakTrailerNode = pDocument->DataMerge_CopyContainer(pTrailerTemplate, pFormNode, pDataScope, TRUE);\r
656             pDocument->DataMerge_UpdateBindingRelations(pBreakTrailerNode);\r
657             XFA_SetLayoutGeneratedNodeFlag(pBreakTrailerNode);\r
658         }\r
659         return TRUE;\r
660     }\r
661     return FALSE;\r
662 }\r
663 FX_BOOL CXFA_LayoutPageMgr::ProcessBookendLeaderOrTrailer(CXFA_Node* pBookendNode, FX_BOOL bLeader, CXFA_Node* &pBookendAppendNode)\r
664 {\r
665     CXFA_Node* pLeaderTemplate = NULL;\r
666     CXFA_Node* pFormNode = pBookendNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);\r
667     if(ResolveBookendLeaderOrTrailer(pBookendNode, bLeader, pLeaderTemplate)) {\r
668         CXFA_Document *pDocument = pBookendNode->GetDocument();\r
669         CXFA_Node     *pDataScope = NULL;\r
670         if(pLeaderTemplate) {\r
671             if(!pDataScope) {\r
672                 pDataScope = XFA_DataMerge_FindDataScope(pFormNode);\r
673             }\r
674             pBookendAppendNode = pDocument->DataMerge_CopyContainer(pLeaderTemplate, pFormNode, pDataScope, TRUE);\r
675             pDocument->DataMerge_UpdateBindingRelations(pBookendAppendNode);\r
676             XFA_SetLayoutGeneratedNodeFlag(pBookendAppendNode);\r
677             return TRUE;\r
678         }\r
679     }\r
680     return FALSE;\r
681 }\r
682 CXFA_Node* CXFA_LayoutPageMgr::BreakOverflow(CXFA_Node* pOverflowNode, CXFA_Node*& pLeaderTemplate, CXFA_Node*& pTrailerTemplate, FX_BOOL bCreatePage )\r
683 {\r
684     CFX_WideStringC wsOverflowLeader, wsOverflowTrailer;\r
685     CXFA_Node *pContainer = pOverflowNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode)->GetTemplateNode();\r
686     if(pOverflowNode->GetClassID() == XFA_ELEMENT_Break) {\r
687         CFX_WideStringC wsOverflowLeader;\r
688         CFX_WideStringC wsOverflowTarget;\r
689         CFX_WideStringC wsOverflowTrailer;\r
690         pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader);\r
691         pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer);\r
692         pOverflowNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget);\r
693         if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || !wsOverflowTarget.IsEmpty()) {\r
694             if(!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) {\r
695                 CXFA_Node* pTarget = XFA_ResolveBreakTarget(this->m_pTemplatePageSetRoot, TRUE, wsOverflowTarget);\r
696                 if(pTarget) {\r
697                     m_bCreateOverFlowPage = TRUE;\r
698                     switch(pTarget->GetClassID()) {\r
699                         case XFA_ELEMENT_PageArea:\r
700                             RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget, TRUE);\r
701                             break;\r
702                         case XFA_ELEMENT_ContentArea:\r
703                             RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea, pTarget, TRUE);\r
704                             break;\r
705                         default:\r
706                             break;\r
707                     }\r
708                 }\r
709             }\r
710             if(!bCreatePage) {\r
711                 pLeaderTemplate  = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader);\r
712                 pTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer);\r
713             }\r
714             return pOverflowNode;\r
715         }\r
716         return NULL;\r
717     } else if(pOverflowNode->GetClassID() == XFA_ELEMENT_Overflow) {\r
718         CFX_WideStringC wsOverflowTarget;\r
719         pOverflowNode->TryCData(XFA_ATTRIBUTE_Leader, wsOverflowLeader);\r
720         pOverflowNode->TryCData(XFA_ATTRIBUTE_Trailer, wsOverflowTrailer);\r
721         pOverflowNode->TryCData(XFA_ATTRIBUTE_Target, wsOverflowTarget);\r
722         if(!wsOverflowTarget.IsEmpty() && bCreatePage && !m_bCreateOverFlowPage) {\r
723             CXFA_Node* pTarget = XFA_ResolveBreakTarget(this->m_pTemplatePageSetRoot, TRUE, wsOverflowTarget);\r
724             if(pTarget) {\r
725                 m_bCreateOverFlowPage = TRUE;\r
726                 switch(pTarget->GetClassID()) {\r
727                     case XFA_ELEMENT_PageArea:\r
728                         RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_PageArea, pTarget, TRUE);\r
729                         break;\r
730                     case XFA_ELEMENT_ContentArea:\r
731                         RunBreak(XFA_ELEMENT_Overflow, XFA_ATTRIBUTEENUM_ContentArea, pTarget, TRUE);\r
732                         break;\r
733                     default:\r
734                         break;\r
735                 }\r
736             }\r
737         }\r
738         if(!bCreatePage) {\r
739             pLeaderTemplate  = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowLeader);\r
740             pTrailerTemplate = XFA_ResolveBreakTarget(pContainer, TRUE, wsOverflowTrailer);\r
741         }\r
742         return pOverflowNode;\r
743     }\r
744     return NULL;\r
745 }\r
746 FX_BOOL CXFA_LayoutPageMgr::ProcessOverflow(CXFA_Node* pFormNode, CXFA_Node* &pLeaderNode, CXFA_Node* &pTrailerNode,  FX_BOOL bDataMerge, FX_BOOL bCreatePage)\r
747 {\r
748     if(pFormNode == NULL) {\r
749         return FALSE;\r
750     }\r
751     CXFA_Node *pLeaderTemplate = NULL, *pTrailerTemplate = NULL;\r
752     FX_BOOL bIsOverflowNode = FALSE;\r
753     if(pFormNode->GetClassID() == XFA_ELEMENT_Overflow || pFormNode->GetClassID() == XFA_ELEMENT_Break) {\r
754         bIsOverflowNode = TRUE;\r
755     }\r
756     for(CXFA_Node* pCurNode = bIsOverflowNode ? pFormNode : pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) {\r
757         if(BreakOverflow(pCurNode, pLeaderTemplate, pTrailerTemplate, bCreatePage)) {\r
758             if(bIsOverflowNode) {\r
759                 pFormNode = pCurNode->GetNodeItem(XFA_NODEITEM_Parent);\r
760             }\r
761             CXFA_Document *pDocument = pCurNode->GetDocument();\r
762             CXFA_Node     *pDataScope = NULL;\r
763             if(pLeaderTemplate) {\r
764                 if(!pDataScope) {\r
765                     pDataScope = XFA_DataMerge_FindDataScope(pFormNode);\r
766                 }\r
767                 pLeaderNode = pDocument->DataMerge_CopyContainer(pLeaderTemplate, pFormNode, pDataScope, TRUE);\r
768                 pDocument->DataMerge_UpdateBindingRelations(pLeaderNode);\r
769                 XFA_SetLayoutGeneratedNodeFlag(pLeaderNode);\r
770             }\r
771             if(pTrailerTemplate) {\r
772                 if(!pDataScope) {\r
773                     pDataScope = XFA_DataMerge_FindDataScope(pFormNode);\r
774                 }\r
775                 pTrailerNode = pDocument->DataMerge_CopyContainer(pTrailerTemplate, pFormNode, pDataScope, TRUE);\r
776                 pDocument->DataMerge_UpdateBindingRelations(pTrailerNode);\r
777                 XFA_SetLayoutGeneratedNodeFlag(pTrailerNode);\r
778             }\r
779             return TRUE;\r
780         }\r
781         if(bIsOverflowNode) {\r
782             break;\r
783         }\r
784     }\r
785     return FALSE;\r
786 }\r
787 FX_BOOL CXFA_LayoutPageMgr::ResolveBookendLeaderOrTrailer(CXFA_Node* pBookendNode, FX_BOOL bLeader, CXFA_Node* &pBookendAppendTemplate)\r
788 {\r
789     CFX_WideStringC wsBookendLeader;\r
790     CXFA_Node *pContainer = pBookendNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode)->GetTemplateNode();\r
791     if(pBookendNode->GetClassID() == XFA_ELEMENT_Break) {\r
792         pBookendNode->TryCData(bLeader ? XFA_ATTRIBUTE_BookendLeader : XFA_ATTRIBUTE_BookendTrailer, wsBookendLeader);\r
793         if (!wsBookendLeader.IsEmpty()) {\r
794             pBookendAppendTemplate  = XFA_ResolveBreakTarget(pContainer, FALSE, wsBookendLeader);\r
795             return TRUE;\r
796         }\r
797         return FALSE;\r
798     } else if(pBookendNode->GetClassID() == XFA_ELEMENT_Bookend) {\r
799         pBookendNode->TryCData(bLeader ? XFA_ATTRIBUTE_Leader : XFA_ATTRIBUTE_Trailer, wsBookendLeader);\r
800         pBookendAppendTemplate  = XFA_ResolveBreakTarget(pContainer, TRUE, wsBookendLeader);\r
801         return TRUE;\r
802     }\r
803     return FALSE;\r
804 }\r
805 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet(CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery)\r
806 {\r
807     if(pPageSet == NULL && pStartChild == NULL) {\r
808         return FALSE;\r
809     }\r
810     FX_INT32 iPageSetCount = 0;\r
811     if(IsPageSetRootOrderedOccurrence()) {\r
812         return FindPageAreaFromPageSet_Ordered(pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage, bQuery);\r
813     }\r
814     XFA_ATTRIBUTEENUM ePreferredPosition = m_pCurrentContainerRecord ? XFA_ATTRIBUTEENUM_Rest : XFA_ATTRIBUTEENUM_First;\r
815     return FindPageAreaFromPageSet_SimplexDuplex(pPageSet, pStartChild, pTargetPageArea, pTargetContentArea, bNewPage, bQuery, ePreferredPosition);\r
816 }\r
817 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_Ordered(CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery)\r
818 {\r
819     FX_INT32 iPageSetCount = 0;\r
820     if(!pStartChild && !bQuery) {\r
821         m_pPageSetMap.Lookup(pPageSet, iPageSetCount);\r
822         FX_INT32 iMax = -1;\r
823         CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur);\r
824         if(pOccurNode) {\r
825             pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE);\r
826         }\r
827         if (iMax >= 0 && iMax <= iPageSetCount) {\r
828             return FALSE;\r
829         }\r
830     }\r
831     FX_BOOL bRes = FALSE;\r
832     CXFA_Node *pCurrentNode = pStartChild ? pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling) : pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild);\r
833     for(; pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
834         if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {\r
835             if((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) {\r
836                 if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) == NULL) {\r
837                     if(pTargetPageArea == pCurrentNode) {\r
838                         CreateMinPageRecord(pCurrentNode, TRUE);\r
839                         pTargetPageArea = NULL;\r
840                     }\r
841                     continue;\r
842                 }\r
843                 if (!bQuery) {\r
844                     CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(pCurrentNode, pStartChild == NULL);\r
845                     AddPageAreaLayoutItem(pNewRecord, pCurrentNode);\r
846                     if(pTargetContentArea == NULL) {\r
847                         pTargetContentArea = pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
848                     }\r
849                     AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);\r
850                 }\r
851                 m_pCurPageArea = pCurrentNode;\r
852                 m_nCurPageCount = 1;\r
853                 bRes = TRUE;\r
854                 break;\r
855             }\r
856             if(!bQuery) {\r
857                 CreateMinPageRecord(pCurrentNode, FALSE);\r
858             }\r
859         } else if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
860             if(FindPageAreaFromPageSet_Ordered(pCurrentNode, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) {\r
861                 bRes = TRUE;\r
862                 break;\r
863             }\r
864             if(!bQuery) {\r
865                 CreateMinPageSetRecord(pCurrentNode, TRUE);\r
866             }\r
867         }\r
868     }\r
869     if(!pStartChild && bRes && !bQuery) {\r
870         m_pPageSetMap.SetAt(pPageSet, ++ iPageSetCount);\r
871     }\r
872     return bRes;\r
873 }\r
874 FX_BOOL CXFA_LayoutPageMgr::FindPageAreaFromPageSet_SimplexDuplex(CXFA_Node* pPageSet, CXFA_Node* pStartChild, CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery, XFA_ATTRIBUTEENUM ePreferredPosition)\r
875 {\r
876     XFA_ATTRIBUTEENUM eAdvisedPagePosition = pTargetPageArea ? pTargetPageArea->GetEnum(XFA_ATTRIBUTE_PagePosition) : (XFA_ATTRIBUTEENUM) - 1;\r
877     const XFA_ATTRIBUTEENUM eFallbackPosition = XFA_ATTRIBUTEENUM_Any;\r
878     CXFA_Node *pPreferredPageArea = NULL, *pFallbackPageArea = NULL;\r
879     CXFA_Node* pCurrentNode = NULL;\r
880     if (!pStartChild || pStartChild->GetClassID() == XFA_ELEMENT_PageArea) {\r
881         pCurrentNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild);\r
882     } else {\r
883         pCurrentNode = pStartChild->GetNodeItem(XFA_NODEITEM_NextSibling);\r
884     }\r
885     for(; pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
886         if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {\r
887             if(!MatchPageAreaOddOrEven(pCurrentNode, FALSE)) {\r
888                 continue;\r
889             }\r
890             XFA_ATTRIBUTEENUM eCurPagePosition = pCurrentNode->GetEnum(XFA_ATTRIBUTE_PagePosition);\r
891             if(ePreferredPosition == XFA_ATTRIBUTEENUM_Last) {\r
892                 if (eCurPagePosition != ePreferredPosition) {\r
893                     continue;\r
894                 }\r
895                 if (m_ePageSetMode == XFA_ATTRIBUTEENUM_SimplexPaginated || pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == XFA_ATTRIBUTEENUM_Any) {\r
896                     pPreferredPageArea = pCurrentNode;\r
897                     break;\r
898                 }\r
899                 CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
900                 AddPageAreaLayoutItem(pNewRecord, pCurrentNode);\r
901                 AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea));\r
902                 pPreferredPageArea = pCurrentNode;\r
903                 return FALSE;\r
904             } else if(ePreferredPosition == XFA_ATTRIBUTEENUM_Only) {\r
905                 if (eCurPagePosition != ePreferredPosition) {\r
906                     continue;\r
907                 }\r
908                 if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated || pCurrentNode->GetEnum(XFA_ATTRIBUTE_OddOrEven) == XFA_ATTRIBUTEENUM_Any) {\r
909                     pPreferredPageArea = pCurrentNode;\r
910                     break;\r
911                 }\r
912                 return FALSE;\r
913             }\r
914             if((pTargetPageArea == pCurrentNode || pTargetPageArea == NULL)) {\r
915                 if (pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea) == NULL) {\r
916                     if(pTargetPageArea == pCurrentNode) {\r
917                         CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
918                         AddPageAreaLayoutItem(pNewRecord, pCurrentNode);\r
919                         pTargetPageArea = NULL;\r
920                     }\r
921                     continue;\r
922                 }\r
923                 if((ePreferredPosition == XFA_ATTRIBUTEENUM_Rest && eCurPagePosition == XFA_ATTRIBUTEENUM_Any) || eCurPagePosition == ePreferredPosition) {\r
924                     pPreferredPageArea = pCurrentNode;\r
925                     break;\r
926                 } else if(eCurPagePosition == eFallbackPosition && !pFallbackPageArea) {\r
927                     pFallbackPageArea = pCurrentNode;\r
928                 }\r
929             } else if (pTargetPageArea && !MatchPageAreaOddOrEven(pTargetPageArea, FALSE)) {\r
930                 CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
931                 AddPageAreaLayoutItem(pNewRecord, pCurrentNode);\r
932                 AddContentAreaLayoutItem(pNewRecord, pCurrentNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea));\r
933             }\r
934         } else if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
935             if(FindPageAreaFromPageSet_SimplexDuplex(pCurrentNode, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery, ePreferredPosition)) {\r
936                 break;\r
937             }\r
938         }\r
939     }\r
940     CXFA_Node* pCurPageArea = NULL;\r
941     if(pPreferredPageArea) {\r
942         pCurPageArea = pPreferredPageArea;\r
943     } else if(pFallbackPageArea) {\r
944         pCurPageArea = pFallbackPageArea;\r
945     }\r
946     if (!pCurPageArea) {\r
947         return FALSE;\r
948     }\r
949     if (!bQuery) {\r
950         CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
951         AddPageAreaLayoutItem(pNewRecord, pCurPageArea);\r
952         if(pTargetContentArea == NULL) {\r
953             pTargetContentArea = pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
954         }\r
955         AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);\r
956     }\r
957     m_pCurPageArea = pCurPageArea;\r
958     return TRUE;\r
959 }\r
960 FX_BOOL CXFA_LayoutPageMgr::MatchPageAreaOddOrEven(CXFA_Node* pPageArea, FX_BOOL bLastMatch)\r
961 {\r
962     if (m_ePageSetMode != XFA_ATTRIBUTEENUM_DuplexPaginated) {\r
963         return TRUE;\r
964     }\r
965     XFA_ATTRIBUTEENUM eOddOrEven = XFA_ATTRIBUTEENUM_Any;\r
966     pPageArea->TryEnum(XFA_ATTRIBUTE_OddOrEven, eOddOrEven);\r
967     if (eOddOrEven != XFA_ATTRIBUTEENUM_Any) {\r
968         FX_INT32 iPageCount = GetPageCount();\r
969         if (bLastMatch) {\r
970             return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 1 : iPageCount % 2 == 0;\r
971         }\r
972         return eOddOrEven == XFA_ATTRIBUTEENUM_Odd ? iPageCount % 2 == 0 : iPageCount % 2 == 1;\r
973     }\r
974     return TRUE;\r
975 }\r
976 CXFA_Node* CXFA_LayoutPageMgr::GetNextAvailPageArea(CXFA_Node* pTargetPageArea, CXFA_Node* pTargetContentArea, FX_BOOL bNewPage, FX_BOOL bQuery)\r
977 {\r
978     if(m_pCurPageArea == NULL) {\r
979         FindPageAreaFromPageSet(m_pTemplatePageSetRoot, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery);\r
980         ASSERT(m_pCurPageArea);\r
981         return m_pCurPageArea;\r
982     }\r
983     if(pTargetPageArea == NULL || pTargetPageArea == m_pCurPageArea) {\r
984         if(!bNewPage && GetNextContentArea(pTargetContentArea)) {\r
985             return m_pCurPageArea;\r
986         }\r
987         if(IsPageSetRootOrderedOccurrence()) {\r
988             FX_INT32 iMax = -1;\r
989             CXFA_Node* pOccurNode = m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur);\r
990             if(pOccurNode) {\r
991                 pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE);\r
992             }\r
993             if((iMax < 0 || m_nCurPageCount < iMax)) {\r
994                 if (!bQuery) {\r
995                     CXFA_ContainerRecord* pNewRecord = CreateContainerRecord(m_pCurPageArea);\r
996                     AddPageAreaLayoutItem(pNewRecord, m_pCurPageArea);\r
997                     if(pTargetContentArea == NULL) {\r
998                         pTargetContentArea = m_pCurPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
999                     }\r
1000                     AddContentAreaLayoutItem(pNewRecord, pTargetContentArea);\r
1001                 }\r
1002                 m_nCurPageCount ++;\r
1003                 return m_pCurPageArea;\r
1004             }\r
1005         }\r
1006     }\r
1007     if(!bQuery && IsPageSetRootOrderedOccurrence()) {\r
1008         CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE);\r
1009     }\r
1010     if(FindPageAreaFromPageSet(m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent), m_pCurPageArea, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) {\r
1011         return m_pCurPageArea;\r
1012     }\r
1013     CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent);\r
1014     while(TRUE) {\r
1015         if (FindPageAreaFromPageSet(pPageSet, NULL, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) {\r
1016             return m_pCurPageArea;\r
1017         }\r
1018         if(!bQuery && IsPageSetRootOrderedOccurrence()) {\r
1019             CreateMinPageSetRecord(pPageSet);\r
1020         }\r
1021         if(FindPageAreaFromPageSet(NULL, pPageSet, pTargetPageArea, pTargetContentArea, bNewPage, bQuery)) {\r
1022             return m_pCurPageArea;\r
1023         }\r
1024         if(pPageSet == m_pTemplatePageSetRoot) {\r
1025             break;\r
1026         }\r
1027         pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent);\r
1028     }\r
1029     return NULL;\r
1030 }\r
1031 static FX_BOOL XFA_LayoutPageMgr_CheckContentAreaNotUsed(CXFA_ContainerLayoutItemImpl* pPageAreaLayoutItem, CXFA_Node* pContentArea, CXFA_ContainerLayoutItemImpl*& pContentAreaLayoutItem)\r
1032 {\r
1033     for(CXFA_ContainerLayoutItemImpl* pLayoutItem = (CXFA_ContainerLayoutItemImpl*)pPageAreaLayoutItem->m_pFirstChild; pLayoutItem; pLayoutItem = (CXFA_ContainerLayoutItemImpl*)pLayoutItem->m_pNextSibling) {\r
1034         if(pLayoutItem->m_pFormNode == pContentArea) {\r
1035             if(pLayoutItem->m_pFirstChild == NULL) {\r
1036                 pContentAreaLayoutItem = pLayoutItem;\r
1037                 return TRUE;\r
1038             }\r
1039             return FALSE;\r
1040         }\r
1041     }\r
1042     return TRUE;\r
1043 }\r
1044 FX_BOOL CXFA_LayoutPageMgr::GetNextContentArea(CXFA_Node* pContentArea)\r
1045 {\r
1046     CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode;\r
1047     if(pContentArea == NULL) {\r
1048         pContentArea = pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea);\r
1049         if(pContentArea == NULL) {\r
1050             return FALSE;\r
1051         }\r
1052     } else {\r
1053         if(pContentArea->GetNodeItem(XFA_NODEITEM_Parent) != m_pCurPageArea) {\r
1054             return FALSE;\r
1055         }\r
1056         CXFA_ContainerLayoutItemImpl* pContentAreaLayout = NULL;\r
1057         if(!XFA_LayoutPageMgr_CheckContentAreaNotUsed(GetCurrentContainerRecord()->pCurPageArea, pContentArea, pContentAreaLayout)) {\r
1058             return FALSE;\r
1059         }\r
1060         if(pContentAreaLayout) {\r
1061             if(pContentAreaLayout->m_pFormNode != pCurContentNode) {\r
1062                 CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
1063                 pNewRecord->pCurContentArea = pContentAreaLayout;\r
1064                 return TRUE;\r
1065             } else {\r
1066                 return FALSE;\r
1067             }\r
1068         }\r
1069     }\r
1070     CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
1071     AddContentAreaLayoutItem(pNewRecord, pContentArea);\r
1072     return TRUE;\r
1073 }\r
1074 void CXFA_LayoutPageMgr::InitPageSetMap()\r
1075 {\r
1076     if(!IsPageSetRootOrderedOccurrence()) {\r
1077         return;\r
1078     }\r
1079     CXFA_NodeIterator sIterator(m_pTemplatePageSetRoot);\r
1080     for (CXFA_Node* pPageSetNode = sIterator.GetCurrent(); pPageSetNode; pPageSetNode = sIterator.MoveToNext()) {\r
1081         if(pPageSetNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
1082             XFA_ATTRIBUTEENUM eRelation = pPageSetNode->GetEnum(XFA_ATTRIBUTE_Relation);\r
1083             if(eRelation == XFA_ATTRIBUTEENUM_OrderedOccurrence) {\r
1084                 m_pPageSetMap.SetAt(pPageSetNode, 0);\r
1085             }\r
1086         }\r
1087     }\r
1088 }\r
1089 FX_INT32 CXFA_LayoutPageMgr::CreateMinPageRecord(CXFA_Node* pPageArea, FX_BOOL bTargetPageArea, FX_BOOL bCreateLast)\r
1090 {\r
1091     if(pPageArea == NULL) {\r
1092         return 0;\r
1093     }\r
1094     CXFA_Node* pOccurNode = pPageArea->GetFirstChildByClass(XFA_ELEMENT_Occur);\r
1095     FX_INT32 iMin = 0;\r
1096     if((pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) || bTargetPageArea) {\r
1097         CXFA_Node* pContentArea = pPageArea->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
1098         if (iMin < 1 && bTargetPageArea && !pContentArea) {\r
1099             iMin = 1;\r
1100         }\r
1101         FX_INT32 i = 0;\r
1102         if(bCreateLast) {\r
1103             i = m_nCurPageCount;\r
1104         }\r
1105         for(; i < iMin; i++) {\r
1106             CXFA_ContainerRecord* pNewRecord = CreateContainerRecord();\r
1107             AddPageAreaLayoutItem(pNewRecord, pPageArea);\r
1108             AddContentAreaLayoutItem(pNewRecord, pContentArea);\r
1109         }\r
1110     }\r
1111     return iMin;\r
1112 }\r
1113 void CXFA_LayoutPageMgr::CreateMinPageSetRecord(CXFA_Node* pPageSet, FX_BOOL bCreateAll)\r
1114 {\r
1115     if(pPageSet == NULL) {\r
1116         return;\r
1117     }\r
1118     FX_INT32 iCurSetCount = 0;\r
1119     if(!m_pPageSetMap.Lookup(pPageSet, iCurSetCount)) {\r
1120         return;\r
1121     }\r
1122     if(bCreateAll) {\r
1123         iCurSetCount = 0;\r
1124     }\r
1125     CXFA_Node* pOccurNode = pPageSet->GetFirstChildByClass(XFA_ELEMENT_Occur);\r
1126     FX_INT32 iMin = 0;\r
1127     if(pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Min, iMin, FALSE)) {\r
1128         if(iCurSetCount < iMin) {\r
1129             for(FX_INT32 i = 0; i < iMin - iCurSetCount; i++) {\r
1130                 for(CXFA_Node *pCurrentPageNode = pPageSet->GetNodeItem(XFA_NODEITEM_FirstChild); pCurrentPageNode; pCurrentPageNode = pCurrentPageNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
1131                     if(pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageArea) {\r
1132                         CreateMinPageRecord(pCurrentPageNode, FALSE);\r
1133                     } else if(pCurrentPageNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
1134                         CreateMinPageSetRecord(pCurrentPageNode, TRUE);\r
1135                     }\r
1136                 }\r
1137             }\r
1138             m_pPageSetMap.SetAt(pPageSet, iMin);\r
1139         }\r
1140     }\r
1141 }\r
1142 void CXFA_LayoutPageMgr::CreateNextMinRecord(CXFA_Node* pRecordNode)\r
1143 {\r
1144     if(pRecordNode == NULL) {\r
1145         return;\r
1146     }\r
1147     for(CXFA_Node *pCurrentNode = pRecordNode->GetNodeItem(XFA_NODEITEM_NextSibling); pCurrentNode; pCurrentNode = pCurrentNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
1148         if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageArea) {\r
1149             CreateMinPageRecord(pCurrentNode, FALSE);\r
1150         } else if(pCurrentNode->GetClassID() == XFA_ELEMENT_PageSet) {\r
1151             CreateMinPageSetRecord(pCurrentNode, TRUE);\r
1152         }\r
1153     }\r
1154 }\r
1155 void CXFA_LayoutPageMgr::ProcessLastPageSet()\r
1156 {\r
1157     CreateMinPageRecord(m_pCurPageArea, FALSE, TRUE);\r
1158     CreateNextMinRecord(m_pCurPageArea);\r
1159     CXFA_Node* pPageSet = m_pCurPageArea->GetNodeItem(XFA_NODEITEM_Parent);\r
1160     while(TRUE) {\r
1161         CreateMinPageSetRecord(pPageSet);\r
1162         if(pPageSet == m_pTemplatePageSetRoot) {\r
1163             break;\r
1164         }\r
1165         CreateNextMinRecord(pPageSet);\r
1166         pPageSet = pPageSet->GetNodeItem(XFA_NODEITEM_Parent);\r
1167     }\r
1168 }\r
1169 FX_BOOL CXFA_LayoutPageMgr::GetNextAvailContentHeight(FX_FLOAT fChildHeight)\r
1170 {\r
1171     CXFA_Node* pCurContentNode = GetCurrentContainerRecord()->pCurContentArea->m_pFormNode;\r
1172     if(pCurContentNode == NULL) {\r
1173         return FALSE;\r
1174     }\r
1175     pCurContentNode = pCurContentNode->GetNextSameClassSibling(XFA_ELEMENT_ContentArea);\r
1176     if(pCurContentNode) {\r
1177         FX_FLOAT fNextContentHeight = pCurContentNode->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);\r
1178         return fNextContentHeight > fChildHeight ? TRUE : FALSE;\r
1179     }\r
1180     CXFA_Node* pPageNode = GetCurrentContainerRecord()->pCurPageArea->m_pFormNode;\r
1181     CXFA_Node* pOccurNode = pPageNode->GetFirstChildByClass(XFA_ELEMENT_Occur);\r
1182     FX_INT32 iMax = 0;\r
1183     if(pOccurNode && pOccurNode->TryInteger(XFA_ATTRIBUTE_Max, iMax, FALSE)) {\r
1184         if(m_nCurPageCount == iMax) {\r
1185             CXFA_Node* pSrcPage = m_pCurPageArea;\r
1186             FX_INT32 nSrcPageCount = m_nCurPageCount;\r
1187             FX_POSITION psSrcRecord = m_rgProposedContainerRecord.GetTailPosition();\r
1188             CXFA_Node* pNextPage = GetNextAvailPageArea(NULL, NULL, FALSE, TRUE);\r
1189             m_pCurPageArea = pSrcPage;\r
1190             m_nCurPageCount = nSrcPageCount;\r
1191             CXFA_ContainerRecord* pPrevRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(psSrcRecord);\r
1192             while (psSrcRecord) {\r
1193                 FX_POSITION psSaveRecord = psSrcRecord;\r
1194                 CXFA_ContainerRecord* pInsertRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(psSrcRecord);\r
1195                 RemoveLayoutRecord(pInsertRecord, pPrevRecord);\r
1196                 delete pInsertRecord;\r
1197                 m_rgProposedContainerRecord.RemoveAt(psSaveRecord);\r
1198             }\r
1199             if(pNextPage) {\r
1200                 CXFA_Node* pContentArea = pNextPage->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
1201                 if(pContentArea) {\r
1202                     FX_FLOAT fNextContentHeight = pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);\r
1203                     if(fNextContentHeight > fChildHeight) {\r
1204                         return TRUE;\r
1205                     }\r
1206                 }\r
1207             }\r
1208             return FALSE;\r
1209         }\r
1210     }\r
1211     CXFA_Node* pContentArea = pPageNode->GetFirstChildByClass(XFA_ELEMENT_ContentArea);\r
1212     FX_FLOAT fNextContentHeight = pContentArea->GetMeasure(XFA_ATTRIBUTE_H).ToUnit(XFA_UNIT_Pt);\r
1213     if (fNextContentHeight < XFA_LAYOUT_FLOAT_PERCISION) {\r
1214         return TRUE;\r
1215     }\r
1216     if(fNextContentHeight > fChildHeight) {\r
1217         return TRUE;\r
1218     }\r
1219     return FALSE;\r
1220 }\r
1221 void CXFA_LayoutPageMgr::ClearData()\r
1222 {\r
1223     ClearRecordList();\r
1224 }\r
1225 void CXFA_LayoutPageMgr::ClearRecordList()\r
1226 {\r
1227     if (!m_pTemplatePageSetRoot) {\r
1228         return;\r
1229     }\r
1230     if(m_rgProposedContainerRecord.GetCount() > 0) {\r
1231         FX_POSITION sPos;\r
1232         sPos = m_rgProposedContainerRecord.GetHeadPosition();\r
1233         while(sPos) {\r
1234             CXFA_ContainerRecord* pRecord = (CXFA_ContainerRecord*)m_rgProposedContainerRecord.GetNext(sPos);\r
1235             delete pRecord;\r
1236         }\r
1237         m_rgProposedContainerRecord.RemoveAll();\r
1238     }\r
1239     m_pCurrentContainerRecord = NULL;\r
1240     m_pCurPageArea = NULL;\r
1241     m_nCurPageCount = 0;\r
1242     m_bCreateOverFlowPage = FALSE;\r
1243     m_pPageSetMap.RemoveAll();\r
1244 }\r
1245 CXFA_LayoutItemImpl* CXFA_LayoutPageMgr::FindOrCreateLayoutItem(CXFA_Node* pFormNode)\r
1246 {\r
1247 #if defined(_XFA_LAYOUTITEM_MAPCACHE_)\r
1248     if (m_NodeToContent.GetCount() > 0) {\r
1249         CXFA_ContentLayoutItemImpl* pLayoutItem = NULL;\r
1250         if (m_NodeToContent.Lookup(pFormNode, (void*&)pLayoutItem)) {\r
1251             if (pLayoutItem->m_pNext) {\r
1252                 m_NodeToContent.SetAt(pFormNode, pLayoutItem->m_pNext);\r
1253                 pLayoutItem->m_pNext->m_pPrev = NULL;\r
1254                 pLayoutItem->m_pNext = NULL;\r
1255             } else {\r
1256                 m_NodeToContent.RemoveKey(pFormNode);\r
1257             }\r
1258             pLayoutItem->m_pFormNode = pFormNode;\r
1259             return pLayoutItem;\r
1260         }\r
1261     }\r
1262 #endif\r
1263     return (CXFA_LayoutItemImpl*)pFormNode->GetDocument()->GetParser()->GetNotify()->OnCreateLayoutItem(pFormNode);\r
1264 }\r
1265 #if defined(_XFA_LAYOUTITEM_MAPCACHE_)\r
1266 void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItemImpl* pParentLayoutItem)\r
1267 {\r
1268     CXFA_LayoutItemImpl *pNextLayoutItem, *pCurLayoutItem = pParentLayoutItem->m_pFirstChild;\r
1269     while (pCurLayoutItem) {\r
1270         pNextLayoutItem = pCurLayoutItem->m_pNextSibling;\r
1271         if (pCurLayoutItem->m_pFirstChild) {\r
1272             SaveLayoutItem(pCurLayoutItem);\r
1273         }\r
1274         if (pCurLayoutItem->IsContentLayoutItem()) {\r
1275             if (m_NodeToContent.GetValueAt(pCurLayoutItem->m_pFormNode) == NULL) {\r
1276                 pCurLayoutItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL);\r
1277                 m_NodeToContent.SetAt(pCurLayoutItem->m_pFormNode, pCurLayoutItem);\r
1278             }\r
1279         } else if (pCurLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {\r
1280             delete pCurLayoutItem;\r
1281             pCurLayoutItem = NULL;\r
1282         }\r
1283         if (pCurLayoutItem) {\r
1284             pCurLayoutItem->m_pParent = NULL;\r
1285             pCurLayoutItem->m_pNextSibling = NULL;\r
1286             pCurLayoutItem->m_pFirstChild = NULL;\r
1287         }\r
1288         pCurLayoutItem = pNextLayoutItem;\r
1289     }\r
1290 }\r
1291 #elif defined(_XFA_LAYOUTITEM_ProcessCACHE_)\r
1292 static void XFA_SyncRemoveLayoutItem(CXFA_LayoutItemImpl* pParentLayoutItem, IXFA_Notify* pNotify, IXFA_DocLayout* pDocLayout)\r
1293 {\r
1294     CXFA_LayoutItemImpl *pNextLayoutItem, *pCurLayoutItem = pParentLayoutItem->m_pFirstChild;\r
1295     while (pCurLayoutItem) {\r
1296         pNextLayoutItem = pCurLayoutItem->m_pNextSibling;\r
1297         if (pCurLayoutItem->m_pFirstChild) {\r
1298             XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);\r
1299         }\r
1300         pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pCurLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1301         delete pCurLayoutItem;\r
1302         pCurLayoutItem = pNextLayoutItem;\r
1303     }\r
1304 }\r
1305 void CXFA_LayoutPageMgr::SaveLayoutItem(CXFA_LayoutItemImpl* pParentLayoutItem)\r
1306 {\r
1307     CXFA_LayoutItemImpl *pNextLayoutItem, *pCurLayoutItem = pParentLayoutItem->m_pFirstChild;\r
1308     while (pCurLayoutItem) {\r
1309         pNextLayoutItem = pCurLayoutItem->m_pNextSibling;\r
1310         if (pCurLayoutItem->IsContentLayoutItem()) {\r
1311             FX_DWORD dwFlag = pCurLayoutItem->m_pFormNode->GetFlag();\r
1312             if (dwFlag & (XFA_NODEFLAG_HasRemoved)) {\r
1313                 IXFA_Notify* pNotify = m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify();\r
1314                 IXFA_DocLayout* pDocLayout = m_pTemplatePageSetRoot->GetDocument()->GetDocLayout();\r
1315                 if (pCurLayoutItem->m_pFirstChild) {\r
1316                     XFA_SyncRemoveLayoutItem(pCurLayoutItem, pNotify, pDocLayout);\r
1317                 }\r
1318                 pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pCurLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1319                 delete pCurLayoutItem;\r
1320                 pCurLayoutItem = pNextLayoutItem;\r
1321                 continue;\r
1322             }\r
1323             if (dwFlag & XFA_NODEFLAG_LayoutGeneratedNode) {\r
1324                 CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pCurLayoutItem->m_pFormNode);\r
1325                 for(CXFA_Node *pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) {\r
1326                     pNode->SetFlag(XFA_NODEFLAG_UnusedNode, TRUE, FALSE);\r
1327                 }\r
1328             }\r
1329         }\r
1330         if (pCurLayoutItem->m_pFirstChild) {\r
1331             SaveLayoutItem(pCurLayoutItem);\r
1332         }\r
1333         pCurLayoutItem->m_pParent = NULL;\r
1334         pCurLayoutItem->m_pNextSibling = NULL;\r
1335         pCurLayoutItem->m_pFirstChild = NULL;\r
1336         if (!pCurLayoutItem->IsContentLayoutItem() && pCurLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {\r
1337             delete pCurLayoutItem;\r
1338         }\r
1339         pCurLayoutItem = pNextLayoutItem;\r
1340     }\r
1341 }\r
1342 #endif\r
1343 CXFA_Node* CXFA_LayoutPageMgr::QueryOverflow(CXFA_Node* pFormNode, CXFA_LayoutContext* pLayoutContext)\r
1344 {\r
1345     for(CXFA_Node* pCurNode = pFormNode->GetNodeItem(XFA_NODEITEM_FirstChild); pCurNode; pCurNode = pCurNode->GetNodeItem((XFA_NODEITEM_NextSibling))) {\r
1346         if(pCurNode->GetClassID() == XFA_ELEMENT_Break) {\r
1347             CFX_WideStringC wsOverflowLeader;\r
1348             CFX_WideStringC wsOverflowTarget;\r
1349             CFX_WideStringC wsOverflowTrailer;\r
1350             pCurNode->TryCData(XFA_ATTRIBUTE_OverflowLeader, wsOverflowLeader);\r
1351             pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTrailer, wsOverflowTrailer);\r
1352             pCurNode->TryCData(XFA_ATTRIBUTE_OverflowTarget, wsOverflowTarget);\r
1353             if (!wsOverflowLeader.IsEmpty() || !wsOverflowTrailer.IsEmpty() || !wsOverflowTarget.IsEmpty()) {\r
1354                 return pCurNode;\r
1355             }\r
1356             return NULL;\r
1357         } else if(pCurNode->GetClassID() == XFA_ELEMENT_Overflow) {\r
1358             return pCurNode;\r
1359         }\r
1360     }\r
1361     return NULL;\r
1362 }\r
1363 void CXFA_LayoutPageMgr::MergePageSetContents()\r
1364 {\r
1365     CXFA_Document *pDocument = m_pTemplatePageSetRoot->GetDocument();\r
1366     IXFA_Notify* pNotify = pDocument->GetParser()->GetNotify();\r
1367     IXFA_DocLayout* pDocLayout = pDocument->GetDocLayout();\r
1368     CXFA_ContainerLayoutItemImpl* pRootLayout = this->GetRootLayoutItem();\r
1369     {\r
1370         for(FX_INT32 iIndex = 0; iIndex < pDocument->m_pPendingPageSet.GetSize(); iIndex ++) {\r
1371             CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pDocument->m_pPendingPageSet.GetAt(iIndex));\r
1372             for(CXFA_Node *pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) {\r
1373                 if(pNode->IsContainerNode()) {\r
1374                     CXFA_Node* pBindNode = pNode->GetBindData();\r
1375                     if (pBindNode) {\r
1376                         pBindNode->RemoveBindItem(pNode);\r
1377                         pNode->SetObject(XFA_ATTRIBUTE_BindingNode, NULL);\r
1378                     }\r
1379                 }\r
1380                 pNode->SetFlag(XFA_NODEFLAG_UnusedNode);\r
1381             }\r
1382         }\r
1383     }\r
1384     FX_INT32 iIndex = 0;\r
1385     CXFA_Node* pPendingPageSet = NULL;\r
1386     for(; pRootLayout; pRootLayout = (CXFA_ContainerLayoutItemImpl* )pRootLayout->m_pNextSibling) {\r
1387         pPendingPageSet = NULL;\r
1388         CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItemImpl, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iterator(pRootLayout);\r
1389         CXFA_ContainerLayoutItemImpl* pRootPageSetContainerItem = iterator.GetCurrent();\r
1390         ASSERT(pRootPageSetContainerItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet);\r
1391         if(iIndex < pDocument->m_pPendingPageSet.GetSize()) {\r
1392             pPendingPageSet = pDocument->m_pPendingPageSet.GetAt(iIndex);\r
1393             iIndex ++;\r
1394         }\r
1395         if(!pPendingPageSet) {\r
1396             if(pRootPageSetContainerItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Template) {\r
1397                 pPendingPageSet = pRootPageSetContainerItem->m_pFormNode->CloneTemplateToForm(FALSE);\r
1398             } else {\r
1399                 pPendingPageSet = pRootPageSetContainerItem->m_pFormNode;\r
1400             }\r
1401         }\r
1402         if (pRootPageSetContainerItem->m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY) == pRootPageSetContainerItem) {\r
1403             pRootPageSetContainerItem->m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL);\r
1404         }\r
1405         pRootPageSetContainerItem->m_pFormNode = pPendingPageSet;\r
1406         pPendingPageSet->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);\r
1407         for(CXFA_ContainerLayoutItemImpl* pContainerItem = iterator.MoveToNext(); pContainerItem; pContainerItem = iterator.MoveToNext()) {\r
1408             CXFA_Node* pNode = pContainerItem->m_pFormNode;\r
1409             if(pNode->GetPacketID() != XFA_XDPPACKET_Template) {\r
1410                 continue;\r
1411             }\r
1412             switch(pNode->GetClassID()) {\r
1413                 case XFA_ELEMENT_PageSet: {\r
1414                         CXFA_Node* pParentNode =  pContainerItem->m_pParent->m_pFormNode;\r
1415                         pContainerItem->m_pFormNode = XFA_NodeMerge_CloneOrMergeContainer(pDocument, pParentNode, pContainerItem->m_pFormNode, TRUE);\r
1416                     }\r
1417                     break;\r
1418                 case XFA_ELEMENT_PageArea: {\r
1419                         CXFA_ContainerLayoutItemImpl* pFormLayout = pContainerItem;\r
1420                         CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode;\r
1421                         FX_BOOL bIsExistForm = TRUE;\r
1422                         for(FX_INT32 iLevel = 0; iLevel < 3; iLevel ++) {\r
1423                             pFormLayout = (CXFA_ContainerLayoutItemImpl*)pFormLayout->m_pFirstChild;\r
1424                             if(iLevel == 2) {\r
1425                                 while(pFormLayout && !XFA_ItemLayoutProcessor_IsTakingSpace(pFormLayout->m_pFormNode)) {\r
1426                                     pFormLayout = (CXFA_ContainerLayoutItemImpl*)pFormLayout->m_pNextSibling;\r
1427                                 }\r
1428                             }\r
1429                             if(pFormLayout == NULL) {\r
1430                                 bIsExistForm = FALSE;\r
1431                                 break;\r
1432                             }\r
1433                         }\r
1434                         if(bIsExistForm) {\r
1435                             CXFA_Node* pNewSubform = pFormLayout->m_pFormNode;\r
1436                             if( pContainerItem->m_pOldSubform != NULL && pContainerItem->m_pOldSubform != pNewSubform) {\r
1437                                 CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(pDocument, pContainerItem->m_pFormNode->GetClassID(), pContainerItem->m_pFormNode->GetNameHash(), pParentNode);\r
1438                                 CXFA_ContainerIterator sIterator(pExistingNode);\r
1439                                 for(CXFA_Node *pNode = sIterator.GetCurrent(); pNode; pNode = sIterator.MoveToNext()) {\r
1440                                     if(pNode->GetClassID() != XFA_ELEMENT_ContentArea) {\r
1441                                         CXFA_LayoutItemImpl* pLayoutItem = (CXFA_LayoutItemImpl*)pNode->GetUserData(XFA_LAYOUTITEMKEY);\r
1442                                         if(pLayoutItem) {\r
1443                                             pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1444                                             delete pLayoutItem;\r
1445                                         }\r
1446                                     }\r
1447                                 }\r
1448                                 if(pExistingNode) {\r
1449                                     pParentNode->RemoveChild(pExistingNode);\r
1450                                 }\r
1451                             }\r
1452                             pContainerItem->m_pOldSubform = pNewSubform;\r
1453                         }\r
1454                         pContainerItem->m_pFormNode = pDocument->DataMerge_CopyContainer(pContainerItem->m_pFormNode, pParentNode, (CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Record), TRUE);\r
1455                     }\r
1456                     break;\r
1457                 case XFA_ELEMENT_ContentArea: {\r
1458                         CXFA_Node* pParentNode = pContainerItem->m_pParent->m_pFormNode;\r
1459                         for(CXFA_Node* pChildNode = pParentNode->GetNodeItem(XFA_NODEITEM_FirstChild); pChildNode; pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
1460                             if(pChildNode->GetTemplateNode() != pContainerItem->m_pFormNode) {\r
1461                                 continue;\r
1462                             }\r
1463                             pContainerItem->m_pFormNode = pChildNode;\r
1464                             break;\r
1465                         }\r
1466                     }\r
1467                     break;\r
1468                 default:\r
1469                     break;\r
1470             }\r
1471         }\r
1472         if(!pPendingPageSet->GetNodeItem(XFA_NODEITEM_Parent)) {\r
1473             CXFA_Node* pFormToplevelSubform = ((CXFA_Node*)pDocument->GetXFANode(XFA_HASHCODE_Form))->GetFirstChildByClass(XFA_ELEMENT_Subform);\r
1474             pFormToplevelSubform->InsertChild(pPendingPageSet);\r
1475         }\r
1476         pDocument->DataMerge_UpdateBindingRelations(pPendingPageSet);\r
1477         pPendingPageSet->SetFlag(XFA_NODEFLAG_Initialized);\r
1478     }\r
1479     pPendingPageSet = GetRootLayoutItem()->m_pFormNode;\r
1480     while(pPendingPageSet) {\r
1481         CXFA_Node* pNextPendingPageSet = pPendingPageSet->GetNextSameClassSibling(XFA_ELEMENT_PageSet);\r
1482         CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(pPendingPageSet);\r
1483         CXFA_Node *pNode = sIterator.GetCurrent();\r
1484         while(pNode) {\r
1485             if(pNode->HasFlag(XFA_NODEFLAG_UnusedNode)) {\r
1486                 if(pNode->GetObjectType() == XFA_OBJECTTYPE_ContainerNode) {\r
1487                     XFA_ELEMENT eCurId = pNode->GetClassID();\r
1488                     if (eCurId == XFA_ELEMENT_PageArea || eCurId == XFA_ELEMENT_PageSet) {\r
1489                         CXFA_ContainerIterator iteChild(pNode);\r
1490                         CXFA_Node* pChildNode = iteChild.MoveToNext();\r
1491                         for (; pChildNode; pChildNode = iteChild.MoveToNext()) {\r
1492                             CXFA_LayoutItemImpl* pLayoutItem = (CXFA_LayoutItemImpl*)pChildNode->GetUserData(XFA_LAYOUTITEMKEY);\r
1493                             if(pLayoutItem) {\r
1494                                 pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1495                                 delete pLayoutItem;\r
1496                             }\r
1497                         }\r
1498                     } else if (eCurId != XFA_ELEMENT_ContentArea) {\r
1499                         CXFA_LayoutItemImpl* pLayoutItem = (CXFA_LayoutItemImpl*)pNode->GetUserData(XFA_LAYOUTITEMKEY);\r
1500                         if(pLayoutItem) {\r
1501                             pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1502                             delete pLayoutItem;\r
1503                         }\r
1504                     }\r
1505                     CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();\r
1506                     pNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pNode);\r
1507                     pNode = pNext;\r
1508                 } else {\r
1509                     pNode->SetFlag(XFA_NODEFLAG_UnusedNode, FALSE);\r
1510                     pNode->SetFlag(XFA_NODEFLAG_Initialized);\r
1511                     pNode = sIterator.MoveToNext();\r
1512                 }\r
1513             } else {\r
1514                 pNode->SetFlag(XFA_NODEFLAG_Initialized);\r
1515                 pNode = sIterator.MoveToNext();\r
1516             }\r
1517         }\r
1518         pPendingPageSet = pNextPendingPageSet;\r
1519     }\r
1520 }\r
1521 void CXFA_LayoutPageMgr::LayoutPageSetContents()\r
1522 {\r
1523     CXFA_ContainerLayoutItemImpl* pRootLayoutItem = this->GetRootLayoutItem();\r
1524     for(; pRootLayoutItem; pRootLayoutItem = (CXFA_ContainerLayoutItemImpl*)pRootLayoutItem->m_pNextSibling) {\r
1525         CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItemImpl, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iterator(pRootLayoutItem);\r
1526         for(CXFA_ContainerLayoutItemImpl* pContainerItem = iterator.GetCurrent(); pContainerItem; pContainerItem = iterator.MoveToNext()) {\r
1527             CXFA_Node* pNode = pContainerItem->m_pFormNode;\r
1528             switch(pNode->GetClassID()) {\r
1529                 case XFA_ELEMENT_PageArea:\r
1530                     m_pLayoutProcessor->GetRootRootItemLayoutProcessor()->DoLayoutPageArea(pContainerItem);\r
1531                     break;\r
1532                 default:\r
1533                     break;\r
1534             }\r
1535         }\r
1536     }\r
1537 }\r
1538 void XFA_SyncContainer(IXFA_Notify* pNotify, IXFA_DocLayout* pDocLayout, CXFA_LayoutItemImpl* pContainerItem, FX_DWORD dwRelevant, FX_BOOL bVisible, FX_INT32 nPageIndex)\r
1539 {\r
1540     FX_BOOL bVisibleItem = FALSE;\r
1541     FX_DWORD dwStatus = 0;\r
1542     FX_DWORD dwRelevantContainer = 0;\r
1543     if (bVisible) {\r
1544         XFA_ATTRIBUTEENUM eAttributeValue = pContainerItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence);\r
1545         if(eAttributeValue == XFA_ATTRIBUTEENUM_Visible || eAttributeValue == XFA_ATTRIBUTEENUM_Unknown) {\r
1546             bVisibleItem = TRUE;\r
1547         }\r
1548         dwRelevantContainer = XFA_GetRelevant(pContainerItem->m_pFormNode, dwRelevant);\r
1549         dwStatus = (bVisibleItem ? XFA_LAYOUTSTATUS_Visible : 0) | dwRelevantContainer;\r
1550     }\r
1551     pNotify->OnLayoutEvent(pDocLayout, (CXFA_LayoutItem*)pContainerItem, XFA_LAYOUTEVENT_ItemAdded, (FX_LPVOID)(FX_UINTPTR)nPageIndex, (FX_LPVOID)(FX_UINTPTR)dwStatus);\r
1552     CXFA_LayoutItemImpl *pChild = pContainerItem->m_pFirstChild;\r
1553     while (pChild) {\r
1554         if (!pChild->IsContentLayoutItem()) {\r
1555             pChild = pChild->m_pNextSibling;\r
1556             continue;\r
1557         }\r
1558         XFA_SyncContainer(pNotify, pDocLayout, pChild, dwRelevantContainer, bVisibleItem, nPageIndex);\r
1559         pChild = pChild->m_pNextSibling;\r
1560     }\r
1561 }\r
1562 void CXFA_LayoutPageMgr::SyncLayoutData()\r
1563 {\r
1564     MergePageSetContents();\r
1565     LayoutPageSetContents();\r
1566     IXFA_Notify* pNotify = m_pTemplatePageSetRoot->GetDocument()->GetParser()->GetNotify();\r
1567     FX_INT32 nPageIdx = -1;\r
1568     CXFA_ContainerLayoutItemImpl* pRootLayoutItem = this->GetRootLayoutItem();\r
1569     for(; pRootLayoutItem; pRootLayoutItem = (CXFA_ContainerLayoutItemImpl*)pRootLayoutItem->m_pNextSibling) {\r
1570         CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItemImpl, CXFA_TraverseStrategy_ContentAreaContainerLayoutItem> iteratorParent(pRootLayoutItem);\r
1571         for(CXFA_ContainerLayoutItemImpl* pContainerItem = iteratorParent.GetCurrent(); pContainerItem; pContainerItem = iteratorParent.MoveToNext()) {\r
1572             switch(pContainerItem->m_pFormNode->GetClassID()) {\r
1573                 case XFA_ELEMENT_PageArea: {\r
1574                         nPageIdx++;\r
1575                         FX_DWORD dwRelevant = XFA_LAYOUTSTATUS_Viewable | XFA_LAYOUTSTATUS_Printable;\r
1576                         CXFA_NodeIteratorTemplate<CXFA_LayoutItem, CXFA_TraverseStrategy_LayoutItem> iterator((CXFA_LayoutItem*)pContainerItem);\r
1577                         for(CXFA_LayoutItem* pChildLayoutItem = iterator.GetCurrent(); pChildLayoutItem;) {\r
1578                             if (!((CXFA_LayoutItemImpl*)pChildLayoutItem)->IsContentLayoutItem()) {\r
1579                                 pChildLayoutItem = iterator.MoveToNext();\r
1580                                 continue;\r
1581                             }\r
1582                             CXFA_ContentLayoutItemImpl* pContentItem = (CXFA_ContentLayoutItemImpl*)pChildLayoutItem;\r
1583                             FX_BOOL bVisible = (pContentItem->m_pFormNode->GetEnum(XFA_ATTRIBUTE_Presence) == XFA_ATTRIBUTEENUM_Visible);\r
1584                             FX_DWORD dwRelevantChild = XFA_GetRelevant(pContentItem->m_pFormNode, dwRelevant);\r
1585                             XFA_SyncContainer(pNotify, m_pLayoutProcessor, pContentItem, dwRelevantChild, bVisible, nPageIdx);\r
1586                             pChildLayoutItem = iterator.SkipChildrenAndMoveToNext();\r
1587                         }\r
1588                     }\r
1589                     break;\r
1590                 default:\r
1591                     break;\r
1592             }\r
1593         }\r
1594     }\r
1595     FX_INT32 nPage = m_PageArray.GetSize();\r
1596     for (FX_INT32 i = nPage - 1; i >= m_nAvailPages; i--) {\r
1597         CXFA_ContainerLayoutItemImpl* pPage = m_PageArray[i];\r
1598         m_PageArray.RemoveAt(i);\r
1599         pNotify->OnPageEvent((IXFA_LayoutPage*)pPage, XFA_PAGEEVENT_PageRemoved);\r
1600         delete pPage;\r
1601     }\r
1602     ClearRecordList();\r
1603 }\r
1604 void XFA_ReleaseLayoutItem_NoPageArea(CXFA_LayoutItemImpl *pLayoutItem)\r
1605 {\r
1606     CXFA_LayoutItemImpl *pNext, *pNode = pLayoutItem->m_pFirstChild;\r
1607     while (pNode) {\r
1608         pNext = pNode->m_pNextSibling;\r
1609         pNode->m_pParent = NULL;\r
1610         XFA_ReleaseLayoutItem_NoPageArea(pNode);\r
1611         pNode = pNext;\r
1612     }\r
1613     if (pLayoutItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {\r
1614         delete pLayoutItem;\r
1615     }\r
1616 }\r
1617 void CXFA_LayoutPageMgr::PrepareLayout()\r
1618 {\r
1619     m_pPageSetCurRoot = NULL;\r
1620     m_ePageSetMode = XFA_ATTRIBUTEENUM_OrderedOccurrence;\r
1621     m_nAvailPages = 0;\r
1622     ClearRecordList();\r
1623     if (!m_pPageSetLayoutItemRoot) {\r
1624         return;\r
1625     }\r
1626     CXFA_ContainerLayoutItemImpl* pRootLayoutItem = m_pPageSetLayoutItemRoot;\r
1627     if(pRootLayoutItem && pRootLayoutItem->m_pFormNode->GetPacketID() == XFA_XDPPACKET_Form) {\r
1628         CXFA_Node* pPageSetFormNode = pRootLayoutItem->m_pFormNode;\r
1629         pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.RemoveAll();\r
1630         if (pPageSetFormNode->HasFlag(XFA_NODEFLAG_HasRemoved)) {\r
1631             XFA_ReleaseLayoutItem(pRootLayoutItem);\r
1632             m_pPageSetLayoutItemRoot = NULL;\r
1633             pRootLayoutItem = NULL;\r
1634             pPageSetFormNode = NULL;\r
1635             m_PageArray.RemoveAll();\r
1636         }\r
1637         while(pPageSetFormNode) {\r
1638             CXFA_Node* pNextPageSet = pPageSetFormNode->GetNextSameClassSibling(XFA_ELEMENT_PageSet);\r
1639             pPageSetFormNode->GetNodeItem(XFA_NODEITEM_Parent)->RemoveChild(pPageSetFormNode, FALSE);\r
1640             pRootLayoutItem->m_pFormNode->GetDocument()->m_pPendingPageSet.Add(pPageSetFormNode);\r
1641             pPageSetFormNode = pNextPageSet;\r
1642         }\r
1643     }\r
1644 #if defined(_XFA_LAYOUTITEM_MAPCACHE_) || defined(_XFA_LAYOUTITEM_ProcessCACHE_)\r
1645     pRootLayoutItem = m_pPageSetLayoutItemRoot;\r
1646     CXFA_ContainerLayoutItemImpl* pNextLayout = NULL;\r
1647     for(; pRootLayoutItem; pRootLayoutItem = pNextLayout) {\r
1648         pNextLayout = (CXFA_ContainerLayoutItemImpl*)pRootLayoutItem->m_pNextSibling;\r
1649         SaveLayoutItem(pRootLayoutItem);\r
1650         delete pRootLayoutItem;\r
1651     }\r
1652     m_pPageSetLayoutItemRoot = NULL;\r
1653 #else\r
1654     IXFA_Notify* pNotify = m_pLayoutProcessor->GetDocument()->GetParser()->GetNotify();\r
1655     pRootLayoutItem = m_pPageSetLayoutItemRoot;\r
1656     for(; pRootLayoutItem; pRootLayoutItem = (CXFA_ContainerLayoutItemImpl*)pRootLayoutItem->m_pNextSibling) {\r
1657         CXFA_NodeIteratorTemplate<CXFA_ContainerLayoutItemImpl, CXFA_TraverseStrategy_PageAreaContainerLayoutItem> iterator(pRootLayoutItem);\r
1658         for(CXFA_ContainerLayoutItemImpl* pContainerItem = iterator.GetCurrent(); pContainerItem; pContainerItem = iterator.MoveToNext()) {\r
1659             if(pContainerItem->m_pFormNode->GetClassID() != XFA_ELEMENT_PageArea) {\r
1660                 continue;\r
1661             }\r
1662             CXFA_NodeIteratorTemplate<CXFA_LayoutItem, CXFA_TraverseStrategy_LayoutItem> iterator((CXFA_LayoutItem*)pContainerItem);\r
1663             for(CXFA_LayoutItemImpl* pLayoutItem = (CXFA_LayoutItemImpl*)iterator.GetCurrent(); pLayoutItem; pLayoutItem = (CXFA_LayoutItemImpl*)iterator.MoveToNext()) {\r
1664                 if (!pLayoutItem->IsContentLayoutItem()) {\r
1665                     continue;\r
1666                 }\r
1667                 pNotify->OnLayoutEvent(m_pLayoutProcessor, (CXFA_LayoutItem*)pLayoutItem, XFA_LAYOUTEVENT_ItemRemoving);\r
1668             }\r
1669             pNotify->OnPageEvent((IXFA_LayoutPage*)pContainerItem, XFA_PAGEEVENT_PageRemoved);\r
1670         }\r
1671     }\r
1672     pRootLayoutItem = m_pPageSetLayoutItemRoot;\r
1673     CXFA_ContainerLayoutItemImpl* pNextLayout = NULL;\r
1674     for(; pRootLayoutItem; pRootLayoutItem = pNextLayout) {\r
1675         pNextLayout = (CXFA_ContainerLayoutItemImpl*)pRootLayoutItem->m_pNextSibling;\r
1676         XFA_ReleaseLayoutItem_NoPageArea(pRootLayoutItem);\r
1677     }\r
1678     m_pPageSetLayoutItemRoot = NULL;\r
1679 #endif\r
1680 }\r