1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: t -*- */
2 
3 /* AbiWord
4  * Copyright (C) 1998 AbiSource, Inc.
5  * Copyright (C) 2002 Martin Sevior (msevior@physics.unimelb.edu.au>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301 USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <string.h>
28 #include <stdlib.h>
29 
30 #include "ut_types.h"
31 #include "ut_string.h"
32 
33 #include "ap_Prefs.h"
34 #include "fl_SectionLayout.h"
35 #include "fl_FootnoteLayout.h"
36 #include "fl_Layout.h"
37 #include "fl_DocLayout.h"
38 #include "fl_TOCLayout.h"
39 #include "fl_BlockLayout.h"
40 #include "fl_TableLayout.h"
41 #include "fp_TableContainer.h"
42 #include "fb_LineBreaker.h"
43 #include "fb_ColumnBreaker.h"
44 #include "fp_FootnoteContainer.h"
45 #include "fp_TOCContainer.h"
46 #include "fp_Page.h"
47 #include "fp_Line.h"
48 #include "fp_Column.h"
49 #include "pd_Document.h"
50 #include "pp_AttrProp.h"
51 #include "gr_Graphics.h"
52 #include "pp_Property.h"
53 #include "px_ChangeRecord.h"
54 #include "px_CR_Object.h"
55 #include "px_CR_ObjectChange.h"
56 #include "px_CR_Span.h"
57 #include "px_CR_SpanChange.h"
58 #include "px_CR_Strux.h"
59 #include "px_CR_StruxChange.h"
60 #include "px_CR_Glob.h"
61 #include "fv_View.h"
62 #include "fp_Run.h"
63 #include "ut_debugmsg.h"
64 #include "ut_assert.h"
65 #include "ut_units.h"
66 #include "fg_Graphic.h"
67 #include "pt_Types.h"
68 #include "xap_App.h"
69 /*
70   TODO this file is now really too long.  divide it up
71   into smaller ones.
72 */
73 
fl_SectionLayout(FL_DocLayout * pLayout,pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP,SectionType iType,fl_ContainerType iCType,PTStruxType iStrux,fl_ContainerLayout * pMyContainerLayout)74 fl_SectionLayout::fl_SectionLayout(FL_DocLayout* pLayout, pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP, SectionType iType, fl_ContainerType iCType, PTStruxType iStrux, fl_ContainerLayout * pMyContainerLayout)
75 	: fl_ContainerLayout(pMyContainerLayout, sdh, indexAP,iStrux, iCType),
76 	  m_iType(iType),
77 	  m_pLayout(pLayout),
78 	  m_bIsCollapsed(false), // collapsed layouts cannot contain point, and this value never changes
79 	  m_bNeedsReformat(true),
80 	  m_bNeedsRedraw(true),
81 	  m_pGraphicImage(NULL),
82 	  m_pImageImage(NULL),
83 	  m_iGraphicTick(0),
84 	  m_iDocImageWidth(0),
85 	  m_iDocImageHeight(0)
86 
87 {
88 	UT_ASSERT(pLayout);
89 	m_pDoc = pLayout->getDocument();
90 }
91 
~fl_SectionLayout()92 fl_SectionLayout::~fl_SectionLayout()
93 {
94 	DELETEP(m_pGraphicImage);
95 	DELETEP(m_pImageImage);
96 }
97 
getDocLayout(void) const98 FL_DocLayout* fl_SectionLayout::getDocLayout(void) const
99 {
100 	if(m_pLayout == NULL)
101 	{
102 		return fl_ContainerLayout::getDocLayout();
103 	}
104 	return m_pLayout;
105 }
106 
recalculateFields(UT_uint32 iUpdateCount)107 bool fl_SectionLayout::recalculateFields(UT_uint32 iUpdateCount)
108 {
109 	bool bResult = false;
110 
111 	fl_ContainerLayout*	pL = getFirstLayout();
112 
113 	while (pL)
114 	{
115 		bResult = pL->recalculateFields(iUpdateCount) || bResult;
116 
117 		pL = pL->getNext();
118 	}
119 
120 	return bResult;
121 }
122 
123 
markAllRunsDirty(void)124 void fl_SectionLayout::markAllRunsDirty(void)
125 {
126 	fl_ContainerLayout*	pL = getFirstLayout();
127 	while (pL)
128 	{
129 		pL->markAllRunsDirty();
130 		pL = pL->getNext();
131 	}
132 }
133 
_purgeLayout()134 void fl_SectionLayout::_purgeLayout()
135 {
136 	fl_ContainerLayout*	pL = getLastLayout();
137 
138 	while (pL)
139 	{
140 		fl_ContainerLayout* pNuke = pL;
141 
142 		pL = pL->getPrev();
143 		pNuke->setNext(NULL);
144 		delete pNuke;
145 	}
146 
147 	return;
148 }
149 
removeFromUpdate(fl_ContainerLayout * pCL)150 void fl_SectionLayout::removeFromUpdate(fl_ContainerLayout * pCL)
151 {
152   while((m_vecFormatLayout.getItemCount() > 0) && (m_vecFormatLayout.findItem(pCL) >= 0))
153   {
154     UT_sint32 i = m_vecFormatLayout.findItem(pCL);
155     m_vecFormatLayout.deleteNthItem(i);
156   }
157 }
158 
159 
clearNeedsReformat(fl_ContainerLayout * pCL)160 void fl_SectionLayout::clearNeedsReformat(fl_ContainerLayout * pCL)
161 {
162        UT_sint32 i = m_vecFormatLayout.findItem(pCL);
163        if(i>= 0)
164        {
165 	   m_vecFormatLayout.deleteNthItem(i);
166        }
167        if(m_vecFormatLayout.getItemCount() == 0)
168        {
169 	   m_bNeedsReformat = false;
170        }
171 }
172 
setNeedsReformat(fl_ContainerLayout * pCL,UT_uint32)173 void fl_SectionLayout::setNeedsReformat(fl_ContainerLayout * pCL, UT_uint32 /*offset*/)
174 {
175         UT_sint32 i = m_vecFormatLayout.findItem(pCL);
176 	if(i< 0)
177 	{
178 	  m_vecFormatLayout.addItem(pCL);
179 	}
180 	m_bNeedsReformat = true;
181 	xxx_UT_DEBUGMSG(("SetNeedsReformat in %s from %s number to format %d\n",getContainerString(),pCL->getContainerString(),m_vecFormatLayout.getItemCount()));
182 	if(myContainingLayout() != NULL && (static_cast<fl_SectionLayout *>(myContainingLayout()) != this) && (getContainerType() != FL_CONTAINER_SHADOW))
183 	{
184 		static_cast<fl_SectionLayout *>(myContainingLayout())->setNeedsReformat(this);
185 	}
186 	if(getContainerType() == FL_CONTAINER_SHADOW)
187 	{
188 		fl_HdrFtrShadow * pShad = static_cast<fl_HdrFtrShadow *>(this);
189 		pShad->getHdrFtrSectionLayout()->setNeedsReformat(this,0);
190 	}
191 }
192 
193 
setNeedsRedraw(void)194 void fl_SectionLayout::setNeedsRedraw(void)
195 {
196 	m_bNeedsRedraw = true;
197 	if(myContainingLayout() != NULL  && static_cast<fl_SectionLayout *>(myContainingLayout()) != this)
198 	{
199 		static_cast<fl_SectionLayout *>(myContainingLayout())->setNeedsRedraw();
200 	}
201 }
202 
bl_doclistener_populateSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs,PT_BlockOffset blockOffset,UT_uint32 len)203 bool fl_SectionLayout::bl_doclistener_populateSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs, PT_BlockOffset blockOffset, UT_uint32 len)
204 {
205     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
206 	if(pBL->getPrev()!= NULL && pBL->getPrev()->getLastContainer()==NULL)
207 	{
208 		UT_DEBUGMSG(("In bl_doclistner_pop no LastLine \n"));
209 		UT_DEBUGMSG(("getPrev = %p this = %p \n",pBL->getPrev(),pBL));
210 		//  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
211 	}
212 	bool bres = true;
213 	if(pHFSL)
214 	{
215 		if(pBL)
216 		{
217 			bres = pHFSL->bl_doclistener_populateSpan(pBL,pcrs,blockOffset,len);
218 		}
219 		else
220 		{
221 			return false;
222 		}
223 		return bres;
224 	}
225 
226 	return static_cast<fl_BlockLayout *>(pBL)->doclistener_populateSpan(pcrs, blockOffset, len);
227 }
228 
bl_doclistener_populateObject(fl_ContainerLayout * pBL,PT_BlockOffset blockOffset,const PX_ChangeRecord_Object * pcro)229 bool fl_SectionLayout::bl_doclistener_populateObject(fl_ContainerLayout* pBL, PT_BlockOffset blockOffset, const PX_ChangeRecord_Object * pcro)
230 {
231     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
232 	bool bres = true;
233 	if(pHFSL)
234 	{
235 		if(pBL)
236 		{
237 			bres = pHFSL->bl_doclistener_populateObject(pBL,blockOffset,pcro);
238 		}
239 		else
240 		{
241 			return false;
242 		}
243 		return bres;
244 	}
245 	return static_cast<fl_BlockLayout *>(pBL)->doclistener_populateObject(blockOffset, pcro);
246 }
247 
bl_doclistener_insertSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs)248 bool fl_SectionLayout::bl_doclistener_insertSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs)
249 {
250     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
251 	bool bres = true;
252 	if(pHFSL)
253 	{
254 		if(pBL)
255 		{
256 			bres = pHFSL->bl_doclistener_insertSpan(pBL,pcrs);
257 		}
258 		else
259 		{
260 			return false;
261 		}
262 		pHFSL->checkAndAdjustCellSize(this);
263 		return bres;
264 	}
265     bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertSpan(pcrs);
266 	checkAndAdjustCellSize();
267 	return bres;
268 }
269 
bl_doclistener_deleteSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs)270 bool fl_SectionLayout::bl_doclistener_deleteSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs)
271 {
272     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
273 	bool bres = true;
274 	if(pHFSL)
275 	{
276 		if(pBL)
277 		{
278 			bres = pHFSL->bl_doclistener_deleteSpan(pBL,pcrs);
279 		}
280 		else
281 		{
282 			return false;
283 		}
284 		pHFSL->checkAndAdjustCellSize(this);
285 		return bres;
286 	}
287 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteSpan(pcrs);
288 	checkAndAdjustCellSize();
289 	return bres;
290 }
291 
bl_doclistener_changeSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_SpanChange * pcrsc)292 bool fl_SectionLayout::bl_doclistener_changeSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_SpanChange * pcrsc)
293 {
294     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
295 	bool bres = true;
296 	if(pHFSL)
297 	{
298 		if(pBL)
299 		{
300 			bres = pHFSL->bl_doclistener_changeSpan(pBL,pcrsc);
301 		}
302 		else
303 		{
304 			return false;
305 		}
306 		pHFSL->checkAndAdjustCellSize(this);
307 		return bres;
308 	}
309 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeSpan(pcrsc);
310 	checkAndAdjustCellSize();
311 	return bres;
312 }
313 
bl_doclistener_deleteStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx)314 bool fl_SectionLayout::bl_doclistener_deleteStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx)
315 {
316     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
317 	bool bres = true;
318 	if(pHFSL)
319 	{
320 		if(pBL)
321 		{
322 			bres = pHFSL->bl_doclistener_deleteStrux(pBL,pcrx);
323 		}
324 		else
325 		{
326 			return false;
327 		}
328 		pHFSL->checkAndAdjustCellSize(this);
329 		return bres;
330 	}
331 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteStrux(pcrx);
332 	checkAndAdjustCellSize();
333 	return bres;
334 }
335 
bl_doclistener_changeStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_StruxChange * pcrxc)336 bool fl_SectionLayout::bl_doclistener_changeStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_StruxChange * pcrxc)
337 {
338     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
339 	bool bres = true;
340 	if(pHFSL)
341 	{
342 		if(pBL)
343 		{
344 			bres = pHFSL->bl_doclistener_changeStrux(pBL,pcrxc);
345 		}
346 		else
347 		{
348 			return false;
349 		}
350 		pHFSL->checkAndAdjustCellSize(this);
351 		return bres;
352 	}
353 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeStrux(pcrxc);
354 	checkAndAdjustCellSize();
355 	return bres;
356 }
357 
bl_doclistener_insertBlock(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))358 bool fl_SectionLayout::bl_doclistener_insertBlock(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx,
359 												  pf_Frag_Strux* sdh,
360 												  PL_ListenerId lid,
361 												  void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
362 																		  PL_ListenerId lid,
363 																		  fl_ContainerLayout* sfhNew))
364 {
365     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
366 	bool bres = true;
367 	UT_ASSERT(m_pDoc->getAllowChangeInsPoint());
368 	if(pHFSL)
369 	{
370 		if(pBL)
371 		{
372 			pHFSL->bl_doclistener_insertBlock(pBL,pcrx, sdh, lid, pfnBindHandles);
373 		}
374 		else
375 		{
376 			// Insert the block at the beginning of the section
377 			fl_BlockLayout*	pNewBL = static_cast<fl_BlockLayout *>(insert(sdh, NULL, pcrx->getIndexAP(),FL_CONTAINER_BLOCK));
378 			if (!pNewBL)
379 			{
380 				UT_DEBUGMSG(("no memory for BlockLayout\n"));
381 				return false;
382 			}
383 			bres = pNewBL->doclistener_insertFirstBlock(pcrx, sdh,
384 													lid, pfnBindHandles);			// Insert the block at the beginning of the section in the HDrFtr
385             // Typically a cell of a table
386 			bres = pHFSL->bl_doclistener_insertFirstBlock(this,pcrx, sdh, lid);
387 		}
388 		pHFSL->checkAndAdjustCellSize(this);
389 		UT_ASSERT(m_pDoc->getAllowChangeInsPoint());
390 		return bres;
391 	}
392 	if (pBL)
393 		return static_cast<fl_BlockLayout *>(pBL)->doclistener_insertBlock(pcrx, sdh, lid, pfnBindHandles);
394 	else
395 	{
396 		// Insert the block at the beginning of the section
397 		fl_BlockLayout*	pNewBL = static_cast<fl_BlockLayout *>(insert(sdh, NULL, pcrx->getIndexAP(),FL_CONTAINER_BLOCK));
398 		if (!pNewBL)
399 		{
400 			UT_DEBUGMSG(("no memory for BlockLayout\n"));
401 			return false;
402 		}
403 		UT_ASSERT(m_pDoc->getAllowChangeInsPoint());
404 		return pNewBL->doclistener_insertFirstBlock(pcrx, sdh,
405 													lid, pfnBindHandles);
406 
407 	}
408 }
409 
checkAndAdjustCellSize(void)410 void fl_SectionLayout::checkAndAdjustCellSize(void)
411 {
412 	if(getContainerType() != FL_CONTAINER_CELL)
413 	{
414 		return;
415 	}
416 	fl_CellLayout * pCell = static_cast<fl_CellLayout *>(this);
417 	pCell->checkAndAdjustCellSize();
418 }
419 
bl_doclistener_insertSection(fl_ContainerLayout * pPrevL,SectionType iType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))420 bool fl_SectionLayout::bl_doclistener_insertSection(fl_ContainerLayout* pPrevL,
421 													SectionType iType,
422 													const PX_ChangeRecord_Strux * pcrx,
423 													pf_Frag_Strux* sdh,
424 													PL_ListenerId lid,
425 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
426 																			PL_ListenerId lid,
427 																			fl_ContainerLayout* sfhNew))
428 {
429 	if(pPrevL->getContainerType() == FL_CONTAINER_BLOCK)
430 	{
431 		bool bres = static_cast<fl_BlockLayout *>(pPrevL)->doclistener_insertSection(pcrx, iType, sdh, lid, pfnBindHandles);
432 		return bres;
433 	}
434 	else if(iType == FL_SECTION_TOC)
435 	{
436 		PT_AttrPropIndex indexAP = pcrx->getIndexAP();
437 		fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(insert(sdh,pPrevL,indexAP, FL_CONTAINER_TOC));
438 
439 		// Must call the bind function to complete the exchange of handles
440 		// with the document (piece table) *** before *** anything tries
441 		// to call down into the document (like all of the view
442 		// listeners).
443 
444 		fl_ContainerLayout* sfhNew = pSL;
445 		//
446 		// Don't bind to shadows
447 		//
448 		if(pfnBindHandles)
449 		{
450 			pfnBindHandles(sdh,lid,sfhNew);
451 		}
452 		//
453 		// That's all we need to do except update the view pointers I guess..
454 		//
455 		FV_View* pView = m_pLayout->getView();
456 		if (pView && (pView->isActive() || pView->isPreview()))
457 		{
458 			pView->setPoint(pcrx->getPosition() + fl_BLOCK_STRUX_OFFSET);
459 		}
460 		else if(pView && pView->getPoint() > pcrx->getPosition())
461 		{
462 			//
463 			// For EndTOC
464 			//
465 			pView->setPoint(pView->getPoint() + fl_BLOCK_STRUX_OFFSET + fl_BLOCK_STRUX_OFFSET);
466 		}
467 		if(pView)
468 		        pView->updateCarets(pcrx->getPosition(),1);
469 		return true;
470 
471 	}
472 	else if(((pPrevL->getContainerType() == FL_CONTAINER_FRAME) ||(pPrevL->getContainerType() == FL_CONTAINER_TABLE)) && (iType == FL_SECTION_HDRFTR))
473 	{
474 		fl_SectionLayout * pSL = new fl_HdrFtrSectionLayout(FL_HDRFTR_NONE,m_pLayout,NULL, sdh, pcrx->getIndexAP());
475 		fl_HdrFtrSectionLayout * pHFSL = static_cast<fl_HdrFtrSectionLayout *>(pSL);
476 		m_pLayout->addHdrFtrSection(pHFSL);
477 //
478 // Need to find the DocSectionLayout associated with this.
479 //
480 		const PP_AttrProp* pHFAP = NULL;
481 		PT_AttrPropIndex indexAP = pcrx->getIndexAP();
482 		bool bres = (m_pDoc->getAttrProp(indexAP, &pHFAP) && pHFAP);
483 		UT_UNUSED(bres);
484 		UT_ASSERT(bres);
485 		const gchar* pszNewID = NULL;
486 		pHFAP->getAttribute("id", pszNewID);
487 //
488 // pszHFID may not be defined yet. If not we can't do this stuff. If it is defined
489 // this step is essential
490 //
491 		if(pszNewID)
492 		{
493 		  // plam mystery code
494 			// plam, MES here, I need this code for inserting headers/footers.
495 		  UT_DEBUGMSG(("new id: tell plam if you see this message\n"));
496 //		  UT_ASSERT(0);
497 			fl_DocSectionLayout* pDocSL = m_pLayout->findSectionForHdrFtr(static_cast<const char*>(pszNewID));
498 			UT_ASSERT(pDocSL);
499 //
500 // Determine if this is a header or a footer.
501 //
502 			const gchar* pszSectionType = NULL;
503 			pHFAP->getAttribute("type", pszSectionType);
504 
505 			HdrFtrType hfType = FL_HDRFTR_NONE;
506 			if (pszSectionType && *pszSectionType)
507 			{
508 				if(strcmp(pszSectionType,"header") == 0)
509 					hfType = FL_HDRFTR_HEADER;
510 				else if (strcmp(pszSectionType,"header-even") == 0)
511 					hfType = FL_HDRFTR_HEADER_EVEN;
512 				else if (strcmp(pszSectionType,"header-first") == 0)
513 					hfType = FL_HDRFTR_HEADER_FIRST;
514 				else if (strcmp(pszSectionType,"header-last") == 0)
515 					hfType = FL_HDRFTR_HEADER_LAST;
516 				else if (strcmp(pszSectionType,"footer") == 0)
517 					hfType = FL_HDRFTR_FOOTER;
518 				else if (strcmp(pszSectionType,"footer-even") == 0)
519 					hfType = FL_HDRFTR_FOOTER_EVEN;
520 				else if (strcmp(pszSectionType,"footer-first") == 0)
521 					hfType = FL_HDRFTR_FOOTER_FIRST;
522 				else if (strcmp(pszSectionType,"footer-last") == 0)
523 					hfType = FL_HDRFTR_FOOTER_LAST;
524 
525 				if(hfType != FL_HDRFTR_NONE)
526 				{
527 					pHFSL->setDocSectionLayout(pDocSL);
528 					pHFSL->setHdrFtr(hfType);
529 					//
530 					// Set the pointers to this header/footer
531 					//
532 					pDocSL->setHdrFtr(hfType, pHFSL);
533 				}
534 			}
535 		}
536 		else
537 		{
538 			UT_DEBUGMSG(("NO ID found with insertSection HdrFtr \n"));
539 		}
540 
541 	// Must call the bind function to complete the exchange of handles
542 	// with the document (piece table) *** before *** anything tries
543 	// to call down into the document (like all of the view
544 	// listeners).
545 
546 		fl_ContainerLayout* sfhNew = pSL;
547 		//
548 		// Don't bind to shadows
549 		//
550 		if(pfnBindHandles)
551 		{
552 			pfnBindHandles(sdh,lid,sfhNew);
553 		}
554 
555 		fl_SectionLayout* pOldSL = getDocSectionLayout();
556 //
557 // Now move all the containers following into the new section
558 //
559 		fl_ContainerLayout* pCL = pPrevL->getNext();
560 	//
561 	// BUT!!! Don't move the immediate Footnotes, Endnotes or Annotations
562 	//
563 		fl_ContainerLayout * pLastCL = pPrevL;
564 
565 		while(pCL && (static_cast<fl_SectionLayout *>(pCL) == pSL))
566 		{
567 			pCL = pCL->getNext();
568 		}
569 		while(pCL && ((pCL->getContainerType() == FL_CONTAINER_FOOTNOTE) ||
570 					  (pCL->getContainerType() == FL_CONTAINER_ENDNOTE)||
571 					  (pCL->getContainerType() == FL_CONTAINER_ANNOTATION)))
572 		{
573 			pLastCL = pCL;
574 			pCL = pCL->getNext();
575 		}
576 		fl_BlockLayout * pBL = NULL;
577 		while (pCL)
578 		{
579 			fl_ContainerLayout* pNext = pCL->getNext();
580 			pBL = NULL;
581 			pCL->collapse();
582 			if(pCL->getContainerType()==FL_CONTAINER_BLOCK)
583 			{
584 				pBL = static_cast<fl_BlockLayout *>(pCL);
585 			}
586 			if(pBL && pBL->isHdrFtr())
587 			{
588 				fl_HdrFtrSectionLayout * pHF = static_cast<fl_HdrFtrSectionLayout *>(pBL->getSectionLayout());
589 				pHF->collapseBlock(pBL);
590 			}
591 			pOldSL->remove(pCL);
592 			pSL->add(pCL);
593 			if(pBL)
594 			{
595 				pBL->setSectionLayout( pSL);
596 				pBL->setNeedsReformat(pBL,0);
597 			}
598 			pCL = pNext;
599 		}
600 
601 //
602 // Terminate blocklist here. This Block is the last in this section.
603 //
604 		if (pLastCL)
605 		{
606 			pLastCL->setNext(NULL);
607 			pOldSL->setLastLayout(pLastCL);
608 		}
609 		if(pszNewID)
610 		{
611 			pSL->format();
612 			pSL->redrawUpdate();
613 		}
614 		else
615 			return true;
616 
617 		FV_View* pView = m_pLayout->getView();
618 		if (pView && (pView->isActive() || pView->isPreview()))
619 		{
620 			pView->setPoint(pcrx->getPosition() + fl_BLOCK_STRUX_OFFSET + fl_BLOCK_STRUX_OFFSET);
621 		}
622 		else if(pView && pView->getPoint() > pcrx->getPosition())
623 		{
624 			pView->setPoint(pView->getPoint() + fl_BLOCK_STRUX_OFFSET + fl_BLOCK_STRUX_OFFSET);
625 		}
626 		if(pView)
627 		  pView->updateCarets(pcrx->getPosition(),1);
628 		return true;
629 	}
630 	return false;
631 }
632 
633 
bl_doclistener_insertTable(fl_ContainerLayout * pBL,SectionType iType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))634 fl_SectionLayout * fl_SectionLayout::bl_doclistener_insertTable(fl_ContainerLayout* pBL,
635 													SectionType iType,
636 													const PX_ChangeRecord_Strux * pcrx,
637 													pf_Frag_Strux* sdh,
638 													PL_ListenerId lid,
639 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
640 																			PL_ListenerId lid,
641 																			fl_ContainerLayout* sfhNew))
642 {
643 	fl_SectionLayout * pSL = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertTable(pcrx, iType, sdh, lid, pfnBindHandles);
644 	checkAndAdjustCellSize();
645 	return pSL;
646 }
647 
648 
649 
bl_doclistener_insertTable(SectionType iType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))650 fl_SectionLayout * fl_SectionLayout::bl_doclistener_insertTable(SectionType iType,
651 													const PX_ChangeRecord_Strux * pcrx,
652 													pf_Frag_Strux* sdh,
653 													PL_ListenerId lid,
654 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
655 																			PL_ListenerId lid,
656 																			fl_ContainerLayout* sfhNew))
657 {
658 	UT_UNUSED(iType);
659 	UT_ASSERT(iType == FL_SECTION_TABLE);
660 	UT_return_val_if_fail(pcrx, NULL);
661 	UT_ASSERT(pcrx->getType() == PX_ChangeRecord::PXT_InsertStrux);
662 	PT_DocPosition pos1;
663 //
664 // This is to clean the fragments
665 //
666 	m_pDoc->getBounds(true,pos1);
667 
668 	fl_SectionLayout* pSL = NULL;
669 	bool bFrame = (getContainerType() == FL_CONTAINER_FRAME);
670 	PT_DocPosition pos = getPosition(true)+1;
671 	bool bTooFar = (pcrx->getPosition() > pos);
672 	if(bFrame && bTooFar)
673 	{
674 	  //
675 	  // This happens if a table is inserted right after an end frame strux
676 	  //
677 	  fl_DocSectionLayout * pDSL = getDocSectionLayout();
678 	  fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(this);
679 	  pSL = static_cast<fl_SectionLayout *>(static_cast<fl_ContainerLayout *>(pDSL)->insert(sdh,pCL,pcrx->getIndexAP(), FL_CONTAINER_TABLE));
680 
681 	}
682 	else
683 	{
684 	  pSL = static_cast<fl_SectionLayout *>(static_cast<fl_ContainerLayout *>(this)->insert(sdh,this,pcrx->getIndexAP(), FL_CONTAINER_TABLE));
685 	}
686 	fl_ContainerLayout* sfhNew = pSL;
687 	//
688 	// Don't bind to shadows
689 	//
690 	if(pfnBindHandles)
691 	{
692 		pfnBindHandles(sdh,lid,sfhNew);
693 	}
694 
695 //
696 // increment the insertion point in the view.
697 //
698 	FV_View* pView = m_pLayout->getView();
699 	if (pView && (pView->isActive() || pView->isPreview()))
700 	{
701 		pView->setPoint(pcrx->getPosition() + fl_BLOCK_STRUX_OFFSET);
702 	}
703 	else if(pView && pView->getPoint() > pcrx->getPosition())
704 	{
705 		pView->setPoint(pView->getPoint() + fl_BLOCK_STRUX_OFFSET);
706 	}
707 	if(pView)
708 		pView->updateCarets(pcrx->getPosition(),1);
709 //
710 // OK that's it!
711 //
712 	checkAndAdjustCellSize();
713 	return pSL;
714 }
715 
getFirstBlock(void) const716 fl_BlockLayout * fl_SectionLayout::getFirstBlock(void) const
717 {
718   fl_ContainerLayout * pCL = getFirstLayout();
719   if(pCL == NULL)
720   {
721     return NULL;
722   }
723   if(pCL->getContainerType() == FL_CONTAINER_BLOCK)
724   {
725     return static_cast<fl_BlockLayout *>(pCL);
726   }
727   return pCL->getNextBlockInDocument();
728 }
729 
bl_doclistener_insertFrame(fl_ContainerLayout * pBL,SectionType iType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))730 fl_SectionLayout * fl_SectionLayout::bl_doclistener_insertFrame(fl_ContainerLayout* pBL,
731 													SectionType iType,
732 													const PX_ChangeRecord_Strux * pcrx,
733 													pf_Frag_Strux* sdh,
734 													PL_ListenerId lid,
735 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
736 																			PL_ListenerId lid,
737 																			fl_ContainerLayout* sfhNew))
738 {
739 	fl_SectionLayout * pSL = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertFrame(pcrx, iType, sdh, lid, pfnBindHandles);
740 	return pSL;
741 }
742 
bl_doclistener_insertObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_Object * pcro)743 bool fl_SectionLayout::bl_doclistener_insertObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_Object * pcro)
744 {
745     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
746 	bool bres = true;
747 	if(pHFSL)
748 	{
749 		if(pBL)
750 		{
751 			bres = pHFSL->bl_doclistener_insertObject(pBL,pcro);
752 		}
753 		else
754 		{
755 			return false;
756 		}
757 		pHFSL->checkAndAdjustCellSize(this);
758 		return bres;
759 	}
760 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertObject(pcro);
761 	checkAndAdjustCellSize();
762 	return bres;
763 }
764 
bl_doclistener_deleteObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_Object * pcro)765 bool fl_SectionLayout::bl_doclistener_deleteObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_Object * pcro)
766 {
767     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
768 	bool bres = true;
769 	if(pHFSL)
770 	{
771 		if(pBL)
772 		{
773 			bres = pHFSL->bl_doclistener_deleteObject(pBL,pcro);
774 		}
775 		else
776 		{
777 			return false;
778 		}
779 		pHFSL->checkAndAdjustCellSize(this);
780 		return bres;
781 	}
782 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteObject(pcro);
783 	checkAndAdjustCellSize();
784 	return bres;
785 }
786 
bl_doclistener_changeObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_ObjectChange * pcroc)787 bool fl_SectionLayout::bl_doclistener_changeObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_ObjectChange * pcroc)
788 {
789     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
790 	bool bres = true;
791 	if(pHFSL)
792 	{
793 		if(pBL)
794 		{
795 			bres = pHFSL->bl_doclistener_changeObject(pBL,pcroc);
796 		}
797 		else
798 		{
799 			return false;
800 		}
801 		pHFSL->checkAndAdjustCellSize(this);
802 		return bres;
803 	}
804 
805 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeObject(pcroc);
806 	checkAndAdjustCellSize();
807 	return bres;
808 }
809 
bl_doclistener_insertFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMark * pcrfm)810 bool fl_SectionLayout::bl_doclistener_insertFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMark * pcrfm)
811 {
812     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
813 	bool bres = true;
814 	if(pHFSL)
815 	{
816 		if(pBL)
817 		{
818 			bres = pHFSL->bl_doclistener_insertFmtMark(pBL,pcrfm);
819 		}
820 		else
821 		{
822 			return false;
823 		}
824 		pHFSL->checkAndAdjustCellSize(this);
825 		return bres;
826 	}
827 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertFmtMark(pcrfm);
828 	checkAndAdjustCellSize();
829 	return bres;
830 }
831 
bl_doclistener_deleteFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMark * pcrfm)832 bool fl_SectionLayout::bl_doclistener_deleteFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMark * pcrfm)
833 {
834     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
835 	bool bres = true;
836 	if(pHFSL)
837 	{
838 		if(pBL)
839 		{
840 			bres = pHFSL->bl_doclistener_deleteFmtMark(pBL,pcrfm);
841 		}
842 		else
843 		{
844 			return false;
845 		}
846 		pHFSL->checkAndAdjustCellSize(this);
847 		return bres;
848 	}
849 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteFmtMark(pcrfm);
850 	checkAndAdjustCellSize();
851 	return bres;
852 }
853 
bl_doclistener_changeFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMarkChange * pcrfmc)854 bool fl_SectionLayout::bl_doclistener_changeFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMarkChange * pcrfmc)
855 {
856     fl_HdrFtrSectionLayout * pHFSL = getHdrFtrLayout();
857 	bool bres = true;
858 	if(pHFSL)
859 	{
860 		if(pBL)
861 		{
862 			bres = pHFSL->bl_doclistener_changeFmtMark(pBL,pcrfmc);
863 		}
864 		else
865 		{
866 			return false;
867 		}
868 		pHFSL->checkAndAdjustCellSize(this);
869 		return bres;
870 	}
871 	bres = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeFmtMark(pcrfmc);
872 	checkAndAdjustCellSize();
873 	return bres;
874 }
875 
876 
setImageWidth(UT_sint32 iWidth)877 void fl_SectionLayout::setImageWidth(UT_sint32 iWidth)
878 {
879     m_iDocImageWidth = iWidth;
880 }
881 
setImageHeight(UT_sint32 iHeight)882 void  fl_SectionLayout::setImageHeight(UT_sint32 iHeight)
883 {
884     m_iDocImageHeight = iHeight;
885 }
886 
checkGraphicTick(GR_Graphics * pG)887 void fl_SectionLayout::checkGraphicTick(GR_Graphics * pG)
888 {
889   if(getDocLayout()->getGraphicTick() != m_iGraphicTick)
890     {
891       xxx_UT_DEBUGMSG(("Current tick == %d layout Tick == %d \n",m_iGraphicTick,getDocLayout()->getGraphicTick()));
892     }
893   if(m_pGraphicImage && ((getDocLayout()->getGraphicTick() != m_iGraphicTick) || (m_pImageImage == NULL) ))
894 	{
895 		DELETEP(m_pImageImage);
896 		m_pImageImage = m_pGraphicImage->regenerateImage(pG);
897 		const UT_Rect rec(0,0,m_iDocImageWidth,m_iDocImageHeight);
898 		m_pImageImage->scaleImageTo(pG,rec);
899 		m_iGraphicTick = getDocLayout()->getGraphicTick();
900 	}
901 }
902 
903 
904 //////////////////////////////////////////////////////////////////
905 //////////////////////////////////////////////////////////////////
906 #ifdef _MSC_VER	// MSVC++ warns about using 'this' in initializer list.
907 #pragma warning(disable: 4355)
908 #endif
fl_DocSectionLayout(FL_DocLayout * pLayout,pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP,SectionType iType)909 fl_DocSectionLayout::fl_DocSectionLayout(FL_DocLayout* pLayout, pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP, SectionType iType)
910 	: fl_SectionLayout(pLayout, sdh, indexAP, iType, FL_CONTAINER_DOCSECTION,PTX_Section, this),
911 	  m_ColumnBreaker(this),
912 	  m_pHeaderSL(NULL),
913 	  m_pFooterSL(NULL),
914 	  m_pHeaderEvenSL(NULL),
915 	  m_pFooterEvenSL(NULL),
916 	  m_pHeaderFirstSL(NULL),
917 	  m_pFooterFirstSL(NULL),
918 	  m_pHeaderLastSL(NULL),
919 	  m_pFooterLastSL(NULL),
920 	  m_iNumColumns(1),
921 	  m_iColumnGap(0),
922 	  m_bColumnLineBetween(false),
923 	  m_iColumnOrder(0),
924 	  m_iSpaceAfter(0),
925 	  m_bRestart(false),
926 	  m_iRestartValue(0),
927 
928 	  m_iLeftMargin(0),
929 	  m_dLeftMarginUserUnits(0.0),
930 	  m_iRightMargin(0),
931 	  m_dRightMarginUserUnits(0.0),
932 	  m_iTopMargin(0),
933 	  m_dTopMarginUserUnits(0.0),
934 	  m_iBottomMargin(0),
935 	  m_dBottomMarginUserUnits(0.0),
936 	  m_iFooterMargin(0),
937 	  m_dFooterMarginUserUnits(0.0),
938 	  m_iHeaderMargin(0),
939 	  m_dHeaderMarginUserUnits(0.0),
940 	  m_iMaxSectionColumnHeight(0),
941 	  m_dMaxSectionColumnHeight(0.0),
942 	  m_iFootnoteLineThickness(0),
943 	  m_iFootnoteYoff(0),
944 
945 	  m_pFirstColumn(NULL),
946 	  m_pLastColumn(NULL),
947 	  m_pFirstOwnedPage(NULL),
948 
949 	  m_bNeedsFormat(false),
950 	  m_bNeedsRebuild(false),
951 	  m_bNeedsSectionBreak(true),
952 	  m_pFirstEndnoteContainer(NULL),
953 	  m_pLastEndnoteContainer(NULL),
954 	  m_bDeleteingBrokenContainers(false),
955 	  m_iNewHdrHeight(0),
956 	  m_iNewFtrHeight(0),
957 	  m_pHdrFtrChangeTimer(NULL),
958 	  m_bDoingCollapse(false)
959 {
960 	UT_ASSERT(iType == FL_SECTION_DOC);
961 
962 	m_pDoc= pLayout->getDocument();
963 
964 	m_sPaperColor.clear();
965 	m_sScreenColor.clear();
966 	lookupProperties();
967 }
968 
~fl_DocSectionLayout()969 fl_DocSectionLayout::~fl_DocSectionLayout()
970 {
971 // Remove any background HdrFtr change callbacks
972 
973 	if(m_pHdrFtrChangeTimer)
974 	{
975 		m_pHdrFtrChangeTimer->stop();
976 		DELETEP(m_pHdrFtrChangeTimer);
977 	}
978 	// Don't delete broken tables since their pages have been removed
979 
980 	// NB: be careful about the order of these
981 	_purgeLayout();
982 
983 	UT_GenericVector<fl_HdrFtrSectionLayout*> vecHdrFtr;
984 	getVecOfHdrFtrs( &vecHdrFtr);
985 	UT_sint32 i = 0;
986 	fl_HdrFtrSectionLayout * pHdrFtr = NULL;
987 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
988 	{
989 		pHdrFtr = vecHdrFtr.getNthItem(i);
990 		delete pHdrFtr;
991 	}
992 
993 	fp_Column* pCol = m_pFirstColumn;
994 	while (pCol)
995 	{
996 		fp_Column* pNext = static_cast<fp_Column *>(pCol->getNext());
997 
998 		delete pCol;
999 
1000 		pCol = pNext;
1001 	}
1002 }
1003 
setFirstEndnoteContainer(fp_EndnoteContainer * pECon)1004 void fl_DocSectionLayout::setFirstEndnoteContainer(fp_EndnoteContainer * pECon)
1005 {
1006 	m_pFirstEndnoteContainer = pECon;
1007 }
1008 
1009 
setLastEndnoteContainer(fp_EndnoteContainer * pECon)1010 void fl_DocSectionLayout::setLastEndnoteContainer(fp_EndnoteContainer * pECon)
1011 {
1012 	m_pLastEndnoteContainer = pECon;
1013 }
1014 
1015 
getFirstEndnoteContainer(void)1016 fp_Container * fl_DocSectionLayout::getFirstEndnoteContainer(void)
1017 {
1018 	fp_Container * pCon = static_cast<fp_Container *>(m_pFirstEndnoteContainer);
1019 	return pCon;
1020 }
1021 
getLastEndnoteContainer(void)1022 fp_Container * fl_DocSectionLayout::getLastEndnoteContainer(void)
1023 {
1024 	fp_Container * pCon = static_cast<fp_Container *>(m_pLastEndnoteContainer);
1025 	return pCon;
1026 }
1027 
1028 
getFootnoteLayout(UT_uint32 pid)1029 fl_FootnoteLayout * fl_DocSectionLayout::getFootnoteLayout(UT_uint32 pid)
1030 {
1031 	fl_ContainerLayout * pCL = getFirstLayout();
1032 	fl_FootnoteLayout * pFL = NULL;
1033 	bool bFound = false;
1034 	while(pCL && !bFound)
1035 	{
1036 		if(pCL->getContainerType() == FL_CONTAINER_FOOTNOTE)
1037 		{
1038 			pFL = static_cast<fl_FootnoteLayout *>(pCL);
1039 			if(pFL->getFootnotePID() == pid)
1040 			{
1041 				bFound = true;
1042 				break;
1043 			}
1044 		}
1045 		pCL = pCL->getNext();
1046 	}
1047 	if(bFound)
1048 	{
1049 		return pFL;
1050 	}
1051 	return NULL;
1052 }
1053 
1054 
getAnnotationLayout(UT_uint32 pid)1055 fl_AnnotationLayout * fl_DocSectionLayout::getAnnotationLayout(UT_uint32 pid)
1056 {
1057 	fl_ContainerLayout * pCL = getFirstLayout();
1058 	fl_AnnotationLayout * pAL = NULL;
1059 	bool bFound = false;
1060 	while(pCL && !bFound)
1061 	{
1062 		if(pCL->getContainerType() == FL_CONTAINER_ANNOTATION)
1063 		{
1064 			pAL = static_cast<fl_AnnotationLayout *>(pCL);
1065 			if(pAL->getAnnotationPID() == pid)
1066 			{
1067 				bFound = true;
1068 				break;
1069 			}
1070 		}
1071 		pCL = pCL->getNext();
1072 	}
1073 	if(bFound)
1074 	{
1075 		return pAL;
1076 	}
1077 	return NULL;
1078 }
1079 
1080 /*!
1081  * Returns the usuable height of the Column in logical units (after subtracting
1082  * top and bottom margins)
1083  */
getActualColumnHeight(void)1084 UT_sint32 fl_DocSectionLayout::getActualColumnHeight(void)
1085 {
1086 	UT_sint32 Height = static_cast<UT_sint32>(m_pLayout->m_docViewPageSize.Height(DIM_IN) * UT_LAYOUT_RESOLUTION /m_pLayout->m_docViewPageSize.getScale());
1087 	Height -= (getTopMargin() + getBottomMargin());
1088 	if(m_iMaxSectionColumnHeight > 0)
1089 	{
1090 		Height = m_iMaxSectionColumnHeight;
1091 	}
1092 	return Height;
1093 }
1094 
1095 
1096 /*!
1097  * Returns the usuable width of the Column in logical units (after subtracting
1098  * left and right margins)
1099  */
1100 
getActualColumnWidth(void)1101 UT_sint32 fl_DocSectionLayout::getActualColumnWidth(void)
1102 {
1103 	UT_sint32 width = static_cast<UT_sint32>(m_pLayout->m_docViewPageSize.Width(DIM_IN) * UT_LAYOUT_RESOLUTION /m_pLayout->m_docViewPageSize.getScale());
1104 	width -= (getLeftMargin() + getRightMargin());
1105 	if(m_iNumColumns > 1)
1106 	{
1107 		width -= m_iNumColumns*m_iColumnGap;
1108 		width = width/m_iNumColumns;
1109 	}
1110 	return width;
1111 }
1112 
getWidth(void)1113 UT_sint32 fl_DocSectionLayout::getWidth(void)
1114 {
1115 	UT_sint32 ires = m_pLayout->getGraphics()->getResolution();
1116 	UT_sint32 width = static_cast<UT_sint32>(ires * m_pLayout->m_docViewPageSize.Width(DIM_IN));
1117 	return width;
1118 }
1119 
setHdrFtr(HdrFtrType iType,fl_HdrFtrSectionLayout * pHFSL)1120 void fl_DocSectionLayout::setHdrFtr(HdrFtrType iType, fl_HdrFtrSectionLayout* pHFSL)
1121 {
1122 	if(pHFSL == NULL)
1123 	{
1124 		switch (iType)
1125 		{
1126 		case FL_HDRFTR_HEADER:
1127 			m_pHeaderSL = pHFSL; break;
1128 		case FL_HDRFTR_HEADER_EVEN:
1129 			m_pHeaderEvenSL = pHFSL; break;
1130 		case FL_HDRFTR_HEADER_FIRST:
1131 			m_pHeaderFirstSL = pHFSL; break;
1132 		case FL_HDRFTR_HEADER_LAST:
1133 			m_pHeaderLastSL = pHFSL; break;
1134 		case FL_HDRFTR_FOOTER:
1135 			m_pFooterSL = pHFSL; break;
1136 		case FL_HDRFTR_FOOTER_EVEN:
1137 			m_pFooterEvenSL = pHFSL; break;
1138 		case FL_HDRFTR_FOOTER_FIRST:
1139 			m_pFooterFirstSL = pHFSL; break;
1140 		case FL_HDRFTR_FOOTER_LAST:
1141 			m_pFooterLastSL = pHFSL; break;
1142 		case FL_HDRFTR_NONE:
1143 			UT_ASSERT(UT_SHOULD_NOT_HAPPEN); break;
1144 		}
1145 		checkAndRemovePages();
1146 		return;
1147 	}
1148 	const char* pszID = pHFSL->getAttribute("id");
1149 
1150 	const char* pszAtt = NULL;
1151 
1152 	pszAtt = getAttribute("header");
1153 	if (pszAtt && (0 == strcmp(pszAtt, pszID)) && (iType == FL_HDRFTR_HEADER) )
1154 	{
1155 		m_pHeaderSL = pHFSL;
1156 		checkAndRemovePages();
1157 		return;
1158 	}
1159 
1160 	pszAtt = getAttribute("header-even");
1161 	if (pszAtt && (0 == strcmp(pszAtt, pszID))&& (iType == FL_HDRFTR_HEADER_EVEN) )
1162 	{
1163 		m_pHeaderEvenSL = pHFSL;
1164 		checkAndRemovePages();
1165 		return;
1166 	}
1167 
1168 	pszAtt = getAttribute("header-first");
1169 	if (pszAtt && (0 == strcmp(pszAtt, pszID))&& (iType == FL_HDRFTR_HEADER_FIRST) )
1170 	{
1171 		m_pHeaderFirstSL = pHFSL;
1172 		checkAndRemovePages();
1173 		return;
1174 	}
1175 
1176 	pszAtt = getAttribute("header-last");
1177 	if (pszAtt && (0 == strcmp(pszAtt, pszID))&& (iType == FL_HDRFTR_HEADER_LAST) )
1178 	{
1179 		m_pHeaderLastSL = pHFSL;
1180 		checkAndRemovePages();
1181 		return;
1182 	}
1183 
1184 	pszAtt = getAttribute("footer");
1185 	if (pszAtt && (0 == strcmp(pszAtt, pszID))&& (iType == FL_HDRFTR_FOOTER))
1186 	{
1187 		m_pFooterSL = pHFSL;
1188 		checkAndRemovePages();
1189 		return;
1190 	}
1191 
1192 	pszAtt = getAttribute("footer-even");
1193 	if (pszAtt && (0 == strcmp(pszAtt, pszID)) && (iType == FL_HDRFTR_FOOTER_EVEN)	)
1194 	{
1195 		m_pFooterEvenSL = pHFSL;
1196 		checkAndRemovePages();
1197 		return;
1198 	}
1199 
1200 	pszAtt = getAttribute("footer-first");
1201 	if (pszAtt && (0 == strcmp(pszAtt, pszID)) && (iType == FL_HDRFTR_FOOTER_FIRST)	)
1202 	{
1203 		m_pFooterFirstSL = pHFSL;
1204 		checkAndRemovePages();
1205 		return;
1206 	}
1207 
1208 	pszAtt = getAttribute("footer-last");
1209 	if (pszAtt && (0 == strcmp(pszAtt, pszID)) && (iType == FL_HDRFTR_FOOTER_LAST)	)
1210 	{
1211 		m_pFooterLastSL = pHFSL;
1212 		checkAndRemovePages();
1213 		return;
1214 	}
1215 
1216 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
1217 }
1218 
1219 /*!
1220  * The calback that implements the HdrFtr size change
1221  */
_HdrFtrChangeCallback(UT_Worker * pWorker)1222 void fl_DocSectionLayout::_HdrFtrChangeCallback(UT_Worker * pWorker)
1223 {
1224 	UT_return_if_fail(pWorker);
1225 	UT_DEBUGMSG(("Doing HdrFtr change callback %p \n",pWorker));
1226 	// Get the docSectionLayout
1227 	fl_DocSectionLayout * pDSL = static_cast<fl_DocSectionLayout *>(pWorker->getInstanceData());
1228 	UT_return_if_fail(pDSL);
1229 
1230 	// Win32 timers can fire prematurely on asserts (the dialog's
1231 	// message pump releases the timers)
1232 	if (!pDSL->getDocument())
1233 	{
1234 		return;
1235 	}
1236 	// Don't do anything while PT is changing
1237 	PD_Document * pDoc = pDSL->getDocument();
1238 	if(pDoc->isPieceTableChanging())
1239 	{
1240 		return;
1241 	}
1242 	if(pDSL->m_pLayout->isLayoutFilling())
1243 	{
1244 // FIXME:
1245 // Don't resize on load for now. Put this back laters when I can workout
1246 // how to avoid horrible slowdowns and crashes.
1247 //
1248 		pDSL->m_sHdrFtrChangeProps.clear();
1249 		pDSL->m_pHdrFtrChangeTimer->stop();
1250 		DELETEP(pDSL->m_pHdrFtrChangeTimer);
1251 		return;
1252 	}
1253 	// Don't do anything while a redrawupdate is happening either...
1254 	if(pDoc->isRedrawHappenning())
1255 	{
1256 		return;
1257 	}
1258 // Don't do anything until insertion point is allowed to change
1259 	if (!pDoc->getAllowChangeInsPoint())
1260 	{
1261 		return;
1262 	}
1263 	fl_DocSectionLayout * pPrev = static_cast<fl_DocSectionLayout *>(pDSL->getPrev());
1264 	bool bDoit = true;
1265 	while(pPrev && bDoit)
1266 	{
1267 //
1268 // If a timer has been set on a previous docsection don't do this until it's
1269 // cleared.
1270 //
1271 		if(pPrev->m_pHdrFtrChangeTimer != NULL)
1272 		{
1273 			return;
1274 		}
1275 		fl_DocSectionLayout * pPPrev = static_cast<fl_DocSectionLayout *>(pDSL->getPrev());
1276 		if(pPPrev != pPrev)
1277 		{
1278 			pPrev = pPPrev;
1279 		}
1280 		else
1281 		{
1282 			bDoit = false;
1283 			break;
1284 		}
1285 	}
1286 	const char * pProps = pDSL->m_sHdrFtrChangeProps.c_str();
1287 	UT_DEBUGMSG(("Header/Footer change props %s \n",pProps));
1288 	const gchar * pszAtts[4] = {"props",pProps,NULL,NULL};
1289 	pDoc->notifyPieceTableChangeStart();
1290 	FV_View * pView =  pDSL->m_pLayout->getView();
1291 	pf_Frag_Strux* sdh = pDSL->getStruxDocHandle();
1292     PT_DocPosition insPos = pView->getPoint();
1293 	fl_HdrFtrShadow * pShadow = pView->getEditShadow();
1294 	HdrFtrType hfType = FL_HDRFTR_HEADER;
1295 	if(pShadow)
1296 	{
1297 		hfType = pShadow->getHdrFtrSectionLayout()->getHFType();
1298 	}
1299 	UT_sint32 iPage = -1;
1300 	if(pShadow)
1301 	{
1302 		iPage = pDSL->m_pLayout->findPage(pShadow->getPage());
1303 	}
1304 	pDoc->setMarginChangeOnly( true);
1305 	pDoc->changeStruxFmtNoUndo(PTC_AddFmt,sdh,pszAtts,NULL);
1306 	pDoc->setMarginChangeOnly(false);
1307 //
1308 // Stop the resizer and delete and clear it's pointer. It's job is done now.
1309 //
1310 	pDSL->m_pHdrFtrChangeTimer->stop();
1311 //
1312 // update the screen
1313 //
1314 	pDSL->format();
1315 	pDSL->formatAllHdrFtr();
1316 	pDSL->updateLayout(true);
1317 	pDoc->signalListeners(PD_SIGNAL_UPDATE_LAYOUT);
1318 	pDoc->notifyPieceTableChangeEnd();
1319 	pDSL->m_sHdrFtrChangeProps.clear();
1320 //
1321 // Put the point at the right point in the header/footer on the right page.
1322 //
1323 	if(iPage >= 0)
1324 	{
1325 		fp_Page * pPage = pDSL->m_pLayout->getNthPage(iPage);
1326 		if(pPage)
1327 		{
1328 			fp_ShadowContainer* pShadowC = pPage->getHdrFtrP(hfType);
1329 			pShadow = pShadowC->getShadow();
1330 			pView->setHdrFtrEdit(pShadow);
1331 		}
1332 	}
1333     pView->setPoint(insPos);
1334 	pView->notifyListeners(AV_CHG_MOTION | AV_CHG_HDRFTR );
1335     pView->setPoint(insPos);
1336 	pView->ensureInsertionPointOnScreen();
1337 	DELETEP(pDSL->m_pHdrFtrChangeTimer);
1338 	pDSL->m_pHdrFtrChangeTimer = NULL;
1339 }
1340 
1341 /*!
1342  * This method is called if the top and bottom margins of the pages
1343  * have changed following an auto-resize request from the header.
1344  * We try to avoid a complete rebuild.
1345  */
doMarginChangeOnly(void)1346 void fl_DocSectionLayout::doMarginChangeOnly(void)
1347 {
1348 	const PP_AttrProp* pAP = NULL;
1349 	getAP(pAP);
1350 	UT_return_if_fail(pAP);
1351 
1352 	const gchar* pszSectionType = NULL;
1353 	pAP->getAttribute("type", pszSectionType);
1354 	lookupProperties();
1355 	fp_Page * pMyPage = m_pLayout->getFirstPage();
1356 	while(pMyPage && pMyPage->getOwningSection() != this)
1357 	{
1358 		pMyPage = pMyPage->getNext();
1359 	}
1360 	if(pMyPage == NULL)
1361 	{
1362 		return;
1363 	}
1364 //
1365 // Remove broken tables. They need to be rebroken.
1366 //
1367 	deleteBrokenTablesFromHere(NULL);
1368 	while(pMyPage && pMyPage->getOwningSection() == this)
1369 	{
1370 		pMyPage->TopBotMarginChanged();
1371 		pMyPage = pMyPage->getNext();
1372 	}
1373 //
1374 // Rebreak the document. Place containers on their new pages.
1375 //
1376 	fl_DocSectionLayout * pDSL = this;
1377 	while(pDSL)
1378 	{
1379 		pDSL->completeBreakSection();
1380 		pDSL = pDSL->getNextDocSection();
1381 	}
1382 }
1383 /*!
1384  * Signal a PT change at the next opportunity to change the height of a Hdr
1385  * (true) or footer (false)
1386  *
1387  * newHeight is the value in layout units of the new height of the
1388  * header/footer
1389  *
1390  * In both caes the header/footers grow "into" the document area.
1391  */
setHdrFtrHeightChange(bool bHdrFtr,UT_sint32 newHeight)1392 bool fl_DocSectionLayout::setHdrFtrHeightChange(bool bHdrFtr, UT_sint32 newHeight)
1393 {
1394 //
1395 // Look to see if we've already sent a signal and if we have to adjust
1396 // the height of the HdrFtr
1397 //
1398 	if(bHdrFtr)
1399 	{
1400 	        UT_DEBUGMSG(("newHeight %d  m_iNewHdrHeight %d \n",newHeight,m_iNewHdrHeight));
1401 		if(newHeight <= m_iNewHdrHeight)
1402 		{
1403 			return false;
1404 		}
1405 		m_iNewHdrHeight = newHeight;
1406 		getDocument()->setNewHdrHeight(newHeight);
1407 		UT_sint32 fullHeight = newHeight + getHeaderMargin();
1408 		UT_String sHeight = m_pLayout->getGraphics()->invertDimension(DIM_IN, static_cast<double>(fullHeight));
1409 		UT_String sProp = "page-margin-top";
1410 		UT_String_setProperty(m_sHdrFtrChangeProps,sProp,sHeight);
1411 	}
1412 	else
1413 	{
1414 		if(newHeight <= m_iNewFtrHeight)
1415 		{
1416 			return false;
1417 		}
1418 		m_iNewFtrHeight = newHeight;
1419 		getDocument()->setNewFtrHeight(newHeight);
1420 		UT_sint32 fullHeight = newHeight + getFooterMargin();
1421 		UT_String sHeight = m_pLayout->getGraphics()->invertDimension(DIM_IN, static_cast<double>(fullHeight));
1422 		UT_String sProp = "page-margin-bottom";
1423 		UT_String_setProperty(m_sHdrFtrChangeProps,sProp,sHeight);
1424 	}
1425 //
1426 // OK the idea is to run the timer in the idle loop until the Piecetable
1427 // is clear and we're not redrawing
1428 //
1429 // This means the resize will happen at the first opportunity after the
1430 // current edit is finished.
1431 //
1432 	if(m_pHdrFtrChangeTimer == NULL)
1433 	{
1434 	    int inMode = UT_WorkerFactory::IDLE | UT_WorkerFactory::TIMER;
1435 	    UT_WorkerFactory::ConstructMode outMode = UT_WorkerFactory::NONE;
1436 
1437 	    m_pHdrFtrChangeTimer = UT_WorkerFactory::static_constructor (_HdrFtrChangeCallback, this, inMode, outMode);
1438 
1439 	    UT_ASSERT(m_pHdrFtrChangeTimer);
1440 	    UT_ASSERT(outMode != UT_WorkerFactory::NONE);
1441 
1442 		// If the worker is working on a timer instead of in the idle
1443 		// time, set the frequency of the checks.
1444 	    if ( UT_WorkerFactory::TIMER == outMode )
1445 		{
1446 			// this is really a timer, so it's safe to static_cast it
1447 			static_cast<UT_Timer*>(m_pHdrFtrChangeTimer)->set(100);
1448 		}
1449 	    m_pHdrFtrChangeTimer->start();
1450 	}
1451 	return true;
1452 }
1453 
getHeader(void) const1454 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getHeader(void) const
1455 {
1456 	return m_pHeaderSL;
1457 }
1458 
getFooter(void) const1459 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getFooter(void) const
1460 {
1461 	return m_pFooterSL;
1462 }
1463 
1464 
getHeaderEven(void) const1465 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getHeaderEven(void) const
1466 {
1467 	return m_pHeaderEvenSL;
1468 }
1469 
getFooterEven(void) const1470 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getFooterEven(void) const
1471 {
1472 	return m_pFooterEvenSL;
1473 }
1474 
1475 
getHeaderFirst(void) const1476 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getHeaderFirst(void) const
1477 {
1478 	return m_pHeaderFirstSL;
1479 }
1480 
getFooterFirst(void) const1481 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getFooterFirst(void) const
1482 {
1483 	return m_pFooterFirstSL;
1484 }
1485 
1486 
getHeaderLast(void) const1487 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getHeaderLast(void) const
1488 {
1489 	return m_pHeaderLastSL;
1490 }
1491 
getFooterLast(void) const1492 fl_HdrFtrSectionLayout*   fl_DocSectionLayout::getFooterLast(void) const
1493 {
1494 	return m_pFooterLastSL;
1495 }
1496 
1497 
getFirstContainer() const1498 fp_Container* fl_DocSectionLayout::getFirstContainer() const
1499 {
1500 	return m_pFirstColumn;
1501 }
1502 
getLastContainer() const1503 fp_Container* fl_DocSectionLayout::getLastContainer() const
1504 {
1505 	return m_pLastColumn;
1506 }
1507 
setFirstContainer(fp_Container * pCon)1508 void fl_DocSectionLayout::setFirstContainer(fp_Container * pCon)
1509 {
1510 	UT_DEBUGMSG(("docSectionLayout: DocSec %p First container set to %p \n",this,pCon));
1511 	m_pFirstColumn = static_cast<fp_Column *>(pCon);
1512 }
1513 
1514 
setLastContainer(fp_Container * pCon)1515 void fl_DocSectionLayout::setLastContainer(fp_Container * pCon)
1516 {
1517 	m_pLastColumn = static_cast<fp_Column *>(pCon);
1518 }
1519 
1520 /*!
1521   Create new container
1522   \return The newly created container
1523 
1524   This creates a new column or row of same.
1525 
1526 */
getNewContainer(fp_Container * pFirstContainer)1527 fp_Container* fl_DocSectionLayout::getNewContainer(fp_Container * pFirstContainer)
1528 {
1529 	fp_Page* pPage = NULL;
1530 	fp_Column* pLastColumn = static_cast<fp_Column*>(getLastContainer());
1531 	fp_Column* pAfterColumn = NULL;
1532 	UT_sint32 iNextCtrHeight = 0;
1533 
1534 	if (pLastColumn)
1535 	{
1536 		fp_Container * prevContainer = NULL;
1537 		fp_Page* pTmpPage = NULL;
1538 		UT_sint32 pageHeight = 0;
1539 		pTmpPage = pLastColumn->getPage();
1540 		iNextCtrHeight = 0;
1541 		if(pFirstContainer != NULL)
1542 		{
1543 			prevContainer = static_cast<fp_Container *>(pFirstContainer->getPrevContainerInSection());
1544 		}
1545 		//
1546 		// Look to see if this page already has columns from this docSections
1547 		//
1548 		bool bColAlready = false;
1549 		UT_sint32 iCol = 0;
1550 		for(iCol =0; pTmpPage->countColumnLeaders(); iCol++)
1551 		{
1552 		    if(pTmpPage->getNthColumnLeader(iCol)->getDocSectionLayout() == this)
1553 		    {
1554 		 	 bColAlready = true;
1555 			 break;
1556 		    }
1557 		}
1558 //
1559 // Calculate from the page height up to prevContainer
1560 //
1561 		pageHeight = pTmpPage->getFilledHeight(prevContainer);
1562 		UT_sint32 avail =  pTmpPage->getAvailableHeight();
1563 		UT_sint32 newHeight = pageHeight+ 3*iNextCtrHeight;
1564 
1565 		if(pFirstContainer != NULL)
1566 		{
1567 			iNextCtrHeight = pFirstContainer->getHeight();
1568 		}
1569 		else if( pLastColumn->getLastContainer())
1570 		{
1571 			iNextCtrHeight = pLastColumn->getLastContainer()->getHeight();
1572 		}
1573 		else
1574 		{
1575 			iNextCtrHeight =12*14; // approximately one average line
1576 		}
1577 		xxx_UT_DEBUGMSG(("SEVIOR: Pageheight =%d nextlineheight =%d newheight = %d availableheight =%d linepos %d \n",pageHeight,iNextCtrHeight,newHeight,avail));
1578 		if( (newHeight  >= avail) || (pFirstContainer == NULL) || bColAlready)
1579 		{
1580 			xxx_UT_DEBUGMSG(("SEVIOR: Container on new page \n"));
1581 			if (pTmpPage->getNext())
1582 			{
1583 				pPage = pTmpPage->getNext();
1584 			}
1585 			else
1586 			{
1587 				bool bIsFilling = m_pLayout->isLayoutFilling();
1588 				pPage = m_pLayout->addNewPage(this,bIsFilling);
1589 			}
1590 		}
1591 		else
1592 		{
1593 			xxx_UT_DEBUGMSG(("SEVIOR: Container on current page \n"));
1594 			pPage = pTmpPage;
1595 			if(prevContainer == NULL)
1596 			{
1597 				pAfterColumn = pPage->getNthColumnLeader(pPage->countColumnLeaders()-1);
1598 			}
1599 			else
1600 			{
1601 				pAfterColumn = static_cast<fp_Column *>(prevContainer->getContainer())->getLeader();
1602 			}
1603 
1604 		}
1605 	}
1606 	else
1607 	{
1608 		// We currently have no columns in this section.  Time to
1609 		// create some.  If there is a previous section, then we need
1610 		// to start our section right after that one.  If not, then we
1611 		// start our section on the first page.  If there is no first
1612 		// page, then we need to create one.
1613 		fl_DocSectionLayout* pPrevSL = getPrevDocSection();
1614 		if (pPrevSL)
1615 		{
1616 			fp_Column * pPrevCol = static_cast<fp_Column *>(pPrevSL->getLastContainer());
1617 			while(pPrevCol == NULL)
1618 			{
1619 				UT_DEBUGMSG(("BUG! BUG! Prev section has no last container! Attempting to fix this \n"));
1620 				pPrevSL->format();
1621 				pPrevCol = static_cast<fp_Column *>(pPrevSL->getLastContainer());
1622 			}
1623 			pPage = pPrevCol->getPage();
1624 			pAfterColumn = pPage->getNthColumnLeader(pPage->countColumnLeaders()-1);
1625 		}
1626 		else
1627 		{
1628 			if (m_pLayout->countPages() > 0)
1629 			{
1630 				pPage = m_pLayout->getFirstPage();
1631 			}
1632 			else
1633 			{
1634 				pPage = m_pLayout->addNewPage(this,true);
1635 			}
1636 		}
1637 	}
1638 
1639 	UT_ASSERT(pPage);
1640 
1641 	// Create row of columns
1642 	fp_Column* pLeaderColumn = NULL;
1643 	fp_Column* pTail = NULL;
1644 	UT_uint32 i = 0;
1645 	for (i=0; i<m_iNumColumns; i++)
1646 	{
1647 		fp_Column* pCol = new fp_Column(this);
1648 		if (pTail)
1649 		{
1650 			pCol->setLeader(pLeaderColumn);
1651 			pTail->setFollower(pCol);
1652 			pTail->setNext(pCol);
1653 			pCol->setPrev(pTail);
1654 
1655 			pTail = pCol;
1656 		}
1657 		else
1658 		{
1659 			pLeaderColumn = pTail = pCol;
1660 			pLeaderColumn->setLeader(pLeaderColumn);
1661 		}
1662 	}
1663 
1664 	// Append added columns to any previous columns in this section.
1665 	if (m_pLastColumn)
1666 	{
1667 		UT_ASSERT(m_pFirstColumn);
1668 
1669 		m_pLastColumn->setNext(pLeaderColumn);
1670 		pLeaderColumn->setPrev(m_pLastColumn);
1671 	}
1672 	else
1673 	{
1674 		UT_ASSERT(!m_pFirstColumn);
1675 		UT_return_val_if_fail(pLeaderColumn, NULL);
1676 		m_pFirstColumn = pLeaderColumn;
1677 	}
1678 
1679 	// Find last added column and set that as the last in the section.
1680 	fp_Column* pLastNewCol = pLeaderColumn;
1681 	while (pLastNewCol->getFollower())
1682 	{
1683 		pLastNewCol = pLastNewCol->getFollower();
1684 	}
1685 	m_pLastColumn = pLastNewCol;
1686 	UT_ASSERT(!(m_pLastColumn->getNext()));
1687 	UT_ASSERT(!(m_pLastColumn->getFollower()));
1688 
1689 	pPage->insertColumnLeader(pLeaderColumn, pAfterColumn);
1690 
1691 	fp_Column* pTmpCol = pLeaderColumn;
1692 	i = 0;
1693  	while (pTmpCol)
1694 	{
1695 		UT_ASSERT(pTmpCol->getPage());
1696 
1697 		pTmpCol = pTmpCol->getFollower();
1698 		i++;
1699 	}
1700 
1701 	// Check if a frame needs to be inserted on this page
1702 	if (m_pLayout->isLayoutFilling())
1703 	{
1704 	    fp_FrameContainer * pFrame = m_pLayout->findFramesToBeInserted(pPage);
1705 	    while(pFrame)
1706 	    {
1707 		if (pPage->findFrameContainer(pFrame) < 0)
1708 		{
1709 		    pPage->insertFrameContainer(pFrame);
1710 		}
1711 		m_pLayout->removeFramesToBeInserted(pFrame);
1712 		pFrame = m_pLayout->findFramesToBeInserted(pPage);
1713 	    }
1714 	}
1715 
1716 	return pLeaderColumn;
1717 }
1718 
format(void)1719 void fl_DocSectionLayout::format(void)
1720 {
1721 	fl_ContainerLayout*	pBL = getFirstLayout();
1722 	FV_View * pView = m_pLayout->getView();
1723 
1724 	bool bShowHidden = pView && pView->getShowPara();
1725 	FPVisibility eHidden;
1726 	bool bHidden;
1727 
1728 	while (pBL)
1729 	{
1730 		eHidden  = pBL->isHidden();
1731 		bHidden = ((eHidden == FP_HIDDEN_TEXT && !bShowHidden)
1732 		              || eHidden == FP_HIDDEN_REVISION
1733 		              || eHidden == FP_HIDDEN_REVISION_AND_TEXT);
1734 
1735 		if(!bHidden)
1736 		{
1737 			pBL->format();
1738 			UT_sint32 count = 0;
1739 			while(pBL->getLastContainer() == NULL || pBL->getFirstContainer()==NULL)
1740 			{
1741 				UT_DEBUGMSG(("Error formatting a block try again \n"));
1742 				count = count + 1;
1743 				pBL->format();
1744 				if(count > 3)
1745 				{
1746 					UT_DEBUGMSG(("Give up trying to format. Hope for the best :-( \n"));
1747 					break;
1748 				}
1749 			}
1750 		}
1751 
1752 		pBL = pBL->getNext();
1753 	}
1754 	fp_Column * pCol = static_cast<fp_Column *>(getFirstContainer());
1755 	if(pCol == NULL)
1756 	{
1757 	        m_bNeedsFormat = false;
1758 		return;
1759 	}
1760 	//
1761 	// When the document is first loaded, all the lines
1762 	// in the section have been stuffed into the first column.
1763 	// When we do a break section, the lines that don't
1764 	// fit in the first column are shuffled into the
1765 	// second, then the ones that don't fit are shuffled
1766 	// into the third etc. This leads to a N^2 slow down
1767 	// in Breaksection. So instead we empty this column
1768 	// and let BreakSection fill each empty column as
1769 	// needed.
1770 	//
1771       	if(pCol && m_pLayout->isLayoutFilling())
1772 	{
1773 	      pCol->removeAll();
1774 	}
1775 
1776 	m_ColumnBreaker.breakSection();
1777 	m_bNeedsFormat = false;
1778 }
1779 
markAllRunsDirty(void)1780 void fl_DocSectionLayout::markAllRunsDirty(void)
1781 {
1782 	fl_ContainerLayout*	pBL = getFirstLayout();
1783 	while (pBL)
1784 	{
1785 		pBL->markAllRunsDirty();
1786 		pBL = pBL->getNext();
1787 	}
1788 	if(m_pHeaderSL)
1789 	{
1790 		m_pHeaderSL->markAllRunsDirty();
1791 	}
1792 	if(m_pHeaderEvenSL)
1793 	{
1794 		m_pHeaderEvenSL->markAllRunsDirty();
1795 	}
1796 	if(m_pHeaderFirstSL)
1797 	{
1798 		m_pHeaderFirstSL->markAllRunsDirty();
1799 	}
1800 	if(m_pHeaderLastSL)
1801 	{
1802 		m_pHeaderLastSL->markAllRunsDirty();
1803 	}
1804 	if(m_pFooterSL)
1805 	{
1806 		m_pFooterSL->markAllRunsDirty();
1807 	}
1808 	if(m_pFooterEvenSL)
1809 	{
1810 		m_pFooterEvenSL->markAllRunsDirty();
1811 	}
1812 	if(m_pFooterFirstSL)
1813 	{
1814 		m_pFooterFirstSL->markAllRunsDirty();
1815 	}
1816 	if(m_pFooterLastSL)
1817 	{
1818 		m_pFooterLastSL->markAllRunsDirty();
1819 	}
1820 }
1821 
updateLayout(bool bDoFull)1822 void fl_DocSectionLayout::updateLayout(bool bDoFull)
1823 {
1824 	fl_ContainerLayout*	pBL = getFirstLayout();
1825 	FV_View * pView = m_pLayout->getView();
1826 	bool bShowHidden = pView && pView->getShowPara();
1827 	FPVisibility eHidden;
1828 	bool bHidden;
1829 	//
1830 	// FIXME!! Do extensive tests to see if we can remove this line!
1831 	//
1832 	bDoFull = true;
1833 	UT_DEBUGMSG(("Doing DocSection Update layout (section %p)\n",this));
1834 	if (!bDoFull || (m_vecFormatLayout.getItemCount() > 0))
1835 	{
1836 	        UT_sint32 i =0;
1837 		UT_sint32 j = 0;
1838 		UT_sint32 count = m_vecFormatLayout.getItemCount();
1839 		for(i=0; i<count; i++)
1840 		{
1841 		        if(j >= m_vecFormatLayout.getItemCount())
1842 			    break;
1843 		        pBL = m_vecFormatLayout.getNthItem(j);
1844 			j++;
1845 		        eHidden  = pBL->isHidden();
1846 			bHidden = ((eHidden == FP_HIDDEN_TEXT && !bShowHidden)
1847 				   || eHidden == FP_HIDDEN_REVISION
1848 				   || eHidden == FP_HIDDEN_REVISION_AND_TEXT);
1849 
1850 			if(!bHidden)
1851 			{
1852 			  xxx_UT_DEBUGMSG(("container %x type %s needformat %d \n",pBL,pBL->getContainerString(),pBL->needsReformat()));
1853 			     if (pBL->needsReformat())
1854 			     {
1855 			          if(!(m_pLayout->isLayoutFilling() && pBL->getContainerType() == FL_CONTAINER_TOC))
1856 				  {
1857 				       pBL->format();
1858 				       j--;
1859 				       if(j < m_vecFormatLayout.getItemCount())
1860 				       {
1861 					    UT_sint32 k = m_vecFormatLayout.findItem(pBL);
1862 					    if(k == j)
1863 					         m_vecFormatLayout.deleteNthItem(j);
1864 				       }
1865 				  }
1866 			     }
1867 			     if (pBL->getContainerType() != FL_CONTAINER_BLOCK && !getDocument()->isDontImmediateLayout())
1868 			     {
1869 			          pBL->updateLayout(false);
1870 			     }
1871 			}
1872 
1873 		}
1874 	}
1875 	else if(bDoFull)
1876 	{
1877 	        while (pBL)
1878 		{
1879 		        eHidden  = pBL->isHidden();
1880 			bHidden = ((eHidden == FP_HIDDEN_TEXT && !bShowHidden)
1881 				   || eHidden == FP_HIDDEN_REVISION
1882 				   || eHidden == FP_HIDDEN_REVISION_AND_TEXT);
1883 
1884 			if(!bHidden)
1885 			{
1886 			     if (pBL->needsReformat())
1887 			     {
1888 			          if(!(m_pLayout->isLayoutFilling() && pBL->getContainerType() == FL_CONTAINER_TOC))
1889 				  {
1890 				       pBL->format();
1891 				  }
1892 			     }
1893 			     if (pBL->getContainerType() != FL_CONTAINER_BLOCK && !getDocument()->isDontImmediateLayout())
1894 			     {
1895 			          pBL->updateLayout(false);
1896 			     }
1897 			}
1898 
1899 			pBL = pBL->getNext();
1900 		}
1901 	}
1902 	m_vecFormatLayout.clear();
1903 	if(needsSectionBreak() && !getDocument()->isDontImmediateLayout() )
1904 	{
1905 		if (!isFirstPageValid())
1906 		{
1907 			// The previous section ends on a page farther in the document than the present section
1908 			// first page. We reformat completely the section
1909 			// TODO: a better method would be to create one new page and move the present section
1910 			//       first page columns to that new page. Then insert the page at the correct place
1911 			//       in the page list. If the section starts with a page break, there would not be any
1912 			//       other changes necessary to the document.
1913 			collapse();
1914 			format();
1915 			return;
1916 		}
1917 		m_ColumnBreaker.breakSection();
1918 	}
1919 	if(needsRebuild() && !getDocument()->isDontImmediateLayout() )
1920 	{
1921 		checkAndRemovePages();
1922 		addValidPages();
1923 	}
1924 	xxx_UT_DEBUGMSG(("Doing fl_DocSectionLayout::updateLayout here %p view %p \n",this, m_pLayout->getView()));
1925 	m_pLayout->getView()->getGraphics()->allCarets()->setPendingBlink(); // place caret after entry
1926 	m_pLayout->getView()->getGraphics()->flush(); // schedule redraw for Wayland
1927 }
1928 
setNeedsSectionBreak(bool bSet,fp_Page * pPage)1929 void fl_DocSectionLayout::setNeedsSectionBreak(bool bSet, fp_Page * pPage)
1930 {
1931 	m_bNeedsSectionBreak = bSet;
1932 	fp_Page * pOldP = m_ColumnBreaker.getStartPage();
1933 	UT_sint32 iOldP = 999999999;
1934 	if(pPage == NULL)
1935 	{
1936 	  UT_DEBUGMSG(("SectionBreak from start \n"));
1937 		m_ColumnBreaker.setStartPage(pPage);
1938 		return;
1939 	}
1940 	if(pPage->getOwningSection() != this)
1941 	{
1942 		m_ColumnBreaker.setStartPage(NULL);
1943 		return;
1944 	}
1945 	if(pOldP)
1946 	{
1947 		iOldP = getDocLayout()->findPage(pOldP);
1948 	}
1949 	UT_sint32 iNewP = getDocLayout()->findPage(pPage);
1950 	xxx_UT_DEBUGMSG(("setNeedsSectionBreak: new Page %d OldPage %d \n",iNewP,iOldP));
1951 	if( (iNewP > -1) && (iNewP < iOldP))
1952 	{
1953 		xxx_UT_DEBUGMSG(("setNeedsSectionBreak: Rebuild from Page %x \n",pPage));
1954 		m_ColumnBreaker.setStartPage(pPage);
1955 	}
1956 }
1957 
1958 
completeBreakSection(void)1959 void fl_DocSectionLayout::completeBreakSection(void)
1960 {
1961 	m_bNeedsSectionBreak = true;
1962 	updateLayout(true);
1963 	m_ColumnBreaker.setStartPage(NULL);
1964 	m_ColumnBreaker.breakSection();
1965 	m_bNeedsSectionBreak = false;
1966 }
1967 
1968 
redrawUpdate(void)1969 void fl_DocSectionLayout::redrawUpdate(void)
1970 {
1971         if(getDocLayout()->isLayoutFilling())
1972 	         return;
1973 	fl_ContainerLayout*	pBL = getFirstLayout();
1974 
1975 	// we only need to break and redo this section if its contents
1976 	// have changed, i.e., if the field values changed
1977 	xxx_UT_DEBUGMSG(("Doing redraw update \n"));
1978 	while (pBL)
1979 	{
1980 		if(pBL->getContainerType() == FL_CONTAINER_BLOCK && static_cast<fl_BlockLayout *>(pBL)->hasUpdatableField())
1981 		{
1982 			bool bReformat = pBL->recalculateFields(getDocLayout()->getRedrawCount());
1983 			if(bReformat)
1984 			{
1985 				pBL->format();
1986 			}
1987 		}
1988 		else
1989 		{
1990 			pBL->recalculateFields(getDocLayout()->getRedrawCount());
1991 		}
1992 		if (pBL->needsRedraw())
1993 		{
1994 			pBL->redrawUpdate();
1995 		}
1996 
1997 		pBL = pBL->getNext();
1998 	}
1999 	xxx_UT_DEBUGMSG(("Finished Doing redraw update \n"));
2000 	fp_EndnoteContainer * pECon =  static_cast<fp_EndnoteContainer *>(getFirstEndnoteContainer());
2001 	if(pECon)
2002 	{
2003 		fl_EndnoteLayout * pEL = static_cast<fl_EndnoteLayout *>(pECon->getSectionLayout());
2004 		while(pEL)
2005 		{
2006 			pEL->redrawUpdate();
2007 			pEL = static_cast<fl_EndnoteLayout *>(pEL->getNext());
2008 		}
2009 	}
2010 	if(!getDocLayout()->isLayoutFilling() && (needsSectionBreak() || needsRebuild()))
2011 	{
2012 		m_ColumnBreaker.breakSection();
2013 		m_bNeedsSectionBreak = false;
2014 
2015 		if(needsRebuild())
2016 		{
2017 //			UT_ASSERT(0);
2018 			checkAndRemovePages();
2019 			addValidPages();
2020 			m_bNeedsRebuild = false;
2021 		}
2022 	}
2023 
2024 }
2025 
doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)2026 bool fl_DocSectionLayout::doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)
2027 {
2028 	UT_ASSERT(pcrxc->getType()==PX_ChangeRecord::PXT_ChangeStrux);
2029 
2030 	PT_AttrPropIndex IndexOld = getAttrPropIndex();
2031 
2032 	setAttrPropIndex(pcrxc->getIndexAP());
2033 
2034 	const PP_AttrProp * pAP1;
2035 	getDocument()->getAttrProp(IndexOld, &pAP1);
2036 
2037 	const PP_AttrProp * pAP2;
2038 	getDocument()->getAttrProp(pcrxc->getIndexAP(), &pAP2);
2039 
2040 	if(!pAP1 || !pAP2)
2041 	{
2042 		getDocLayout()->rebuildFromHere(this);
2043 	}
2044 
2045 	const gchar * prop = "dom-dir";
2046 	const gchar * val1 = NULL;
2047 	const gchar * val2 = NULL;
2048 
2049 	pAP1->getProperty(prop, val1);
2050 	pAP2->getProperty(prop, val2);
2051 
2052 	if(!val1 || !val2 || strcmp(val1, val2))
2053 	{
2054 		lookupProperties();
2055 		fl_ContainerLayout * pCL = getFirstLayout();
2056 		while(pCL)
2057 		{
2058 			pCL->lookupProperties();
2059 			pCL = pCL->getNext();
2060 		}
2061 
2062 		getDocLayout()->rebuildFromHere(this);
2063 	}
2064 
2065 
2066 	return true;
2067 }
2068 
updateDocSection(void)2069 void fl_DocSectionLayout::updateDocSection(void)
2070 {
2071 
2072 	const PP_AttrProp* pAP = NULL;
2073 	getAP(pAP);
2074 	UT_return_if_fail(pAP);
2075 
2076 	const gchar* pszSectionType = NULL;
2077 	pAP->getAttribute("type", pszSectionType);
2078 	lookupProperties();
2079 
2080 	// clear all the columns
2081     // Assume that all columns and formatting have already been removed via a collapseDocSection()
2082     //
2083 
2084 	/*
2085 	  TODO to more closely mirror the architecture we're using for BlockLayout, this code
2086 	  should probably just set a flag, indicating the need to reformat this section.  Then,
2087 	  when it's time to update everything, we'll actually do the format.
2088 	*/
2089 
2090 	FV_View * pView = m_pLayout->getView();
2091 	if(pView)
2092 	{
2093 		pView->setScreenUpdateOnGeneralUpdate(false);
2094 	}
2095 	setNeedsSectionBreak(true,NULL);
2096 	format();
2097 	checkAndRemovePages();
2098 	formatAllHdrFtr();
2099 	markAllRunsDirty();
2100 
2101 	if(pView)
2102 	{
2103 		pView->setScreenUpdateOnGeneralUpdate(true);
2104 	}
2105 
2106 //	if (pView)
2107 //	{
2108 //		pView->updateScreen(false);
2109 //		pView->notifyListeners(AV_CHG_TYPING | AV_CHG_FMTSECTION);
2110 //	}
2111 
2112 	return;
2113 }
2114 
_lookupMarginProperties(const PP_AttrProp *)2115 void fl_DocSectionLayout::_lookupMarginProperties(const PP_AttrProp* /*pSectionAP*/)
2116 {
2117 	// force lookup on all container layouts in this section
2118 
2119 	fl_ContainerLayout*	pBL = getFirstLayout();
2120 	while (pBL)
2121 	{
2122 		pBL->lookupMarginProperties();
2123 		pBL = pBL->getNext();
2124 	}
2125 
2126 	// header/footers
2127 	UT_GenericVector<fl_HdrFtrSectionLayout*> vecHdrFtr;
2128 	getVecOfHdrFtrs( &vecHdrFtr);
2129 	UT_sint32 i = 0;
2130 	fl_HdrFtrSectionLayout * pHdrFtr = NULL;
2131 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2132 	{
2133 		pHdrFtr = vecHdrFtr.getNthItem(i);
2134 		pHdrFtr->lookupMarginProperties();
2135 	}
2136 
2137 }
2138 
_lookupProperties(const PP_AttrProp * pSectionAP)2139 void fl_DocSectionLayout::_lookupProperties(const PP_AttrProp* pSectionAP)
2140 {
2141 	UT_return_if_fail(pSectionAP);
2142 
2143 	m_iNewHdrHeight = getDocument()->getNewHdrHeight();
2144 	m_iNewFtrHeight = getDocument()->getNewFtrHeight();
2145 
2146 	m_sHdrFtrChangeProps.clear();
2147 
2148 
2149 	/*
2150 	  TODO shouldn't we be using PP_evalProperty like
2151 	  the blockLayout does?
2152 
2153 	  Yes, since PP_evalProperty does a fallback to the
2154 	  last-chance defaults, whereas the code below is
2155 	  hard-coding its own defaults.  Bad idea.
2156 	*/
2157 
2158 	const char* pszNumColumns = NULL;
2159 	pSectionAP->getProperty("columns", (const gchar *&)pszNumColumns);
2160 	if (pszNumColumns && pszNumColumns[0])
2161 	{
2162 		m_iNumColumns = atoi(pszNumColumns);
2163 	}
2164 	else
2165 	{
2166 		m_iNumColumns = 1;
2167 	}
2168 
2169 	const char* pszColumnGap = NULL;
2170 	pSectionAP->getProperty("column-gap", (const gchar *&)pszColumnGap);
2171 	if (pszColumnGap && pszColumnGap[0])
2172 	{
2173 		m_iColumnGap = UT_convertToLogicalUnits(pszColumnGap);
2174 	}
2175 	else
2176 	{
2177 		m_iColumnGap = UT_convertToLogicalUnits("0.25in");
2178 	}
2179 	UT_ASSERT(m_iColumnGap < 2000000);
2180 	const char* pszColumnLineBetween = NULL;
2181 	pSectionAP->getProperty("column-line", (const gchar *&)pszColumnLineBetween);
2182 	if (pszColumnLineBetween && pszColumnLineBetween[0])
2183 	{
2184 		m_bColumnLineBetween = (strcmp(pszColumnLineBetween, "on") == 0) ? true : false;
2185 	}
2186 	else
2187 	{
2188 		m_bColumnLineBetween = false;
2189 	}
2190 
2191 	/* column-order */
2192 	//we use the mechanism used by BlockLayout, since otherwise we
2193 	//cannot recode the default value
2194 	const PP_AttrProp * pSpanAP = NULL;
2195 	const PP_AttrProp * pBlockAP = NULL;
2196 
2197 	const char * pszColumnOrder = PP_evalProperty("dom-dir",pSpanAP,pBlockAP,pSectionAP,m_pDoc,false);
2198     UT_DEBUGMSG(("column order: %s\n", pszColumnOrder));
2199 
2200 	FV_View * pView = m_pLayout->getView();
2201 
2202 	if(pView && pView->getBidiOrder() != FV_Order_Visual)
2203 	{
2204 		if(pView->getBidiOrder() == FV_Order_Logical_LTR)
2205 			m_iColumnOrder = 0;
2206 		else
2207 			m_iColumnOrder = 0;
2208 	}
2209 	else if(pszColumnOrder && pszColumnOrder[0])
2210 	{
2211 		m_iColumnOrder = strcmp(pszColumnOrder, "ltr")	? 1 : 0;
2212 	}
2213 	else
2214 	{
2215 		m_iColumnOrder = 0;
2216 	}
2217 
2218 	const char* pszSpaceAfter = NULL;
2219 	pSectionAP->getProperty("section-space-after", (const gchar *&)pszSpaceAfter);
2220 	if (pszSpaceAfter && pszSpaceAfter[0])
2221 	{
2222 		m_iSpaceAfter = UT_convertToLogicalUnits(pszSpaceAfter);
2223 	}
2224 	else
2225 	{
2226 		m_iSpaceAfter = UT_convertToLogicalUnits("0in");
2227 	}
2228 
2229 	const char* pszRestart = NULL;
2230 	pSectionAP->getProperty("section-restart", (const gchar *&)pszRestart);
2231 	if (pszRestart && pszRestart[0])
2232 	{
2233 		m_bRestart = (strcmp(pszRestart,"1")==0);
2234 	}
2235 	else
2236 	{
2237 		m_bRestart = false;
2238 	}
2239 
2240 	const char* pszRestartValue = NULL;
2241 	pSectionAP->getProperty("section-restart-value", (const gchar *&)pszRestartValue);
2242 	if (pszRestartValue && pszRestartValue[0])
2243 	{
2244 		m_iRestartValue = atoi(pszRestartValue);
2245 	}
2246 	else
2247 	{
2248 		m_iRestartValue = 1;
2249 	}
2250 
2251 	const char* pszLeftMargin = NULL;
2252 	const char* pszTopMargin = NULL;
2253 	const char* pszRightMargin = NULL;
2254 	const char* pszBottomMargin = NULL;
2255 	const char* pszFooterMargin = NULL;
2256 	const char* pszHeaderMargin = NULL;
2257 	const char* pszMaxColumnHeight = NULL;
2258 	pSectionAP->getProperty("page-margin-left", (const gchar *&)pszLeftMargin);
2259 	pSectionAP->getProperty("page-margin-top", (const gchar *&)pszTopMargin);
2260 	pSectionAP->getProperty("page-margin-right", (const gchar *&)pszRightMargin);
2261 	pSectionAP->getProperty("page-margin-bottom", (const gchar *&)pszBottomMargin);
2262 	pSectionAP->getProperty("page-margin-footer", (const gchar *&)pszFooterMargin);
2263 	pSectionAP->getProperty("page-margin-header", (const gchar *&)pszHeaderMargin);
2264 
2265 
2266 	const gchar * szRulerUnits;
2267 	UT_Dimension dim;
2268 	if (XAP_App::getApp()->getPrefsValue(AP_PREF_KEY_RulerUnits,&szRulerUnits))
2269 		dim = UT_determineDimension(szRulerUnits);
2270 	else
2271 		dim = DIM_IN;
2272 
2273 	UT_UTF8String defaultMargin = fp_PageSize::getDefaultPageMargin(dim);
2274 
2275 	if(pszLeftMargin && pszLeftMargin[0])
2276 	{
2277 		m_iLeftMargin = UT_convertToLogicalUnits(pszLeftMargin);
2278 		m_dLeftMarginUserUnits = UT_convertDimensionless(pszLeftMargin);
2279 	}
2280 	else
2281 	{
2282 		m_iLeftMargin = UT_convertToLogicalUnits(defaultMargin.utf8_str());
2283 		m_dLeftMarginUserUnits = UT_convertDimensionless(defaultMargin.utf8_str());
2284 	}
2285 
2286 	if(pszTopMargin && pszTopMargin[0])
2287 	{
2288 		m_iTopMargin = UT_convertToLogicalUnits(pszTopMargin);
2289 		m_dTopMarginUserUnits = UT_convertDimensionless(pszTopMargin);
2290 	}
2291 	else
2292 	{
2293 		m_iTopMargin = UT_convertToLogicalUnits(defaultMargin.utf8_str());
2294 		m_dTopMarginUserUnits = UT_convertDimensionless(defaultMargin.utf8_str());
2295 	}
2296 
2297 	if(pszRightMargin && pszRightMargin[0])
2298 	{
2299 		m_iRightMargin = UT_convertToLogicalUnits(pszRightMargin);
2300 		m_dRightMarginUserUnits = UT_convertDimensionless(pszRightMargin);
2301 	}
2302 	else
2303 	{
2304 		m_iRightMargin = UT_convertToLogicalUnits(defaultMargin.utf8_str());
2305 		m_dRightMarginUserUnits = UT_convertDimensionless(defaultMargin.utf8_str());
2306 	}
2307 
2308 	if(pszBottomMargin && pszBottomMargin[0])
2309 	{
2310 		m_iBottomMargin = UT_convertToLogicalUnits(pszBottomMargin);
2311 		m_dBottomMarginUserUnits = UT_convertDimensionless(pszBottomMargin);
2312 	}
2313 	else
2314 	{
2315 		m_iBottomMargin = UT_convertToLogicalUnits(defaultMargin.utf8_str());
2316 		m_dBottomMarginUserUnits = UT_convertDimensionless(defaultMargin.utf8_str());
2317 	}
2318 
2319 	if(pszFooterMargin && pszFooterMargin[0])
2320 	{
2321 		m_iFooterMargin = UT_convertToLogicalUnits(pszFooterMargin);
2322 		m_dFooterMarginUserUnits = UT_convertDimensionless(pszFooterMargin);
2323 	}
2324 	else
2325 	{
2326 		m_iFooterMargin = UT_convertToLogicalUnits("0.0in");
2327 		m_dFooterMarginUserUnits = UT_convertDimensionless("0.0in");
2328 	}
2329 
2330 	if(pszHeaderMargin && pszHeaderMargin[0])
2331 	{
2332 		m_iHeaderMargin = UT_convertToLogicalUnits(pszHeaderMargin);
2333 		m_dHeaderMarginUserUnits = UT_convertDimensionless(pszHeaderMargin);
2334 	}
2335 	else
2336 	{
2337 		m_iHeaderMargin = UT_convertToLogicalUnits("0.0in");
2338 		m_dHeaderMarginUserUnits = UT_convertDimensionless("0.0in");
2339 	}
2340 
2341 	pSectionAP->getProperty("section-max-column-height", (const gchar *&)pszMaxColumnHeight);
2342 	if (pszMaxColumnHeight && pszMaxColumnHeight[0])
2343 	{
2344 		m_iMaxSectionColumnHeight = UT_convertToLogicalUnits(pszMaxColumnHeight);
2345 	}
2346 	else
2347 	{
2348 		m_iMaxSectionColumnHeight = UT_convertToLogicalUnits("0in");
2349 	}
2350 
2351 	const gchar * pszFootnoteLine = NULL;
2352 	pSectionAP->getProperty("section-footnote-line-thickness", (const gchar *&)pszFootnoteLine);
2353 	if (pszFootnoteLine && pszFootnoteLine[0])
2354 	{
2355 		m_iFootnoteLineThickness = UT_convertToLogicalUnits(pszFootnoteLine);
2356 	}
2357 	else
2358 	{
2359 		m_iFootnoteLineThickness = UT_convertToLogicalUnits("0.005in");
2360 	}
2361 
2362 
2363 	const gchar * pszFootnoteYoff = NULL;
2364 	pSectionAP->getProperty("section-footnote-yoff", (const gchar *&)pszFootnoteYoff);
2365 	if (pszFootnoteYoff && pszFootnoteYoff[0])
2366 	{
2367 		m_iFootnoteYoff = UT_convertToLogicalUnits(pszFootnoteYoff);
2368 	}
2369 	else
2370 	{
2371 		m_iFootnoteYoff = UT_convertToLogicalUnits("0.01in");
2372 	}
2373 
2374 	const gchar * pszDataID = NULL;
2375 	pSectionAP->getAttribute(PT_STRUX_IMAGE_DATAID, (const gchar *&)pszDataID);
2376 	DELETEP(m_pGraphicImage);
2377 	DELETEP(m_pImageImage);
2378 	if(pszDataID && *pszDataID)
2379 	{
2380 		m_pGraphicImage = FG_Graphic::createFromStrux(this);
2381 	}
2382 	setPaperColor();
2383 }
2384 
getTopMargin(void) const2385 UT_sint32 fl_DocSectionLayout::getTopMargin(void) const
2386 {
2387 	return m_iTopMargin;
2388 }
2389 
getBottomMargin(void) const2390 UT_sint32 fl_DocSectionLayout::getBottomMargin(void) const
2391 {
2392 	return m_iBottomMargin;
2393 }
2394 
2395 /*!
2396  * Set the color of the background paper in the following order of precedence
2397  * 1. If The section level proper "background-color" is present and is
2398  *    not transparent use that.
2399  * 2. If this section is being displayed to the screen use the
2400  *     ColorForTransparency preference item color.
2401  * 3. Otherwise use white
2402  */
setPaperColor(void)2403 void fl_DocSectionLayout::setPaperColor(void)
2404 {
2405 	const PP_AttrProp* pSectionAP = NULL;
2406 	getAP(pSectionAP);
2407 	UT_return_if_fail(pSectionAP);
2408 
2409 	const char* pszClrPaper = NULL;
2410 	pSectionAP->getProperty("background-color", (const gchar *&)pszClrPaper);
2411 	FV_View * pView = m_pLayout->getView();
2412 	if(pszClrPaper && strcmp(pszClrPaper,"transparent") != 0)
2413 	{
2414 		m_sPaperColor = pszClrPaper;
2415 		m_sScreenColor.clear();
2416 	}
2417 	else if( pView && pView->getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN) )
2418 	{
2419 		XAP_App * pApp = pView->getApp();
2420 		XAP_Prefs * pPrefs = pApp->getPrefs();
2421 		const gchar * pszTransparentColor = NULL;
2422 		pPrefs->getPrefsValue(static_cast<const gchar *>(XAP_PREF_KEY_ColorForTransparent),&pszTransparentColor);
2423 		m_sPaperColor.clear();
2424 		m_sScreenColor = pszTransparentColor;
2425 	}
2426 	else
2427 	{
2428 		m_sPaperColor.clear();
2429 		m_sScreenColor.clear();
2430 	}
2431 }
2432 
2433 /*!
2434  * Delete Empty Column containers in this section.
2435  */
deleteEmptyColumns(void)2436 void fl_DocSectionLayout::deleteEmptyColumns(void)
2437 {
2438 	fp_Column* pCol = m_pFirstColumn;
2439 	while (pCol)
2440 	{
2441 		if (pCol->getLeader() == pCol)
2442 		{
2443 			fp_Column* pCol2 = pCol;
2444 			bool bAllEmpty = true;
2445 			fp_Column* pLastInGroup = NULL;
2446 
2447 			while (pCol2)
2448 			{
2449 				if (!pCol2->isEmpty())
2450 				{
2451 					bAllEmpty = false;
2452 				}
2453 
2454 				if (!(pCol2->getFollower()))
2455 				{
2456 					pLastInGroup = pCol2;
2457 				}
2458 
2459 				pCol2 = pCol2->getFollower();
2460 			}
2461 
2462 			if (bAllEmpty)
2463 			{
2464 				UT_ASSERT(pLastInGroup);
2465 				if(pCol->getPage() != NULL)
2466 				{
2467 					pCol->getPage()->removeColumnLeader(pCol);
2468 				}
2469 				if (pCol == m_pFirstColumn)
2470 				{
2471 					m_pFirstColumn = static_cast<fp_Column *>(pLastInGroup->getNext());
2472 					UT_ASSERT(m_pFirstColumn);
2473 				}
2474 
2475 				if (pLastInGroup == m_pLastColumn)
2476 				{
2477 					m_pLastColumn = static_cast<fp_Column *>(pCol->getPrev());
2478 				}
2479 
2480 				if (pCol->getPrev())
2481 				{
2482 					pCol->getPrev()->setNext(pLastInGroup->getNext());
2483 				}
2484 
2485 				if (pLastInGroup->getNext())
2486 				{
2487 					pLastInGroup->getNext()->setPrev(pCol->getPrev());
2488 				}
2489 
2490 				fp_Column* pCol3 = pCol;
2491 				pCol = static_cast<fp_Column *>(pLastInGroup->getNext());
2492 				while (pCol3)
2493 				{
2494 					fp_Column* pNext = pCol3->getFollower();
2495 
2496 					delete pCol3;
2497 
2498 					pCol3 = pNext;
2499 				}
2500 			}
2501 			else
2502 			{
2503 				pCol = static_cast<fp_Column *>(pLastInGroup->getNext());
2504 			}
2505 		}
2506 		else
2507 		{
2508 			pCol = static_cast<fp_Column *>(pCol->getNext());
2509 		}
2510 	}
2511 }
2512 
getNumColumns(void) const2513 UT_uint32 fl_DocSectionLayout::getNumColumns(void) const
2514 {
2515 	return m_iNumColumns;
2516 }
2517 
getColumnGap(void) const2518 UT_sint32 fl_DocSectionLayout::getColumnGap(void) const
2519 {
2520 	UT_ASSERT( m_iColumnGap < 200000);
2521 	return m_iColumnGap;
2522 }
2523 
getColumnOrder(void) const2524 UT_uint32 fl_DocSectionLayout::getColumnOrder(void) const
2525 {
2526 	return m_iColumnOrder;
2527 }
2528 
deleteBrokenTablesFromHere(fl_ContainerLayout * pTL)2529 void fl_DocSectionLayout::deleteBrokenTablesFromHere(fl_ContainerLayout * pTL)
2530 {
2531 	xxx_UT_DEBUGMSG(("Doing delete broken tables from here \n"));
2532 	if(m_bDeleteingBrokenContainers)
2533 	{
2534 		return;
2535 	}
2536 	if(!m_pLayout || m_pLayout->isLayoutDeleting())
2537 	{
2538 	        return;
2539 	}
2540 	m_bDeleteingBrokenContainers = true;
2541 	if(pTL == NULL)
2542 	{
2543 		pTL = getFirstLayout();
2544 	}
2545 	fl_ContainerLayout * pCL = pTL->getNext();
2546 	while(pCL != NULL)
2547 	{
2548 		if(pCL->getContainerType() == FL_CONTAINER_TABLE)
2549 		{
2550 			fl_TableLayout * pTabL = static_cast<fl_TableLayout *>(pCL);
2551 			fp_TableContainer * pTabC = static_cast<fp_TableContainer *>(pTabL->getFirstContainer());
2552 			if(pTabC != NULL)
2553 			{
2554 				pTabC->deleteBrokenTables(true);
2555 			}
2556 		}
2557 		else if(pCL->getContainerType() == FL_CONTAINER_TOC)
2558 		{
2559 			fl_TOCLayout * pTOCL = static_cast<fl_TOCLayout *>(pCL);
2560 			fp_TOCContainer * pTOC = static_cast<fp_TOCContainer *>(pTOCL->getFirstContainer());
2561 			if(pTOC != NULL)
2562 			{
2563 				pTOC->deleteBrokenTOCs(true);
2564 			}
2565 		}
2566 		pCL = pCL->getNext();
2567 	}
2568 	m_bDeleteingBrokenContainers = false;
2569 }
2570 
2571 
getNextDocSection(void) const2572 fl_DocSectionLayout* fl_DocSectionLayout::getNextDocSection(void) const
2573 {
2574 	fl_DocSectionLayout * pSL = static_cast<fl_DocSectionLayout *>(getNext());
2575 	if(pSL != NULL && pSL->getType()== FL_SECTION_DOC)
2576 		return pSL;
2577 	return NULL;
2578 }
2579 
getPrevDocSection(void) const2580 fl_DocSectionLayout* fl_DocSectionLayout::getPrevDocSection(void) const
2581 {
2582 	fl_DocSectionLayout * pSL = static_cast<fl_DocSectionLayout *>(getPrev());
2583 	while(pSL != NULL && pSL->getType()!= FL_SECTION_DOC)
2584 	{
2585 		pSL = static_cast<fl_DocSectionLayout *>(pSL->getPrev());
2586 	}
2587 	return pSL;
2588 }
2589 
collapse(void)2590 void fl_DocSectionLayout::collapse(void)
2591 {
2592 	UT_DEBUGMSG(("DocSectionLayout: Collapsing all content in %p \n",this));
2593 	fp_Column* pCol2 = m_pFirstColumn;
2594 	m_bDoingCollapse = true;
2595 	while (pCol2)
2596 	{
2597 		pCol2->clearScreen();
2598 
2599 		pCol2 = static_cast<fp_Column *>(pCol2->getNext());
2600 	}
2601 	//
2602 	// Clear the header/footers too
2603 	//
2604 	UT_GenericVector<fl_HdrFtrSectionLayout*> vecHdrFtr;
2605 	getVecOfHdrFtrs( &vecHdrFtr);
2606 	UT_sint32 i = 0;
2607 	fl_HdrFtrSectionLayout * pHdrFtr = NULL;
2608 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2609 	{
2610 		pHdrFtr = vecHdrFtr.getNthItem(i);
2611 		pHdrFtr->clearScreen();
2612 	}
2613 	//
2614 	// Collapse the header/footers now
2615 	//
2616 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2617 	{
2618 		pHdrFtr = vecHdrFtr.getNthItem(i);
2619 		pHdrFtr->collapse();
2620 	}
2621 	// remove all the columns from their pages
2622 	pCol2 = m_pFirstColumn;
2623 	while (pCol2)
2624 	{
2625 //
2626 // The endnote in a column may originate from a totally different
2627 // docsection. We must collapse these endnotes first
2628 //
2629 		pCol2->collapseEndnotes();
2630 		if (pCol2->getLeader() == pCol2)
2631 		{
2632 			pCol2->getPage()->removeColumnLeader(pCol2);
2633 		}
2634 
2635 		pCol2 = static_cast<fp_Column *>(pCol2->getNext());
2636 	}
2637 
2638 	// get rid of all the layout information for every block
2639 	fl_ContainerLayout*	pBL = getFirstLayout();
2640 	while (pBL)
2641 	{
2642 		if(pBL->getContainerType() == FL_CONTAINER_ENDNOTE)
2643 		{
2644 			fp_Container * pCon = pBL->getFirstContainer();
2645 			UT_ASSERT_HARMLESS( pCon );
2646 			if(pCon)
2647 			{
2648 				fp_Column * pCol = static_cast<fp_Column *>(pCon->getColumn());
2649 				UT_DEBUGMSG(("Got and endnote in this section!! \n"));
2650 				UT_DEBUGMSG(("Remove Endnote con %p from col %p \n",pCon,pCol));
2651 				pCol->removeContainer(pCon);
2652 			}
2653 		}
2654 		pBL->collapse();
2655 		pBL = pBL->getNext();
2656 
2657 	}
2658 
2659 	// delete all our columns
2660 	pCol2 = m_pFirstColumn;
2661 	while (pCol2)
2662 	{
2663 		fp_Column* pNext = static_cast<fp_Column *>(pCol2->getNext());
2664 		delete pCol2;
2665 		pCol2 = pNext;
2666 	}
2667 	m_pFirstColumn = NULL;
2668 	m_pLastColumn = NULL;
2669 	setFirstEndnoteContainer(NULL);
2670 	setLastEndnoteContainer(NULL);
2671 //
2672 // Remove all the empty pages thus created. Don't notify of the deletion though.
2673 //
2674 	fp_Page* pPage = m_ColumnBreaker.getStartPage();
2675 	if (pPage && pPage->isEmpty())
2676 		m_ColumnBreaker.setStartPage(NULL);
2677 	getDocLayout()->deleteEmptyPages(true);
2678 //
2679 // This Doc Section No longer owns pages so this becomes NULL
2680 //
2681 	m_pFirstOwnedPage = NULL;
2682 	m_bDoingCollapse = false;
2683 }
2684 
doclistener_deleteStrux(const PX_ChangeRecord_Strux * pcrx)2685 bool fl_DocSectionLayout::doclistener_deleteStrux(const PX_ChangeRecord_Strux * pcrx)
2686 {
2687 	UT_ASSERT(pcrx->getType()==PX_ChangeRecord::PXT_DeleteStrux);
2688 	UT_ASSERT(pcrx->getStruxType()==PTX_Section);
2689 	UT_DEBUGMSG(("Doing Section delete \n"));
2690 	fl_DocSectionLayout* pPrevSL = getPrevDocSection();
2691 	UT_DEBUGMSG(("Deleting DocSec %p Prev DocSec %p \n",this,pPrevSL));
2692 	if (!pPrevSL)
2693 	{
2694 		// TODO shouldn't this just assert?
2695 		UT_DEBUGMSG(("no prior SectionLayout"));
2696 		return false;
2697 	}
2698 
2699 //
2700 // Collapse previous section too. We need this so it can be rebuilt properly.
2701 //
2702 	pPrevSL->collapse();
2703 
2704 	// clear all the columns
2705 	collapse();
2706 
2707 	DELETEP(m_pHeaderSL);
2708 	DELETEP(m_pHeaderEvenSL);
2709 	DELETEP(m_pHeaderFirstSL);
2710 	DELETEP(m_pHeaderLastSL);
2711 	DELETEP(m_pFooterSL);
2712 	DELETEP(m_pFooterEvenSL);
2713 	DELETEP(m_pFooterFirstSL);
2714 	DELETEP(m_pFooterLastSL);
2715 
2716 //
2717 // Collapse the subsequent sections too. These will be reformatted in a few lines.
2718 //
2719 	fl_DocSectionLayout * pDSL = getNextDocSection();
2720 	while(pDSL != NULL)
2721 	{
2722 		pDSL->collapse();
2723 		pDSL = pDSL->getNextDocSection();
2724 	}
2725 //
2726 // OK set the links and move all blocks in this section into the previous section.
2727 	if(getFirstLayout())
2728 	{
2729 		fl_ContainerLayout * pBCur = getFirstLayout();
2730 		fl_ContainerLayout * pBPrev = pPrevSL->getLastLayout();
2731 		UT_ASSERT(pBCur && pBPrev);
2732 
2733 		pBCur->setPrev(pBPrev);
2734 		pBPrev->setNext(pBCur);
2735 		while(pBCur != NULL)
2736 		{
2737 			xxx_UT_DEBUGMSG(("updating block %x \n",pBCur));
2738 			pBCur->setContainingLayout(pPrevSL);
2739 			if(pBCur->getContainerType() == FL_CONTAINER_BLOCK)
2740 			{
2741 				static_cast<fl_BlockLayout *>(pBCur)->
2742 					setSectionLayout(pPrevSL);
2743 			}
2744 			if(pBCur->getContainerType() == FL_CONTAINER_FOOTNOTE)
2745 			{
2746 				static_cast<fl_FootnoteLayout *>(pBCur)->
2747 					setDocSectionLayout(pPrevSL);
2748 			}
2749 			if(pBCur->getContainerType() == FL_CONTAINER_ANNOTATION)
2750 			{
2751 				static_cast<fl_AnnotationLayout *>(pBCur)->
2752 					setDocSectionLayout(pPrevSL);
2753 			}
2754 			if(pBCur->getContainerType() == FL_CONTAINER_ENDNOTE)
2755 			{
2756 				static_cast<fl_EndnoteLayout *>(pBCur)->
2757 					setDocSectionLayout(pPrevSL);
2758 			}
2759 
2760 			pPrevSL->setLastLayout(pBCur);
2761 			pBCur = pBCur->getNext();
2762 		}
2763 	}
2764 	setFirstLayout(NULL);
2765 	setLastLayout(NULL);
2766 
2767 //
2768 // Get this before we remove this section from the run list!
2769 //
2770     pDSL = getNextDocSection();
2771 	m_pLayout->removeSection(this);
2772 	pPrevSL->format();
2773 
2774 	FV_View* pView = m_pLayout->getView();
2775 	if (pView)
2776   	{
2777   		pView->_setPoint(pcrx->getPosition());
2778   	}
2779 //
2780 // Update the following sections.
2781 //
2782 	while(pDSL != NULL)
2783 	{
2784 		pDSL->updateDocSection();
2785 		pDSL = pDSL->getNextDocSection();
2786 	}
2787 	delete this;			// TODO whoa!  this construct is VERY dangerous.
2788 
2789 	return true;
2790 }
2791 
addOwnedPage(fp_Page * pPage)2792 void fl_DocSectionLayout::addOwnedPage(fp_Page* pPage)
2793 {
2794 	// TODO do we really need the vecOwnedPages member? YES!!!
2795 
2796 	if(m_pFirstOwnedPage == NULL)
2797 		m_pFirstOwnedPage = pPage;
2798 	fp_Page * pPrev = m_pFirstOwnedPage;
2799 	pPage->getFillType().setDocLayout(getDocLayout());
2800 	setImageWidth(pPage->getWidth());
2801 	setImageHeight(pPage->getHeight());
2802 	if(m_pGraphicImage)
2803 	{
2804 		if(m_pImageImage == NULL)
2805 		{
2806 			const PP_AttrProp * pAP = NULL;
2807 			getAP(pAP);
2808 			GR_Image * pImage = m_pGraphicImage->generateImage(getDocLayout()->getGraphics(),pAP,pPage->getWidth(),pPage->getHeight());
2809 			m_iGraphicTick = getDocLayout()->getGraphicTick();
2810 			UT_Rect rec(0,0,pPage->getWidth(),pPage->getHeight());
2811 			pImage->scaleImageTo(getDocLayout()->getGraphics(),rec);
2812 			m_pImageImage = pImage;
2813 		}
2814 		pPage->getFillType().setImagePointer(&m_pGraphicImage,&m_pImageImage);
2815 	}
2816 	else if(m_sPaperColor.size() > 0)
2817 	{
2818 		pPage->getFillType().setColor(m_sPaperColor.c_str());
2819 	}
2820 	else if(m_sScreenColor.size() > 0)
2821 	{
2822 		pPage->getFillType().setTransColor(m_sScreenColor.c_str());
2823 		pPage->getFillType().markTransparentForPrint();
2824 	}
2825 
2826 //
2827 // The addPage methods will add the page to the correct HdrFtrSL.
2828 //
2829 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
2830 	getVecOfHdrFtrs( &vecHdrFtr);
2831 	UT_sint32 i = 0;
2832 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2833 	{
2834 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
2835 		if(pHdrFtr->getHFType() < FL_HDRFTR_FOOTER)
2836 		{
2837 			if(pPrev && pPrev->getOwningSection() == this && pPrev->getHdrFtrP(FL_HDRFTR_HEADER) == NULL )
2838 				prependOwnedHeaderPage(pPrev);
2839 
2840 			pHdrFtr->addPage(pPage);
2841 		}
2842 		else
2843 		{
2844 			if(pPrev && pPrev->getOwningSection() == this && pPrev->getHdrFtrP(FL_HDRFTR_FOOTER) == NULL)
2845 			{
2846 				prependOwnedFooterPage(pPrev);
2847 			}
2848 			pHdrFtr->addPage(pPage);
2849 		}
2850 	}
2851 	fl_DocSectionLayout * pDSL = this;
2852 	while(pDSL != NULL)
2853 	{
2854 		pDSL->checkAndRemovePages();
2855 		pDSL->addValidPages();
2856 		pDSL = pDSL->getNextDocSection();
2857 	}
2858 }
2859 
prependOwnedHeaderPage(fp_Page * pPage)2860 void fl_DocSectionLayout::prependOwnedHeaderPage(fp_Page* pPage)
2861 {
2862 	//
2863 	// Skip back through the pages until the first owned page of this section
2864 	//
2865 	fp_Page * pPrev = pPage->getPrev();
2866 	if(pPrev && pPrev->getOwningSection() == this && pPrev->getHdrFtrP(FL_HDRFTR_HEADER) == NULL)
2867 	{
2868 		prependOwnedHeaderPage(pPrev);
2869 	}
2870 //
2871 // The addPage methods will add the page to the correct HdrFtrSL.
2872 //
2873 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
2874 	getVecOfHdrFtrs( &vecHdrFtr);
2875 	UT_sint32 i = 0;
2876 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2877 	{
2878 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
2879 		if(pHdrFtr->getHFType() < FL_HDRFTR_FOOTER)
2880 		{
2881 			xxx_UT_DEBUGMSG(("SEVIOR: prepending page %x \n",pPage));
2882 			pHdrFtr->addPage(pPage);
2883 		}
2884 	}
2885 }
2886 
2887 
prependOwnedFooterPage(fp_Page * pPage)2888 void fl_DocSectionLayout::prependOwnedFooterPage(fp_Page* pPage)
2889 {
2890 	//
2891 	// Skip back through the pages until the first owned page of this section
2892 	//
2893 	fp_Page * pPrev = pPage->getPrev();
2894 	if(pPrev && pPrev->getOwningSection() == this && pPrev->getHdrFtrP(FL_HDRFTR_FOOTER) == NULL)
2895 	{
2896 		prependOwnedFooterPage(pPrev);
2897 	}
2898 //
2899 // The addPage methods will add the page to the correct HdrFtrSL.
2900 //
2901 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
2902 	getVecOfHdrFtrs( &vecHdrFtr);
2903 	UT_sint32 i = 0;
2904 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2905 	{
2906 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
2907 		if(pHdrFtr->getHFType() >= FL_HDRFTR_FOOTER)
2908 		{
2909 			pHdrFtr->addPage(pPage);
2910 		}
2911 	}
2912 }
2913 
2914 
2915 /*!
2916  * This fills a vector with all the valid header/footers.
2917  */
getVecOfHdrFtrs(UT_GenericVector<fl_HdrFtrSectionLayout * > * vecHdrFtr)2918 void fl_DocSectionLayout::getVecOfHdrFtrs(UT_GenericVector<fl_HdrFtrSectionLayout *> * vecHdrFtr)
2919 {
2920 	vecHdrFtr->clear();
2921 	if (m_pHeaderFirstSL != NULL)
2922 	{
2923 		vecHdrFtr->addItem(m_pHeaderFirstSL);
2924 	}
2925 	if (m_pHeaderLastSL  != NULL)
2926 	{
2927 		vecHdrFtr->addItem(m_pHeaderLastSL);
2928 	}
2929 	if (m_pHeaderEvenSL  != NULL)
2930 	{
2931 		vecHdrFtr->addItem(m_pHeaderEvenSL);
2932 	}
2933 	if (m_pHeaderSL  != NULL)
2934 	{
2935 		vecHdrFtr->addItem(m_pHeaderSL);
2936 	}
2937 	if (m_pFooterFirstSL != NULL)
2938 	{
2939 		vecHdrFtr->addItem(m_pFooterFirstSL);
2940 	}
2941 	if (m_pFooterLastSL != NULL)
2942 	{
2943 		vecHdrFtr->addItem(m_pFooterLastSL);
2944 	}
2945 	if (m_pFooterEvenSL != NULL)
2946 	{
2947 		vecHdrFtr->addItem(m_pFooterEvenSL);
2948 	}
2949 	if (m_pFooterSL != NULL)
2950 	{
2951 		vecHdrFtr->addItem(m_pFooterSL);
2952 	}
2953 }
2954 
2955 /*!
2956  * This method formats all the header/footers
2957  */
formatAllHdrFtr(void)2958 void fl_DocSectionLayout::formatAllHdrFtr(void)
2959 {
2960 	xxx_UT_DEBUGMSG(("SEVIOR: Doing formatAllHdrFtr \n"));
2961 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
2962 	getVecOfHdrFtrs( &vecHdrFtr);
2963 	UT_sint32 i = 0;
2964 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2965 	{
2966 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
2967 		xxx_UT_DEBUGMSG(("SEVIOR: Doing formatting %x in formatAllHdrFtr \n",pHdrFtr));
2968 		pHdrFtr->format();
2969 	}
2970 }
2971 
2972 /*!
2973  * This method checks each header for valid pages and removes the page if it's not
2974  * valid. ie it remove odd pages from even headers etc.
2975  */
checkAndRemovePages(void)2976 void fl_DocSectionLayout::checkAndRemovePages(void)
2977 {
2978 	UT_GenericVector <fl_HdrFtrSectionLayout *> vecHdrFtr;
2979 	getVecOfHdrFtrs( &vecHdrFtr);
2980 	UT_sint32 i = 0;
2981 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2982 	{
2983 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
2984 		pHdrFtr->checkAndRemovePages();
2985 	}
2986 }
2987 
2988 
2989 /*!
2990  * This method adds valid pages to every valid header/footer in the docsection if
2991  * they're not there already.
2992  */
addValidPages(void)2993 void fl_DocSectionLayout::addValidPages(void)
2994 {
2995 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
2996 	getVecOfHdrFtrs( &vecHdrFtr);
2997 	UT_sint32 i = 0;
2998 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
2999 	{
3000 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
3001 		pHdrFtr->addValidPages();
3002 	}
3003 }
3004 
3005 /*!
3006  * This method deletes the owned page from the DocSectionLayout and all
3007  * the header files.
3008  */
deleteOwnedPage(fp_Page * pPage,bool bReallyDeleteIt)3009 void fl_DocSectionLayout::deleteOwnedPage(fp_Page* pPage, bool bReallyDeleteIt)
3010 {
3011 	UT_GenericVector<fl_HdrFtrSectionLayout *> vecHdrFtr;
3012 	getVecOfHdrFtrs( &vecHdrFtr);
3013 	UT_sint32 i = 0;
3014 	xxx_UT_DEBUGMSG(("Delete Owned Page %x \n",pPage));
3015 	for(i = 0; i < vecHdrFtr.getItemCount(); i++)
3016 	{
3017 		fl_HdrFtrSectionLayout * pHdrFtr = vecHdrFtr.getNthItem(i);
3018 		if(pHdrFtr->isPageHere(pPage))
3019 		{
3020 			pHdrFtr->deletePage(pPage);
3021 			xxx_UT_DEBUGMSG(("Delete Owned Page %x from HdrFtr %x \n",pPage,pHdrFtr));
3022 		}
3023 	}
3024 //
3025 // Remove this page from the list of owned pages
3026 //
3027 	if(m_pFirstOwnedPage == pPage)
3028 	{
3029 		fp_Page * pNext = pPage->getNext();
3030 		if(pNext && pNext->getOwningSection() == this)
3031 		{
3032 			m_pFirstOwnedPage = pNext;
3033 		}
3034 		else
3035 		{
3036 			m_pFirstOwnedPage = NULL;
3037 		}
3038 	}
3039 	fl_DocSectionLayout * pDSL = this;
3040 	if(!getDocLayout()->isLayoutDeleting() && bReallyDeleteIt)
3041 	{
3042 		if(m_pLayout->findPage(pPage) > 0)
3043 		{
3044 			UT_DEBUGMSG(("fl_DocSec: deleting page %p ReallyDeleteIt %d \n",pPage,bReallyDeleteIt));
3045 			m_pLayout->deletePage(pPage,true);
3046 		}
3047 		while(pDSL != NULL)
3048 		{
3049 			pDSL->checkAndRemovePages();
3050 			pDSL->addValidPages();
3051 			pDSL = pDSL->getNextDocSection();
3052 		}
3053 	}
3054 }
3055 
3056 /*
3057   This method returns true if the first column of the section starts on the
3058   same page as the last column of the previous section and false otherwise.
3059   If this is the first section, it tests whether the section starts on the first page.
3060  */
3061 
isFirstPageValid(void) const3062 bool fl_DocSectionLayout::isFirstPageValid(void) const
3063 {
3064 	fp_Container * pFirstCon = getFirstContainer();
3065 	fp_Page * pFirstPage = NULL;
3066 	if (!pFirstCon)
3067 	{
3068 		return true;
3069 	}
3070 	pFirstPage = pFirstCon->getPage();
3071 	UT_return_val_if_fail(pFirstPage,true);
3072 	if (!getPrev())
3073 	{
3074 		// This is the first section of the document
3075 		return (pFirstPage->getPageNumber() == 0)? true:false;
3076 	}
3077 
3078 	fp_Container * pPrevLastCon = getPrev()->getLastContainer();
3079 	fp_Page * pPrevLastPage = NULL;
3080 	UT_return_val_if_fail(pPrevLastCon,false);
3081 	pPrevLastPage = pPrevLastCon->getPage();
3082 	UT_return_val_if_fail(pPrevLastPage,false);
3083 
3084 	return (pFirstPage == pPrevLastPage)? true:false;
3085 }
3086 
3087 /*!
3088  * This method returns true if the pPage pointer matches the header/footer type
3089  * given.
3090 \param hfType The type of the header/Footer
3091 \param fp_Page * pThisPage pointer to the page queried.
3092  */
isThisPageValid(HdrFtrType hfType,fp_Page * pThisPage)3093 bool fl_DocSectionLayout::isThisPageValid(HdrFtrType hfType, fp_Page * pThisPage)
3094 {
3095 	if (!m_pFirstOwnedPage)
3096 		return false;
3097 
3098     // No header/footerness assigned yet. Page is invalid.
3099 	if(hfType == FL_HDRFTR_NONE)
3100 		return false;
3101 
3102 	if(hfType == FL_HDRFTR_HEADER_FIRST ||
3103 	   hfType == FL_HDRFTR_FOOTER_FIRST)
3104 		return (pThisPage == m_pFirstOwnedPage);
3105 
3106 //
3107 // If there is a header page defined and this is a header page bail now!
3108 //
3109 	if ((pThisPage == m_pFirstOwnedPage) &&
3110 		 ((m_pHeaderFirstSL && hfType < FL_HDRFTR_FOOTER) ||
3111 		  (m_pFooterFirstSL && hfType >= FL_HDRFTR_FOOTER)))
3112 		return false;
3113 
3114 	fp_Page * pPage = m_pFirstOwnedPage;
3115 	fp_Page * pNext = pPage->getNext();
3116 	while(pNext && (pNext->getOwningSection() == this))
3117 	{
3118 		pPage = pNext;
3119 		pNext = pNext->getNext();
3120 	}
3121 
3122 	if(hfType == FL_HDRFTR_HEADER_LAST ||
3123 	   hfType == FL_HDRFTR_FOOTER_LAST)
3124 	{
3125 		return (pPage == pThisPage);
3126 	}
3127 //
3128 // If there is a Last SL defined and this is the last page in the SLpage bail now!
3129 //
3130 	if ((pThisPage == pPage) &&
3131 		 ((m_pHeaderLastSL && hfType < FL_HDRFTR_FOOTER) ||
3132 		  (m_pFooterLastSL && hfType >= FL_HDRFTR_FOOTER)))
3133 		return false;
3134 
3135 	UT_sint32 i = 0;
3136 	for(i=0; i < getDocLayout()->countPages(); i++)
3137 	{
3138 		if (getDocLayout()->getNthPage(i) == pThisPage)
3139 			break;
3140 	}
3141 
3142 	UT_ASSERT(i < getDocLayout()->countPages());
3143 
3144 	if((hfType == FL_HDRFTR_HEADER_EVEN) ||
3145 	   (hfType == FL_HDRFTR_FOOTER_EVEN))
3146 	{
3147 		if(i % 2 == 0)
3148 			return true;
3149 		else
3150 			return false;
3151 	}
3152 //
3153 // If there is an Even SL defined and this is an even page in the SL page bail now!
3154 //
3155 	if ((i % 2 == 0) &&
3156 		((m_pHeaderEvenSL && hfType < FL_HDRFTR_FOOTER) ||
3157 		 (m_pFooterEvenSL && hfType >= FL_HDRFTR_FOOTER)))
3158 		return false;
3159 
3160 	return true; //if we're here all pages are valid.
3161 }
3162 
checkAndAdjustColumnGap(UT_sint32 iLayoutWidth)3163 void fl_DocSectionLayout::checkAndAdjustColumnGap(UT_sint32 iLayoutWidth)
3164 {
3165 	// Check to make sure column gap is not to wide to fit on the page with the
3166 	// given number of columns.
3167 	UT_sint32 minColumnWidth =0;
3168 	UT_sint32 iColWidth= 0;
3169 	if(m_iNumColumns > 1)
3170 	{
3171 		minColumnWidth = UT_convertToLogicalUnits("0.5in");	//TODO should this dimension be hard coded.
3172 		iColWidth = (iLayoutWidth - static_cast<UT_sint32>(((m_iNumColumns - 1) * m_iColumnGap))) / static_cast<UT_sint32>(m_iNumColumns);
3173 
3174 		if(iColWidth < minColumnWidth)
3175 		{
3176 			m_iColumnGap = (iLayoutWidth - minColumnWidth * static_cast<UT_sint32>(m_iNumColumns)) / (static_cast<UT_sint32>(m_iNumColumns) - 1);
3177 		}
3178 
3179 	}
3180 	UT_ASSERT(m_iColumnGap < 2000000);
3181 	if(m_iColumnGap < 30 || (m_iColumnGap > 200000))
3182 	{
3183 		m_iColumnGap = 30;
3184 	}
3185 }
3186 
3187 //////////////////////////////////////////////////////////////////
3188 //////////////////////////////////////////////////////////////////
3189 
3190 class ABI_EXPORT _PageHdrFtrShadowPair
3191 {
3192 public:
_PageHdrFtrShadowPair(void)3193 	_PageHdrFtrShadowPair(void)
3194 	   {
3195 			m_pPage = NULL;
3196 			m_pShadow = NULL;
3197 		}
~_PageHdrFtrShadowPair(void)3198 	virtual ~_PageHdrFtrShadowPair(void)
3199 		{
3200 			m_pPage = NULL;
3201 			m_pShadow = NULL;
3202 		}
setPage(fp_Page * pPage)3203 	void setPage (fp_Page * pPage) { m_pPage = pPage;}
setShadow(fl_HdrFtrShadow * pShadow)3204 	void setShadow (fl_HdrFtrShadow * pShadow) { m_pShadow = pShadow;}
getPage(void) const3205 	fp_Page * getPage(void) const {return m_pPage;}
getShadow(void) const3206 	fl_HdrFtrShadow * getShadow(void) const {return m_pShadow;}
3207 private:
3208 	fp_Page*			m_pPage;
3209 	fl_HdrFtrShadow*	m_pShadow;
3210 };
3211 
3212 
fl_HdrFtrSectionLayout(HdrFtrType iHFType,FL_DocLayout * pLayout,fl_DocSectionLayout * pDocSL,pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP)3213 fl_HdrFtrSectionLayout::fl_HdrFtrSectionLayout(HdrFtrType iHFType, FL_DocLayout* pLayout, fl_DocSectionLayout* pDocSL, pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP)
3214 	: fl_SectionLayout(pLayout, sdh, indexAP, FL_SECTION_HDRFTR,FL_CONTAINER_HDRFTR,PTX_SectionHdrFtr,pDocSL),
3215 	  m_pDocSL(pDocSL),
3216 	  m_iHFType(iHFType),
3217 	  m_pHdrFtrContainer(NULL)
3218 {
3219 	fl_Layout::setType(PTX_SectionHdrFtr); // Set the type of this strux
3220 	UT_DEBUGMSG(("SEVIOR: Creating HFType =%d \n",m_iHFType));
3221 	xxx_UT_DEBUGMSG(("DocSectionLayout is %p \n",getDocSectionLayout()));
3222 //
3223 // Since we're almost certainly removing blocks at the end of the doc, tell the
3224 // view to remember the current position on the active view.
3225 //
3226 // 	FV_View * pView = m_pLayout->getView();
3227 // 	if(pView && pView->isActive())
3228 // 	{
3229 // 		pView->markSavedPositionAsNeeded();
3230 // 	}
3231 }
3232 
~fl_HdrFtrSectionLayout()3233 fl_HdrFtrSectionLayout::~fl_HdrFtrSectionLayout()
3234 {
3235 	xxx_UT_DEBUGMSG(("SEVIOR: Deleting HFType =%d \n",m_iHFType));
3236 	UT_uint32 iCount = m_vecPages.getItemCount();
3237 	for (UT_uint32 i=0; i<iCount; i++)
3238 	{
3239 		_PageHdrFtrShadowPair* pPair = static_cast<_PageHdrFtrShadowPair*>(m_vecPages.getNthItem(i));
3240 
3241 		delete pPair->getShadow();
3242 	}
3243 	_purgeLayout();
3244 	DELETEP(m_pHdrFtrContainer);
3245 //
3246 // Take this section layout out of the linked list
3247 //
3248 	m_pLayout->removeHdrFtrSection(static_cast<fl_SectionLayout *>(this));
3249 	m_pDocSL->removeFromUpdate(this);
3250 //
3251 // Null out pointer to this HdrFtrSection in the attached DocLayoutSection
3252 //
3253 	m_pDocSL->setHdrFtr(m_iHFType, NULL);
3254 //
3255 // Since we're almost certainly removing blocks at the end of the doc, tell the
3256 // view to remember the current position on the active view.
3257 //
3258 // 	FV_View * pView = m_pLayout->getView();
3259 // 	if(pView && pView->isActive())
3260 // 	{
3261 // 		pView->markSavedPositionAsNeeded();
3262 // 	}
3263 //
3264 	UT_VECTOR_PURGEALL(_PageHdrFtrShadowPair*, m_vecPages);
3265 }
3266 
3267 /*!
3268  * This method removes all the lines and containers associated with the shadows
3269  * and the lines associated with this HdrFtrSectionLayout.
3270  *
3271  */
collapse(void)3272 void fl_HdrFtrSectionLayout::collapse(void)
3273 {
3274 //
3275 // If a view exists and we're editting a header footer take the pointer out of
3276 // the header/footer. This will also clear the box around the header/footer
3277 //
3278 	FV_View * pView = m_pLayout->getView();
3279 	if(pView && pView->isHdrFtrEdit())
3280 	{
3281 		pView->clearHdrFtrEdit();
3282 		pView->warpInsPtToXY(0,0,false);
3283 		pView->rememberCurrentPosition();
3284 	}
3285 
3286 	_localCollapse();
3287 	UT_uint32 iCount = m_vecPages.getItemCount();
3288 	UT_uint32 i;
3289 	for (i=0; i<iCount; i++)
3290 	{
3291 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3292 		fp_Page * ppPage = pPair->getPage();
3293 		delete pPair->getShadow();
3294 		ppPage->removeHdrFtr(getHFType());
3295 		delete pPair;
3296 	}
3297 	m_vecPages.clear();
3298 	DELETEP(m_pHdrFtrContainer);
3299 }
3300 
3301 /*!
3302  * This method removes the block pBlock from all the shadowLayouts.
3303  */
collapseBlock(fl_ContainerLayout * pBlock)3304 void fl_HdrFtrSectionLayout::collapseBlock(fl_ContainerLayout *pBlock)
3305 {
3306 	UT_uint32 iCount = m_vecPages.getItemCount();
3307 	UT_uint32 i;
3308 	for (i=0; i<iCount; i++)
3309 	{
3310 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3311 		fl_ContainerLayout * pShadowBL = pPair->getShadow()->findMatchingContainer(pBlock);
3312 		UT_ASSERT(pShadowBL);
3313 		UT_DEBUGMSG(("Doing collapseBlock %p \n",pBlock));
3314 		if(pShadowBL)
3315 		{
3316 #ifdef ENABLE_SPELL
3317 			// In case we've never checked this one
3318 			if(pShadowBL->getContainerType() == FL_CONTAINER_BLOCK)
3319 			{
3320 				m_pLayout->dequeueBlockForBackgroundCheck(static_cast<fl_BlockLayout *>(pShadowBL));
3321 			}
3322 #endif
3323 			pPair->getShadow()->remove( pShadowBL);
3324 			delete pShadowBL;
3325 			pPair->getShadow()->format();
3326 		}
3327 	}
3328 }
3329 
recalculateFields(UT_uint32 iUpdateCount)3330 bool fl_HdrFtrSectionLayout::recalculateFields(UT_uint32 iUpdateCount)
3331 {
3332 	bool bResult = false;
3333 
3334 	UT_uint32 iCount = m_vecPages.getItemCount();
3335 	for (UT_uint32 i=0; i<iCount; i++)
3336 	{
3337 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3338 		UT_continue_if_fail(pPair->getShadow());
3339 		bResult = pPair->getShadow()->recalculateFields(iUpdateCount) || bResult;
3340 	}
3341 	return bResult;
3342 }
3343 
3344 
getFirstShadow(void)3345 fl_HdrFtrShadow * fl_HdrFtrSectionLayout::getFirstShadow(void)
3346 {
3347 	UT_uint32 iCount = m_vecPages.getItemCount();
3348 	if(iCount != 0)
3349 	{
3350 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(0);
3351 		return pPair->getShadow();
3352 	}
3353 	return NULL;
3354 }
3355 
getFirstContainer() const3356 fp_Container* fl_HdrFtrSectionLayout::getFirstContainer() const
3357 {
3358 	return m_pHdrFtrContainer;
3359 }
3360 
3361 
getLastContainer() const3362 fp_Container* fl_HdrFtrSectionLayout::getLastContainer() const
3363 {
3364 	return m_pHdrFtrContainer;
3365 }
3366 
getNewContainer(fp_Container *)3367 fp_Container* fl_HdrFtrSectionLayout::getNewContainer(fp_Container * /*pFirstContainer*/)
3368 {
3369 	DELETEP(m_pHdrFtrContainer);
3370 	UT_sint32 iWidth = m_pDocSL->getFirstContainer()->getPage()->getWidth(); // why is this different than the next one ?
3371 	m_pHdrFtrContainer = static_cast<fp_Container *>(new fp_HdrFtrContainer(iWidth, static_cast<fl_SectionLayout *>(this)));
3372 	return m_pHdrFtrContainer;
3373 }
3374 
isPageHere(fp_Page * pPage)3375 bool fl_HdrFtrSectionLayout::isPageHere(fp_Page * pPage)
3376 {
3377 	return (_findShadow(pPage) >=0 );
3378 }
3379 
findShadow(fp_Page * pPage)3380 fl_HdrFtrShadow *  fl_HdrFtrSectionLayout::findShadow(fp_Page* pPage)
3381 {
3382        UT_sint32 iPage = _findShadow(pPage);
3383        if(iPage < 0)
3384 	        return NULL;
3385        _PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(iPage);
3386        return pPair->getShadow();
3387 }
3388 
_findShadow(fp_Page * pPage)3389 UT_sint32 fl_HdrFtrSectionLayout::_findShadow(fp_Page* pPage)
3390 {
3391 	UT_uint32 iCount = m_vecPages.getItemCount();
3392 	for (UT_uint32 i=0; i<iCount; i++)
3393 	{
3394 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3395 
3396 		if (pPair->getPage() == pPage)
3397 		{
3398 			return i;
3399 		}
3400 	}
3401 
3402 	return -1;
3403 }
3404 /*!
3405  * This method converts a previously existing section to this header/footer.
3406  * Code liberally stolen from fl_DocSectionLayout::doclistener_deleteStrux
3407  \param fl_DocSectionLayout * pSL sectionlayout to be converted to a
3408  *     HdrFtrSectionLayout
3409 */
changeIntoHdrFtrSection(fl_DocSectionLayout * pSL)3410 void fl_HdrFtrSectionLayout::changeIntoHdrFtrSection( fl_DocSectionLayout * pSL)
3411 {
3412 	UT_ASSERT(pSL->getPrevDocSection());
3413 	// clear all the columns
3414 	fp_Column* pCol =NULL;
3415 
3416 	pCol = static_cast<fp_Column *>(pSL->getFirstContainer());
3417 	while (pCol)
3418 	{
3419 		pCol->clearScreen();
3420 
3421 		pCol = static_cast<fp_Column *>(pCol->getNext());
3422 	}
3423 
3424 	// remove all the columns from their pages
3425 	pCol = static_cast<fp_Column *>(pSL->getFirstContainer());
3426 	while (pCol)
3427 	{
3428 		if (pCol->getLeader() == pCol)
3429 		{
3430 			pCol->getPage()->removeColumnLeader(pCol);
3431 		}
3432 
3433 		pCol = static_cast<fp_Column *>(pCol->getNext());
3434 	}
3435 
3436 
3437 	// get rid of all the layout information for every block
3438 	fl_ContainerLayout*	pBL = pSL->getFirstLayout();
3439 	while (pBL)
3440 	{
3441 		pBL->collapse();
3442 
3443 		pBL = pBL->getNext();
3444 	}
3445 
3446 	//
3447 	// Change the section type
3448 	//
3449 
3450 	// transfer the Sections' blocks into this header/footer
3451 
3452 	while (pSL->getFirstLayout())
3453 	{
3454 		pBL = pSL->getFirstLayout();
3455 		pSL->remove(pBL);
3456 		add(pBL);
3457 		static_cast<fl_BlockLayout *>(pBL)->setSectionLayout(this);
3458 		static_cast<fl_BlockLayout *>(pBL)->setHdrFtr();
3459 	}
3460 	//
3461 	// Remove old section from the section linked list!!
3462 	//
3463 	m_pLayout->removeSection(pSL);
3464 //
3465 	DELETEP(pSL); // Old Section layout is totally gone
3466 	//
3467 	// Create and Format the shadows
3468 	//
3469 	format();
3470 
3471 	// Finished! we now have a header/footer
3472 }
3473 
3474 /*!
3475  * Remove the strux identifing this as a seperate section has been deleted so
3476  * we have to remove this HdrFtrSectionLayout class and all the shadow sections
3477  * attached to it. The blocks in this class are moved to the DocSectionLayout
3478  * associated with this class.
3479  * I do this because I expect that this will be called as part
3480  * on an undo "Insert Header" command. The rest of the undo needs blocks to
3481  * delete so I'm putting them there to keep the rest of the undo code happy
3482 \param pcr the changerecord identifying this action as necesary.
3483 \returns true
3484 */
doclistener_deleteStrux(const PX_ChangeRecord * pcr)3485 bool fl_HdrFtrSectionLayout::doclistener_deleteStrux(const PX_ChangeRecord * pcr)
3486 {
3487 	UT_ASSERT(pcr->getType()==PX_ChangeRecord::PXT_DeleteStrux ||
3488 			  pcr->getType()==PX_ChangeRecord::PXT_ChangeStrux);
3489 
3490 
3491 	if(pcr->getType()==PX_ChangeRecord::PXT_ChangeStrux)
3492 	{
3493 		PX_ChangeRecord_StruxChange * pcrxc = (PX_ChangeRecord_StruxChange *) pcr;
3494 		UT_UNUSED(pcrxc);
3495 		UT_ASSERT_HARMLESS( pcrxc->isRevisionDelete() );
3496 	}
3497 	else
3498 	{
3499 		PX_ChangeRecord_Strux * pcrx = (PX_ChangeRecord_Strux *) pcr;
3500 		UT_UNUSED(pcrx);
3501 		UT_ASSERT(pcrx->getStruxType()==PTX_SectionHdrFtr);
3502 	}
3503 
3504 //
3505 // Get last doc section. Move all the blocks from here to there after deleting
3506 // this strux.
3507 //
3508 	fl_DocSectionLayout* pPrevSL = m_pDocSL;
3509 	if (!pPrevSL)
3510 	{
3511 		UT_DEBUGMSG(("no prior SectionLayout"));
3512 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
3513 	}
3514 //
3515 // Get rid of all the shadows, all the containers, and all the layout
3516 // information for all the blocks.
3517 //
3518 	collapse();
3519 //
3520 // Now copy these line-less blocks into the previous docSectionLayout.
3521 // Note: I expect that these blocks will be deleted by a later delete strux
3522 // on these blocks.
3523 //
3524 	fl_ContainerLayout * pBL = NULL;
3525 	while (getFirstLayout())
3526 	{
3527 		pBL = getFirstLayout();
3528 		remove(pBL);
3529 		pPrevSL->add(pBL);
3530 	}
3531 //
3532 // Remove the pointer to this hdrftr
3533 //
3534 //
3535 // Null out pointer to this HdrFtrSection in the attached DocLayoutSection
3536 // This prevent a new page being created in the format statement that follows.
3537 //
3538 	m_pDocSL->setHdrFtr(m_iHFType, NULL);
3539 //
3540 // Format the new section containing the blocks.
3541 //
3542 	pPrevSL->format();
3543 //
3544 // Finally delete this HdrFtrSectionLayout. This could be done the docListener
3545 // class but here I'm following the convention for the DocSectionLayout. It
3546 // works there so I hope it works here. The HdrFtrSection destructor takes care
3547 // of the details of unlinking the section etc.
3548 //
3549 	delete this;
3550 	return true;
3551 }
3552 
addPage(fp_Page * pPage)3553 void fl_HdrFtrSectionLayout::addPage(fp_Page* pPage)
3554 {
3555 //
3556 //  Sevior:
3557 //  This triggers if we're rebuilding a section before page is defined like in a section change
3558 //  strux. Reinstate if needed to find other bugs.
3559 //	UT_ASSERT(0 > _findShadow(pPage));
3560 //
3561 //
3562 // This might actually be called before we have any content to put in it. If so
3563 // return and hope we get called later.
3564 //
3565 	if(getFirstLayout() == NULL)
3566 	{
3567 		UT_DEBUGMSG(("HdrFtr BUG. No content but we're asking to create a shadow !! \n"));
3568 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
3569 		return;
3570 	}
3571 
3572 	if(_findShadow(pPage) > -1)
3573 		return;
3574 //
3575 // Check this page is valid for this type of hdrftr
3576 //
3577 	if(!getDocSectionLayout()->isThisPageValid(m_iHFType, pPage))
3578 	{
3579 		return;
3580 	}
3581 	//
3582 	// see if this page has a shadow attached already. This can happen
3583     // is a page goes from being odd to even.
3584 	//
3585 	fp_ShadowContainer* pOldShadow = pPage->getHdrFtrP(m_iHFType);
3586 	//
3587 	// If so remove it.
3588 	//
3589 	if(pOldShadow != NULL)
3590 	{
3591 		pOldShadow->getHdrFtrSectionLayout()->deletePage(pPage);
3592 		pPage->removeHdrFtr(m_iHFType);
3593 	}
3594 
3595 	_PageHdrFtrShadowPair* pPair = new _PageHdrFtrShadowPair();
3596 	UT_return_if_fail( pPair );
3597 
3598 	// TODO outofmem
3599 	xxx_UT_DEBUGMSG(("SEVIOR: Add page %x to pair %x \n",pPage,pPair));
3600 	pPair->setPage(pPage);
3601 	pPair->setShadow(new fl_HdrFtrShadow(m_pLayout, pPage, this, getStruxDocHandle(), m_apIndex));
3602 	//
3603 	// Make sure we register the shadow before populating it.
3604 	//
3605 	m_vecPages.addItem(pPair);
3606 	//
3607 	// Populate the shadow
3608 	//
3609 	fl_ShadowListener* pShadowListener = new fl_ShadowListener(this, pPair->getShadow());
3610 	UT_return_if_fail( pShadowListener );
3611 	if(m_iHFType < FL_HDRFTR_FOOTER) {
3612 	  UT_DEBUGMSG(("shadow listener %p created For Header \n",pShadowListener));
3613 	}
3614 	else {
3615 	  UT_DEBUGMSG(("shadow listener %p created For Footer \n",pShadowListener));
3616 	}
3617 
3618 //
3619 // Populate with just this section so find the start and end of it
3620 //
3621 	PT_DocPosition posStart,posEnd,posDocEnd;
3622 	m_pDoc->getBounds(true,posDocEnd);
3623 	posStart = getFirstLayout()->getPosition(true) - 1;
3624 	pf_Frag_Strux* sdStart = getFirstLayout()->getStruxDocHandle();
3625 	pf_Frag_Strux* sdEnd = NULL;
3626 	m_pDoc->getNextStruxOfType(sdStart,PTX_SectionHdrFtr,&sdEnd);
3627 	if(sdEnd)
3628 	{
3629 	    posEnd = m_pDoc->getStruxPosition(sdEnd);
3630 	}
3631 	else
3632 	{
3633 	    posEnd = posDocEnd;
3634 	}
3635 	UT_ASSERT(posEnd > posStart);
3636 	PD_DocumentRange * docRange = new PD_DocumentRange(m_pDoc,posStart,posEnd);
3637 	m_pDoc->tellListenerSubset(pShadowListener, docRange);
3638 	delete docRange;
3639 	delete pShadowListener;
3640 	markAllRunsDirty();
3641 }
3642 
isPointInHere(PT_DocPosition pos)3643 bool fl_HdrFtrSectionLayout::isPointInHere(PT_DocPosition pos)
3644 {
3645 //
3646 // Skip through the Containers in this shadow to find the one containing this
3647 // point.
3648 //
3649     fl_ContainerLayout*	pBL = getFirstLayout();
3650 	if(pBL == NULL)
3651 		return false;
3652 	if(pos < pBL->getPosition())
3653 	{
3654 //
3655 // This corner case is that pos == position of the HdrFtr strux
3656 //
3657 		if(pos == (pBL->getPosition() - 1))
3658 		{
3659 			return true;
3660 		}
3661 		return false;
3662 	}
3663 //
3664 // OK see if the next hdrftr is ahead of the pos
3665 //
3666 	fl_HdrFtrSectionLayout * pHF = static_cast<fl_HdrFtrSectionLayout *>(getNext());
3667 	if(pHF == NULL)
3668 	{
3669 		PT_DocPosition posEOD;
3670 		m_pDoc->getBounds(true,posEOD);
3671 		if(pos <= posEOD)
3672 		{
3673 			return true;
3674 		}
3675 		// This happens when you're erasing the last character in the document.
3676 		// Not sure if assert should stay or not.
3677 		return false;
3678 	}
3679 	fl_ContainerLayout * ppBL = pHF->getFirstLayout();
3680 	if(ppBL != NULL)
3681 	{
3682 		if(pos < (ppBL->getPosition()-1))
3683 		{
3684 			return true;
3685 		}
3686 		return false;
3687 	}
3688 
3689 	fl_ContainerLayout* pNext = pBL->getNext();
3690 	while(pNext != NULL && pNext->getPosition( true) < pos)
3691 	{
3692 		pBL = pNext;
3693 		pNext = pNext->getNext();
3694 	}
3695 	if(pNext != NULL)
3696 	{
3697 		return true;
3698 	}
3699 	else if(pBL && pBL->getPosition() == pos)
3700 	{
3701 		return true;
3702 	}
3703 //
3704 // Now the point MIGHT be in this last block. Use code from pd_Document
3705 // to find out. Have to check whether we're out of docrange first
3706 //
3707 	pf_Frag_Strux* sdh=NULL;
3708 	bool bres;
3709 	bres = m_pDoc->getStruxOfTypeFromPosition(pos, PTX_Block, &sdh);
3710 	if(bres && sdh == pBL->getStruxDocHandle())
3711 	{
3712 		return true;
3713 	}
3714 	return false;
3715 }
3716 
3717 /*!
3718  * Removes the shadow and the corresponding element pointing to the shadow for this
3719  * Page.
3720  */
deletePage(fp_Page * pPage)3721 void fl_HdrFtrSectionLayout::deletePage(fp_Page* pPage)
3722 {
3723 	UT_sint32 iShadow = _findShadow(pPage);
3724 //
3725 // This shadow might have already been deleted via the collapse method
3726 //
3727 	if(iShadow <  0)
3728 		return;
3729 	_PageHdrFtrShadowPair* pPair = static_cast<_PageHdrFtrShadowPair*>(m_vecPages.getNthItem(iShadow));
3730 	UT_return_if_fail(pPair);
3731 
3732 	UT_ASSERT(pPair->getShadow());
3733 
3734 
3735 	fp_Page * ppPage = pPair->getPage();
3736 	UT_ASSERT(pPage == ppPage);
3737 	delete pPair->getShadow();
3738 	xxx_UT_DEBUGMSG(("Doing deletePage %x \n",pPage));
3739 	if(getDocLayout()->findPage(ppPage) >= 0)
3740 	{
3741 			ppPage->removeHdrFtr(getHFType());
3742 	}
3743 	delete pPair;
3744 	m_vecPages.deleteNthItem(iShadow);
3745 }
3746 
3747 
3748 /*!
3749  *  Just format the HdrFtrSectionLayout blocks for an insertBlock method.
3750  *  these blocks will be collapsed afterwards.
3751  */
localFormat(void)3752 void fl_HdrFtrSectionLayout::localFormat(void)
3753 {
3754 	xxx_UT_DEBUGMSG(("Doing a Local Format of the hdrftr section \n"));
3755 	if(!getDocSectionLayout())
3756 		return;
3757 	fl_ContainerLayout*	pBL = getFirstLayout();
3758 	UT_ASSERT(pBL->getContainerType() != FL_CONTAINER_HDRFTR);
3759 	while (pBL)
3760 	{
3761 		if(pBL->getContainerType() == FL_CONTAINER_BLOCK)
3762 		{
3763 			static_cast<fl_BlockLayout *>(pBL)->setHdrFtr();
3764 		}
3765 		pBL->format();
3766 		pBL = pBL->getNext();
3767 	}
3768 }
3769 
3770 /*!
3771  *  Just collapse the HdrFtrSectionLayout blocks for an insertBlock method.
3772  *  This removes all lines and references to containers but leaves the blocks
3773  *  and runs intact.
3774  */
_localCollapse(void)3775 void fl_HdrFtrSectionLayout::_localCollapse(void)
3776 {
3777 	fl_ContainerLayout*	pBL = getFirstLayout();
3778 	while (pBL)
3779 	{
3780 		pBL->collapse();
3781 		pBL = pBL->getNext();
3782 	}
3783 }
3784 
3785 /*!
3786  * This routine returns the matching block within this HdrFtrSectionLayout of the
3787  * shadow.
3788  \param fl_ContainerLayout * Pointer to block in shadow
3789  \returns the pinter to the matching block in the HdrFtr
3790  */
findMatchingContainer(fl_ContainerLayout * pBL)3791 fl_ContainerLayout* fl_HdrFtrSectionLayout::findMatchingContainer(fl_ContainerLayout* pBL)
3792 {
3793 	// This routine returns the matching block within the
3794 	// hdrftrSectionlayout.
3795 	//
3796 	fl_ContainerLayout* ppBL = getFirstLayout();
3797 	bool bInTable = false;
3798 	while(ppBL && (ppBL->getStruxDocHandle() != pBL->getStruxDocHandle()))
3799 	{
3800 		if(ppBL && (ppBL->getContainerType() == FL_CONTAINER_TABLE))
3801 		{
3802 			ppBL = ppBL->getFirstLayout();
3803 			bInTable = true;
3804 		}
3805 		else if(bInTable && ppBL->getContainerType() == FL_CONTAINER_CELL)
3806 		{
3807 			ppBL = ppBL->getFirstLayout();
3808 		}
3809 		else if(bInTable && (ppBL->getNext() == NULL))
3810 		{
3811 			if(ppBL->myContainingLayout()->getNext() == NULL)
3812 			{
3813 				ppBL = ppBL->myContainingLayout();
3814 				ppBL = ppBL->myContainingLayout()->getNext();
3815 				bInTable = false;
3816 			}
3817 			else
3818 			{
3819 				ppBL = ppBL->myContainingLayout()->getNext();
3820 			}
3821 		}
3822 		else
3823 		{
3824 			ppBL = ppBL->getNext();
3825 		}
3826 	}
3827 	UT_ASSERT(ppBL);
3828 	//xxx_UT_DEBUGMSG(("This header/footer is %x in findmatchingBlock \n",this));
3829 	return ppBL;
3830 }
3831 
3832 /*!
3833  * This method checks that the pages in this header are valid and removes them if
3834  * they're not.
3835  */
checkAndRemovePages(void)3836 void fl_HdrFtrSectionLayout::checkAndRemovePages(void)
3837 {
3838 	UT_sint32 iCount = m_vecPages.getItemCount();
3839 //
3840 // Check that the pages we have are still valid. Delete them if they're not.
3841 //
3842 	UT_sint32 i = 0;
3843 	UT_GenericVector<fp_Page*> pageForDelete;
3844 	for(i =0; i< iCount; i++)
3845 	{
3846 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3847 		UT_continue_if_fail(pPair);
3848 		UT_ASSERT(pPair->getShadow());
3849 
3850 		fp_Page * ppPage = pPair->getPage();
3851 		if(getDocLayout()->findPage(ppPage) >= 0)
3852 		{
3853 			if(!getDocSectionLayout()->isThisPageValid(getHFType(),ppPage))
3854 			{
3855 				pageForDelete.addItem(ppPage);
3856 			}
3857 		}
3858 		else
3859 		{
3860 			pageForDelete.addItem(ppPage);
3861 		}
3862 	}
3863 	for(i=0; i< pageForDelete.getItemCount(); i++)
3864 	{
3865 		fp_Page * pPage = pageForDelete.getNthItem(i);
3866 		deletePage(pPage);
3867 	}
3868 	if( pageForDelete.getItemCount() > 0)
3869 	{
3870 		markAllRunsDirty();
3871 	}
3872 }
3873 
3874 /*!
3875  * This method adds valid pages to the collection of shadows.
3876  */
addValidPages(void)3877 void fl_HdrFtrSectionLayout::addValidPages(void)
3878 {
3879 	//
3880 	// Check that all the pages this header/footer should have are
3881     // in place.
3882 	// We have to extract this information from m_pDocSL
3883 	// Loop through all the columns in m_pDocSl and find the pages owned
3884 	// by m_pDocSL
3885 	//
3886         fp_Column * pCol = NULL;
3887 	pCol = static_cast<fp_Column *>(m_pDocSL->getFirstContainer());
3888 	fp_Page * pOldPage = NULL;
3889 	fp_Page * pNewPage = NULL;
3890 	while(pCol)
3891 	{
3892 		pNewPage = pCol->getPage();
3893 		if((pNewPage != NULL) && (pNewPage != pOldPage) && (getDocLayout()->findPage(pNewPage) >=0))
3894 		{
3895 			fl_DocSectionLayout* pDocSec = pNewPage->getOwningSection();
3896 			if(pDocSec == m_pDocSL && _findShadow(pNewPage) < 0)
3897 			{
3898 //
3899 // The addPage Method checks that only valid pages are added to this HdrFtr based on
3900 // the HFType
3901 //
3902 				addPage(pNewPage);
3903 			}
3904 		}
3905 		pCol = static_cast<fp_Column *>(pCol->getNext());
3906 	}
3907 }
3908 
3909 /*!
3910  * Format the overall HdrFtrSectionLayout in it's virtual container.
3911  * Also check that all the correct pages have been found for this HdrFtr. Then
3912  * format the Shadows.
3913  */
format(void)3914 void fl_HdrFtrSectionLayout::format(void)
3915 {
3916 	if(getFirstLayout() == NULL)
3917 	{
3918 		return;
3919 	}
3920 	UT_sint32 iCount =0;
3921 	UT_sint32 i = 0;
3922 	localFormat();
3923 	//
3924 	// Fail safe code to add pages if we don't have them.
3925 	//
3926 	addValidPages();
3927 
3928 	iCount = m_vecPages.getItemCount();
3929 
3930 	for (i=0; i<iCount; i++)
3931 	{
3932 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3933 		pPair->getShadow()->format();
3934 	}
3935 	layout();
3936 }
3937 
updateLayout(bool)3938 void fl_HdrFtrSectionLayout::updateLayout(bool /*bDoFull*/)
3939 {
3940 	bool bredraw = false;
3941 	fl_ContainerLayout*	pBL = getFirstLayout();
3942 	if(needsReformat())
3943 	{
3944 		format();
3945 		bredraw = true;
3946 		m_bNeedsReformat = false;
3947 	}
3948 	m_vecFormatLayout.clear();
3949 	while (pBL)
3950 	{
3951 		if (pBL->needsReformat())
3952 		{
3953 			bredraw = true;
3954 			pBL->format();
3955 		}
3956 
3957 		pBL = pBL->getNext();
3958 	}
3959 	if(bredraw == true)
3960 	{
3961 		if(m_pHdrFtrContainer)
3962 			static_cast<fp_HdrFtrContainer *>(m_pHdrFtrContainer)->layout();
3963  	}
3964 	//
3965 	// update Just the  blocks in the shadowlayouts
3966 	//
3967   	UT_uint32 iCount = m_vecPages.getItemCount();
3968 	if(bredraw)
3969 	{
3970 	      for (UT_uint32 i=0; i<iCount; i++)
3971 	      {
3972 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3973 
3974 		pPair->getShadow()->updateLayout(false);
3975 	      }
3976 	}
3977 }
3978 
3979 /*!
3980  * Mark all runs and lines in the all shadows for redraw.
3981  */
markAllRunsDirty(void)3982 void fl_HdrFtrSectionLayout::markAllRunsDirty(void)
3983 {
3984   	UT_uint32 iCount = m_vecPages.getItemCount();
3985 	for (UT_uint32 i=0; i<iCount; i++)
3986 	{
3987 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
3988 
3989 		pPair->getShadow()->markAllRunsDirty();
3990 	}
3991 }
3992 
3993 /*!
3994  * Layout the overall HdrFtr and everything underneath it.
3995  */
layout(void)3996 void fl_HdrFtrSectionLayout::layout(void)
3997 {
3998     if(m_pHdrFtrContainer)
3999 	static_cast<fp_HdrFtrContainer *>(m_pHdrFtrContainer)->layout();
4000 	//
4001 	// update the shadowlayouts
4002 	//
4003   	UT_uint32 iCount = m_vecPages.getItemCount();
4004 	for (UT_uint32 i=0; i<iCount; i++)
4005 	{
4006 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4007 
4008 		pPair->getShadow()->layout();
4009 	}
4010 }
4011 
clearScreen(void)4012 void fl_HdrFtrSectionLayout::clearScreen(void)
4013 {
4014 	//
4015 	// update Just the  blocks in the shadowlayouts
4016 	//
4017   	UT_uint32 iCount = m_vecPages.getItemCount();
4018 	for (UT_uint32 i=0; i<iCount; i++)
4019 	{
4020 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4021 
4022 		pPair->getShadow()->clearScreen();
4023 	}
4024 }
4025 
redrawUpdate(void)4026 void fl_HdrFtrSectionLayout::redrawUpdate(void)
4027 {
4028 //
4029 // Do another layout but don't redraw.
4030 //
4031 	if(m_pHdrFtrContainer)
4032 		static_cast<fp_HdrFtrContainer *>(m_pHdrFtrContainer)->layout();
4033 	//
4034 	// Don't need to draw here since this is never displayed on the screen?
4035 	//
4036 	UT_uint32 iCount = m_vecPages.getItemCount();
4037 	for (UT_uint32 i=0; i<iCount; i++)
4038 	{
4039 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4040 		if(m_pLayout->findPage(pPair->getPage()) >= 0)
4041 		{
4042 			pPair->getShadow()->redrawUpdate();
4043 		}
4044 	}
4045 
4046 }
4047 
doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)4048 bool fl_HdrFtrSectionLayout::doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)
4049 {
4050 	UT_ASSERT(pcrxc->getType()==PX_ChangeRecord::PXT_ChangeStrux);
4051 
4052 	setAttrPropIndex(pcrxc->getIndexAP());
4053 
4054 	// TODO what happens here?
4055 
4056 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
4057 
4058 	return false;
4059 }
4060 
4061 /*!
4062     this function is only to be called by fl_ContainerLayout::lookupProperties()
4063     all other code must call lookupProperties() instead
4064 */
_lookupProperties(const PP_AttrProp *)4065 void fl_HdrFtrSectionLayout::_lookupProperties(const PP_AttrProp* /*pAP*/)
4066 {
4067 }
4068 
_lookupMarginProperties(const PP_AttrProp *)4069 void fl_HdrFtrSectionLayout::_lookupMarginProperties(const PP_AttrProp* /*pAP*/)
4070 {
4071 	fl_ContainerLayout * pShadow = NULL;
4072 	UT_uint32 iCount = m_vecPages.getItemCount();
4073 
4074 	for (UT_uint32 i=0; i<iCount; i++)
4075 	{
4076 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4077 		// Find matching block in this shadow.
4078 		pShadow = pPair->getShadow();
4079 		if(pShadow)
4080 		{
4081 			pShadow->lookupMarginProperties();
4082 		}
4083 	}
4084 }
4085 
bl_doclistener_populateSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs,PT_BlockOffset blockOffset,UT_uint32 len)4086 bool fl_HdrFtrSectionLayout::bl_doclistener_populateSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs, PT_BlockOffset blockOffset, UT_uint32 len)
4087 {
4088 //
4089 // We need to populate block in the header/footer but to do that we need the
4090 // header/footer to be fomatted. So do it then unformat after.
4091 //
4092 	bool bResult = true;
4093 	fl_ContainerLayout * pShadowBL = NULL;
4094 	UT_uint32 iCount = m_vecPages.getItemCount();
4095 	m_pDoc->setDontChangeInsPoint();
4096 
4097 	for (UT_uint32 i=0; i<iCount; i++)
4098 	{
4099 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4100 		// Find matching block in this shadow.
4101 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4102 		if(pShadowBL)
4103 		{
4104 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_populateSpan(pcrs,blockOffset,len)
4105 				&& bResult;
4106 		}
4107 		else
4108 		{
4109 			UT_ASSERT(0);
4110 			break;
4111 		}
4112 	}
4113 	m_pDoc->allowChangeInsPoint();
4114 	pBL = findMatchingContainer(pBL);
4115 	if(pBL)
4116 	{
4117 	  bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_populateSpan(pcrs,blockOffset,len)
4118 	    && bResult;
4119 	}
4120 	return bResult;
4121 }
4122 
4123 /*!
4124  * Now for all these methods which manipulate the shadow sections, turn off
4125  * Insertion Point changes while the shadows are manipulated.
4126  * Re Enabled insertion point changes for the overall hdrftrsection so it
4127  * is changed just once.
4128  */
4129 
bl_doclistener_populateObject(fl_ContainerLayout * pBL,PT_BlockOffset blockOffset,const PX_ChangeRecord_Object * pcro)4130 bool fl_HdrFtrSectionLayout::bl_doclistener_populateObject(fl_ContainerLayout* pBL, PT_BlockOffset blockOffset, const PX_ChangeRecord_Object * pcro)
4131 {
4132 //
4133 // We need to populate block in the header/footer but to do that we need the
4134 // header/footer to be fomatted. So do it then unformat after.
4135 //
4136   	bool bResult = true;
4137 	fl_ContainerLayout * pShadowBL = NULL;
4138 	UT_uint32 iCount = m_vecPages.getItemCount();
4139 	m_pDoc->setDontChangeInsPoint();
4140 	for (UT_uint32 i=0; i<iCount; i++)
4141 	{
4142 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4143 		// Find matching block in this shadow.
4144 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4145 		if(pShadowBL)
4146 		{
4147 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_populateObject(blockOffset,pcro)
4148 				&& bResult;
4149 		}
4150 		else
4151 		{
4152 			bResult = false;
4153 		}
4154 	}
4155 	m_pDoc->allowChangeInsPoint();
4156 	pBL = findMatchingContainer(pBL);
4157 	if(pBL)
4158 	{
4159 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_populateObject(blockOffset,pcro)
4160 			&& bResult;
4161 	}
4162 	else
4163 	{
4164 		bResult = false;
4165 	}
4166 	return bResult;
4167 }
4168 
bl_doclistener_insertSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs)4169 bool fl_HdrFtrSectionLayout::bl_doclistener_insertSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs)
4170 {
4171 	bool bResult = true;
4172 	fl_ContainerLayout * pShadowBL = NULL;
4173 	UT_uint32 iCount = m_vecPages.getItemCount();
4174 	m_pDoc->setDontChangeInsPoint();
4175 	for (UT_uint32 i=0; i<iCount; i++)
4176 	{
4177 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4178 
4179 		// Find matching block in this shadow.
4180 
4181 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4182 		if(pShadowBL)
4183 		{
4184 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_insertSpan(pcrs)
4185 				&& bResult;
4186 		}
4187 	}
4188 	m_pDoc->allowChangeInsPoint();
4189 	// Update the overall block too.
4190 	fl_BlockLayout * ppBL = static_cast<fl_BlockLayout *>(findMatchingContainer(pBL));
4191 	if(ppBL)
4192 	{
4193 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertSpan(pcrs)
4194 	&& bResult;
4195 	}
4196 	return bResult;
4197 }
4198 
bl_doclistener_deleteSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_Span * pcrs)4199 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_Span * pcrs)
4200 {
4201 	bool bResult = true;
4202 	fl_ContainerLayout * pShadowBL = NULL;
4203 	UT_uint32 iCount = m_vecPages.getItemCount();
4204 	m_pDoc->setDontChangeInsPoint();
4205 	for (UT_uint32 i=0; i<iCount; i++)
4206 	{
4207 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4208 
4209 		// Find matching block in this shadow.
4210 
4211 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4212 		if(pShadowBL)
4213 		{
4214 		  bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_deleteSpan(pcrs)
4215 		    && bResult;
4216 		}
4217 	}
4218 	// Update the overall block too.
4219 
4220 	m_pDoc->allowChangeInsPoint();
4221 	pBL = findMatchingContainer(pBL);
4222 	if(pBL)
4223         {
4224 	  bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteSpan(pcrs)
4225 	    && bResult;
4226 	}
4227 	return bResult;
4228 }
4229 
bl_doclistener_changeSpan(fl_ContainerLayout * pBL,const PX_ChangeRecord_SpanChange * pcrsc)4230 bool fl_HdrFtrSectionLayout::bl_doclistener_changeSpan(fl_ContainerLayout* pBL, const PX_ChangeRecord_SpanChange * pcrsc)
4231 {
4232 	bool bResult = true;
4233 	fl_ContainerLayout * pShadowBL = NULL;
4234 	UT_uint32 iCount = m_vecPages.getItemCount();
4235 	m_pDoc->setDontChangeInsPoint();
4236 	for (UT_uint32 i=0; i<iCount; i++)
4237 	{
4238 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4239 
4240 		// Find matching block in this shadow.
4241 
4242 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4243 		if(pShadowBL)
4244 		{
4245 		  bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_changeSpan(pcrsc) && bResult;
4246 		}
4247 	}
4248 	// Update the overall block too.
4249 
4250 	m_pDoc->allowChangeInsPoint();
4251 	pBL = findMatchingContainer(pBL);
4252 	if(pBL)
4253 	{
4254 	  bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeSpan(pcrsc)
4255 		&& bResult;
4256 	}
4257 	return bResult;
4258 }
4259 
bl_doclistener_deleteStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx)4260 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx)
4261 {
4262 	bool bResult = true;
4263 	fl_ContainerLayout * pShadowBL = NULL;
4264 	UT_uint32 iCount = m_vecPages.getItemCount();
4265 	m_pDoc->setDontChangeInsPoint();
4266 	for (UT_uint32 i=0; i<iCount; i++)
4267 	{
4268 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4269 
4270 		// Find matching block in this shadow.
4271 
4272 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4273 		if(pShadowBL)
4274 		{
4275 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_deleteStrux(pcrx)
4276 				&& bResult;
4277 		}
4278 		else
4279 		{
4280 			UT_ASSERT(0);
4281 		}
4282 	}
4283 	// Update the overall block too.
4284 
4285 	m_pDoc->allowChangeInsPoint();
4286 	pBL = findMatchingContainer(pBL);
4287 	if(pBL)
4288 	{
4289 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteStrux(pcrx) && bResult;
4290 	}
4291 	return bResult;
4292 }
4293 
4294 /*!
4295  * Delete Just the cell struxes from the HdrFtr shadows
4296  */
bl_doclistener_deleteCellStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx)4297 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteCellStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx)
4298 {
4299 	bool bResult = true;
4300 	UT_ASSERT(pBL->getContainerType() == FL_CONTAINER_CELL);
4301 	fl_ContainerLayout * pShadowBL = NULL;
4302 	UT_uint32 iCount = m_vecPages.getItemCount();
4303 	if(iCount <=0)
4304 	{
4305 		UT_ASSERT(0);
4306 	}
4307 	for (UT_uint32 i=0; i<iCount; i++)
4308 	{
4309 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4310 
4311 		// Find matching block in this shadow.
4312 
4313 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4314 		if(pShadowBL)
4315 		{
4316 			UT_ASSERT(pShadowBL->getContainerType() == FL_CONTAINER_CELL);
4317 			bResult = static_cast<fl_CellLayout *>(pShadowBL)->doclistener_deleteStrux(pcrx)
4318 				&& bResult;
4319 		}
4320 		else
4321 		{
4322 			UT_ASSERT(0);
4323 		}
4324 	}
4325 	return bResult;
4326 }
4327 
4328 
4329 /*!
4330  * Delete Just the table struxes from the HdrFtr shadows
4331  */
bl_doclistener_deleteTableStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx)4332 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteTableStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx)
4333 {
4334 	bool bResult = true;
4335 	UT_ASSERT(pBL->getContainerType() == FL_CONTAINER_TABLE);
4336 	fl_ContainerLayout * pShadowBL = NULL;
4337 	UT_uint32 iCount = m_vecPages.getItemCount();
4338 	if(iCount <=0)
4339 	{
4340 		UT_ASSERT(0);
4341 	}
4342 	for (UT_uint32 i=0; i<iCount; i++)
4343 	{
4344 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4345 
4346 		// Find matching block in this shadow.
4347 
4348 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4349 		if(pShadowBL)
4350 		{
4351 			UT_ASSERT(pShadowBL->getContainerType() == FL_CONTAINER_TABLE);
4352 			bResult = static_cast<fl_TableLayout *>(pShadowBL)->doclistener_deleteStrux(pcrx)
4353 				&& bResult;
4354 		}
4355 		else
4356 		{
4357 			UT_ASSERT(0);
4358 		}
4359 	}
4360 	return bResult;
4361 }
4362 
4363 
bl_doclistener_changeFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMarkChange * pcrfmc)4364 bool fl_HdrFtrSectionLayout::bl_doclistener_changeFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMarkChange * pcrfmc)
4365 {
4366 	bool bResult = true;
4367 	fl_ContainerLayout * pShadowBL = NULL;
4368 	UT_uint32 iCount = m_vecPages.getItemCount();
4369 	m_pDoc->setDontChangeInsPoint();
4370 	for (UT_uint32 i=0; i<iCount; i++)
4371 	{
4372 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4373 
4374 		// Find matching block in this shadow.
4375 
4376 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4377 		if(pShadowBL)
4378 		{
4379 		  bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_changeFmtMark(pcrfmc)
4380 		    && bResult;
4381 		}
4382 	}
4383 	// Update the overall block too.
4384 
4385 	m_pDoc->allowChangeInsPoint();
4386 	pBL = findMatchingContainer(pBL);
4387 	if(pBL)
4388 	{
4389 	  bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeFmtMark(pcrfmc) && bResult;
4390 	}
4391 	return bResult;
4392 }
4393 
bl_doclistener_changeStrux(fl_ContainerLayout * pBL,const PX_ChangeRecord_StruxChange * pcrxc)4394 bool fl_HdrFtrSectionLayout::bl_doclistener_changeStrux(fl_ContainerLayout* pBL, const PX_ChangeRecord_StruxChange * pcrxc)
4395 {
4396 	bool bResult = true;
4397 	fl_ContainerLayout * pShadowBL = NULL;
4398 	UT_uint32 iCount = m_vecPages.getItemCount();
4399 	m_pDoc->setDontChangeInsPoint();
4400 	for (UT_uint32 i=0; i<iCount; i++)
4401 	{
4402 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4403 
4404 		// Find matching block in this shadow.
4405 
4406 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4407 		if(pShadowBL)
4408 		{
4409 			if(pShadowBL->getContainerType() == FL_CONTAINER_BLOCK)
4410 			{
4411 				bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_changeStrux(pcrxc)
4412 					&& bResult;
4413 			}
4414 			else if(pShadowBL->getContainerType() == FL_CONTAINER_TABLE)
4415 			{
4416 				bResult = static_cast<fl_TableLayout *>(pShadowBL)->doclistener_changeStrux(pcrxc)
4417 				&& bResult;
4418 			}
4419 			else if(pShadowBL->getContainerType() == FL_CONTAINER_CELL)
4420 			{
4421 				bResult = static_cast<fl_CellLayout *>(pShadowBL)->doclistener_changeStrux(pcrxc)
4422 				&& bResult;
4423 			}
4424 		}
4425 	}
4426 	// Update the overall block too.
4427 
4428 	m_pDoc->allowChangeInsPoint();
4429 	pBL = findMatchingContainer(pBL);
4430 	if(pBL && (pBL->getContainerType() == FL_CONTAINER_BLOCK))
4431 	{
4432 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeStrux(pcrxc)
4433 			&& bResult;
4434 	}
4435 	return bResult;
4436 }
4437 
4438 /*!
4439  * Insert a cell into every table in the HdrFtr
4440  */
bl_doclistener_insertCell(fl_ContainerLayout * pCell,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,fl_TableLayout * pTL)4441 bool fl_HdrFtrSectionLayout::bl_doclistener_insertCell(fl_ContainerLayout* pCell,
4442 											  const PX_ChangeRecord_Strux * pcrx,
4443 											  pf_Frag_Strux* sdh,
4444 											  PL_ListenerId lid,
4445 											  fl_TableLayout * pTL)
4446 {
4447 	UT_uint32 iCount = m_vecPages.getItemCount();
4448 	fl_ContainerLayout * pShadowBL = NULL;
4449 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertCells into shadows \n"));
4450 	m_pDoc->setDontChangeInsPoint();
4451 	bool bResult = true;
4452 	for (UT_uint32 i=0; i<iCount; i++)
4453 	{
4454 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4455 
4456 		// Find matching Table in this shadow.
4457 
4458 		pShadowBL = pPair->getShadow()->findMatchingContainer(pTL);
4459 		fl_ContainerLayout * pPrevCell = NULL;
4460 		if(pCell)
4461 		{
4462 			pPrevCell = pPair->getShadow()->findMatchingContainer(pCell);
4463 		}
4464 		UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertCell into Table shadow \n"));
4465 		if(pShadowBL)
4466 		{
4467 			bResult = static_cast<fl_TableLayout *>(pShadowBL)->bl_doclistener_insertCell(pPrevCell,pcrx,sdh,lid,NULL)
4468 				&& bResult;
4469 		}
4470 	}
4471 	m_pDoc->allowChangeInsPoint();
4472 	return true;
4473 
4474 }
4475 
4476 
4477 /*!
4478  * Insert an endTable cell into every table in the HdrFtr
4479  */
bl_doclistener_insertEndTable(fl_ContainerLayout * pTab,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid)4480 bool fl_HdrFtrSectionLayout::bl_doclistener_insertEndTable(fl_ContainerLayout* pTab,
4481 											  const PX_ChangeRecord_Strux * pcrx,
4482 											  pf_Frag_Strux* sdh,
4483 											  PL_ListenerId lid)
4484 {
4485 	UT_uint32 iCount = m_vecPages.getItemCount();
4486 	fl_ContainerLayout * pShadowBL = NULL;
4487 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertEndTables into shadows \n"));
4488 	m_pDoc->setDontChangeInsPoint();
4489 	bool bResult = true;
4490 	for (UT_uint32 i=0; i<iCount; i++)
4491 	{
4492 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4493 
4494 		// Find matching Table in this shadow.
4495 
4496 		pShadowBL = pPair->getShadow()->findMatchingContainer(pTab);
4497 		UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertEndTable into shadow \n"));
4498 		if(pShadowBL)
4499 		{
4500 			bResult = static_cast<fl_TableLayout *>(pShadowBL)->bl_doclistener_insertEndTable(NULL,pcrx,sdh,lid,NULL)
4501 				&& bResult;
4502 		}
4503 	}
4504 	m_pDoc->allowChangeInsPoint();
4505 	return true;
4506 
4507 }
4508 
bl_doclistener_insertTable(fl_ContainerLayout * pBL,SectionType iType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4509 fl_SectionLayout * fl_HdrFtrSectionLayout::bl_doclistener_insertTable(fl_ContainerLayout* pBL,
4510 													SectionType iType,
4511 													const PX_ChangeRecord_Strux * pcrx,
4512 													pf_Frag_Strux* sdh,
4513 													PL_ListenerId lid,
4514 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
4515 																			PL_ListenerId lid,
4516 																			fl_ContainerLayout* sfhNew))
4517 {
4518 	fl_SectionLayout * pSL = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertTable(pcrx, iType, sdh, lid, pfnBindHandles);
4519 //	UT_ASSERT(0);
4520 	fl_SectionLayout::checkAndAdjustCellSize();
4521 //
4522 // FIXME: Propagate this to the shadows
4523 //      : Write code to handle populate cases in the shadows
4524 	bool bResult = true;
4525 //
4526 // Now insert it into all the shadows.
4527 //
4528 	UT_uint32 iCount = m_vecPages.getItemCount();
4529 	fl_ContainerLayout * pShadowBL = NULL;
4530 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertTable \n"));
4531 	m_pDoc->setDontChangeInsPoint();
4532 	for (UT_uint32 i=0; i<iCount; i++)
4533 	{
4534 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4535 
4536 		// Find matching block in this shadow.
4537 		if(pBL)
4538 		{
4539 			pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4540 			UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertTable into shadow 1 \n"));
4541 			if(pShadowBL)
4542 			{
4543 				bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_insertTable(pcrx,iType,sdh,lid,NULL)
4544 					&& bResult;
4545 			}
4546 			pPair->getShadow()->checkAndAdjustCellSize();
4547 		}
4548 		else
4549 //
4550 // FIXME: Handle case of inserting a table at the start of the HdrFtr
4551 //
4552 		{
4553 			UT_ASSERT(0);
4554 		}
4555 	}
4556 	m_pDoc->allowChangeInsPoint();
4557 	return pSL;
4558 }
4559 
4560 /*!
4561  * Insert a Table at the start of a HdrFtr
4562  */
bl_doclistener_insertTable(SectionType,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4563 fl_SectionLayout * fl_HdrFtrSectionLayout::bl_doclistener_insertTable(SectionType /*iType*/,
4564 													const PX_ChangeRecord_Strux * pcrx,
4565 													pf_Frag_Strux* sdh,
4566 													PL_ListenerId lid,
4567 													void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
4568 																			PL_ListenerId lid,
4569 																			fl_ContainerLayout* sfhNew))
4570 {
4571 
4572 	fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(static_cast<fl_ContainerLayout *>(this)->insert(sdh,this,pcrx->getIndexAP(), FL_CONTAINER_TABLE));
4573 
4574 	fl_ContainerLayout* sfhNew = pSL;
4575 	//
4576 	// Don't bind to shadows
4577 	//
4578 	if(pfnBindHandles)
4579 	{
4580 		pfnBindHandles(sdh,lid,sfhNew);
4581 	}
4582 //
4583 // increment the insertion point in the view.
4584 //
4585 	FV_View* pView = m_pLayout->getView();
4586 	if (pView && (pView->isActive() || pView->isPreview()))
4587 	{
4588 		pView->setPoint(pcrx->getPosition() + fl_BLOCK_STRUX_OFFSET);
4589 	}
4590 	else if(pView && pView->getPoint() > pcrx->getPosition())
4591 	{
4592 		pView->setPoint(pView->getPoint() + fl_BLOCK_STRUX_OFFSET);
4593 	}
4594 	if(pView)
4595 		pView->updateCarets(pcrx->getPosition(),1);
4596 
4597 	fl_SectionLayout::checkAndAdjustCellSize();
4598 //
4599 // Now insert it into all the shadows.
4600 //
4601 	UT_uint32 iCount = m_vecPages.getItemCount();
4602 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertTable At start \n"));
4603 	m_pDoc->setDontChangeInsPoint();
4604 	fl_HdrFtrShadow * pShadowL = NULL;
4605 	for (UT_uint32 i=0; i<iCount; i++)
4606 	{
4607 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4608 
4609 		pShadowL = pPair->getShadow();
4610 
4611 		UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertTable into start of shadow 1 \n"));
4612 		if(pShadowL)
4613 		{
4614 		     pShadowL->bl_doclistener_insertTable(FL_SECTION_TABLE, pcrx,sdh,lid,NULL);
4615 		     pShadowL->checkAndAdjustCellSize();
4616 		}
4617 	}
4618 	m_pDoc->allowChangeInsPoint();
4619 	return pSL;
4620 }
4621 
4622 /*!
4623  * Insert the first block of the container in HdrFtr. We need to propage this
4624  * to all the shadows.
4625  */
bl_doclistener_insertFirstBlock(fl_ContainerLayout * pCL,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid)4626 bool fl_HdrFtrSectionLayout::bl_doclistener_insertFirstBlock(fl_ContainerLayout* pCL, const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux* sdh,PL_ListenerId lid)
4627 {
4628 	UT_uint32 iCount = m_vecPages.getItemCount();
4629 	fl_ContainerLayout * pShadowBL = NULL;
4630 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insert First block into shadow Cells \n"));
4631 	m_pDoc->setDontChangeInsPoint();
4632 	for (UT_uint32 i=0; i<iCount; i++)
4633 	{
4634 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4635 
4636 		// Find matching Table in this shadow.
4637 
4638 		pShadowBL = pPair->getShadow()->findMatchingContainer(pCL);
4639 		UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertFirstBlock into (CELL) shadow 1 \n"));
4640 		if(pShadowBL)
4641 		{
4642 			fl_BlockLayout*	pNewBL = static_cast<fl_BlockLayout *>(pShadowBL->insert(sdh, NULL, pcrx->getIndexAP(),FL_CONTAINER_BLOCK));
4643 			pNewBL->doclistener_insertFirstBlock(pcrx, sdh,	lid, NULL);
4644 		}
4645 	}
4646 	m_pDoc->allowChangeInsPoint();
4647 	return true;
4648 
4649 }
4650 
bl_doclistener_insertBlock(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4651 bool fl_HdrFtrSectionLayout::bl_doclistener_insertBlock(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux* sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,	PL_ListenerId lid, fl_ContainerLayout* sfhNew))
4652 {
4653 	bool bResult = true;
4654 //
4655 // Now insert it into all the shadows.
4656 //
4657 	UT_uint32 iCount = m_vecPages.getItemCount();
4658 	fl_ContainerLayout * pShadowBL = NULL;
4659 	UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertBlock \n"));
4660 	m_pDoc->setDontChangeInsPoint();
4661 	for (UT_uint32 i=0; i<iCount; i++)
4662 	{
4663 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4664 
4665 		// Find matching block in this shadow.
4666 		if(pBL)
4667 		{
4668 			pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4669 			xxx_UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertBlock into shadow 1 \n"));
4670 			if(pShadowBL)
4671 			{
4672 				bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_insertBlock(pcrx,sdh,lid,NULL)
4673 					&& bResult;
4674 			}
4675 		}
4676 		else
4677 //
4678 // This is the first block in the shadow
4679 //
4680 		{
4681 			fl_ContainerLayout*	pNewBL = pPair->getShadow()->insert(sdh, NULL, pcrx->getIndexAP(),FL_CONTAINER_BLOCK);
4682 			if (!pNewBL)
4683 			{
4684 				UT_DEBUGMSG(("no memory for BlockLayout\n"));
4685 				return false;
4686 			}
4687 			xxx_UT_DEBUGMSG(("fl_HdrFtrSectionLayout: insertBlock into shadow 2 \n"));
4688 			bResult = bResult && static_cast<fl_BlockLayout *>(pNewBL)->doclistener_insertFirstBlock(pcrx, sdh,
4689 													lid, NULL);
4690 		}
4691 	}
4692 //
4693 // Find Matching Block in this HdrFtrSectionLayout!!
4694 //
4695 	m_pDoc->allowChangeInsPoint();
4696 	if(pBL)
4697 	{
4698 		fl_ContainerLayout * ppBL = findMatchingContainer(pBL);
4699 		if(ppBL)
4700 		{
4701 		  static_cast<fl_BlockLayout *>(ppBL)->setHdrFtr();
4702 		  bResult = static_cast<fl_BlockLayout *>(ppBL)->doclistener_insertBlock(pcrx,sdh,lid,pfnBindHandles)
4703 			&& bResult;
4704 //
4705 // Mark the Block as HdrFtr
4706 //
4707 		  static_cast<fl_BlockLayout *>(ppBL->getNext())->setHdrFtr();
4708 		}
4709 		setNeedsReformat(this);
4710 	}
4711 	else
4712 //
4713 // First block in the section
4714 //
4715 	{
4716 		fl_ContainerLayout*	pNewBL = insert(sdh, NULL, pcrx->getIndexAP(),FL_CONTAINER_BLOCK);
4717 		if (!pNewBL)
4718 		{
4719 			UT_DEBUGMSG(("no memory for BlockLayout\n"));
4720 			return false;
4721 		}
4722 		bResult = bResult && static_cast<fl_BlockLayout *>(pNewBL)->doclistener_insertFirstBlock(pcrx, sdh,
4723 													lid, pfnBindHandles);
4724 		static_cast<fl_BlockLayout *>(pNewBL)->setHdrFtr();
4725 		setNeedsReformat(this);
4726 	}
4727 	return bResult;
4728 }
4729 
bl_doclistener_insertSection(fl_ContainerLayout * pBL,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4730 bool fl_HdrFtrSectionLayout::bl_doclistener_insertSection(fl_ContainerLayout* pBL, const PX_ChangeRecord_Strux * pcrx,
4731 														  pf_Frag_Strux* sdh,
4732 														  PL_ListenerId lid,
4733 														  void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
4734 																				  PL_ListenerId lid,
4735 																				  fl_ContainerLayout* sfhNew))
4736 {
4737 	// TODO this should NEVER happen, right?
4738 	UT_DEBUGMSG(("Insert Section is header/footer!!! \n"));
4739 	UT_ASSERT(0);
4740 	bool bResult = true;
4741 	UT_uint32 iCount = m_vecPages.getItemCount();
4742 	for (UT_uint32 i=0; i<iCount; i++)
4743 	{
4744 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4745 
4746 		bResult = pPair->getShadow()->bl_doclistener_insertSection(pBL, FL_SECTION_DOC, pcrx, sdh, lid, pfnBindHandles)
4747 			&& bResult;
4748 	}
4749 
4750 	return bResult;
4751 }
4752 
bl_doclistener_insertObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_Object * pcro)4753 bool fl_HdrFtrSectionLayout::bl_doclistener_insertObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_Object * pcro)
4754 {
4755 	bool bResult = true;
4756 	fl_ContainerLayout * pShadowBL = NULL;
4757 	UT_uint32 iCount = m_vecPages.getItemCount();
4758 	m_pDoc->setDontChangeInsPoint();
4759 	for (UT_uint32 i=0; i<iCount; i++)
4760 	{
4761 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4762 		// Find matching block in this shadow.
4763 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4764 		if(pShadowBL)
4765 		{
4766 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_insertObject(pcro)
4767 				&& bResult;
4768 		}
4769 	}
4770 	// Update the overall block too.
4771 	m_pDoc->allowChangeInsPoint();
4772 	pBL = findMatchingContainer(pBL);
4773 	if(pBL)
4774 	{
4775 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertObject(pcro) && bResult;
4776 	}
4777 	return bResult;
4778 }
4779 
bl_doclistener_deleteObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_Object * pcro)4780 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_Object * pcro)
4781 {
4782 	bool bResult = true;
4783 	fl_ContainerLayout * pShadowBL = NULL;
4784 	UT_uint32 iCount = m_vecPages.getItemCount();
4785 	m_pDoc->setDontChangeInsPoint();
4786 	for (UT_uint32 i=0; i<iCount; i++)
4787 	{
4788 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4789 		// Find matching block in this shadow.
4790 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4791 		if(pShadowBL)
4792 		{
4793 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_deleteObject(pcro)
4794 				&& bResult;
4795 		}
4796 	}
4797 	// Update the overall block too.
4798 	m_pDoc->allowChangeInsPoint();
4799 	pBL = findMatchingContainer(pBL);
4800 	if(pBL)
4801 	{
4802 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteObject(pcro) && bResult;
4803 	}
4804 	return bResult;
4805 }
4806 
bl_doclistener_changeObject(fl_ContainerLayout * pBL,const PX_ChangeRecord_ObjectChange * pcroc)4807 bool fl_HdrFtrSectionLayout::bl_doclistener_changeObject(fl_ContainerLayout* pBL, const PX_ChangeRecord_ObjectChange * pcroc)
4808 {
4809 	bool bResult = true;
4810 	fl_ContainerLayout * pShadowBL = NULL;
4811 	UT_uint32 iCount = m_vecPages.getItemCount();
4812 	m_pDoc->setDontChangeInsPoint();
4813 	for (UT_uint32 i=0; i<iCount; i++)
4814 	{
4815 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4816 		// Find matching block in this shadow.
4817 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4818 		if(pShadowBL)
4819 		{
4820 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_changeObject(pcroc)
4821 				&& bResult;
4822 		}
4823 	}
4824 	// Update the overall block too.
4825 	m_pDoc->allowChangeInsPoint();
4826 	pBL = findMatchingContainer(pBL);
4827 	if(pBL)
4828 	{
4829 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_changeObject(pcroc) && bResult;
4830 	}
4831 
4832 	return bResult;
4833 }
4834 
bl_doclistener_insertFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMark * pcrfm)4835 bool fl_HdrFtrSectionLayout::bl_doclistener_insertFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMark * pcrfm)
4836 {
4837 	bool bResult = true;
4838 	fl_ContainerLayout * pShadowBL = NULL;
4839 	UT_uint32 iCount = m_vecPages.getItemCount();
4840 	m_pDoc->setDontChangeInsPoint();
4841 	for (UT_uint32 i=0; i<iCount; i++)
4842 	{
4843 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4844 		// Find matching block in this shadow.
4845 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4846 		if(pShadowBL)
4847 		{
4848 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_insertFmtMark(pcrfm)
4849 				&& bResult;
4850 		}
4851 		else
4852 		{
4853 			bResult = false;
4854 		}
4855 	}
4856 	// Update the overall block too.
4857 	m_pDoc->allowChangeInsPoint();
4858 	pBL = findMatchingContainer(pBL);
4859 	if(pBL)
4860 	{
4861 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_insertFmtMark(pcrfm) && bResult;
4862 	}
4863 	else
4864 	{
4865 		bResult = false;
4866 	}
4867 	return bResult;
4868 }
4869 
bl_doclistener_deleteFmtMark(fl_ContainerLayout * pBL,const PX_ChangeRecord_FmtMark * pcrfm)4870 bool fl_HdrFtrSectionLayout::bl_doclistener_deleteFmtMark(fl_ContainerLayout* pBL, const PX_ChangeRecord_FmtMark * pcrfm)
4871 {
4872 	bool bResult = true;
4873 	fl_ContainerLayout * pShadowBL = NULL;
4874 	UT_uint32 iCount = m_vecPages.getItemCount();
4875 	m_pDoc->setDontChangeInsPoint();
4876 	for (UT_uint32 i=0; i<iCount; i++)
4877 	{
4878 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4879 		// Find matching block in this shadow.
4880 		pShadowBL = pPair->getShadow()->findMatchingContainer(pBL);
4881 		if(pShadowBL)
4882 		{
4883 			bResult = static_cast<fl_BlockLayout *>(pShadowBL)->doclistener_deleteFmtMark(pcrfm)
4884 				&& bResult;
4885 		}
4886 		else
4887 		{
4888 			bResult = false;
4889 		}
4890 	}
4891 	// Update the overall block too.
4892 	m_pDoc->allowChangeInsPoint();
4893 	pBL = findMatchingContainer(pBL);
4894 	if(pBL)
4895 	{
4896 		bResult = static_cast<fl_BlockLayout *>(pBL)->doclistener_deleteFmtMark(pcrfm)	&& bResult;
4897 	}
4898 	else
4899 	{
4900 		bResult = false;
4901 	}
4902 	return bResult;
4903 }
4904 
checkAndAdjustCellSize(fl_ContainerLayout * pCL)4905 void fl_HdrFtrSectionLayout::checkAndAdjustCellSize(fl_ContainerLayout * pCL)
4906 {
4907 	if(pCL->getContainerType() != FL_CONTAINER_CELL)
4908 	{
4909 		return;
4910 	}
4911 	fl_ContainerLayout * pShadowBL = NULL;
4912 	UT_uint32 iCount = m_vecPages.getItemCount();
4913 	for (UT_uint32 i=0; i<iCount; i++)
4914 	{
4915 		_PageHdrFtrShadowPair* pPair = m_vecPages.getNthItem(i);
4916 		// Find matching block in this shadow.
4917 		pShadowBL = pPair->getShadow()->findMatchingContainer(pCL);
4918 		if(pShadowBL)
4919 		{
4920 			static_cast<fl_SectionLayout *>(pShadowBL)->checkAndAdjustCellSize();
4921 		}
4922 	}
4923 	// Update the overall block too.
4924 
4925 	fl_ContainerLayout * pBL = findMatchingContainer(pCL);
4926 	if(pBL)
4927 	{
4928 		static_cast<fl_CellLayout *>(pBL)->checkAndAdjustCellSize();
4929 	}
4930 	return;
4931 }
4932 
4933 ////////////////////////////////////////////////////////////////////////////
4934 
bl_doclistener_insertFootnote(fl_ContainerLayout * pFootnote,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4935 bool fl_DocSectionLayout::bl_doclistener_insertFootnote(fl_ContainerLayout* pFootnote,
4936 											  const PX_ChangeRecord_Strux * pcrx,
4937 											  pf_Frag_Strux* sdh,
4938 											  PL_ListenerId lid,
4939 											  void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
4940 																	  PL_ListenerId lid,
4941 																	  fl_ContainerLayout* sfhNew))
4942 {
4943 	fl_ContainerLayout * pNewCL = NULL;
4944 	fl_DocSectionLayout * pCol = static_cast<fl_DocSectionLayout *>(myContainingLayout());
4945 	pNewCL = pCol->insert(sdh,pFootnote,pcrx->getIndexAP(), FL_CONTAINER_FOOTNOTE);
4946 
4947 		// Must call the bind function to complete the exchange of handles
4948 		// with the document (piece table) *** before *** anything tries
4949 		// to call down into the document (like all of the view
4950 		// listeners).
4951 
4952 	fl_ContainerLayout* sfhNew = pNewCL;
4953 	pfnBindHandles(sdh,lid,sfhNew);
4954 
4955 
4956 //
4957 // increment the insertion point in the view.
4958 //
4959 	FV_View* pView = m_pLayout->getView();
4960 	if (pView && (pView->isActive() || pView->isPreview()))
4961 	{
4962 		pView->setPoint(pcrx->getPosition() +  fl_BLOCK_STRUX_OFFSET);
4963 	}
4964 	else if(pView && pView->getPoint() > pcrx->getPosition())
4965 	{
4966 		pView->setPoint(pView->getPoint() +  fl_BLOCK_STRUX_OFFSET);
4967 	}
4968 	if(pView)
4969 		pView->updateCarets(pcrx->getPosition(),1);
4970 	return true;
4971 }
4972 
4973 
bl_doclistener_insertAnnotation(fl_ContainerLayout * pFootnote,const PX_ChangeRecord_Strux * pcrx,pf_Frag_Strux * sdh,PL_ListenerId lid,void (* pfnBindHandles)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))4974 bool fl_DocSectionLayout::bl_doclistener_insertAnnotation(fl_ContainerLayout* pFootnote,
4975 											  const PX_ChangeRecord_Strux * pcrx,
4976 											  pf_Frag_Strux* sdh,
4977 											  PL_ListenerId lid,
4978 											  void (* pfnBindHandles)(pf_Frag_Strux* sdhNew,
4979 																	  PL_ListenerId lid,
4980 																	  fl_ContainerLayout* sfhNew))
4981 {
4982 	fl_ContainerLayout * pNewCL = NULL;
4983 	fl_DocSectionLayout * pCol = static_cast<fl_DocSectionLayout *>(myContainingLayout());
4984 	pNewCL = pCol->insert(sdh,pFootnote,pcrx->getIndexAP(), FL_CONTAINER_ANNOTATION);
4985 
4986 		// Must call the bind function to complete the exchange of handles
4987 		// with the document (piece table) *** before *** anything tries
4988 		// to call down into the document (like all of the view
4989 		// listeners).
4990 
4991 	fl_ContainerLayout* sfhNew = pNewCL;
4992 	pfnBindHandles(sdh,lid,sfhNew);
4993 
4994 
4995 //
4996 // increment the insertion point in the view.
4997 //
4998 	FV_View* pView = m_pLayout->getView();
4999 	if (pView && (pView->isActive() || pView->isPreview()))
5000 	{
5001 		pView->setPoint(pcrx->getPosition() +  fl_BLOCK_STRUX_OFFSET);
5002 	}
5003 	else if(pView && pView->getPoint() > pcrx->getPosition())
5004 	{
5005 		pView->setPoint(pView->getPoint() +  fl_BLOCK_STRUX_OFFSET);
5006 	}
5007 	if(pView)
5008 		pView->updateCarets(pcrx->getPosition(),1);
5009 	return true;
5010 }
5011 
5012 //////////////////////////////////////////////////////////////////
5013 //////////////////////////////////////////////////////////////////
5014 
fl_HdrFtrShadow(FL_DocLayout * pLayout,fp_Page * pPage,fl_HdrFtrSectionLayout * pHdrFtrSL,pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP)5015 fl_HdrFtrShadow::fl_HdrFtrShadow(FL_DocLayout* pLayout, fp_Page* pPage, fl_HdrFtrSectionLayout* pHdrFtrSL, pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP)
5016 	: fl_SectionLayout(pLayout, sdh, indexAP, FL_SECTION_SHADOW,FL_CONTAINER_SHADOW,PTX_Section,pHdrFtrSL->getDocSectionLayout()),
5017 	  m_pPage(pPage),
5018 	  m_pHdrFtrSL(pHdrFtrSL)
5019 {
5020 	// Force creation of the appropriate container object;
5021 	// throw away return value
5022         xxx_UT_DEBUGMSG(("In Shadow Constructor %p DocSectionLayout %p \n",this,getDocSectionLayout()));
5023 	m_pPage->getHdrFtrContainer(m_pHdrFtrSL);
5024 	xxx_UT_DEBUGMSG(("check that m_iType is indeed FL_SECTION_SHADOW \n"));
5025 	UT_ASSERT(m_iType == FL_SECTION_SHADOW);
5026 //	UT_ASSERT(0);
5027 	fl_Layout::setType(PTX_Section); // Set the type of this strux
5028 }
5029 
~fl_HdrFtrShadow()5030 fl_HdrFtrShadow::~fl_HdrFtrShadow()
5031 {
5032 	_purgeLayout();
5033 }
5034 
getFirstContainer() const5035 fp_Container* fl_HdrFtrShadow::getFirstContainer() const
5036 {
5037 	return m_pPage->getHdrFtrContainer(m_pHdrFtrSL);
5038 }
5039 
getLastContainer() const5040 fp_Container* fl_HdrFtrShadow::getLastContainer() const
5041 {
5042 	return m_pPage->getHdrFtrContainer(m_pHdrFtrSL);
5043 }
5044 
getNewContainer(fp_Container *)5045 fp_Container* fl_HdrFtrShadow::getNewContainer(fp_Container * /*pFirstContainer*/)
5046 {
5047 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5048 
5049 	return NULL;
5050 }
5051 
findMatchingContainer(fl_ContainerLayout * pBL)5052 fl_ContainerLayout* fl_HdrFtrShadow::findMatchingContainer(fl_ContainerLayout* pBL)
5053 {
5054 	// This routine returns the matching block within this shadow of the
5055 	// hdrftrSectionlayout.
5056 	//
5057 	fl_ContainerLayout* ppBL = getFirstLayout();
5058 	bool bInTable = false;
5059 	while(ppBL && (ppBL->getStruxDocHandle() != pBL->getStruxDocHandle()))
5060 	{
5061 		if(ppBL->getContainerType() == FL_CONTAINER_TABLE)
5062 		{
5063 			ppBL = ppBL->getFirstLayout();
5064 			bInTable = true;
5065 		}
5066 		else if(bInTable && ppBL->getContainerType() == FL_CONTAINER_CELL)
5067 		{
5068 			ppBL = ppBL->getFirstLayout();
5069 		}
5070 		else if(bInTable && (ppBL->getNext() == NULL))
5071 		{
5072 			if(ppBL->myContainingLayout()->getNext() == NULL)
5073 			{
5074 				ppBL = ppBL->myContainingLayout();
5075 				ppBL = ppBL->myContainingLayout()->getNext();
5076 				bInTable = false;
5077 			}
5078 			else
5079 			{
5080 				ppBL = ppBL->myContainingLayout()->getNext();
5081 			}
5082 		}
5083 		else
5084 		{
5085 			ppBL = ppBL->getNext();
5086 		}
5087 	}
5088 	if(ppBL == NULL)
5089 	{
5090 		//UT_ASSERT(0);
5091 		m_pDoc->miniDump(pBL->getStruxDocHandle(),6);
5092 		if(pBL->getContainerType() == FL_CONTAINER_BLOCK)
5093 		{
5094 			ppBL = getFirstLayout();
5095 			while(ppBL && ppBL->getStruxDocHandle() != pBL->getStruxDocHandle())
5096 			{
5097 				ppBL = ppBL->getNextBlockInDocument();
5098 			}
5099 		}
5100 	}
5101 	//UT_ASSERT(ppBL);
5102 	xxx_UT_DEBUGMSG(("Search for block in shadow %x \n",this));
5103 	return ppBL;
5104 }
5105 
format(void)5106 void fl_HdrFtrShadow::format(void)
5107 {
5108 	fl_ContainerLayout*	pBL = getFirstLayout();
5109 	while (pBL)
5110 	{
5111 		if(pBL->getContainerType() == FL_CONTAINER_TABLE)
5112 		{
5113 			UT_DEBUGMSG(("!!!!Format Shadow Table!!!!!!!!!!\n"));
5114 		}
5115 		pBL->format();
5116 		pBL = pBL->getNext();
5117 	}
5118 }
5119 
5120 /*!
5121  * Scans through the shadow looking for the block at the specified Document
5122  * Position.
5123  \param pos the Document position
5124  \return A pointer to the block containing the point. Returns NULL if no block
5125          is found
5126  */
findBlockAtPosition(PT_DocPosition pos)5127 fl_ContainerLayout * fl_HdrFtrShadow::findBlockAtPosition(PT_DocPosition pos)
5128 {
5129 //
5130 // Skip through the blocks in this shadow to find the one containing this
5131 // point.
5132 //
5133     fl_ContainerLayout*	pBL = getFirstBlock();
5134     if(pBL == NULL)
5135 		return NULL;
5136 	if(pos < pBL->getPosition(true))
5137 	{
5138 //
5139 // This corner case is that pos == position of the HdrFtr strux
5140 //
5141 		if(pos == (pBL->getPosition(true) - 1))
5142 		{
5143 			if(pBL->getContainerType() != FL_CONTAINER_BLOCK)
5144 			{
5145 				pBL= pBL->getNextBlockInDocument();
5146 			}
5147 			return pBL;
5148 		}
5149 		return NULL;
5150 	}
5151 	fl_ContainerLayout* pNext = NULL;
5152 	pNext = pBL->getNextBlockInDocument();
5153 	bool doNext = false;
5154 	if(pNext != NULL)
5155 	{
5156 		doNext = (pNext->getPosition(true) < pos);
5157 	}
5158 	while(doNext)
5159 	{
5160 		pBL = pNext;
5161 		pNext = pNext->getNextBlockInDocument();
5162 		if(pNext && (pNext->getPosition(true) < pos))
5163 		{
5164 			if(getNext())
5165 			{
5166 				if(getNext()->getPosition(true) > pNext->getPosition(true))
5167 				{
5168 					doNext = true;
5169 				}
5170 				else
5171 				{
5172 					doNext = false;
5173 				}
5174 			}
5175 			else
5176 			{
5177 				doNext = true;
5178 			}
5179 		}
5180 		else
5181 		{
5182 			doNext = false;
5183 		}
5184 	}
5185 
5186 	if(pNext != NULL)
5187 	{
5188 		UT_ASSERT(pNext->getPosition(true) >= pos);
5189 		if(pBL->getContainerType() == FL_CONTAINER_BLOCK)
5190 		{
5191 			return pBL;
5192 		}
5193 		else if(pNext->getContainerType() == FL_CONTAINER_BLOCK)
5194 		{
5195 			return pNext;
5196 		}
5197 	}
5198 	else if(pBL && pBL->getPosition() == pos)
5199 	{
5200 		return pBL;
5201 	}
5202 	else
5203 	{
5204 		return NULL;
5205 	}
5206 //
5207 // Next corner case. See if position is inside the edittableBounds of this
5208 // section
5209 //
5210 	PT_DocPosition posEnd;
5211 	FV_View * pView = m_pLayout->getView();
5212 	if(pView)
5213 	{
5214 		pView->getEditableBounds(true,posEnd);
5215 		if(pos <= posEnd)
5216 			return pBL;
5217 	}
5218 //
5219 // Now the point MIGHT be in this last block. Use code from pd_Document
5220 // to find out. Have to check whether we're out of docrange first
5221 //
5222 	m_pDoc->getBounds(true,posEnd);
5223 	if(pos > posEnd)
5224 		return NULL;
5225 	pf_Frag_Strux* sdh=NULL;
5226 	bool bres;
5227 	bres = m_pDoc->getStruxOfTypeFromPosition(pos, PTX_Block, &sdh);
5228 	if(bres && sdh == pBL->getStruxDocHandle())
5229 		return pBL;
5230 //
5231 // Not here!!
5232 //
5233 	return NULL;
5234 }
5235 
updateLayout(bool)5236 void fl_HdrFtrShadow::updateLayout(bool /*bDoAll*/)
5237 {
5238 	bool bredraw = false;
5239 	xxx_UT_DEBUGMSG(("Doing Update layout in shadow %x \n",this));
5240 	fl_ContainerLayout*	pBL = getFirstLayout();
5241 	m_vecFormatLayout.clear();
5242 	while (pBL)
5243 	{
5244 		if (pBL->needsReformat())
5245 		{
5246 			bredraw = true;
5247 			pBL->format();
5248 		}
5249 
5250 		pBL = pBL->getNext();
5251 	}
5252 	if(bredraw)
5253 	{
5254 		//    clearScreen();
5255 		static_cast<fp_ShadowContainer *>(getFirstContainer())->layout();
5256  	}
5257 }
5258 
layout(void)5259 void fl_HdrFtrShadow::layout(void)
5260 {
5261 	if(needsReformat())
5262 	{
5263 		format();
5264 	}
5265 	static_cast<fp_ShadowContainer *>(getFirstContainer())->layout();
5266 }
5267 
clearScreen(void)5268 void fl_HdrFtrShadow::clearScreen(void)
5269 {
5270 	UT_ASSERT(getFirstContainer());
5271 	if(getFirstContainer())
5272 		static_cast<fp_ShadowContainer *>(getFirstContainer())->clearScreen();
5273 }
5274 
redrawUpdate(void)5275 void fl_HdrFtrShadow::redrawUpdate(void)
5276 {
5277 	FV_View * pView = m_pLayout->getView();
5278 	fl_ContainerLayout*	pBL = getFirstLayout();
5279 	bool bDoLayout = false;
5280 	while (pBL && (pView != NULL))
5281 	{
5282 		if(pBL->getContainerType() == FL_CONTAINER_BLOCK && static_cast<fl_BlockLayout *>(pBL)->hasUpdatableField())
5283 		{
5284 			bool bReformat = pBL->recalculateFields(getDocLayout()->getRedrawCount());
5285 			if(bReformat)
5286 			{
5287 				pBL->format();
5288 				bDoLayout = true;
5289 			}
5290 		}
5291 		else
5292 		{
5293 			pBL->recalculateFields(getDocLayout()->getRedrawCount());
5294 		}
5295 
5296 		if(pView && pBL->needsRedraw())
5297 		{
5298 			pBL->redrawUpdate();
5299 		}
5300 		pBL = pBL->getNext();
5301 	}
5302 	if(bDoLayout)
5303 	{
5304 	       static_cast<fp_ShadowContainer *>(getFirstContainer())->layout();
5305 	}
5306 }
doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)5307 bool fl_HdrFtrShadow::doclistener_changeStrux(const PX_ChangeRecord_StruxChange * pcrxc)
5308 {
5309 	UT_ASSERT(pcrxc->getType()==PX_ChangeRecord::PXT_ChangeStrux);
5310 
5311 	setAttrPropIndex(pcrxc->getIndexAP());
5312 
5313 	// TODO
5314 
5315 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5316 
5317 	return false;
5318 }
5319 
5320 /*!
5321     this function is only to be called by fl_ContainerLayout::lookupProperties()
5322     all other code must call lookupProperties() instead
5323 */
_lookupProperties(const PP_AttrProp *)5324 void fl_HdrFtrShadow::_lookupProperties(const PP_AttrProp* /*pAP*/)
5325 {
5326 }
5327 
_lookupMarginProperties(const PP_AttrProp *)5328 void fl_HdrFtrShadow::_lookupMarginProperties(const PP_AttrProp* /*pAP*/)
5329 {
5330 	fl_ContainerLayout*	pBL = getFirstLayout();
5331 	while (pBL)
5332 	{
5333 		pBL->lookupMarginProperties();
5334 		pBL = pBL->getNext();
5335 	}
5336 }
5337 
5338 //////////////////////////////////////////////////////////////////
5339 //////////////////////////////////////////////////////////////////
5340 
fl_ShadowListener(fl_HdrFtrSectionLayout * pHFSL,fl_HdrFtrShadow * pShadow)5341 fl_ShadowListener::fl_ShadowListener(fl_HdrFtrSectionLayout* pHFSL, fl_HdrFtrShadow* pShadow):
5342 	m_pDoc(pHFSL->getDocLayout()->getDocument()),
5343 	m_pShadow(pShadow),
5344 	m_bListening(false),
5345 	m_pCurrentBL(NULL),
5346 	m_pHFSL(pHFSL),
5347 	m_pCurrentTL(NULL),
5348 	m_pCurrentCell(NULL)
5349 {
5350 }
5351 
~fl_ShadowListener()5352 fl_ShadowListener::~fl_ShadowListener()
5353 {
5354 }
5355 
populate(fl_ContainerLayout * sfh,const PX_ChangeRecord * pcr)5356 bool fl_ShadowListener::populate(fl_ContainerLayout* sfh,
5357 								 const PX_ChangeRecord * pcr)
5358 {
5359 	if (!m_bListening)
5360 	{
5361 		return true;
5362 	}
5363 
5364 	UT_ASSERT(m_pShadow);
5365 //	UT_DEBUGMSG(("fl_ShadowListener::populate shadow %x \n",m_pShadow));
5366 
5367 	bool bResult = false;
5368 	FV_View* pView = m_pHFSL->getDocLayout()->getView();
5369 	PT_DocPosition oldPos = 0;
5370 	//
5371 	// We're not printing
5372 	//
5373 	if(pView != NULL)
5374 	{
5375 		oldPos = pView->getPoint();
5376 	}
5377 	switch (pcr->getType())
5378 	{
5379 	case PX_ChangeRecord::PXT_InsertSpan:
5380 	{
5381 		const PX_ChangeRecord_Span * pcrs = static_cast<const PX_ChangeRecord_Span *> (pcr);
5382 
5383 		{
5384 			const fl_Layout * pL = static_cast<const fl_Layout *>(sfh);
5385 			UT_UNUSED(pL);
5386 			UT_ASSERT(pL->getType() == PTX_Block);
5387 			UT_ASSERT(m_pCurrentBL == (static_cast<const fl_ContainerLayout *>(pL)));
5388 		}
5389 		PT_BlockOffset blockOffset = pcrs->getBlockOffset();
5390 		UT_uint32 len = pcrs->getLength();
5391 
5392 
5393 		bResult = static_cast<fl_BlockLayout *>(m_pCurrentBL)->doclistener_populateSpan(pcrs, blockOffset, len);
5394 		goto finish_up;
5395 	}
5396 
5397 	case PX_ChangeRecord::PXT_InsertObject:
5398 	{
5399 		const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *>(pcr);
5400 
5401 		{
5402 			const fl_Layout * pL = static_cast<const fl_Layout *>(sfh);
5403 			UT_UNUSED(pL);
5404 			UT_ASSERT(pL->getType() == PTX_Block);
5405 			UT_ASSERT(m_pCurrentBL == (static_cast<const fl_ContainerLayout *>(pL)));
5406 		}
5407 		PT_BlockOffset blockOffset = pcro->getBlockOffset();
5408 
5409 // sterwill -- is this call to getSectionLayout() needed?  pBLSL is not used.
5410 
5411 //			fl_SectionLayout* pBLSL = m_pCurrentBL->getSectionLayout();
5412 		bResult = static_cast<fl_BlockLayout *>(m_pCurrentBL)->doclistener_populateObject(blockOffset,pcro);
5413 		goto finish_up;
5414 	}
5415 
5416 	case PX_ChangeRecord::PXT_InsertFmtMark:
5417 	{
5418 		//	const PX_ChangeRecord_FmtMark * pcrfm = static_cast<const PX_ChangeRecord_FmtMark *>(pcr);
5419 
5420 		{
5421 			const fl_Layout * pL = static_cast<const fl_Layout *>(sfh);
5422 			UT_UNUSED(pL);
5423 			UT_ASSERT(pL->getType() == PTX_Block);
5424 			UT_ASSERT(m_pCurrentBL == (static_cast<const fl_ContainerLayout *>(pL)));
5425 		}
5426 		bResult = static_cast<fl_BlockLayout *>(m_pCurrentBL)->doclistener_insertFmtMark( reinterpret_cast<const PX_ChangeRecord_FmtMark *>(pcr));
5427 		goto finish_up;
5428 	}
5429 
5430 	default:
5431 		UT_DEBUGMSG(("Unknown Change record = %d \n",pcr->getType()));
5432 		UT_ASSERT(0);
5433 		//
5434 		// We're not printing
5435 		//
5436 		if(pView != NULL && m_pDoc->getAllowChangeInsPoint())
5437 		{
5438 			pView->setPoint(oldPos);
5439 		}
5440 		return false;
5441 	}
5442 
5443  finish_up:
5444 	//
5445 	// We're not printing
5446 	//
5447 	if(pView != NULL && m_pDoc->getAllowChangeInsPoint())
5448 	{
5449 		pView->setPoint(oldPos);
5450 	}
5451 	return bResult;
5452 }
5453 
populateStrux(pf_Frag_Strux * sdh,const PX_ChangeRecord * pcr,fl_ContainerLayout ** psfh)5454 bool fl_ShadowListener::populateStrux(pf_Frag_Strux* sdh,
5455 									  const PX_ChangeRecord * pcr,
5456 									  fl_ContainerLayout* * psfh)
5457 {
5458 	UT_ASSERT(m_pShadow);
5459 	xxx_UT_DEBUGMSG(("fl_ShadowListener::populateStrux\n"));
5460 
5461 	UT_ASSERT(pcr->getType() == PX_ChangeRecord::PXT_InsertStrux);
5462 	const PX_ChangeRecord_Strux * pcrx = static_cast<const PX_ChangeRecord_Strux *> (pcr);
5463 
5464 	switch (pcrx->getStruxType())
5465 	{
5466 	case PTX_Section:
5467 	{
5468 		PT_AttrPropIndex indexAP = pcr->getIndexAP();
5469 		const PP_AttrProp* pAP = NULL;
5470 
5471 		// need to explode revision attribute
5472 		m_pDoc->getAttrProp(indexAP, &pAP);
5473 		if(pAP)
5474 		{
5475 			UT_return_val_if_fail(m_pHFSL && m_pHFSL->getDocLayout(), false);
5476 			FV_View* pView = m_pHFSL->getDocLayout()->getView();
5477 			UT_return_val_if_fail(pView, false);
5478 
5479 			UT_uint32 iId  = pView->getRevisionLevel();
5480 			bool bShow     = pView->isShowRevisions();
5481 
5482 			PP_RevisionAttr * pRevisions = NULL; // must be NULL
5483 
5484 
5485 			if(  pAP->getRevisedIndex() != 0xffffffff
5486 			  && pAP->getRevisionState().isEqual(iId, bShow, m_pDoc->isMarkRevisions()))
5487 			{
5488 				// the revision has a valid index to an inflated AP, so we use it
5489 				PT_AttrPropIndex revAPI = pAP->getRevisedIndex();
5490 
5491 				m_pDoc->getAttrProp(revAPI, &pAP);
5492 			}
5493 			else
5494 			{
5495 				bool bHiddenRevision;
5496 				const PP_AttrProp * pNewAP = m_pDoc->explodeRevisions(pRevisions, pAP, bShow,
5497 																	  iId, bHiddenRevision);
5498 
5499 				if(pNewAP)
5500 					pAP = pNewAP;
5501 			}
5502 
5503 			delete pRevisions;
5504 		}
5505 
5506 		if (pAP)
5507 		{
5508 			const gchar* pszSectionType = NULL;
5509 			pAP->getAttribute("type", pszSectionType);
5510 			if (
5511 				!pszSectionType
5512 				|| (0 == strcmp(pszSectionType, "doc"))
5513 				)
5514 			{
5515 				m_bListening = false;
5516 			}
5517 			else
5518 			{
5519 				if ( (0 == strcmp(pszSectionType, "header"))
5520 					|| (0 == strcmp(pszSectionType, "footer"))
5521 					 || (0 == strcmp(pszSectionType, "header-first"))
5522 					|| (0 == strcmp(pszSectionType, "footer-first"))
5523 					 || (0 == strcmp(pszSectionType, "header-even"))
5524 					|| (0 == strcmp(pszSectionType, "footer-even"))
5525 					 || (0 == strcmp(pszSectionType, "header-last"))
5526 					|| (0 == strcmp(pszSectionType, "footer-last"))
5527 					)
5528 				{
5529 					// TODO verify id match
5530 
5531 					m_bListening = true;
5532 				}
5533 				else
5534 				{
5535 					return false;
5536 				}
5537 			}
5538 		}
5539 		else
5540 		{
5541 			// TODO fail?
5542 			return false;
5543 		}
5544 	}
5545 	break;
5546 
5547 	case PTX_SectionHdrFtr:
5548 	{
5549 		PT_AttrPropIndex indexAP = pcr->getIndexAP();
5550 		const PP_AttrProp* pAP = NULL;
5551 		// need to explode revision attribute
5552 		m_pDoc->getAttrProp(indexAP, &pAP);
5553 		if(pAP)
5554 		{
5555 			UT_return_val_if_fail(m_pHFSL && m_pHFSL->getDocLayout(), false);
5556 			FV_View* pView = m_pHFSL->getDocLayout()->getView();
5557 			UT_return_val_if_fail(pView, false);
5558 
5559 			UT_uint32 iId  = pView->getRevisionLevel();
5560 			bool bShow     = pView->isShowRevisions();
5561 
5562 			PP_RevisionAttr * pRevisions = NULL; // must be NULL
5563 
5564 
5565 			if(  pAP->getRevisedIndex() != 0xffffffff
5566 			  && pAP->getRevisionState().isEqual(iId, bShow, m_pDoc->isMarkRevisions()))
5567 			{
5568 				// the revision has a valid index to an inflated AP, so we use it
5569 				PT_AttrPropIndex revAPI = pAP->getRevisedIndex();
5570 
5571 				m_pDoc->getAttrProp(revAPI, &pAP);
5572 			}
5573 			else
5574 			{
5575 				bool bHiddenRevision;
5576 				const PP_AttrProp * pNewAP = m_pDoc->explodeRevisions(pRevisions, pAP, bShow,
5577 																	  iId, bHiddenRevision);
5578 
5579 				if(pNewAP)
5580 					pAP = pNewAP;
5581 			}
5582 
5583 			delete pRevisions;
5584 		}
5585 
5586 		if (pAP)
5587 		{
5588 			const gchar* pszSectionType = NULL;
5589 			pAP->getAttribute("type", pszSectionType);
5590 			if (
5591 				!pszSectionType
5592 				|| (0 == strcmp(pszSectionType, "doc"))
5593 				)
5594 			{
5595 				m_bListening = false;
5596 			}
5597 			else
5598 			{
5599 				if ( (0 == strcmp(pszSectionType, "header"))
5600 					|| (0 == strcmp(pszSectionType, "footer"))
5601 					 || (0 == strcmp(pszSectionType, "header-first"))
5602 					|| (0 == strcmp(pszSectionType, "footer-first"))
5603 					 || (0 == strcmp(pszSectionType, "header-even"))
5604 					|| (0 == strcmp(pszSectionType, "footer-even"))
5605 					 || (0 == strcmp(pszSectionType, "header-last"))
5606 					|| (0 == strcmp(pszSectionType, "footer-last"))
5607 					)
5608 				{
5609 					// TODO verify id match
5610 
5611 					m_bListening = true;
5612 				}
5613 				else
5614 				{
5615 					return false;
5616 				}
5617 			}
5618 		}
5619 		else
5620 		{
5621 			// TODO fail?
5622 			return false;
5623 		}
5624 	}
5625 	break;
5626 
5627 	case PTX_Block:
5628 	{
5629 		if (m_bListening)
5630 		{
5631 			// append a new BlockLayout to that SectionLayout
5632 			fl_ContainerLayout*	pBL = NULL;
5633 			if(m_pCurrentCell == NULL)
5634 			{
5635 				pBL = m_pShadow->append(sdh, pcr->getIndexAP(),FL_CONTAINER_BLOCK);
5636 			}
5637 			else
5638 			{
5639 				pBL = m_pCurrentCell->append(sdh, pcr->getIndexAP(),FL_CONTAINER_BLOCK);
5640 			}
5641 			xxx_UT_DEBUGMSG(("New Shadow block %x created and set as current \n",pBL));
5642 			if (!pBL)
5643 			{
5644 				UT_DEBUGMSG(("no memory for BlockLayout"));
5645 				return false;
5646 			}
5647 			m_pCurrentBL = pBL;
5648 			*psfh = pBL;
5649 		}
5650 
5651 	}
5652 	break;
5653 
5654 
5655 	case PTX_SectionTable:
5656 	{
5657 		if (m_bListening)
5658 		{
5659 			// append a new BlockLayout to that SectionLayout
5660 			fl_ContainerLayout*	pTL = m_pShadow->append(sdh, pcr->getIndexAP(),FL_CONTAINER_TABLE);
5661 			UT_DEBUGMSG(("New Shadow Table %p created and set as current \n",pTL));
5662 			m_pCurrentTL = static_cast<fl_TableLayout *>(pTL);
5663 			*psfh = pTL;
5664 		}
5665 
5666 	}
5667 	break;
5668 
5669 
5670 	case PTX_SectionCell:
5671 	{
5672 		if (m_bListening && m_pCurrentTL)
5673 		{
5674 
5675 			// append a new BlockLayout to that SectionLayout
5676 			fl_ContainerLayout*	pCell = m_pCurrentTL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_CELL);
5677 			UT_DEBUGMSG(("New Shadow Cell %p created and set as current \n",pCell));
5678 			m_pCurrentCell = static_cast<fl_CellLayout *>(pCell);
5679 			*psfh = m_pCurrentCell;
5680 		}
5681 
5682 	}
5683 	break;
5684 
5685 	case PTX_EndTable:
5686 	{
5687 		if(m_pCurrentTL == NULL)
5688 		{
5689 			m_pDoc->miniDump(sdh,6);
5690 		}
5691 
5692 		UT_return_val_if_fail(m_pCurrentTL,false);
5693 		UT_DEBUGMSG(("!!!! Append End Table to Shadow \n"));
5694 		if(m_pCurrentTL->getContainerType() != FL_CONTAINER_TABLE)
5695 		{
5696 			UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5697 			return false;
5698 		}
5699 		*psfh = m_pCurrentTL;
5700 		UT_DEBUGMSG(("SEVIOR: End table in  shadow listener \n"));
5701 		m_pCurrentTL->setDirty();
5702 		m_pCurrentTL->setEndTableIn();
5703 		m_pCurrentTL = NULL;
5704 	}
5705 	break;
5706 	case PTX_EndCell:
5707 	{
5708 		UT_ASSERT(m_pCurrentCell);
5709 		UT_DEBUGMSG(("!!!! Append End Cell in Shadow Listener\n"));
5710 		*psfh = m_pCurrentCell;
5711 		m_pCurrentCell = NULL;
5712 	}
5713 	break;
5714 
5715 	default:
5716 		UT_ASSERT(0);
5717 		return false;
5718 	}
5719 	//
5720 	// We're not printing
5721 	//
5722 	return true;
5723 }
5724 
change(fl_ContainerLayout *,const PX_ChangeRecord *)5725 bool fl_ShadowListener::change(fl_ContainerLayout* /*sfh*/,
5726 							   const PX_ChangeRecord * /*pcr*/)
5727 {
5728 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5729 
5730 	return false;
5731 }
5732 
insertStrux(fl_ContainerLayout *,const PX_ChangeRecord *,pf_Frag_Strux *,PL_ListenerId,void (*)(pf_Frag_Strux * sdhNew,PL_ListenerId lid,fl_ContainerLayout * sfhNew))5733 bool fl_ShadowListener::insertStrux(fl_ContainerLayout* /*sfh*/,
5734 									const PX_ChangeRecord * /*pcr*/,
5735 									pf_Frag_Strux* /*sdh*/,
5736 									PL_ListenerId /*lid*/,
5737 									void (* /*pfnBindHandles*/)(pf_Frag_Strux* sdhNew,
5738 																PL_ListenerId lid,
5739 																fl_ContainerLayout* sfhNew))
5740 {
5741 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5742 
5743 	return false;
5744 }
5745 
signal(UT_uint32)5746 bool fl_ShadowListener::signal(UT_uint32 /*iSignal*/)
5747 {
5748 	UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5749 
5750 	return false;
5751 }
5752 
5753 
5754