1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3  * Copyright (C) 1998-2000 AbiSource, Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "ut_types.h"
25 #include "ut_misc.h"
26 
27 #include "fp_Page.h"
28 #include "fl_DocLayout.h"
29 #include "fl_SectionLayout.h"
30 #include "fp_Column.h"
31 #include "fp_Line.h"
32 #include "fp_Run.h"
33 #include "fl_BlockLayout.h"
34 #include "gr_Graphics.h"
35 #include "gr_DrawArgs.h"
36 #include "fv_View.h"
37 #include "fp_FootnoteContainer.h"
38 #include "fl_TOCLayout.h"
39 #include "fl_FootnoteLayout.h"
40 #include "fp_FrameContainer.h"
41 #include "fl_FrameLayout.h"
42 #include "fp_TableContainer.h"
43 #include "ut_debugmsg.h"
44 #include "ut_assert.h"
45 #include "ut_units.h"
46 #include "gr_Painter.h"
47 
fp_Page(FL_DocLayout * pLayout,FV_View * pView,const fp_PageSize & pageSize,fl_DocSectionLayout * pOwner)48 fp_Page::fp_Page(FL_DocLayout* pLayout,
49 		 FV_View* pView,
50 		 const fp_PageSize& pageSize,
51 		 fl_DocSectionLayout* pOwner)
52 	:	m_pLayout(pLayout),
53 		m_pView(pView),
54 		m_pNext(0),
55 		m_pPrev(0),
56 		m_pageSize(pageSize),
57 		m_bNeedsRedraw(true),
58 		m_pOwner(pOwner),
59 		m_pFooter(0),
60 		m_pHeader(0),
61 		m_FillType(NULL,NULL,FG_FILL_TRANSPARENT),
62 		m_pLastMappedTOC(NULL),
63 		m_iCountWrapPasses(0),
64 		m_iFieldPageNumber(-1)
65 {
66 	UT_ASSERT(pLayout);
67 	UT_ASSERT(pOwner);
68 
69 	GR_Graphics * pG = pLayout->getGraphics();
70 	UT_ASSERT(pG);
71 	m_vecColumnLeaders.clear();
72 	m_iResolution = pG->getResolution();
73 	m_rDamageRect.left = 0;
74 	m_rDamageRect.top = 0;
75 	m_rDamageRect.width = 0;
76 	m_rDamageRect.height = 0;
77 	m_vecFootnotes.clear();
78 	m_vecAnnotations.clear();
79 	m_vecAboveFrames.clear();
80 	m_vecBelowFrames.clear();
81 
82 	xxx_UT_DEBUGMSG(("!!!!!!!!!!!!!!!!!!!!!!!!!!Created Page %x \n",this));
83 }
84 
~fp_Page()85 fp_Page::~fp_Page()
86 {
87 	xxx_UT_DEBUGMSG(("fpPage: Deleting page %x \n",this));
88 	if (m_pOwner)
89 	{
90 		fl_DocSectionLayout *pDSL = m_pOwner;
91 		m_pOwner = NULL;
92 		pDSL->deleteOwnedPage(this);
93 	}
94 	if((m_pHeader != NULL) || (m_pFooter != NULL))
95 	{
96 	    fl_HdrFtrSectionLayout * pHdrFtr = NULL;
97 	    if(m_pHeader != NULL)
98 	    {
99 	         pHdrFtr = m_pHeader->getHdrFtrSectionLayout();
100 		 if(pHdrFtr != NULL && pHdrFtr->isPageHere(this))
101 		 {
102 		   pHdrFtr->deletePage(this);
103 		   UT_DEBUGMSG(("Remove Page from Hdr %p in page destructor \n",pHdrFtr));
104 		 }
105 	    }
106 	    if(m_pFooter != NULL)
107 	    {
108 	         pHdrFtr = m_pFooter->getHdrFtrSectionLayout();
109 		 if(pHdrFtr != NULL && pHdrFtr->isPageHere(this))
110 		 {
111 		   pHdrFtr->deletePage(this);
112 		   UT_DEBUGMSG(("Remove Page from Ftr %p in page destructor \n",pHdrFtr));
113 		 }
114 	    }
115 	}
116 	DELETEP(m_pHeader);
117 	DELETEP(m_pFooter);
118 }
119 
120 /*!
121  * FillType class for the page.
122  */
getFillType(void) const123 const fg_FillType & fp_Page::getFillType(void) const
124 {
125 	return m_FillType;
126 }
127 
128 /*!
129  * FillType class for the page.
130  */
getFillType(void)131 fg_FillType & fp_Page::getFillType(void)
132 {
133 	return m_FillType;
134 }
135 
isEmpty(void) const136 bool fp_Page::isEmpty(void) const
137 {
138 	if((m_vecColumnLeaders.getItemCount() == 0) && (m_vecFootnotes.getItemCount() == 0) && (m_vecAnnotations.getItemCount() == 0) && (m_vecAboveFrames.getItemCount() == 0) && (m_vecBelowFrames.getItemCount() == 0))
139 	{
140 		return true;
141 	}
142 	return false;
143 }
144 
145 /*!
146  * This method sets the page number in all thepages frames.
147  */
148 
setPageNumberInFrames(void)149 void fp_Page::setPageNumberInFrames(void)
150 {
151 	UT_sint32 iPage = getDocLayout()->findPage(this);
152 	UT_sint32 i = 0;
153 	for(i=0; i< static_cast<UT_sint32>(countAboveFrameContainers()); i++)
154 	{
155 		fp_FrameContainer * pFrame = getNthAboveFrameContainer(i);
156 		pFrame->setPreferedPageNo(iPage);
157 	}
158 	for(i=0; i< static_cast<UT_sint32>(countBelowFrameContainers()); i++)
159 	{
160 		fp_FrameContainer * pFrame = getNthBelowFrameContainer(i);
161 		pFrame->setPreferedPageNo(iPage);
162 	}
163 }
164 
165 /*!
166  * Fill a vector with all the layouts referenced from this page.
167  */
getAllLayouts(UT_GenericVector<fl_ContainerLayout * > & AllLayouts) const168 void fp_Page::getAllLayouts(UT_GenericVector<fl_ContainerLayout *> & AllLayouts) const
169 {
170 	fp_Column * pCol = NULL;
171 	UT_sint32 i = 0;
172 	fl_ContainerLayout * pPrevCL = NULL;
173 	fl_ContainerLayout * pCurCL = NULL;
174 	for(i= 0; i< m_vecColumnLeaders.getItemCount(); i++)
175 	{
176 		pCol = m_vecColumnLeaders.getNthItem(i);
177 		while(pCol)
178 		{
179 			UT_sint32 j= 0;
180 			fp_ContainerObject * pCon = NULL;
181 			for(j = 0; j< pCol->countCons(); j++)
182 			{
183 				pCon = pCol->getNthCon(j);
184 				if(pCon->getContainerType() == FP_CONTAINER_LINE)
185 				{
186 					pCurCL = static_cast<fl_ContainerLayout *>(static_cast<fp_Line *>(pCon)->getBlock());
187 					if(pCurCL != pPrevCL)
188 					{
189 						pPrevCL = pCurCL;
190 						AllLayouts.addItem(pPrevCL);
191 					}
192 				}
193 				if(pCon->getContainerType() == FP_CONTAINER_TABLE)
194 				{
195 					pCurCL = static_cast<fl_ContainerLayout *>(static_cast<fp_TableContainer *>(pCon)->getSectionLayout());
196 					if(pCurCL != pPrevCL)
197 					{
198 						pPrevCL = pCurCL;
199 						AllLayouts.addItem(pPrevCL);
200 					}
201 				}
202 
203 			}
204 			pCol = pCol->getFollower();
205 		}
206 	}
207 }
208 
isOnScreen(void)209 bool fp_Page::isOnScreen(void)
210 {
211 	if(!m_pView)
212 	{
213 	    return false;
214 	}
215 	UT_sint32 xoff,yoff;
216 	m_pView->getPageScreenOffsets(this,xoff,yoff);
217 	if(yoff+getHeight() < 0)
218 	{
219 		return false;
220 	}
221 	if(!m_pView)
222 		return false;
223 	if(yoff > m_pView->getWindowHeight())
224 	{
225 		return false;
226 	}
227 	return true;
228 }
229 
getWidth(void) const230 UT_sint32 fp_Page::getWidth(void) const
231 {
232 	return static_cast<UT_sint32>(m_iResolution * m_pageSize.Width(DIM_IN));
233 }
234 
getHeight(void) const235 UT_sint32 fp_Page::getHeight(void) const
236 {
237 	return static_cast<UT_sint32>(m_iResolution * m_pageSize.Height(DIM_IN));
238 }
239 
getColumnGap(void) const240 UT_sint32 fp_Page::getColumnGap(void) const
241 {
242 	return getOwningSection()->getColumnGap();
243 }
244 
clearCountWrapNumber(void)245 void fp_Page::clearCountWrapNumber(void)
246 {
247 	m_iCountWrapPasses = 0;
248 }
249 /*!
250  * This method scans the page, looking for lines that overlap wrapped
251  * positioned frames. As it finds them it records the line and the block
252  * After scanning the page it calls a method in the block to rebreak
253  * the papargraph starting from the line supplied, but now making sure
254  * to not overlap any wrapped objects.
255  * If it does a re-break of any paragraph it returns the first container
256  * in the page.
257  * and sets pNextColumn to the first column on the page.
258  * fp_ColumnBreaker then lays out the page again.
259  * If there are no rebreaks it returns NULL and fp_ColumnBreaker moves on to
260  * the next page.
261  * pNextCol is the next column fb_ColumnBreaker will evaluate it is used
262  * as an output..
263  */
updatePageForWrapping(fp_Column * & pNextCol)264 fp_Container * fp_Page::updatePageForWrapping(fp_Column *& pNextCol)
265 {
266 	if(m_iCountWrapPasses > 19)
267 	{
268 		return NULL;
269 	}
270 	m_iCountWrapPasses++;
271 #if 0
272 	UT_sint32 iPage = getDocLayout()->findPage(this);
273 	UT_DEBUGMSG(("Wrap passes = %d page %x page number %d \n",m_iCountWrapPasses,this,iPage ));
274 	if(getPrev())
275 		{
276 			iPage = getDocLayout()->findPage(getPrev());
277 			UT_DEBUGMSG(("Prev page %x Prev page number %d Number Frames %d \n",getPrev(),iPage,getPrev()->countAboveFrameContainers() ));
278 		}
279 #endif
280 	if(m_iCountWrapPasses > 10)
281     {
282 		UT_DEBUGMSG(("Number of wrapped passed = %d \n",m_iCountWrapPasses));
283 	}
284 	UT_sint32 i= 0;
285 	UT_sint32 nWrapped = 0;
286 	fp_Container * pFirst2 = NULL;
287 	fl_BlockLayout * pFirstBL = NULL;
288 	for(i=0; i < static_cast<UT_sint32>(countColumnLeaders()); i++)
289 	{
290 		fp_Column * pCol = getNthColumnLeader(i);
291 		if(i == 0)
292 		{
293 			pFirst2 = static_cast<fp_Container *>(pCol->getNthCon(0));
294 			if(pFirst2 == NULL)
295 			{
296 				return NULL;
297 			}
298 		}
299 		while(pCol)
300 		{
301 			if(m_iCountWrapPasses > 10)
302 			{
303 				nWrapped += pCol->countWrapped();
304 			}
305 			else
306 			{
307 				nWrapped += pCol->getNumWrapped();
308 			}
309 			UT_DEBUGMSG(("Page number %d \n",getDocLayout()->findPage(this)));
310 			UT_DEBUGMSG(("NumWrapped %d \n",nWrapped));
311 			pCol = static_cast<fp_Column *>(pCol->getFollower());
312 		}
313 	}
314 	UT_sint32 nWrappedObjs = 0;
315 	for(i=0; i< static_cast<UT_sint32>(countAboveFrameContainers()); i++)
316 	{
317 		fp_FrameContainer * pFrame = getNthAboveFrameContainer(i);
318 		if(pFrame->isWrappingSet())
319 		{
320 			nWrappedObjs++;
321 		}
322 	}
323 
324 	if((nWrapped == 0) && (nWrappedObjs == 0))
325 	{
326 		xxx_UT_DEBUGMSG(("page %x nWrapped %d nWrappedObjs %d does not need updating \n",this,nWrapped,nWrappedObjs));
327 		fp_Page * pPrevPage = getPrev();
328 		//
329 		// In creating lines that correctly wrap frames on the previous page
330 		// the next page may have inherited some partially broken lines.
331 		// The following code check for the this situation so it can be
332 		// fixed here.
333 		//
334 		if(pPrevPage && (pPrevPage->countAboveFrameContainers() > 0))
335 		{
336 				for(i=0; i< static_cast<UT_sint32>(pPrevPage->countAboveFrameContainers()); i++)
337 				{
338 						fp_FrameContainer * pFrame = pPrevPage->getNthAboveFrameContainer(i);
339 						if(pFrame->isWrappingSet())
340 						{
341 								nWrappedObjs++;
342 						}
343 				}
344 
345 		}
346 		if((nWrappedObjs == 0) &&(m_iCountWrapPasses == 1))
347 		{
348 			return NULL;
349 		}
350 		else if((nWrappedObjs == 0) && (getNext() == NULL))
351 		{
352 				return NULL;
353 		}
354 		else if(nWrappedObjs == 0)
355 		{
356 			fp_Column * pNextNoWrapCol = getNext()->getNthColumnLeader(0);
357 			if(pNextNoWrapCol == NULL)
358 			{
359 				// FIXME this appears to happen sometimes.
360 				// we should work out a better thing to do this this
361 				return NULL;
362 			}
363 			fp_Container * pNewFirstWrapCon = static_cast<fp_Container *>(pNextNoWrapCol->getNthCon(0));
364 			getNext()->clearCountWrapNumber();
365 			return pNewFirstWrapCon;
366 		}
367 	}
368 	bool bFormatAllWrapped = ((nWrapped > 0) && (nWrappedObjs == 0));
369 	UT_GenericVector<_BL *> vecBL;
370 	vecBL.clear();
371 	for(i=0; i < static_cast<UT_sint32>(countColumnLeaders()); i++)
372 	{
373 		fp_Column * pCol2 = getNthColumnLeader(i);
374 		while(pCol2)
375 		{
376 			UT_sint32 j = 0;
377 			for(j=0; j < pCol2->countCons(); j++)
378 			{
379 				fp_Container * pCon = static_cast<fp_Container *>(pCol2->getNthCon(j));
380 				xxx_UT_DEBUGMSG(("Look at con %x at j %d \n",pCon,j));
381 				if(pCon->getContainerType() == FP_CONTAINER_LINE)
382 				{
383 					fp_Line * pLine = static_cast<fp_Line *>(pCon);
384 					UT_Rect recLeft;
385 					UT_Rect recRight;
386 					pLine->genOverlapRects(recLeft,recRight);
387 					bool bFoundOne = false;
388 					if(recLeft.width == 0 && recRight.width == 0)
389 					{
390 						pLine->setWrapped(false);
391 					}
392 					else if((recLeft.width < 0) || (recRight.width <0))
393 					{
394 //
395 // SOMETHING HAS GONE HORRIBALLY WRONG. Try to recover by collapsing the
396 // content in this column and rebuilding
397 //
398 						UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
399 						UT_DEBUGMSG(("-ve width here!!!! %p left %d right %d \n",pLine,recLeft.width,recRight.width));
400 						UT_VECTOR_PURGEALL(_BL *, vecBL);
401 						fl_BlockLayout * pBL = pLine->getBlock();
402 						fl_BlockLayout * pFirst = pBL;
403 						fp_Column * pCol = static_cast<fp_Column *>(pLine->getColumn());
404 						bool bLoop = true;
405 						while(bLoop)
406 						{
407 							if(pBL && pBL->getContainerType() == FL_CONTAINER_BLOCK)
408 							{
409 								if(pBL->getFirstContainer() && (pBL->getFirstContainer()->getColumn() == pCol))
410 								{
411 									bLoop = true;
412 									pFirst = pBL;
413 								}
414 								pBL = static_cast<fl_BlockLayout *>(pBL->getPrev());
415 							}
416 							else
417 							{
418 								bLoop = false;
419 							}
420 						}
421 						fp_Column * pFirstCol = static_cast<fp_Column *>(pFirst->getFirstContainer()->getColumn());
422 						pBL = pFirst;
423 						UT_GenericVector<fl_BlockLayout *> vecCollapse;
424 						vecCollapse.addItem(pBL);
425 						bLoop = true;
426 						while(bLoop)
427 						{
428 							if(pBL && pBL->getContainerType() == FL_CONTAINER_BLOCK)
429 							{
430 								if(pBL->getFirstContainer() && (pBL->getFirstContainer()->getColumn() == pCol))
431 								{
432 									bLoop = true;
433 									vecCollapse.addItem(pBL);
434 								}
435 								pBL = static_cast<fl_BlockLayout *>(pBL->getNext());
436 							}
437 							else
438 							{
439 								bLoop = false;
440 							}
441 						}
442 						UT_sint32 k = 0;
443 						for(k=0; k<vecCollapse.getItemCount();k++)
444 						{
445 							pBL = vecCollapse.getNthItem(k);
446 							pBL->collapse();
447 							pBL->format();
448 						}
449 						pNextCol = pFirstCol;
450 						fp_Container * pNewFirstCon = static_cast<fp_Container *>(pNextCol->getNthCon(0));
451 						if(!pNewFirstCon)
452 						{
453 							pBL = vecCollapse.getNthItem(0);
454 							pNewFirstCon = static_cast<fp_Container *>(pBL->getFirstRun()->getLine());
455 						}
456 						return pNewFirstCon;
457 					}
458 					else
459 					{
460 						pLine->setWrapped(true);
461 						fp_Line * pPrev = static_cast<fp_Line *>(pLine->getPrev());
462  						if(pPrev && !pLine->isSameYAsPrevious())
463  						{
464  							if(pPrev->getY() == pLine->getY())
465  							{
466  								pLine->setSameYAsPrevious(true);
467  							}
468  						}
469 						if(pLine->isSameYAsPrevious())
470 						{
471 						  //
472 						  // Look for a gap between lines.
473 						  //
474 						  UT_Rect recBetween;
475 						  UT_Rect * pPrevRec = pPrev->getScreenRect();
476 						  UT_Rect * pCurRec = pLine->getScreenRect();
477 						  recBetween.left = pPrevRec->left+pPrevRec->width;
478 						  recBetween.width = pCurRec->left - recBetween.left;
479 						  if(pPrevRec->height != pCurRec->height)
480 						  {
481 						         pLine = pPrev;
482 							 j--;
483 							 bFoundOne = true;
484 						  }
485 						  else
486 						  {
487 						         recBetween.height = pPrevRec->height;
488 							 recBetween.top = pPrevRec->top;
489 							 if(!overlapsWrappedFrame(recBetween))
490 							 {
491 							      UT_DEBUGMSG(("Found a gap! \n"));
492 							      pLine = pPrev;
493 							      j--;
494 							      bFoundOne = true;
495 							 }
496 							 else if(recBetween.width < 60)
497 							 {
498 							      UT_DEBUGMSG(("Found a tiny gap! %d \n",recBetween.width));
499 							      pLine = pPrev;
500 							      j--;
501 							      bFoundOne = true;
502 							 }
503 						  }
504 						  delete pPrevRec;
505 						  delete pCurRec;
506 						}
507 					}
508 					if(bFormatAllWrapped)
509 					{
510 						if(pLine->isWrapped())
511 						{
512 							fl_BlockLayout * pBL = pLine->getBlock();
513 							bool bPrev = false;
514 							UT_sint32 k = 0;
515 							for(k=0; k<vecBL.getItemCount(); k++)
516 							{
517 								_BL * ppBL = vecBL.getNthItem(k);
518 								if(ppBL->m_pBL == pBL)
519 								{
520 									bPrev = true;
521 								}
522 							}
523 							if(!bPrev)
524 							{
525 								_BL * pBLine = new _BL(pBL,pLine);
526 								vecBL.addItem(pBLine);
527 							}
528 							k =j;
529 							while(pLine && pLine->getBlock() == pBL)
530 							{
531 								k++;
532 								if(k >= pCol2->countCons())
533 								{
534 									break;
535 								}
536 								pCon = static_cast<fp_Container *>(pCol2->getNthCon(k));
537 								if(pCon->getContainerType() == FP_CONTAINER_LINE)
538 								{
539 									pLine = static_cast<fp_Line *>(pCon);
540 								}
541 								else
542 								{
543 									break;
544 								}
545 							}
546 							j = k-1;
547 						}
548 					}
549 					else
550 					{
551 //
552 // OK look to see if this line either overlaps a wrapped object or has
553 // some space where a wrapped object should be
554 //
555 						fp_Line * pPrev = static_cast<fp_Line *>(pLine->getPrev());
556 						if(pLine->isWrapped())
557 						{
558 							if(overlapsWrappedFrame(pLine))
559 							{
560 //
561 // Wrapped line overlaps a wrapped frame
562 //
563 								xxx_UT_DEBUGMSG(("Found wrapped line %x that overlaps \n",pLine));
564 								bFoundOne = true;
565 							}
566 							else if(pPrev && pLine->isSameYAsPrevious() && (pPrev->getY() != pLine->getY()))
567 							{
568 								pLine = pPrev;
569 								j--;
570 								bFoundOne = true;
571 							}
572 							else if(m_iCountWrapPasses < 101)
573 							{
574 //
575 // Look to see if the wrapped line has no white space that overlaps
576 // a wrapped object. We don't do this if we've tried more than 100
577 // time to layout the page.
578 //
579 
580 								if(!overlapsWrappedFrame(recLeft) &&
581 								   !overlapsWrappedFrame(recRight))
582 								{
583 									xxx_UT_DEBUGMSG(("Found wrapped line with extra  space %x  \n",pLine));
584 									bFoundOne = true;
585 									if(pPrev && pLine->isSameYAsPrevious())
586 									{
587 									  pLine = pPrev;
588 									  j--;
589 									}
590 								}
591 								else if (pPrev &&  pLine->isSameYAsPrevious())
592 								{
593 								  //
594 								  // Look for a gap between lines.
595 								  //
596 								  UT_Rect recBetween;
597 								  UT_Rect * pPrevRec = pPrev->getScreenRect();
598 								  UT_Rect * pCurRec = pLine->getScreenRect();
599 								  recBetween.left = pPrevRec->left+pPrevRec->width;
600 								  recBetween.width = pCurRec->left - recBetween.left;
601 								  if(pPrevRec->height != pCurRec->height)
602 								  {
603 								    pLine = pPrev;
604 								    j--;
605 								    bFoundOne = true;
606 								  }
607 								  else
608 								  {
609 								    recBetween.height = pPrevRec->height;
610 								    recBetween.top = pPrevRec->top;
611 								    if(!overlapsWrappedFrame(recBetween))
612 								    {
613 								      pLine = pPrev;
614 								      j--;
615 								      bFoundOne = true;
616 								    }
617 								  }
618 								  delete pPrevRec;
619 								  delete pCurRec;
620 								}
621 
622 							}
623 							else
624 							{
625 							  xxx_UT_DEBUGMSG(("Not converging \n"));
626 							}
627 
628 						}
629 						else
630 						{
631 //
632 // line overlaps a wrapped frame
633 //
634 							if(overlapsWrappedFrame(pLine))
635 							{
636 								xxx_UT_DEBUGMSG(("Found unwrapped line %x that overlaps \n",pLine));
637 								bFoundOne = true;
638 							}
639 						}
640 						if(bFoundOne)
641 						{
642 							fl_BlockLayout * pBL = pLine->getBlock();
643 							bool bPrev = false;
644 							UT_sint32 k = 0;
645 							for(k=0; k<vecBL.getItemCount(); k++)
646 							{
647 								_BL * ppBL = vecBL.getNthItem(k);
648 								if(ppBL->m_pBL == pBL)
649 								{
650 									bPrev = true;
651 								}
652 							}
653 							if(!bPrev)
654 							{
655 								_BL * pBLine = new _BL(pBL,pLine);
656 								vecBL.addItem(pBLine);
657 							}
658 							k =j;
659 							while(pLine && pLine->getBlock() == pBL)
660 							{
661 								k++;
662 								if(k >= pCol2->countCons())
663 								{
664 									break;
665 								}
666 								pCon = static_cast<fp_Container *>(pCol2->getNthCon(k));
667 								if(pCon->getContainerType() == FP_CONTAINER_LINE)
668 								{
669 									pLine = static_cast<fp_Line *>(pCon);
670 								}
671 								else
672 								{
673 									break;
674 								}
675 							}
676 							j = k-1;
677 						}
678 					}
679 				}
680 				if(j< 0)
681 				  j = 0;
682 			}
683 			pCol2 = static_cast<fp_Column *>(pCol2->getFollower());
684 		}
685 	}
686 	if(vecBL.getItemCount() == 0)
687 	{
688 		return NULL;
689 	}
690 	_BL * pBLine = vecBL.getNthItem(0);
691 	pFirstBL = pBLine->m_pBL;
692 	for(i=0; i<vecBL.getItemCount(); i++)
693 	{
694 		pBLine = vecBL.getNthItem(i);
695 		xxx_UT_DEBUGMSG((" Doing line %x \n",pBLine->m_pL));
696 #if DEBUG
697 		if(m_iCountWrapPasses > 100)
698 		{
699 			xxx_UT_DEBUGMSG(("Not converging \n"));
700 		}
701 #endif
702 		xxx_UT_DEBUGMSG(("Do regular rebreak \n"));
703 		pBLine->m_pBL->formatWrappedFromHere(pBLine->m_pL,this);
704 	}
705 	UT_VECTOR_PURGEALL(_BL *, vecBL);
706 	fp_Container * pNewFirstCon = NULL;
707 	if(pFirstBL)
708 	{
709 		pNewFirstCon = pFirstBL->getFirstContainer();
710 		pNextCol = static_cast<fp_Column *>(pNewFirstCon->getColumn());
711 	}
712 	else
713 	{
714 		return pNewFirstCon;
715 	}
716 	while(pNewFirstCon && pNewFirstCon->getPage() != NULL && pNewFirstCon->getPage() != this)
717 	{
718 		pNewFirstCon = static_cast<fp_Container *>(pNewFirstCon->getNext());
719 	}
720 	if(pNewFirstCon->getColumn() == NULL)
721 	{
722 	       return NULL;
723 	}
724 	pNextCol = static_cast<fp_Column *>(pNewFirstCon->getColumn());
725 	pNewFirstCon = static_cast<fp_Container *>(pNextCol->getNthCon(0));
726 	if(pNewFirstCon && pNewFirstCon->getContainerType() == FP_CONTAINER_LINE)
727 	{
728 #if DEBUG
729 		fp_Line * pFLine = static_cast<fp_Line *>(pNewFirstCon);
730 		UT_ASSERT(pFLine->getBlock() &&
731 				  (pFLine->getBlock()->findLineInBlock(pFLine) >= 0));
732 	    //	    UT_ASSERT(!pFLine-isEmpty());
733 #endif
734 	}
735 	return pNewFirstCon;
736 }
737 
738 
739 /*!
740  * Returns true if the supplied rectangle overlaps with one wrapped frame
741  * on the page.
742  */
overlapsWrappedFrame(fp_Line * pLine)743 bool fp_Page::overlapsWrappedFrame(fp_Line * pLine)
744 {
745 	UT_Rect * pRec = pLine->getScreenRect();
746 	if(pRec == NULL)
747 	{
748 		return false;
749 	}
750 	bool bRes = overlapsWrappedFrame(*pRec);
751 	delete pRec;
752 	return bRes;
753 }
754 /*!
755  * Returns true if the supplied rectangle overlaps with one wrapped frame
756  * on the page. The rectangle is relative to the screen.
757  */
overlapsWrappedFrame(UT_Rect & rec)758 bool fp_Page::overlapsWrappedFrame(UT_Rect & rec)
759 {
760 	UT_sint32 i=0;
761 	for(i=0; i<static_cast<UT_sint32>(countAboveFrameContainers());i++)
762 	{
763 		fp_FrameContainer * pFC = getNthAboveFrameContainer(i);
764 		if(!pFC->isWrappingSet())
765 		{
766 			continue;
767 		}
768 		if(pFC->overlapsRect(rec))
769 		{
770 		        return true;
771 		}
772 	}
773 	return false;
774 }
775 
776 /*!
777  * This method scans the page for the table that contains the point given
778  */
getContainingTable(PT_DocPosition pos)779 fp_TableContainer * fp_Page::getContainingTable(PT_DocPosition pos)
780 {
781 	if(!m_pView)
782 	{
783 	    return NULL;
784 	}
785 	fp_CellContainer * pCell = m_pView->getCellAtPos(pos);
786 	if(pCell == NULL)
787 	{
788 		return NULL;
789 	}
790 	fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pCell->getContainer());
791 	if(m_pView->isInFrame(pos))
792 	{
793 		return pTab;
794 	}
795 
796 	UT_sint32 i = 0;
797 	UT_sint32 j =0;
798 	bool bFound = false;
799 	fp_Column * pColumn = NULL;
800 	for(i =0; (i <static_cast<UT_sint32>(countColumnLeaders())) && !bFound; i++)
801 	{
802 		pColumn = getNthColumnLeader(i);
803 		while(pColumn)
804 		{
805 			for(j =0; j< pColumn->countCons() && !bFound;j++)
806 			{
807 				fp_Container * pCon = static_cast<fp_Container*>(pColumn->getNthCon(j));
808 				if(pCon->getContainerType() == FP_CONTAINER_TABLE)
809 				{
810 					fp_TableContainer * pCurTab = static_cast<fp_TableContainer *>(pCon);
811 					if(pCurTab->isThisBroken())
812 					{
813 						if(pCurTab->getMasterTable() == pTab)
814 						{
815 							bFound = true;
816 							return pCurTab;
817 						}
818 					}
819 					else
820 					{
821 						if(pCurTab == pTab)
822 						{
823 							bFound = true;
824 							return pCurTab;
825 						}
826 					}
827 				}
828 			}
829 			pColumn = pColumn->getFollower();
830 		}
831 	}
832 	return NULL;
833 }
834 
getAvailableHeight(void) const835 UT_sint32 fp_Page::getAvailableHeight(void) const
836 {
837 	fl_DocSectionLayout * pDSL = getOwningSection();
838 	UT_sint32 avail = getHeight() - pDSL->getTopMargin() - pDSL->getBottomMargin();
839 	UT_sint32 i =0;
840 	for(i=0; i< static_cast<UT_sint32>(countFootnoteContainers()); i++)
841 	{
842 		fp_FootnoteContainer * pFC = getNthFootnoteContainer(i);
843 		avail -= pFC->getHeight();
844 	}
845 	if(getDocLayout()->displayAnnotations())
846 	{
847 			for(i=0; i< static_cast<UT_sint32>(countAnnotationContainers()); i++)
848 			{
849 					fp_AnnotationContainer * pAC = getNthAnnotationContainer(i);
850 					avail -= pAC->getHeight();
851 			}
852 	}
853 	return avail;
854 }
855 
856 /*!
857  * Returns true if there is a column with a page break in it
858  */
containsPageBreak(void) const859 bool fp_Page::containsPageBreak(void) const
860 {
861 	fp_Column * pCol = NULL;
862 	UT_sint32 i = 0;
863 	for(i=0; i<countColumnLeaders();i++)
864 	{
865 		pCol = getNthColumnLeader(0);
866 		while(pCol)
867 		{
868 			if(pCol->containsPageBreak())
869 				return true;
870 			pCol = pCol->getFollower();
871 		}
872 	}
873 	return false;
874 }
875 
876 /*!
877  * Returns the physical page number (the numbering starts from 0)
878  */
getPageNumber(void)879 UT_sint32 fp_Page::getPageNumber(void)
880 {
881 	return m_pLayout->findPage(this);
882 }
883 
884 /*!
885  * Return the page number as indicated in a page number field run.
886  * This value depends on the section properties "section-restart"
887  * and "section-restart-value".
888  */
889 
getFieldPageNumber(void) const890 UT_sint32 fp_Page::getFieldPageNumber(void) const
891 {
892 	return m_iFieldPageNumber;
893 }
894 
setFieldPageNumber(UT_sint32 iPageNum)895 void fp_Page::setFieldPageNumber(UT_sint32 iPageNum)
896 {
897 	m_iFieldPageNumber = iPageNum;
898 }
899 
resetFieldPageNumber(void)900 void fp_Page::resetFieldPageNumber(void)
901 {
902 	fl_DocSectionLayout * pDSL = static_cast<fl_DocSectionLayout *>(getOwningSection());
903 	m_iFieldPageNumber = getPageNumber();
904 	if (m_iFieldPageNumber >= 0)
905 	{
906 		m_iFieldPageNumber++;
907 		while(pDSL && !pDSL->arePageNumbersRestarted())
908 		{
909 			pDSL =  pDSL->getPrevDocSection();
910 		}
911 		if(pDSL && pDSL->arePageNumbersRestarted())
912 		{
913 			fp_Page * pFirstPage = pDSL->getFirstOwnedPage();
914 			if(pFirstPage)
915 			{
916 				UT_sint32 iFirstPage = pFirstPage->getPageNumber();
917 				m_iFieldPageNumber += pDSL->getRestartedPageNumber() - iFirstPage - 1;
918 			}
919 		}
920 	}
921 }
922 
923 /*!
924  * This method returns the height available to the requested column. It
925  * subtracts the height given to previous columns on the page as well as the
926  * height given to footnotes and annotations of these columns.
927 */
getAvailableHeightForColumn(const fp_Column * pColumn) const928 UT_sint32 fp_Page::getAvailableHeightForColumn(const fp_Column * pColumn) const
929 {
930 	fp_Column * pLeader = pColumn->getLeader();
931 	fp_Column * pCurLeader = getNthColumnLeader(0);
932 	fl_DocSectionLayout * pDSL = pCurLeader->getDocSectionLayout();
933 	UT_sint32 avail = getHeight() - pDSL->getTopMargin() - pDSL->getBottomMargin();
934 	if ((countColumnLeaders() == 1) || (pCurLeader == pLeader))
935 	{
936 		return avail;
937 	}
938 
939 	// Case with multiple sections on the page
940 	UT_sint32 i = 0;
941 	xxx_UT_DEBUGMSG(("fp_Page:: Total avail after margins subtracted %d \n",avail));
942 	for(i = 0; i < countColumnLeaders(); i++)
943 	{
944 		pCurLeader = getNthColumnLeader(i);
945 		if (pCurLeader == pLeader)
946 		{
947 			break;
948 		}
949 		UT_sint32 iMostHeight = pCurLeader->getHeight();
950 		fp_Column* pTmpCol = pCurLeader;
951 		while(pTmpCol)
952 		{
953 			iMostHeight = UT_MAX(iMostHeight, pTmpCol->getHeight());
954 			pTmpCol = pTmpCol->getFollower();
955 		}
956 		xxx_UT_DEBUGMSG(("fp_Page: Subtracting height %d from column %d \n",iMostHeight,i));
957 		avail -= iMostHeight;
958 	}
959 	UT_ASSERT(getNthColumnLeader(i) == pLeader);
960 
961 	// Now subtract the footnotes and annotations on the page that are part of previous sections
962 
963 	UT_sint32 iLeader = i;
964 	for(i=0; i< static_cast<UT_sint32>(countFootnoteContainers()); i++)
965 	{
966 		fp_FootnoteContainer * pFC = getNthFootnoteContainer(i);
967 		fl_DocSectionLayout * pDSLFoot = static_cast<fl_FootnoteLayout*>(pFC->getSectionLayout())->getDocSectionLayout();
968 		UT_sint32 k = 0;
969 		for (k = 0; k < iLeader; k++)
970 		{
971 			pCurLeader = getNthColumnLeader(i);
972 			if (pCurLeader == NULL)
973 				continue;
974 			if (pDSLFoot == pCurLeader->getDocSectionLayout())
975 			{
976 				avail -= pFC->getHeight();
977 				break;
978 			}
979 		}
980 	}
981 	if(getDocLayout()->displayAnnotations())
982 	{
983 		for(i=0; i< static_cast<UT_sint32>(countAnnotationContainers()); i++)
984 		{
985 			fp_AnnotationContainer * pAC = getNthAnnotationContainer(i);
986 			fl_DocSectionLayout * pDSLAnn = static_cast<fl_AnnotationLayout*>(pAC->getSectionLayout())->getDocSectionLayout();
987 			UT_sint32 k = 0;
988 			for (k = 0; k < iLeader; k++)
989 			{
990 				if (pDSLAnn == getNthColumnLeader(i)->getDocSectionLayout())
991 				{
992 					avail -= pAC->getHeight();
993 					break;
994 				}
995 			}
996 		}
997 	}
998 
999 	return avail;
1000 }
1001 
1002 /*!
1003  * This method scans the page and returns the total height in layout units of all the columns
1004  * on it.
1005  * If prevLine is non-NULL the maximum column height up to this line is calculated.
1006  */
getFilledHeight(fp_Container * prevContainer) const1007 UT_sint32 fp_Page::getFilledHeight(fp_Container * prevContainer) const
1008 {
1009 	UT_sint32 totalHeight = 0;
1010     UT_sint32 maxHeight = 0;
1011 	fp_Column * pColumn = NULL;
1012 	UT_sint32 i =0;
1013 	fp_Column * prevColumn = NULL;
1014 	bool bstop = false;
1015 	if(prevContainer)
1016 	{
1017 		prevColumn = static_cast<fp_Column *>(prevContainer->getContainer());
1018 	}
1019 	for(i=0; !bstop && (i<  m_vecColumnLeaders.getItemCount()); i++)
1020 	{
1021 		maxHeight = 0;
1022 		pColumn = m_vecColumnLeaders.getNthItem(i);
1023 		totalHeight += pColumn->getDocSectionLayout()->getSpaceAfter();
1024 		while(pColumn != NULL)
1025 		{
1026 			if(prevColumn == pColumn)
1027 			{
1028 				bstop = true;
1029 				fp_Container * pCurContainer = static_cast<fp_Container *>(pColumn->getFirstContainer());
1030 				UT_sint32 curHeight = 0;
1031 				while((pCurContainer != NULL) && (pCurContainer != prevContainer))
1032 				{
1033 					if(pCurContainer->getContainerType() == FP_CONTAINER_TABLE)
1034 					{
1035 						fp_TableContainer * pTC = static_cast<fp_TableContainer *>(pCurContainer);
1036 						curHeight += pTC->getHeight();
1037 					}
1038 					else
1039 					{
1040 						curHeight += pCurContainer->getHeight();
1041 					}
1042 					pCurContainer = static_cast<fp_Container *>(pCurContainer->getNext());
1043 				}
1044 				if(pCurContainer == prevContainer)
1045 				{
1046 					if(pCurContainer->getContainerType() == FP_CONTAINER_TABLE)
1047 					{
1048 						fp_TableContainer * pTC = static_cast<fp_TableContainer *>(pCurContainer);
1049 						curHeight += pTC->getHeight();
1050 					}
1051 					else
1052 					{
1053 						curHeight += pCurContainer->getHeight();
1054 					}
1055 				}
1056 				maxHeight = UT_MAX(curHeight,maxHeight);
1057 			}
1058 			else
1059 			{
1060 				maxHeight = UT_MAX(pColumn->getHeight(),maxHeight);
1061 			}
1062 			pColumn = pColumn->getFollower();
1063 		}
1064 		totalHeight += maxHeight;
1065 	}
1066 	return totalHeight;
1067 }
1068 
1069 
getBottom(void) const1070 UT_sint32 fp_Page::getBottom(void) const
1071 {
1072 	int count = countColumnLeaders();
1073 	if (count <= 0)
1074 	{
1075 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
1076 		return 0;
1077 	}
1078 
1079 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1080 	fl_DocSectionLayout* pFirstSectionLayout = pFirstColumnLeader->getDocSectionLayout();
1081 	UT_ASSERT(m_pOwner == pFirstSectionLayout);
1082 
1083 //	UT_sint32 iTopMargin = pFirstSectionLayout->getTopMargin();
1084 	UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
1085 
1086 	return getHeight() - iBottomMargin;
1087 }
1088 
getScreenOffsets(fp_Container * pContainer,UT_sint32 & xoff,UT_sint32 & yoff) const1089 void fp_Page::getScreenOffsets(fp_Container* pContainer, UT_sint32& xoff, UT_sint32& yoff) const
1090 {
1091 	if(!m_pView)
1092 	{
1093 	    return;
1094 	}
1095 	m_pView->getPageScreenOffsets(this, xoff, yoff);
1096 	if(pContainer)
1097         {
1098 	    xoff += pContainer->getX();
1099 	    yoff += pContainer->getY();
1100 	}
1101 }
1102 
getNext(void) const1103 fp_Page* fp_Page::getNext(void) const
1104 {
1105 	return m_pNext;
1106 }
1107 
getPrev(void) const1108 fp_Page* fp_Page::getPrev(void) const
1109 {
1110 	return m_pPrev;
1111 }
1112 
setNext(fp_Page * p)1113 void fp_Page::setNext(fp_Page* p)
1114 {
1115 	m_pNext = p;
1116 	xxx_UT_DEBUGMSG(("Next PAge set to %x \n",p));
1117 //	UT_ASSERT(0);
1118 }
1119 
setPrev(fp_Page * p)1120 void fp_Page::setPrev(fp_Page* p)
1121 {
1122 	m_pPrev = p;
1123 }
1124 
getDocLayout() const1125 FL_DocLayout* fp_Page::getDocLayout() const
1126 {
1127 	return m_pLayout;
1128 }
1129 
_drawCropMarks(dg_DrawArgs * pDA)1130 void fp_Page::_drawCropMarks(dg_DrawArgs* pDA)
1131 {
1132     if(m_pView->getShowPara()
1133 	   && m_pView->getViewMode() == VIEW_PRINT // only draw the cropmarks if we are in the Print Layout view
1134 	   && pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN)
1135 	   && countColumnLeaders() > 0)
1136 	{
1137 		GR_Painter painter(pDA->pG);
1138 
1139         fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1140         fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1141 		UT_ASSERT(m_pOwner == pFirstSectionLayout);
1142 
1143         UT_sint32 iLeftMargin = pFirstSectionLayout->getLeftMargin();
1144         UT_sint32 iRightMargin = pFirstSectionLayout->getRightMargin();
1145         UT_sint32 iTopMargin = pFirstSectionLayout->getTopMargin();
1146         UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
1147 
1148         UT_sint32 xoffStart = pDA->xoff + iLeftMargin - pDA->pG->tlu(1);
1149         UT_sint32 yoffStart = pDA->yoff + iTopMargin - pDA->pG->tlu(1);
1150         UT_sint32 xoffEnd = pDA->xoff + getWidth() - iRightMargin + pDA->pG->tlu(2);
1151         UT_sint32 yoffEnd = pDA->yoff + getHeight() - iBottomMargin + pDA->pG->tlu(2);
1152 
1153         UT_sint32 iLeftWidth = UT_MIN(iLeftMargin,pDA->pG->tlu(20));
1154         UT_sint32 iRightWidth = UT_MIN(iRightMargin,pDA->pG->tlu(20));
1155         UT_sint32 iTopHeight = UT_MIN(iTopMargin,pDA->pG->tlu(20));
1156         UT_sint32 iBottomHeight = UT_MIN(iBottomMargin,pDA->pG->tlu(20));
1157 
1158         pDA->pG->setColor(getDocLayout()->getView()->getColorShowPara());
1159 
1160 		pDA->pG->setLineProperties(pDA->pG->tluD(1.0),
1161 									 GR_Graphics::JOIN_MITER,
1162 									 GR_Graphics::CAP_PROJECTING,
1163 									 GR_Graphics::LINE_SOLID);
1164 
1165         painter.drawLine(xoffStart, yoffStart, xoffStart, yoffStart - iTopHeight);
1166         painter.drawLine(xoffStart, yoffStart, xoffStart - iLeftWidth, yoffStart);
1167 
1168         painter.drawLine(xoffEnd, yoffStart - iTopHeight, xoffEnd, yoffStart);
1169         painter.drawLine(xoffEnd, yoffStart, xoffEnd + iRightWidth, yoffStart);
1170 
1171         painter.drawLine(xoffStart, yoffEnd, xoffStart, yoffEnd + iBottomHeight);
1172         painter.drawLine(xoffStart - iLeftWidth, yoffEnd, xoffStart, yoffEnd);
1173 
1174         painter.drawLine(xoffEnd, yoffEnd, xoffEnd, yoffEnd + iBottomHeight);
1175         painter.drawLine(xoffEnd, yoffEnd, xoffEnd + iRightWidth, yoffEnd);
1176     }
1177 }
1178 
draw(dg_DrawArgs * pDA,bool)1179 void fp_Page::draw(dg_DrawArgs* pDA, bool /*bAlwaysUseWhiteBackground*/)
1180 {
1181 //
1182 // Fill the Page with the page color
1183 //
1184 // only call this for printing and honour the option to not fill the paper with
1185 // color.
1186 //
1187 	xxx_UT_DEBUGMSG(("Draw wrap passes = %d \n",m_iCountWrapPasses));
1188 	m_iCountWrapPasses = 0;
1189 	int i=0;
1190 	if(!pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN))
1191 	{
1192 		getOwningSection()->getDocLayout()->incrementGraphicTick();
1193 	}
1194 	getOwningSection()->checkGraphicTick(pDA->pG);
1195 	if(!pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN))
1196 	{
1197 		getOwningSection()->getDocLayout()->incrementGraphicTick();
1198 	}
1199 	if(!pDA->bDirtyRunsOnly)
1200 	{
1201 		xxx_UT_DEBUGMSG(("Doing a rectangular color fill \n"));
1202  		UT_sint32 xmin = pDA->xoff;
1203   		UT_sint32 ymin = pDA->yoff;
1204 
1205 		UT_sint32 height =getHeight();
1206 		UT_sint32 width = getWidth();
1207 		UT_sint32 srcX = 0;
1208 		UT_sint32 srcY = 0;
1209 		getFillType().Fill(pDA->pG,srcX,srcY,xmin,ymin,width,height);
1210 	}
1211 
1212     _drawCropMarks(pDA);
1213 
1214 	UT_sint32 count = 0;
1215 
1216 	// draw Below Frames
1217 	count = m_vecBelowFrames.getItemCount();
1218 	for (i=0; i<count; i++)
1219 	{
1220 		fp_FrameContainer* pFC = m_vecBelowFrames.getNthItem(i);
1221 		UT_Rect r(pFC->getX(),pFC->getY(),pFC->getWidth(),pFC->getHeight());
1222 		if(m_rDamageRect.intersectsRect(&r))
1223 		{
1224 			pFC->setOverWrote();
1225 		}
1226 
1227 		dg_DrawArgs da = *pDA;
1228 		da.xoff += pFC->getX();
1229 		da.yoff += pFC->getY();
1230 		pFC->draw(&da);
1231 	}
1232 	//
1233 	// Handle Tight wrapped frames
1234 	//
1235 	count = m_vecAboveFrames.getItemCount();
1236 	for (i=0; i<count; i++)
1237 	{
1238 		fp_FrameContainer* pFC = m_vecAboveFrames.getNthItem(i);
1239 		if(!pFC->isTightWrapped())
1240 			continue;
1241 		UT_Rect r(pFC->getX(),pFC->getY(),pFC->getWidth(),pFC->getHeight());
1242 		if(m_rDamageRect.intersectsRect(&r))
1243 		{
1244 			pFC->setOverWrote();
1245 		}
1246 
1247 		dg_DrawArgs da = *pDA;
1248 		da.xoff += pFC->getX();
1249 		da.yoff += pFC->getY();
1250 		pFC->draw(&da);
1251 	}
1252 
1253 
1254 	// draw each column on the page
1255 	count = m_vecColumnLeaders.getItemCount();
1256 
1257 	GR_Painter painter(pDA->pG);
1258 
1259 	for (i=0; i<count; i++)
1260 	{
1261 		fp_Column* pCol = m_vecColumnLeaders.getNthItem(i);
1262 		while (pCol)
1263 		{
1264 			dg_DrawArgs da = *pDA;
1265 			xxx_UT_DEBUGMSG(("Draw in page page X offset %d \n",pDA->xoff));
1266 			da.xoff += pCol->getX();
1267 			da.yoff += pCol->getY(pDA->pG);
1268 
1269 			xxx_UT_DEBUGMSG(("Draw in page col Y offset %d \n",da.yoff));
1270 			pCol->draw(&da);
1271 
1272 			fp_Column *pNextCol = pCol->getFollower();
1273 
1274 			if(pNextCol && pCol->getDocSectionLayout()->getColumnLineBetween())
1275 			{
1276 				// draw line between columns if required.
1277 
1278 				UT_sint32 x = pDA->xoff + (pCol->getX() + pCol->getWidth() + pNextCol->getX()) / 2;
1279 				UT_sint32 y = pDA->yoff + pCol->getY();
1280 				pDA->pG->setColor(m_pView->getColorColumnLine());
1281 				painter.drawLine(x, y, x, y + pCol->getHeight());
1282 			}
1283 
1284 			pCol = pNextCol;
1285 		}
1286 	}
1287 
1288 	// draw the page's headers and footers
1289     if(m_pView->getViewMode() == VIEW_PRINT  || pDA->pG->queryProperties(GR_Graphics::DGP_PAPER))
1290 	{
1291 		if (m_pHeader)
1292 		{
1293 			dg_DrawArgs da = *pDA;
1294 			da.xoff += m_pHeader->getX();
1295 			da.yoff += m_pHeader->getY();
1296 			m_pHeader->draw(&da);
1297 		}
1298 
1299 		if (m_pFooter)
1300 		{
1301 			dg_DrawArgs da = *pDA;
1302 			da.xoff += m_pFooter->getX();
1303 			da.yoff += m_pFooter->getY();
1304 			m_pFooter->draw(&da);
1305 		}
1306 	}
1307 
1308 	// draw footnotes
1309 	count = m_vecFootnotes.getItemCount();
1310 	for (i=0; i<count; i++)
1311 	{
1312 		fp_FootnoteContainer* pFC = m_vecFootnotes.getNthItem(i);
1313 		dg_DrawArgs da = *pDA;
1314 		if(m_pView && (m_pView->getViewMode() != VIEW_PRINT) &&
1315 		   !pDA->pG->queryProperties(GR_Graphics::DGP_PAPER))
1316 		{
1317 			fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1318 			fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1319 			da.yoff -= pFirstSectionLayout->getTopMargin();
1320 		}
1321 		da.xoff += pFC->getX();
1322 		da.yoff += pFC->getY();
1323 		pFC->draw(&da);
1324 	}
1325 
1326 	// draw annotations
1327 	if(getDocLayout()->displayAnnotations())
1328 	{
1329 			count = m_vecAnnotations.getItemCount();
1330 			for (i=0; i<count; i++)
1331 			{
1332 					fp_AnnotationContainer* pAC = m_vecAnnotations.getNthItem(i);
1333 					dg_DrawArgs da = *pDA;
1334 					if(m_pView && (m_pView->getViewMode() != VIEW_PRINT) &&
1335 					   !pDA->pG->queryProperties(GR_Graphics::DGP_PAPER))
1336 					{
1337 							fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1338 							fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1339 							da.yoff -= pFirstSectionLayout->getTopMargin();
1340 					}
1341 					da.xoff += pAC->getX();
1342 					da.yoff += pAC->getY();
1343 					pAC->draw(&da);
1344 			}
1345 	}
1346 
1347 	// draw Above Frames
1348 	count = m_vecAboveFrames.getItemCount();
1349 	for (i=0; i<count; i++)
1350 	{
1351 		fp_FrameContainer* pFC = m_vecAboveFrames.getNthItem(i);
1352 		if(pFC->isTightWrapped())
1353 			continue;
1354 		UT_Rect r(pFC->getX(),pFC->getY(),pFC->getWidth(),pFC->getHeight());
1355 		if(m_rDamageRect.intersectsRect(&r))
1356 		{
1357 			pFC->setOverWrote();
1358 		}
1359 		dg_DrawArgs da = *pDA;
1360 #if 0
1361 		if(m_pView && (m_pView->getViewMode() != VIEW_PRINT) &&
1362 		   !pDA->pG->queryProperties(GR_Graphics::DGP_PAPER))
1363 		{
1364 			fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1365 			fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1366 			da.yoff -= pFirstSectionLayout->getTopMargin();
1367 		}
1368 #endif
1369 		da.xoff += pFC->getX();
1370 		da.yoff += pFC->getY();
1371 		pFC->draw(&da);
1372 	}
1373 
1374 	m_bNeedsRedraw = false;
1375 	m_rDamageRect.left = 0;
1376 	m_rDamageRect.top = 0;
1377 	m_rDamageRect.width = 0;
1378 	m_rDamageRect.height = 0;
1379 
1380 }
1381 
expandDamageRect(UT_sint32 x,UT_sint32 y,UT_sint32 width,UT_sint32 height)1382 void   fp_Page::expandDamageRect(UT_sint32 x, UT_sint32 y,
1383 										 UT_sint32 width, UT_sint32 height)
1384 {
1385 //
1386 // x and y and in screen offsets turn into page coords
1387 //
1388 	UT_sint32 xoff,yoff;
1389 	m_pView->getPageScreenOffsets(this, xoff, yoff);
1390 	x -= xoff;
1391 	y -= yoff;
1392 
1393 	if(m_rDamageRect.width == 0)
1394 	{
1395 		m_rDamageRect.left = x;
1396 		m_rDamageRect.top=y;
1397 		m_rDamageRect.width = width;
1398 		m_rDamageRect.height = height;
1399 		return;
1400 	}
1401 	UT_Rect r(x,y,width,height);
1402 	m_rDamageRect.unionRect(&r);
1403 	return;
1404 }
1405 
1406 /*!
1407  * Returns true if the objects intersects the damaged region
1408  */
intersectsDamagedRect(fp_ContainerObject * pObj)1409 bool   fp_Page::intersectsDamagedRect(fp_ContainerObject * pObj)
1410 {
1411 	UT_Rect * pRec = pObj->getScreenRect();
1412 	bool bIntersects = m_rDamageRect.intersectsRect(pRec);
1413 	delete pRec;
1414 	return bIntersects;
1415 }
1416 
redrawDamagedFrames(dg_DrawArgs * pDA)1417 void   fp_Page::redrawDamagedFrames(dg_DrawArgs* pDA)
1418 {
1419 	// draw Frames
1420 	UT_sint32 count = m_vecAboveFrames.getItemCount();
1421 	UT_sint32 i = 0;
1422 	for (i=0; i<count; i++)
1423 	{
1424 		fp_FrameContainer* pFC = m_vecAboveFrames.getNthItem(i);
1425 		UT_Rect r(pFC->getX(),pFC->getY(),pFC->getWidth(),pFC->getHeight());
1426 		if(m_rDamageRect.intersectsRect(&r))
1427 		{
1428 			pFC->setOverWrote();
1429 		}
1430 		dg_DrawArgs da = *pDA;
1431 #if 0
1432 		if(m_pView && (m_pView->getViewMode() != VIEW_PRINT) &&
1433 		   !pDA->pG->queryProperties(GR_Graphics::DGP_PAPER))
1434 		{
1435 			fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1436 			fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1437 			da.yoff -= pFirstSectionLayout->getTopMargin();
1438 		}
1439 #endif
1440 		da.xoff += pFC->getX();
1441 		da.yoff += pFC->getY();
1442 		pFC->draw(&da);
1443 	}
1444 
1445 	m_rDamageRect.left = 0;
1446 	m_rDamageRect.top = 0;
1447 	m_rDamageRect.width = 0;
1448 	m_rDamageRect.height = 0;
1449 }
1450 
1451 
1452 
needsRedraw(void) const1453 bool fp_Page::needsRedraw(void) const
1454 {
1455 	return m_bNeedsRedraw;
1456 }
1457 
countColumnLeaders(void) const1458 UT_sint32 fp_Page::countColumnLeaders(void) const
1459 {
1460 	return m_vecColumnLeaders.getItemCount();
1461 }
1462 
getNthColumnLeader(UT_sint32 n) const1463 fp_Column* fp_Page::getNthColumnLeader(UT_sint32 n) const
1464 {
1465 	if(n >= m_vecColumnLeaders.getItemCount())
1466 		return NULL;
1467 	return m_vecColumnLeaders.getNthItem(n);
1468 }
1469 
1470 
getNthColumn(UT_uint32 n,fl_DocSectionLayout * pSection) const1471 fp_Container* fp_Page::getNthColumn(UT_uint32 n,fl_DocSectionLayout *pSection) const
1472 {
1473 	fp_Column *pCol = NULL;
1474 	UT_sint32 j = 0;
1475 	bool b_sectionFound = false;
1476 
1477 	if ((!pSection) || (n > pSection->getNumColumns()))
1478 	{ return NULL;}
1479 	for (j = 0;j < countColumnLeaders();j++)
1480 	{
1481 		pCol = getNthColumnLeader(j);
1482 		if (pCol && (pCol->getDocSectionLayout() == pSection))
1483 		{
1484 			b_sectionFound = true;
1485 			break;
1486 		}
1487 	}
1488 	if (!b_sectionFound)
1489 	{ return NULL;}
1490 
1491 	UT_uint32 k = 0;
1492 	while(pCol && k < n)
1493 	{
1494 		pCol = static_cast <fp_Column *>(pCol->getNext());
1495 		k++;
1496 	}
1497 	return pCol;
1498 
1499 }
1500 
1501 /*!
1502  * This method is called following a notification of an increase in
1503  * HdrFtr size
1504  */
TopBotMarginChanged(void)1505 bool fp_Page::TopBotMarginChanged(void)
1506 {
1507 //
1508 // Adjust header/footer shadows first
1509 //
1510 	UT_sint32 iTopM = m_pOwner->getTopMargin();
1511 	UT_sint32 iBotM = m_pOwner->getBottomMargin();
1512 	clearScreenFrames();
1513 	if(m_pHeader)
1514 	{
1515 		m_pHeader->clearScreen();
1516 		m_pHeader->setMaxHeight(iTopM - m_pOwner->getHeaderMargin());
1517 		m_pHeader->layout();
1518 	}
1519 	if(m_pFooter)
1520 	{
1521 		m_pFooter->clearScreen();
1522 		m_pFooter->setMaxHeight(iBotM - m_pOwner->getFooterMargin());
1523 		m_pFooter->setY(getHeight() - iBotM);
1524 		m_pFooter->layout();
1525 	}
1526 	breakPage();
1527 	_reformat();
1528 	return true;
1529 }
1530 /*!
1531  * This method scans the current page to make sure that there is space to at least start
1532  * every column on the page. Columns with space are deleted and their contents redistributed.
1533  */
breakPage(void)1534 bool fp_Page::breakPage(void)
1535 {
1536 	UT_sint32 count = countColumnLeaders();
1537 	if (count == 0)
1538 	{
1539 		return true;
1540 	}
1541 	UT_sint32 iYPrev = 0;
1542 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1543 	fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1544 	UT_ASSERT(m_pOwner == pFirstSectionLayout);
1545 	UT_sint32 iTopMargin = pFirstSectionLayout->getTopMargin();
1546 	UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
1547 	UT_sint32 iY = iTopMargin;
1548 	UT_sint32 availHeight = getHeight() - iBottomMargin;
1549 
1550 	// we need the height of the footnotes on this page, to deduct.
1551 	UT_sint32 i = 0;
1552 	UT_uint32 iFootnoteHeight = 2*pFirstSectionLayout->getFootnoteLineThickness();
1553 	for (i = 0; i < countFootnoteContainers(); i++)
1554 	{
1555 		iFootnoteHeight += getNthFootnoteContainer(i)->getHeight();
1556 	}
1557 	iY += iFootnoteHeight;
1558 
1559 
1560 	// we need the height of the annotations on this page, to deduct.
1561 	if(getDocLayout()->displayAnnotations())
1562 	{
1563 		    UT_sint32 iAnnotationHeight = 0;
1564 			for (i = 0; i < countAnnotationContainers(); i++)
1565 			{
1566 					iAnnotationHeight += getNthAnnotationContainer(i)->getHeight();
1567 			}
1568 			iY += iAnnotationHeight;
1569 	}
1570 
1571 	for (i=0; i<count; i++)
1572 	{
1573 		fp_Column* pLeader = getNthColumnLeader(i);
1574 		fp_Column* pTmpCol = pLeader;
1575 		UT_sint32 iMostHeight = 0;
1576 		iYPrev = iY;
1577 		while (pTmpCol)
1578 		{
1579 			iMostHeight = UT_MAX(iMostHeight, pTmpCol->getHeight());
1580 			pTmpCol = pTmpCol->getFollower();
1581 		}
1582 
1583 		iY += iMostHeight;
1584 		iY += pLeader->getDocSectionLayout()->getSpaceAfter();
1585 		iY += pLeader->getDocSectionLayout()->getSpaceAfter();
1586 		if (iY >= availHeight)
1587 		{
1588 			break;
1589 		}
1590 	}
1591 	if(i < count)
1592 	{
1593 		i++;
1594 	}
1595 	if(i == count)
1596 	{
1597 //
1598 // Clear out 1 line columns at the bottom of the page. If the row of columns
1599 // at the bottom of the page contains a maxium of one line and if adding an
1600 // extra line makes the column bigger than the page size, remove this column
1601 // from the page.
1602 //
1603 		i--;
1604 		if(i < 1)
1605 		{
1606 			return true;
1607 		}
1608 		fp_Column * pPrev = getNthColumnLeader(i);
1609 		UT_sint32 maxContainers= 0;
1610 		UT_sint32 maxContainerHeight = 0;
1611 		fp_Column * pCol = pPrev;
1612 		if (pCol && pCol->getFirstContainer() &&
1613 			(pCol->getFirstContainer()->getContainerType() == FP_CONTAINER_LINE))
1614 		{
1615 			fp_Line * pLine = static_cast <fp_Line*>(pCol->getFirstContainer());
1616 			if (pLine->getFirstRun() &&
1617 				(pLine->getFirstRun()->getType() == FPRUN_FORCEDPAGEBREAK))
1618 			{
1619 				return true;
1620 			}
1621 		}
1622 
1623 		while(pCol != NULL)
1624 		{
1625 			UT_sint32 countContainers = 0;
1626 			fp_Container * pContainer = static_cast<fp_Container *>(pCol->getFirstContainer());
1627 			while(pContainer != NULL && pContainer != static_cast<fp_Container *>(pCol->getLastContainer()))
1628 			{
1629 				countContainers++;
1630 				if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1631 				{
1632 					fp_TableContainer * pTC = static_cast<fp_TableContainer *>(pContainer);
1633 					maxContainerHeight = UT_MAX(maxContainerHeight,pTC->getHeight());
1634 				}
1635 				else
1636 				{
1637 					maxContainerHeight = UT_MAX(maxContainerHeight,pContainer->getHeight());
1638 				}
1639 				pContainer = static_cast<fp_Container *>(pContainer->getNext());			}
1640 			if(pContainer != NULL)
1641 			{
1642 				if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1643 				{
1644 					fp_TableContainer * pTC = static_cast<fp_TableContainer *>(pContainer);
1645 					maxContainerHeight = UT_MAX(maxContainerHeight,pTC->getHeight());
1646 				}
1647 				else
1648 				{
1649 					maxContainerHeight = UT_MAX(maxContainerHeight,pContainer->getHeight());
1650 				}
1651 				countContainers++;
1652 			}
1653 			maxContainers = UT_MAX(maxContainers,countContainers);
1654 			pCol = pCol->getFollower();
1655 		}
1656 		if(maxContainers > 1)
1657 		{
1658 			return true;
1659 		}
1660 //
1661 //OK this is a candidate to clear off this page. Next test, is the column over
1662 //80% of the way down the page?
1663 //
1664 		double rat = static_cast<double>(iYPrev) / static_cast<double>(availHeight);
1665 		if(rat < 0.80)
1666 			return true;
1667 //
1668 // Finally if iYPrev plus 2* prev line height is greater than or equal to the
1669 // total height, remove the container.
1670 //
1671 		if((iYPrev + 2*maxContainerHeight) < availHeight)
1672 		{
1673 //
1674 // OK we want to delete this column if the docsection of the
1675 // previous column continues onto the next or even subsequent pages.
1676 //
1677 			fp_Page * pPNext = getNext();
1678 			fl_DocSectionLayout * pPrevDSL = getNthColumnLeader(i-1)->getDocSectionLayout();
1679 			if(pPNext== NULL)
1680 			{
1681 				return true;
1682 			}
1683 			if(pPrevDSL == pPrev->getDocSectionLayout())
1684 			{
1685 				return true;
1686 			}
1687 			if(pPNext->countColumnLeaders() == 0)
1688 			{
1689 				return true;
1690 			}
1691 			fp_Column * pCNext = pPNext->getNthColumnLeader(0);
1692 			if(pCNext == NULL)
1693 			{
1694 				return true;
1695 			}
1696 			fl_DocSectionLayout * pNextDSL = pCNext->getDocSectionLayout();
1697 			if(pNextDSL != pPrevDSL)
1698 			{
1699 				return true;
1700 			}
1701 		}
1702 	}
1703 	return false;
1704 }
1705 
1706 #if 0
1707 /*!
1708  * Return true if a column on the page has a docsectionlayout as given.
1709  */
1710 bool fp_Page::isDSLOnPage(fl_DocSectionLayout * pDSLToFind)
1711 {
1712 	int count = countColumnLeaders();
1713 	if (count <= 0)
1714 	{
1715 		return;
1716 	}
1717 	UT_uint32 i = 0;
1718 	for(i=0; i< count)
1719 	{
1720 		fl_DocSectionLayout * pDSL = getNthColumnLeader(i)->getDocSectionLayout();
1721 		if(pDSL ==  pDSLToFind)
1722 		{
1723 			return true;
1724 		}
1725 	}
1726 	return false;
1727 }
1728 
1729 /*!
1730  * Return the column previous to this one
1731  */
1732 fp_Column * fp_Page::getPrevColOnPages(fp_Column * pCol, fp_Page * pPage)
1733 {
1734 	UT_sint32 count = pPage->countColumnLeaders();
1735 	UT_sint32 i=0;
1736 	fp_Column * pFound = NULL;
1737 	for(i=0; i< count: i++)
1738 	{
1739 		pFound = static_cast<fp_Column *>(pPage->getNthColumn(i));
1740 		if(pFound == pCol)
1741 		{
1742 			break;
1743 		}
1744 	}
1745 	if( i == count)
1746 	{
1747 		return NULL;
1748 	}
1749 	if(i>0)
1750 	{
1751 		pFound = pPage->getNthColumn(i-1);
1752 		return pFound;
1753 	}
1754 	else
1755 	{
1756 		fp_Page * pPrev = pPage->getPrev();
1757 		if(pPrev == NULL)
1758 		{
1759 			return NULL;
1760 		}
1761 		count = pPage->countColumnLeaders();
1762 		if(count <1 )
1763 		{
1764 			return NULL;
1765 		}
1766 	    else
1767 		{
1768 			pFound = pPrev->getNthColumn(count-1);
1769 		}
1770 	}
1771 }
1772 #endif
1773 
1774 /*!
1775     This function updates the x-offset of all columns without changing any of their
1776     dimensions (it is used when changing the view mode)
1777  */
updateColumnX()1778 void fp_Page::updateColumnX()
1779 {
1780 	UT_uint32 count = countColumnLeaders();
1781 	if (count == 0)
1782 		return;
1783 
1784 	UT_ASSERT(m_pOwner == getNthColumnLeader(0)->getDocSectionLayout());
1785 
1786 
1787 	UT_sint32 iLeftMargin = 0;
1788 	UT_sint32 iRightMargin = 0;
1789 
1790 	for (UT_uint32 i = 0; i < count; i++)
1791 	{
1792 		fp_Column* pLeader = getNthColumnLeader(i);
1793 		UT_ASSERT(pLeader->getContainerType() == FP_CONTAINER_COLUMN);
1794 		fl_DocSectionLayout* pSL = (pLeader->getDocSectionLayout());
1795 
1796 		if((m_pView->getViewMode() == VIEW_NORMAL || m_pView->getViewMode() == VIEW_WEB) &&
1797 		   !m_pLayout->getGraphics()->queryProperties(GR_Graphics::DGP_PAPER))
1798 		{
1799 			iLeftMargin = m_pView->getNormalModeXOffset();
1800 			iRightMargin = 0;
1801 		}
1802 		else
1803 		{
1804 			iLeftMargin = pSL->getLeftMargin();
1805 			iRightMargin = pSL->getRightMargin();
1806 		}
1807 
1808 		UT_uint32 iSpace = getWidth() - iLeftMargin - iRightMargin;
1809 		pSL->checkAndAdjustColumnGap(iSpace);
1810 
1811 		UT_uint32 iNumColumns = pSL->getNumColumns();
1812 		UT_uint32 iColumnGap = pSL->getColumnGap();
1813 		UT_uint32 iColWidth = (iSpace - ((iNumColumns - 1) * iColumnGap)) / iNumColumns;
1814 
1815 		UT_sint32 iX;
1816 		if(pSL->getColumnOrder())
1817 		{
1818 			iX = getWidth() - iRightMargin - iColWidth;
1819 		}
1820 		else
1821 		{
1822 			iX = iLeftMargin;
1823 		}
1824 
1825 		fp_Column* pTmpCol = pLeader;
1826 
1827 		while (pTmpCol)
1828 		{
1829 			UT_ASSERT(pTmpCol->getContainerType() == FP_CONTAINER_COLUMN);
1830 			pTmpCol->setX(iX);
1831 
1832 			if(pSL->getColumnOrder())
1833 			{
1834 				iX -= (iColWidth + iColumnGap);
1835 			}
1836 			else
1837 			{
1838 				iX += (iColWidth + iColumnGap);
1839 			}
1840 
1841 			pTmpCol = pTmpCol->getFollower();
1842 		}
1843 	}
1844 }
1845 
1846 
_reformat(void)1847 void fp_Page::_reformat(void)
1848 {
1849 	// this is naive, because columns can cause the footnotes
1850 	// to change pages.  But it'll do for now.
1851 	_reformatColumns();
1852 	_reformatFootnotes();
1853 	_reformatAnnotations();
1854 }
1855 
_reformatColumns(void)1856 void fp_Page::_reformatColumns(void)
1857 {
1858 	UT_sint32 count = countColumnLeaders();
1859 	if (count == 0)
1860 		return;
1861 
1862 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
1863 	fp_Column * pLastCol = NULL;
1864 	fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
1865 	UT_ASSERT(m_pOwner == pFirstSectionLayout);
1866 
1867 
1868 	UT_sint32 iLeftMargin = 0;
1869 	UT_sint32 iRightMargin = 0;
1870 	UT_sint32 iLeftMarginReal = 0;
1871 	UT_sint32 iRightMarginReal = 0;
1872 	UT_sint32 iTopMargin = pFirstSectionLayout->getTopMargin();
1873 	UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
1874 	UT_sint32 iY = iTopMargin;
1875 
1876 	// we need the height of the footnotes on this page, to deduct.
1877 	UT_sint32 i = 0;
1878 	UT_uint32 iFootnoteHeight = 2*pFirstSectionLayout->getFootnoteLineThickness();
1879 	for (i = 0; i < countFootnoteContainers(); i++)
1880 	{
1881 		iFootnoteHeight += getNthFootnoteContainer(i)->getHeight();
1882 	}
1883 	UT_uint32 iAnnotationHeight = getAnnotationHeight();
1884 	for (i = 0; i < count; i++)
1885 	{
1886 #if 0
1887 		if (iY >= (static_cast<UT_sint32>(getHeight() - iBottomMargin - iFootnoteHeight -AnnotationHeight)))
1888 		{
1889 			xxx_UT_DEBUGMSG(("SEVIOR: Page incorrectly laid out iYlayoutuints= %d  \n",iY));
1890 //			m_pOwner->markForRebuild();
1891 //
1892 // FIXME see if this code works instead
1893 //
1894 //		m_pOwner->setNeedsSectionBreak(true,getPrev());
1895 			// this triggers in docs with lot of footnotes, not sure why it is here, Tomas
1896 			// UT_ASSERT(0);
1897 			return;
1898 //			break;
1899 		}
1900 #endif
1901 
1902 		fp_Column* pLeader = getNthColumnLeader(i);
1903 		UT_ASSERT(pLeader->getContainerType() == FP_CONTAINER_COLUMN);
1904 		fl_DocSectionLayout* pSL = (pLeader->getDocSectionLayout());
1905 
1906 		if((m_pView->getViewMode() == VIEW_NORMAL || m_pView->getViewMode() == VIEW_WEB) &&
1907 		   !m_pLayout->getGraphics()->queryProperties(GR_Graphics::DGP_PAPER))
1908 		{
1909 			iLeftMargin = m_pView->getNormalModeXOffset();
1910 			iRightMargin = 0;
1911 		}
1912 		else
1913 		{
1914 			iLeftMargin = pSL->getLeftMargin();
1915 			iRightMargin = pSL->getRightMargin();
1916 		}
1917 
1918 		iLeftMarginReal = pSL->getLeftMargin();
1919 		iRightMarginReal = pSL->getRightMargin();
1920 
1921 		UT_uint32 iSpace = getWidth() - iLeftMarginReal - iRightMarginReal;
1922 		pSL->checkAndAdjustColumnGap(iSpace);
1923 
1924 		UT_uint32 iNumColumns = pSL->getNumColumns();
1925 		UT_uint32 iColumnGap = pSL->getColumnGap();
1926 		UT_uint32 iColWidth = (iSpace - ((iNumColumns - 1) * iColumnGap)) / iNumColumns;
1927 
1928 		UT_sint32 iX;
1929 		if(pSL->getColumnOrder())
1930 		{
1931 			iX = getWidth() - iRightMargin - iColWidth;
1932 		}
1933 		else
1934 		{
1935 			iX = iLeftMargin;
1936 		}
1937 
1938 		fp_Column* pTmpCol = pLeader;
1939 		UT_sint32 iMostHeight = 0;
1940 
1941 		while (pTmpCol)
1942 		{
1943 			UT_ASSERT(pTmpCol->getContainerType() == FP_CONTAINER_COLUMN);
1944 			pTmpCol->setX(iX);
1945 			pTmpCol->setY(iY);
1946 			pTmpCol->setMaxHeight(getHeight() - iBottomMargin - iY - iFootnoteHeight - iAnnotationHeight);
1947 			pTmpCol->setWidth(iColWidth);
1948 
1949 			if(pSL->getColumnOrder())
1950 			{
1951 				iX -= (iColWidth + iColumnGap);
1952 			}
1953 			else
1954 			{
1955 				iX += (iColWidth + iColumnGap);
1956 			}
1957 
1958 			iMostHeight = UT_MAX(iMostHeight, pTmpCol->getHeight());
1959 			pLastCol = pTmpCol;
1960 			pTmpCol = pTmpCol->getFollower();
1961 		}
1962 
1963 		iY += iMostHeight;
1964 		iY += pLeader->getDocSectionLayout()->getSpaceAfter();
1965 
1966 	}
1967 //	UT_ASSERT(i == count);
1968 //
1969 // Look for blank space to put more text
1970 //
1971 	fp_Column * pFirstOfNext = NULL;
1972 	fp_Page * pNext = getNext();
1973 	if(pNext && pLastCol)
1974 	{
1975 		fp_Container * pLastContainer = static_cast<fp_Container *>(pLastCol->getLastContainer());
1976 		if(pLastContainer)
1977 		{
1978 			if(pLastContainer->getContainerType() == FP_CONTAINER_LINE
1979 			   && static_cast<fp_Line *>(pLastContainer)->containsForcedPageBreak())
1980 			{
1981 				return;
1982 			}
1983 			pFirstOfNext = pNext->getNthColumnLeader(0);
1984 			if(!pFirstOfNext)
1985 			{
1986 				return;
1987 			}
1988 			fp_Container *pFirstNextContainer = static_cast<fp_Container *>(pFirstOfNext->getFirstContainer());
1989 			if(pFirstNextContainer == NULL)
1990 			{
1991 				return;
1992 			}
1993 			UT_sint32 iYNext = pFirstNextContainer->getHeight();
1994 			bool bIsTable = (pFirstNextContainer->getContainerType() == FP_CONTAINER_TABLE)  || (countFootnoteContainers() > 0) || (pNext->countFootnoteContainers() > 0);
1995 			fl_ContainerLayout * pCNext = static_cast<fl_SectionLayout *>(pFirstNextContainer->getSectionLayout());
1996 			if(pCNext == static_cast<fl_ContainerLayout *>(pLastContainer->getSectionLayout()))
1997 		        {
1998 			  bIsTable = true; // only rebuild if we have a change
1999 			                   // of docsection
2000 			}
2001 			if( !bIsTable && (iY + 3*iYNext) < (getHeight() - getFootnoteHeight() - iBottomMargin))
2002 			{
2003 			  UT_DEBUGMSG(("Extra space on page. Mark for rebuild \n"));
2004 			  //m_pOwner->markForRebuild();
2005 //
2006 // FIXME see if this code works instead
2007 //
2008 //		m_pOwner->setNeedsSectionBreak(true,getPrev());
2009 //		UT_ASSERT(0);
2010 
2011 			}
2012 //
2013 // OK now look to see if there are some endnote that should really be on this
2014 // page
2015 //
2016 #if 0
2017 			UT_sint32 iRemainingSpace = getHeight() - getFootnoteHeight() - iBottomMargin;
2018 			if(pFirstNextContainer  && (pFirstNextContainer->getContainerType() == FP_CONTAINER_ENDNOTE) && (iYNext < iRemainingSpace))
2019 			{
2020 				while(pFirstNextContainer  && (pFirstNextContainer->getContainerType() == FP_CONTAINER_ENDNOTE))
2021 				{
2022 					fl_EndnoteLayout * pECL = static_cast<fl_EndnoteLayout *>(pFirstNextContainer->getSectionLayout());
2023 					pFirstNextContainer = pFirstNextContainer->getNextContainerInSection();
2024 //
2025 // Remove old Container from the next page
2026 //
2027 					pECL->collapse();
2028 				}
2029 			}
2030 #endif
2031 		}
2032 	}
2033 	return;
2034 }
2035 
clearScreenFootnotes(void)2036 void fp_Page::clearScreenFootnotes(void)
2037 {
2038 	UT_sint32 i =0;
2039 	for (i = 0; i < countFootnoteContainers(); i++)
2040 	{
2041 		getNthFootnoteContainer(i)->clearScreen();
2042 	}
2043 }
2044 
getFootnoteHeight(void) const2045 UT_sint32 fp_Page::getFootnoteHeight(void) const
2046 {
2047 	UT_uint32 iFootnoteHeight = 0;
2048 	UT_sint32 i = 0;
2049 	for (i = 0; i < countFootnoteContainers(); i++)
2050 	{
2051 		iFootnoteHeight += getNthFootnoteContainer(i)->getHeight();
2052 	}
2053 	return iFootnoteHeight;
2054 }
2055 
_reformatFootnotes(void)2056 void fp_Page::_reformatFootnotes(void)
2057 {
2058 	if(m_vecColumnLeaders.getItemCount() == 0)
2059 	{
2060 //
2061 // Page is being deleted.
2062 //
2063 		return;
2064 	}
2065 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
2066 	fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
2067 	UT_ASSERT(m_pOwner == pFirstSectionLayout);
2068 	UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
2069 	UT_uint32 pageHeight = getHeight() - iBottomMargin;
2070 	pageHeight -= getAnnotationHeight();
2071 	UT_uint32 iFootnoteHeight = 0;
2072 	UT_sint32 i = 0;
2073 	for (i = 0; i < countFootnoteContainers(); i++)
2074 	{
2075 		iFootnoteHeight += getNthFootnoteContainer(i)->getHeight();
2076 	}
2077 
2078 	pageHeight -= iFootnoteHeight;
2079 	xxx_UT_DEBUGMSG(("got page height %d, footnote height %d\n", pageHeight, iFootnoteHeight));
2080 	for (i = 0; i < countFootnoteContainers(); i++)
2081 	{
2082 		fp_FootnoteContainer * pFC = getNthFootnoteContainer(i);
2083 		fl_DocSectionLayout* pSL = (getNthColumnLeader(0)->getDocSectionLayout());
2084 
2085 		if((m_pView->getViewMode() == VIEW_NORMAL || m_pView->getViewMode() == VIEW_WEB) &&
2086 		   !m_pLayout->getGraphics()->queryProperties(GR_Graphics::DGP_PAPER))
2087 			pFC->setX(m_pView->getTabToggleAreaWidth());
2088 		else
2089 			pFC->setX(pSL->getLeftMargin());
2090 
2091 		pFC->setY(pageHeight);
2092 		pageHeight += getNthFootnoteContainer(i)->getHeight();
2093 	}
2094 }
2095 
2096 ///////////////////////////////////////////////////////////////////////////////
2097 // Annotations
2098 //////////////////////////////////////////////////////////////////////////////
2099 
clearScreenAnnotations(void)2100 void fp_Page::clearScreenAnnotations(void)
2101 {
2102 	UT_sint32 i =0;
2103 	for (i = 0; i < countAnnotationContainers(); i++)
2104 	{
2105 		getNthAnnotationContainer(i)->clearScreen();
2106 	}
2107 }
2108 
getAnnotationHeight(void) const2109 UT_sint32 fp_Page::getAnnotationHeight(void) const
2110 {
2111 	if(!getDocLayout()->displayAnnotations())
2112 	{
2113 			return 0;
2114 	}
2115 	UT_uint32 iAnnotationHeight = 0;
2116 	UT_sint32 i = 0;
2117 	for (i = 0; i < countAnnotationContainers(); i++)
2118 	{
2119 		iAnnotationHeight += getNthAnnotationContainer(i)->getHeight();
2120 	}
2121 	return iAnnotationHeight;
2122 }
2123 
_reformatAnnotations(void)2124 void fp_Page::_reformatAnnotations(void)
2125 {
2126 	if(m_vecColumnLeaders.getItemCount() == 0)
2127 	{
2128 //
2129 // Page is being deleted.
2130 //
2131 		return;
2132 	}
2133 	if(!getDocLayout()->displayAnnotations())
2134 		return;
2135 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
2136 	fl_DocSectionLayout* pFirstSectionLayout = (pFirstColumnLeader->getDocSectionLayout());
2137 	UT_ASSERT(m_pOwner == pFirstSectionLayout);
2138 	UT_sint32 iBottomMargin = pFirstSectionLayout->getBottomMargin();
2139 	UT_uint32 pageHeight = getHeight() - iBottomMargin;
2140 	UT_uint32 iAnnotationHeight = 0;
2141 	UT_sint32 i = 0;
2142 	for (i = 0; i < countAnnotationContainers(); i++)
2143 	{
2144 		iAnnotationHeight += getNthAnnotationContainer(i)->getHeight();
2145 	}
2146 
2147 	pageHeight -= iAnnotationHeight;
2148 	xxx_UT_DEBUGMSG(("got page height %d, footnote height %d\n", pageHeight, iAnnotationHeight));
2149 	for (i = 0; i < countAnnotationContainers(); i++)
2150 	{
2151 		fp_AnnotationContainer * pAC = getNthAnnotationContainer(i);
2152 		fl_DocSectionLayout* pSL = (getNthColumnLeader(0)->getDocSectionLayout());
2153 
2154 		if((m_pView->getViewMode() == VIEW_NORMAL || m_pView->getViewMode() == VIEW_WEB) &&
2155 		   !m_pLayout->getGraphics()->queryProperties(GR_Graphics::DGP_PAPER))
2156 			pAC->setX(m_pView->getTabToggleAreaWidth());
2157 		else
2158 			pAC->setX(pSL->getLeftMargin());
2159 
2160 		pAC->setY(pageHeight);
2161 		pageHeight += getNthAnnotationContainer(i)->getHeight();
2162 	}
2163 }
2164 
2165 /*!
2166   Remove column leader from page
2167   \param pLeader Leader to remove
2168 
2169   This will set the page of all columns in the row to NULL
2170 */
removeColumnLeader(fp_Column * pLeader)2171 void fp_Page::removeColumnLeader(fp_Column* pLeader)
2172 {
2173 	UT_sint32 ndx = m_vecColumnLeaders.findItem(pLeader);
2174 	UT_ASSERT(ndx >= 0);
2175 
2176 	// Delete leader from list
2177 	m_vecColumnLeaders.deleteNthItem(ndx);
2178 
2179 	// Urgh! Changes to the document (logical content) cause graphics
2180 	// updates at various times when the physical representation is
2181 	// still in flux, resulting in both crap performance and code to
2182 	// break due to broken assumptions.  This is a point in case where
2183 	// the current page may get asked to render even though it
2184 	// actually doesn't contain any columns (see bug 1385). So we have
2185 	// to leave the pointer here, even if the page doesn't actually
2186 	// have an owner at this time...
2187 #if 0
2188 	// Deassociate this page from the old owner
2189 	m_pOwner->deleteOwnedPage(this);
2190 	m_pOwner = NULL;
2191 #endif
2192 
2193 	// The row of columns are not on this page anymore
2194 	fp_Column* pTmpCol = pLeader;
2195 	while (pTmpCol)
2196 	{
2197 		pTmpCol->setPage(NULL);
2198 		pTmpCol = pTmpCol->getFollower();
2199 	}
2200 
2201 	// Are there still any rows on this page?
2202 	int count = countColumnLeaders();
2203 	if (0 == count)
2204 	{
2205 		return;
2206 	}
2207 	// Update owner and reformat
2208 	fp_Column* pFirstColumnLeader = getNthColumnLeader(0);
2209 //
2210 // Handle change of Page ownership. This can happen when the the previous
2211 // Section expands it's text onto a page owned by the next docsection.
2212 //
2213 // An alternative is to destroy and recreate the page but this will be much nicer
2214 // if it can be made to work.
2215 //
2216 	if(pFirstColumnLeader->getDocSectionLayout() != m_pOwner)
2217 	{
2218 //
2219 // Change ownership of the page. First remove this page from the set owned by
2220 // the old docSectionLayout.
2221 //
2222 		UT_DEBUGMSG(("fp_Page: Remove page %p from DSL %p \n",this,m_pOwner));
2223 		m_pOwner->deleteOwnedPage(this,false);
2224 		fl_DocSectionLayout * pDSLNew = pFirstColumnLeader->getDocSectionLayout();
2225 //
2226 // Now add it to the new DSL.
2227 //
2228 		pDSLNew->addOwnedPage(this);
2229 		m_pOwner = pDSLNew;
2230 	}
2231 	_reformatColumns();
2232 }
2233 
2234 /*!
2235   Insert column leader on page
2236   \param pLeader Leader to insert
2237   \param pAfter The leader to insert after or NULL
2238   \return True
2239 
2240   This will set the page of all columns in the row to this page.
2241 */
insertColumnLeader(fp_Column * pLeader,fp_Column * pAfter)2242 bool fp_Page::insertColumnLeader(fp_Column* pLeader, fp_Column* pAfter)
2243 {
2244 	UT_ASSERT(pLeader);
2245 	if (pAfter)
2246 	{
2247 		UT_sint32 ndx = m_vecColumnLeaders.findItem(pAfter);
2248 		UT_ASSERT(ndx >= 0);
2249 		m_vecColumnLeaders.insertItemAt(pLeader, ndx+1);
2250 	}
2251 	else
2252 	{
2253 		m_vecColumnLeaders.insertItemAt(pLeader, 0);
2254 
2255 		// Update owner and reformat
2256 
2257 //
2258 // Handle change of Page ownership. This can happen when the the previous
2259 // Section expands it's text onto a page owned by the next docsection.
2260 //
2261 // An alternative is to destroy and recreate the page but this will be much nicer
2262 // if it can be made to work.
2263 //
2264 		if(pLeader->getDocSectionLayout() != m_pOwner)
2265 		{
2266 //
2267 // Change ownership of the page. First remove this page from the set owned by
2268 // the old docSectionLayout.
2269 //
2270 			xxx_UT_DEBUGMSG(("SEVIOR: Deleting owned Page from Page \n"));
2271 			if(m_pOwner)
2272 				m_pOwner->deleteOwnedPage(this,false);
2273 			fl_DocSectionLayout * pDSLNew = pLeader->getDocSectionLayout();
2274 //
2275 // Now add it to the new DSL.
2276 //
2277 			pDSLNew->addOwnedPage(this);
2278 			m_pOwner = pDSLNew;
2279 		}
2280 	}
2281 
2282 	fp_Column* pTmpCol = pLeader;
2283 	while (pTmpCol)
2284 	{
2285 		pTmpCol->setPage(this);
2286 
2287 		pTmpCol = pTmpCol->getFollower();
2288 	}
2289 
2290 	_reformat();
2291 
2292 	return true;
2293 }
2294 
2295 
footnoteHeightChanged(void)2296 void fp_Page::footnoteHeightChanged(void)
2297 {
2298 	clearScreenFootnotes();
2299 	m_pOwner->setNeedsSectionBreak(true,getPrev());
2300 	if(breakPage())
2301 	{
2302 		_reformat();
2303 	}
2304 	else
2305 	{
2306 		UT_DEBUGMSG(("SEVIOR: Mark for rebuild from footnoteheight changed. \n"));
2307 		m_pOwner->markForRebuild();
2308 //
2309 // FIXME see if this code works instead
2310 //
2311 //		m_pOwner->setNeedsSectionBreak(true,getPrev());
2312 		UT_ASSERT(0);
2313 	}
2314 }
2315 
2316 
2317 
annotationHeightChanged(void)2318 void fp_Page::annotationHeightChanged(void)
2319 {
2320 	clearScreenAnnotations();
2321 	m_pOwner->setNeedsSectionBreak(true,getPrev());
2322 	if(breakPage())
2323 	{
2324 		_reformat();
2325 	}
2326 	else
2327 	{
2328 		UT_DEBUGMSG(("SEVIOR: Mark for rebuild from annotationheight changed. \n"));
2329 		m_pOwner->markForRebuild();
2330 //
2331 // FIXME see if this code works instead
2332 //
2333 //		m_pOwner->setNeedsSectionBreak(true,getPrev());
2334 		UT_ASSERT(0);
2335 	}
2336 }
2337 
columnHeightChanged(fp_Column * pCol)2338 void fp_Page::columnHeightChanged(fp_Column* pCol)
2339 {
2340 	xxx_UT_DEBUGMSG(("SEVIOR: Column height changed \n"));
2341 	UT_UNUSED(pCol);
2342 	UT_ASSERT(m_vecColumnLeaders.findItem(pCol->getLeader()) >= 0);
2343 	if(breakPage())
2344 	{
2345 		_reformat();
2346 	}
2347 	else
2348 	{
2349 		xxx_UT_DEBUGMSG(("SEVIOR: Mark for rebuild from columnheight changed. \n"));
2350 		m_pOwner->markForRebuild();
2351 //
2352 // FIXME see if this code works instead
2353 //
2354 //		m_pOwner->setNeedsSectionBreak(true,getPrev());
2355 		UT_ASSERT(0);
2356 	}
2357 }
2358 
getFirstLastPos(bool bFirst) const2359 PT_DocPosition fp_Page::getFirstLastPos(bool bFirst) const
2360 {
2361 	PT_DocPosition pos;
2362 
2363 	UT_sint32 cols = countColumnLeaders();
2364 	UT_ASSERT(cols>0);
2365 
2366 	if (bFirst)
2367 	{
2368 		fp_Column* pColumn = getNthColumnLeader(0);
2369 		UT_return_val_if_fail(pColumn, 2);
2370 		fp_Container* pFirstContainer = static_cast<fp_Container *>(pColumn->getFirstContainer());
2371 		while(pFirstContainer && pFirstContainer->getContainerType() != FP_CONTAINER_LINE)
2372 		{
2373 			if(pFirstContainer->getContainerType() == FP_CONTAINER_TABLE)
2374 			{
2375 				fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pFirstContainer);
2376 				pFirstContainer = static_cast<fp_Container *>(pTab->getFirstLineInColumn(pColumn));
2377 			}
2378 			else
2379 			{
2380 				pFirstContainer = static_cast<fp_Container *>(pFirstContainer->getNthCon(0));
2381 			}
2382 		}
2383 
2384 		UT_return_val_if_fail(pFirstContainer, 2);
2385 
2386 		fp_Run* pFirstRun = static_cast<fp_Line *>(pFirstContainer)->getFirstRun();
2387 		fl_BlockLayout* pFirstBlock = static_cast<fp_Line *>(pFirstContainer)->getBlock(); // SEVIOR This needs fix me, FIXME
2388 
2389 		pos = pFirstRun->getBlockOffset() + pFirstBlock->getPosition();
2390 	}
2391 	else
2392 	{
2393 		fp_Column* pColumn = getNthColumnLeader(cols-1);
2394 		UT_return_val_if_fail(pColumn, 2);
2395 		fp_Container* pLastContainer = static_cast<fp_Container *>(pColumn->getLastContainer());
2396 		UT_return_val_if_fail(pLastContainer, 2);
2397 		while(pLastContainer && pLastContainer->getContainerType() != FP_CONTAINER_LINE)
2398 		{
2399 			if(pLastContainer->getContainerType() == FP_CONTAINER_TABLE)
2400 			{
2401 				fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pLastContainer);
2402 				pLastContainer = static_cast<fp_Container *>(pTab->getLastLineInColumn(pColumn));
2403 			}
2404 			else
2405 			{
2406 				pLastContainer = static_cast<fp_Container *>(pLastContainer->getNthCon(0));
2407 			}
2408 		}
2409 
2410 		UT_return_val_if_fail(pLastContainer, 2);
2411 
2412 		fp_Run* pLastRun = static_cast<fp_Line *>(pLastContainer)->getLastRun();
2413 		fl_BlockLayout* pLastBlock = static_cast<fp_Line *>(pLastContainer)->getBlock();
2414 		UT_return_val_if_fail(pLastRun && pLastBlock, 2);
2415 
2416 		while (pLastRun && !pLastRun->isFirstRunOnLine() && pLastRun->isForcedBreak())
2417 		{
2418 			pLastRun = pLastRun->getPrevRun();
2419 		}
2420 		UT_return_val_if_fail(pLastRun, 2);
2421 
2422 		if(pLastRun->isForcedBreak())
2423 		{
2424 			pos = pLastBlock->getPosition() + pLastRun->getBlockOffset();
2425 		}
2426 		else
2427 		{
2428 			pos = pLastBlock->getPosition() + pLastRun->getBlockOffset() + pLastRun->getLength();
2429 		}
2430 	}
2431 
2432 	return pos;
2433 }
2434 
mapXYToPosition(UT_sint32 x,UT_sint32 y,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool & isTOC,bool bUseHdrFtr,fl_HdrFtrShadow ** pShadow) const2435 void fp_Page::mapXYToPosition(UT_sint32 x, UT_sint32 y, PT_DocPosition& pos, bool& bBOL, bool& bEOL,bool &isTOC, bool bUseHdrFtr, fl_HdrFtrShadow ** pShadow ) const
2436 {
2437 	fl_HdrFtrShadow * pShad = NULL;
2438 	if(pShadow == NULL)
2439 	{
2440 		mapXYToPosition(false,x,y,pos,bBOL,bEOL,isTOC, bUseHdrFtr, NULL);
2441 		return;
2442 	}
2443 	else
2444 	{
2445 		mapXYToPosition(false,x,y,pos,bBOL,bEOL,isTOC, bUseHdrFtr, &pShad);
2446 	}
2447 	*pShadow = pShad;
2448 }
2449 /*!
2450  * This method maps an x,y location on the page to the position in the
2451  * document of the corrsponding element.
2452  * This variation looks in the header/footer region and returns the
2453  * SectionLayout shadow of the
2454  \param bNotFrames if true don't look inside frames
2455  \param x coordinate
2456  \param y coordinate
2457  \param bBOL
2458  \param bEOL
2459  \return pos The Document position corresponding the text at location x,y
2460  \return pShadow A pointer to the shadow corresponding to this header/footer
2461  */
mapXYToPosition(bool bNotFrames,UT_sint32 x,UT_sint32 y,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool & isTOC,bool bUseHdrFtr,fl_HdrFtrShadow ** pShadow) const2462 void fp_Page::mapXYToPosition(bool bNotFrames,UT_sint32 x, UT_sint32 y, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool &isTOC, bool bUseHdrFtr, fl_HdrFtrShadow ** pShadow ) const
2463 {
2464 	UT_sint32 count = m_vecColumnLeaders.getItemCount();
2465 	UT_uint32 iMinDist = 0xffffffff;
2466 	fp_VerticalContainer * pMinDist = NULL;
2467 	fp_Column* pColumn = NULL;
2468 	UT_uint32 iMinXDist = 0xffffffff;
2469 	fp_VerticalContainer* pMinXDist = NULL;
2470 	UT_uint32 iDist = 0;
2471 	fp_Column* pLeader = NULL;
2472 //
2473 // Start by looking in Frames for this point.
2474 //
2475 	UT_sint32 i =0;
2476 	fp_FrameContainer * pFrameC = NULL;
2477 	if(!bNotFrames)
2478 	{
2479 //
2480 // The iextra distance gives the space around the text box frame inside the
2481 // frame where the user can select the frame rather than the text inside the
2482 // frame. Without this distance clicking inside a text box would always place
2483 // the caret in text rather than selecting the frame to drag/resize etc.
2484 //
2485 		UT_sint32 iextra = m_pLayout->getGraphics()->tlu(4);
2486 		// loop from high z to low z
2487 		// Because we draw from old to new, the new appears on top
2488 		// and because the new appears on top, it should be treated as such
2489 		for (i = (countAboveFrameContainers()-1); i>=0; i--)
2490 		{
2491 			pFrameC = getNthAboveFrameContainer(i);
2492 			bool isImage = false;
2493 			fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pFrameC->getSectionLayout());
2494 			if(pFL->getFrameType() >= FL_FRAME_WRAPPER_IMAGE)
2495 			{
2496 				isImage = true;
2497 			}
2498 			if ((pFrameC->getFirstContainer()) || isImage )
2499 			{
2500 				if ((x >= (pFrameC->getFullX()- iextra))
2501 					&& (x < (pFrameC->getFullX() + pFrameC->getFullWidth()+iextra))
2502 					&& (y >= (pFrameC->getFullY() - iextra))
2503 					&& (y < (pFrameC->getFullY() + pFrameC->getFullHeight() + iextra))
2504 					)
2505 				{
2506 					if(isImage)
2507 					{
2508 						pos = pFL->getPosition(true);
2509 						return;
2510 					}
2511 					pFrameC->mapXYToPosition(x - pFrameC->getX(), y - pFrameC->getY(), pos, bBOL, bEOL,isTOC);
2512 					return;
2513 				}
2514 
2515 				iDist = pFrameC->distanceFromPoint(x, y);
2516 //
2517 // The tlu(3) makes the distance of the mouse to the sensitive edge of the
2518 // text box 3 pixels. ie Move the mouse within 3 pixels of the textbox and it
2519 // change to show you can select the text box.
2520 //
2521 // If we're outside this distance make sure all other options are excluded
2522 // before placing the point inside the text box
2523 //
2524 
2525 				if(static_cast<UT_sint32>(iDist) > m_pLayout->getGraphics()->tlu(3))
2526 				{
2527 					iDist += 200000;
2528 				}
2529 				if (iDist < iMinDist)
2530 				{
2531 					iMinDist = iDist;
2532 					pMinDist = static_cast<fp_VerticalContainer *>(pFrameC);
2533 				}
2534 
2535 				if ( (y >= pFrameC->getY())
2536 					 && (y < (pFrameC->getY() + pFrameC->getHeight())))
2537 				{
2538 					if (iDist < iMinXDist)
2539 					{
2540 						iMinXDist = iDist;
2541 						pMinXDist = static_cast<fp_VerticalContainer *>(pFrameC);
2542 					}
2543 				}
2544 			}
2545 		}
2546 		for (i = countBelowFrameContainers()-1; i>=0; i--)
2547 		{
2548 			pFrameC = getNthBelowFrameContainer(i);
2549 			bool isImage = false;
2550 			fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pFrameC->getSectionLayout());
2551 			if(pFL->getFrameType() >= FL_FRAME_WRAPPER_IMAGE)
2552 			{
2553 				isImage = true;
2554 			}
2555 			if ((pFrameC->getFirstContainer()) || isImage )
2556 			{
2557 				if ((x >= (pFrameC->getFullX()- iextra))
2558 					&& (x < (pFrameC->getFullX() + pFrameC->getFullWidth()+iextra))
2559 					&& (y >= (pFrameC->getFullY() - iextra))
2560 					&& (y < (pFrameC->getFullY() + pFrameC->getFullHeight() + iextra))
2561 					)
2562 				{
2563 					if(isImage)
2564 					{
2565 						pos = pFL->getPosition(true);
2566 						return;
2567 					}
2568 					pFrameC->mapXYToPosition(x - pFrameC->getX(), y - pFrameC->getY(), pos, bBOL, bEOL,isTOC);
2569 					return;
2570 				}
2571 
2572 				iDist = pFrameC->distanceFromPoint(x, y);
2573 //
2574 // The tlu(3) makes the distance of the mouse to the sensitive edge of the
2575 // text box 3 pixels. ie Move the mouse within 3 pixels of the textbox and it
2576 // change to show you can select the text box.
2577 //
2578 // If we're outside this distance make sure all other options are excluded
2579 // before placing hte point inside th text box
2580 //
2581 
2582 				if(static_cast<UT_sint32>(iDist) > m_pLayout->getGraphics()->tlu(3))
2583 				{
2584 					iDist += 200000;
2585 				}
2586 				if (iDist < iMinDist)
2587 				{
2588 					iMinDist = iDist;
2589 					pMinDist = static_cast<fp_VerticalContainer *>(pFrameC);
2590 				}
2591 
2592 				if ( (y >= pFrameC->getY())
2593 					 && (y < (pFrameC->getY() + pFrameC->getHeight())))
2594 				{
2595 					if (iDist < iMinXDist)
2596 					{
2597 						iMinXDist = iDist;
2598 						pMinXDist = static_cast<fp_VerticalContainer *>(pFrameC);
2599 					}
2600 				}
2601 			}
2602 		}
2603 
2604 	}
2605 //
2606 // Look in header for insertion point
2607 //
2608 	if (bUseHdrFtr)
2609 	{
2610 		if (pShadow)
2611 			*pShadow = NULL;
2612 		if(m_pView && m_pView->getViewMode() == VIEW_PRINT)
2613 		{
2614 			fp_ShadowContainer * hf[2] = { m_pHeader, m_pFooter };
2615 			for (UT_uint32 j = 0; j < G_N_ELEMENTS(hf); j++)
2616 			{
2617 				fp_ShadowContainer * p = hf[j];
2618 
2619 				if(p == NULL || !p->getFirstContainer())
2620 					continue;
2621 
2622 				if ((y >= p->getY()) && (y < (p->getY() + p->getHeight())))
2623 				{
2624 					p->mapXYToPosition(x - p->getX(), y - p->getY(), pos, bBOL, bEOL,isTOC);
2625 					if (pShadow)
2626 						*pShadow = p->getShadow();
2627 					return;
2628 				}
2629 			}
2630 		}
2631 	}
2632 
2633 //
2634 // Now look in page
2635 //
2636 	for (i=0; i<count; i++)
2637 	{
2638 		pLeader = m_vecColumnLeaders.getNthItem(i);
2639 
2640 		pColumn = pLeader;
2641 		iMinXDist = 0xffffffff;
2642 		pMinXDist = NULL;
2643 		while (pColumn)
2644 		{
2645 			if (pColumn->getFirstContainer())
2646 			{
2647 				if (
2648 					(x >= pColumn->getX())
2649 					&& (x < (pColumn->getX() + pColumn->getWidth()))
2650 					&& (y >= pColumn->getY())
2651 					&& (y < (pColumn->getY() + pColumn->getHeight()))
2652 					)
2653 				{
2654 					pColumn->mapXYToPosition(x - pColumn->getX(), y - pColumn->getY(), pos, bBOL, bEOL,isTOC);
2655 					return;
2656 				}
2657 
2658 				iDist = pColumn->distanceFromPoint(x, y);
2659 				if (iDist < iMinDist)
2660 				{
2661 					iMinDist = iDist;
2662 					pMinDist = static_cast<fp_VerticalContainer *>(pColumn);
2663 				}
2664 
2665 				if (
2666 					(y >= pColumn->getY())
2667 					&& (y < (pColumn->getY() + pColumn->getHeight()))
2668 					)
2669 				{
2670 					if (iDist < iMinXDist)
2671 					{
2672 						iMinXDist = iDist;
2673 						pMinXDist = static_cast<fp_VerticalContainer *>(pColumn);
2674 					}
2675 				}
2676 			}
2677 
2678 			pColumn = pColumn->getFollower();
2679 		}
2680 	}
2681 
2682 //
2683 // Now look in footnotes
2684 //
2685 	fp_FootnoteContainer * pFC = NULL;
2686 	for (i=0; i<static_cast<UT_sint32>(countFootnoteContainers()); i++)
2687 	{
2688 		pFC = getNthFootnoteContainer(i);
2689 		if (pFC->getFirstContainer())
2690 		{
2691 			if ((x >= pFC->getX())
2692 				&& (x < (pFC->getX() + pFC->getWidth()))
2693 				&& (y >= pFC->getY())
2694 				&& (y < (pFC->getY() + pFC->getHeight()))
2695 				)
2696 			{
2697 				pFC->mapXYToPosition(x - pFC->getX(), y - pFC->getY(), pos, bBOL, bEOL,isTOC);
2698 					return;
2699 			}
2700 
2701 			iDist = pFC->distanceFromPoint(x, y);
2702 			if (iDist < iMinDist)
2703 			{
2704 				iMinDist = iDist;
2705 				pMinDist = static_cast<fp_VerticalContainer *>(pFC);
2706 			}
2707 
2708 			if ( (y >= pFC->getY())
2709 				 && (y < (pFC->getY() + pFC->getHeight())))
2710 			{
2711 				if (iDist < iMinXDist)
2712 				{
2713 					iMinXDist = iDist;
2714 					pMinXDist = static_cast<fp_VerticalContainer *>(pFC);
2715 				}
2716 			}
2717 		}
2718 	}
2719 
2720 //
2721 // Now look in annotations
2722 //
2723 	if(getDocLayout()->displayAnnotations())
2724 	{
2725 			fp_AnnotationContainer * pAC = NULL;
2726 			for (i=0; i<static_cast<UT_sint32>(countAnnotationContainers()); i++)
2727 			{
2728 					pAC = getNthAnnotationContainer(i);
2729 					if (pAC->getFirstContainer())
2730 					{
2731 							if ((x >= pAC->getX())
2732 								&& (x < (pAC->getX() + pAC->getWidth()))
2733 								&& (y >= pAC->getY())
2734 								&& (y < (pAC->getY() + pAC->getHeight()))
2735 								)
2736 						    {
2737 									pAC->mapXYToPosition(x - pAC->getX(), y - pAC->getY(), pos, bBOL, bEOL,isTOC);
2738 									return;
2739 							}
2740 
2741 							iDist = pAC->distanceFromPoint(x, y);
2742 							if (iDist < iMinDist)
2743 							{
2744 									iMinDist = iDist;
2745 									pMinDist = static_cast<fp_VerticalContainer *>(pAC);
2746 							}
2747 
2748 							if ( (y >= pAC->getY())
2749 								 && (y < (pAC->getY() + pAC->getHeight())))
2750 							{
2751 									if (iDist < iMinXDist)
2752 									{
2753 											iMinXDist = iDist;
2754 											pMinXDist = static_cast<fp_VerticalContainer *>(pAC);
2755 									}
2756 							}
2757 					}
2758 			}
2759 	}
2760 
2761 
2762 
2763 	if (pMinXDist)
2764 	{
2765 		pMinXDist->mapXYToPosition(x - pMinXDist->getX(), y - pMinXDist->getY(), pos, bBOL, bEOL,isTOC);
2766 		return;
2767 	}
2768 
2769 	UT_ASSERT(pMinDist);
2770 
2771 	if (pMinDist)
2772 	{
2773 		pMinDist->mapXYToPosition(x - pMinDist->getX(), y - pMinDist->getY(), pos, bBOL, bEOL,isTOC);
2774 	}
2775 }
2776 
setView(FV_View * pView)2777 void fp_Page::setView(FV_View* pView)
2778 {
2779 	m_pView = pView;
2780 }
2781 
getPageSize(void) const2782 const fp_PageSize&	fp_Page::getPageSize(void) const
2783 {
2784 	return m_pageSize;
2785 }
2786 
2787 // ---------------------------------------------------------------------
2788 // The rest of the functions in this file deal with page headers &
2789 // footers.
2790 
removeHdrFtr(HdrFtrType hfType)2791 void fp_Page::removeHdrFtr(HdrFtrType hfType)
2792 {
2793 	UT_ASSERT(hfType >= FL_HDRFTR_HEADER && hfType <= FL_HDRFTR_FOOTER_LAST);
2794 	if(hfType < FL_HDRFTR_FOOTER)
2795 	{
2796 		xxx_UT_DEBUGMSG(("SEVIOR: Deleting header from page %x m_pHeader = %x \n",this, m_pHeader));
2797 		if(m_pHeader == NULL)
2798 			return;
2799 		delete m_pHeader;
2800 		m_pHeader = NULL;
2801 	}
2802 	else
2803 	{
2804 		xxx_UT_DEBUGMSG(("SEVIOR: Deleting footer from page %x m_pFooter = %x \n",this,m_pFooter));
2805 		if(m_pFooter == NULL)
2806 			return;
2807 		delete m_pFooter;
2808 		m_pFooter = NULL;
2809 	}
2810 }
2811 
getHdrFtrP(HdrFtrType hfType) const2812 fp_ShadowContainer* fp_Page::getHdrFtrP(HdrFtrType hfType) const
2813 {
2814 	if(hfType < FL_HDRFTR_FOOTER)
2815 	{
2816 		return m_pHeader;
2817 	}
2818 	else
2819 	{
2820 		return m_pFooter;
2821 	}
2822 }
2823 
2824 fp_ShadowContainer*
buildHdrFtrContainer(fl_HdrFtrSectionLayout * pHFSL,HdrFtrType hfType)2825 fp_Page::buildHdrFtrContainer(fl_HdrFtrSectionLayout* pHFSL,
2826 							  HdrFtrType hfType)
2827 {
2828 	UT_ASSERT(hfType == FL_HDRFTR_HEADER || hfType == FL_HDRFTR_FOOTER);
2829 	bool bIsHead = (hfType == FL_HDRFTR_HEADER);
2830 	fp_ShadowContainer ** ppHF = bIsHead ? &m_pHeader : &m_pFooter;
2831 
2832 	if (*ppHF)
2833 	{
2834 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2835 		(*ppHF)->getHdrFtrSectionLayout()->deletePage(this);
2836 
2837 		UT_ASSERT_HARMLESS( !*ppHF );
2838 	}
2839 	xxx_UT_DEBUGMSG(("SEVIOR: Building header container. page = %x hdrftr = %x \n",this,pHFSL));
2840 
2841 	//
2842 	// headerMargin is the height from the top of the page.
2843 	//
2844 	if (bIsHead)
2845 	{
2846 	    *ppHF = new fp_ShadowContainer(m_pOwner->getLeftMargin(),
2847 									 m_pOwner->getHeaderMargin(),
2848 									 getWidth() - (m_pOwner->getLeftMargin() +
2849 												   m_pOwner->getRightMargin()),
2850 									 m_pOwner->getTopMargin() -
2851 									   m_pOwner->getHeaderMargin(),
2852 									 pHFSL);
2853 	}
2854 	else
2855 	{
2856 		*ppHF = new fp_ShadowContainer(m_pOwner->getLeftMargin(),
2857 									 getHeight() - m_pOwner->getBottomMargin(),
2858 									 getWidth() - (m_pOwner->getLeftMargin()+
2859                                                   m_pOwner->getRightMargin()),
2860 									   m_pOwner->getBottomMargin() - m_pOwner->getFooterMargin(),
2861 									 pHFSL);
2862 	}
2863 
2864 	UT_return_val_if_fail(*ppHF, NULL);
2865 
2866 	(*ppHF)->setPage(this);
2867 	xxx_UT_DEBUGMSG(("SEVIOR: Page for shadow %x is %x \n",*ppHF,this));
2868 	return *ppHF;
2869 }
2870 
2871 /** Return the first container for pHFSL. */
getHdrFtrContainer(fl_HdrFtrSectionLayout * pHFSL)2872 fp_ShadowContainer* fp_Page::getHdrFtrContainer(fl_HdrFtrSectionLayout* pHFSL)
2873 {
2874 	if (pHFSL->getHFType() < FL_HDRFTR_FOOTER)
2875 	{
2876 		if (m_pHeader)
2877 			return m_pHeader;
2878 		else
2879 			return buildHdrFtrContainer(pHFSL, FL_HDRFTR_HEADER);
2880 	}
2881 	else
2882 	{
2883 		if (m_pFooter)
2884 			return m_pFooter;
2885 		else
2886 			return buildHdrFtrContainer(pHFSL, FL_HDRFTR_FOOTER);
2887 	}
2888 }
2889 
2890 // Frame methods
2891 
frameHeightChanged(void)2892 void fp_Page::frameHeightChanged(void)
2893 {
2894 }
2895 
clearScreenFrames(void)2896 void fp_Page::clearScreenFrames(void)
2897 {
2898 	UT_sint32 i =0;
2899 	for (i = 0; i < countAboveFrameContainers(); i++)
2900 	{
2901 		getNthAboveFrameContainer(i)->clearScreen();
2902 	}
2903 	for (i = 0; i < countBelowFrameContainers(); i++)
2904 	{
2905 		getNthBelowFrameContainer(i)->clearScreen();
2906 	}
2907 }
2908 
markDirtyOverlappingRuns(fp_FrameContainer * pFrameC)2909 void fp_Page::markDirtyOverlappingRuns(fp_FrameContainer * pFrameC)
2910 {
2911 	UT_Rect * pMyFrameRect = pFrameC->getScreenRect();
2912 	if(pMyFrameRect == NULL)
2913 	{
2914 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2915 		return;
2916 	}
2917 	// check each column for redraw
2918 
2919 	UT_sint32 count = m_vecColumnLeaders.getItemCount();
2920 	UT_sint32 i = 0;
2921 	for (i=0; i<count; i++)
2922 	{
2923 		fp_Column* pCol = m_vecColumnLeaders.getNthItem(i);
2924 		while (pCol)
2925 		{
2926 			pCol->markDirtyOverlappingRuns(*pMyFrameRect);
2927 			pCol = pCol->getFollower();
2928 		}
2929 	}
2930 
2931 	// Now do the headers and footers
2932 
2933 	if (m_pHeader)
2934 	{
2935 		m_pHeader->markDirtyOverlappingRuns(*pMyFrameRect);
2936 	}
2937 
2938 	if (m_pFooter)
2939 	{
2940 		m_pFooter->markDirtyOverlappingRuns(*pMyFrameRect);
2941 	}
2942 
2943 	// Now Footnotes
2944 
2945 	count = m_vecFootnotes.getItemCount();
2946 	for (i=0; i<count; i++)
2947 	{
2948 		fp_FootnoteContainer* pFC = m_vecFootnotes.getNthItem(i);
2949 		pFC->markDirtyOverlappingRuns(*pMyFrameRect);
2950 	}
2951 
2952 
2953 	// Now Annotations
2954 	if(getDocLayout()->displayAnnotations())
2955 	{
2956 			count = m_vecAnnotations.getItemCount();
2957 			for (i=0; i<count; i++)
2958 			{
2959 					fp_AnnotationContainer* pAC = m_vecAnnotations.getNthItem(i);
2960 					pAC->markDirtyOverlappingRuns(*pMyFrameRect);
2961 			}
2962 	}
2963 
2964 	// Now Frames
2965 
2966 	count = m_vecAboveFrames.getItemCount();
2967 	for (i=0; i<count; i++)
2968 	{
2969 		fp_FrameContainer* pFC = m_vecAboveFrames.getNthItem(i);
2970 		if(pFC != pFrameC)
2971 		{
2972 			pFC->markDirtyOverlappingRuns(*pMyFrameRect);
2973 		}
2974 	}
2975 
2976 
2977 	count = m_vecBelowFrames.getItemCount();
2978 	for (i=0; i<count; i++)
2979 	{
2980 		fp_FrameContainer* pFC = m_vecBelowFrames.getNthItem(i);
2981 		if(pFC != pFrameC)
2982 		{
2983 			pFC->markDirtyOverlappingRuns(*pMyFrameRect);
2984 		}
2985 	}
2986 	DELETEP(pMyFrameRect);
2987 }
2988 
2989 
countAboveFrameContainers(void) const2990 UT_sint32 fp_Page::countAboveFrameContainers(void) const
2991 {
2992         return m_vecAboveFrames.getItemCount();
2993 }
2994 
2995 
countBelowFrameContainers(void) const2996 UT_sint32 fp_Page::countBelowFrameContainers(void) const
2997 {
2998         return m_vecBelowFrames.getItemCount();
2999 }
3000 
findFrameContainer(fp_FrameContainer * pFC) const3001 UT_sint32 fp_Page::findFrameContainer(fp_FrameContainer * pFC) const
3002 {
3003         UT_sint32 i;
3004         if(pFC->isAbove())
3005 	{
3006 	  i = m_vecAboveFrames.findItem(pFC);
3007 	  return i;
3008 
3009 	}
3010         i = m_vecBelowFrames.findItem(pFC);
3011 	return i;
3012 }
3013 
getNthAboveFrameContainer(UT_sint32 n) const3014 fp_FrameContainer* fp_Page::getNthAboveFrameContainer(UT_sint32 n) const
3015 {
3016 	return m_vecAboveFrames.getNthItem(n);
3017 }
3018 
3019 
getNthBelowFrameContainer(UT_sint32 n) const3020 fp_FrameContainer* fp_Page::getNthBelowFrameContainer(UT_sint32 n) const
3021 {
3022 	return m_vecBelowFrames.getNthItem(n);
3023 }
3024 
insertFrameContainer(fp_FrameContainer * pFC)3025 bool fp_Page::insertFrameContainer(fp_FrameContainer * pFC)
3026 {
3027         if(pFC->isAbove())
3028 	{
3029 	       m_vecAboveFrames.addItem(pFC);
3030 	}
3031 	else
3032 	{
3033 	       m_vecBelowFrames.addItem(pFC);
3034 	}
3035 	if(pFC)
3036 	{
3037 		pFC->setPage(this);
3038 	}
3039 	_reformat();
3040 	return true;
3041 }
3042 
removeFrameContainer(fp_FrameContainer * _pFC)3043 void fp_Page::removeFrameContainer(fp_FrameContainer * _pFC)
3044 {
3045 
3046 	markDirtyOverlappingRuns(_pFC);
3047 	UT_sint32 ndx = 0;
3048 	bool isAbove = false;
3049 	if(_pFC->isAbove())
3050 	{
3051 	    ndx = m_vecAboveFrames.findItem(_pFC);
3052 	    isAbove = true;
3053 	}
3054 	else
3055 	{
3056 	    ndx = m_vecBelowFrames.findItem(_pFC);
3057 	}
3058 	if(ndx>=0)
3059 	{
3060 	        if(isAbove)
3061 		{
3062 		        m_vecAboveFrames.deleteNthItem(ndx);
3063 			for(ndx=0; ndx < static_cast<UT_sint32>(countAboveFrameContainers());ndx++)
3064 			{
3065 			    fp_FrameContainer * pFC = getNthAboveFrameContainer(ndx);
3066 			    fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pFC->getSectionLayout());
3067 			    pFC->clearScreen();
3068 			    pFL->markAllRunsDirty();
3069 			}
3070 		}
3071 		else
3072 		{
3073 		        m_vecBelowFrames.deleteNthItem(ndx);
3074 			for(ndx=0; ndx < static_cast<UT_sint32>(countAboveFrameContainers());ndx++)
3075 			{
3076 			    fp_FrameContainer * pFC = getNthAboveFrameContainer(ndx);
3077 			    fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pFC->getSectionLayout());
3078 			    pFC->clearScreen();
3079 			    pFL->markAllRunsDirty();
3080 			}
3081 		}
3082 		_reformat();
3083 		return;
3084 	}
3085 	return;
3086 }
3087 
3088 // Footnote methods
3089 
countFootnoteContainers(void) const3090 UT_sint32 fp_Page::countFootnoteContainers(void) const
3091 {
3092 	return m_vecFootnotes.getItemCount();
3093 }
3094 
findFootnoteContainer(fp_FootnoteContainer * pFC) const3095 UT_sint32 fp_Page::findFootnoteContainer(fp_FootnoteContainer * pFC) const
3096 {
3097 	UT_sint32 i = m_vecFootnotes.findItem(pFC);
3098 	return i;
3099 }
3100 
getNthFootnoteContainer(UT_sint32 n) const3101 fp_FootnoteContainer* fp_Page::getNthFootnoteContainer(UT_sint32 n) const
3102 {
3103 	return m_vecFootnotes.getNthItem(n);
3104 }
3105 
insertFootnoteContainer(fp_FootnoteContainer * pFC)3106 bool fp_Page::insertFootnoteContainer(fp_FootnoteContainer * pFC)
3107 {
3108 	UT_sint32 i =0;
3109 	UT_sint32 j = findFootnoteContainer(pFC);
3110 	if(j >= 0)
3111 	{
3112 		return false;
3113 	}
3114 	UT_uint32 loc =0;
3115 	UT_sint32 fVal = pFC->getValue();
3116 	fp_FootnoteContainer * pFTemp = NULL;
3117 	for(i=0; i< m_vecFootnotes.getItemCount();i++)
3118 	{
3119 		pFTemp = m_vecFootnotes.getNthItem(i);
3120 		if(fVal < pFTemp->getValue())
3121 		{
3122 			loc = i;
3123 			break;
3124 		}
3125 	}
3126 	if(pFTemp == NULL)
3127 	{
3128 		m_vecFootnotes.addItem(pFC);
3129 	}
3130 	else if( i>= m_vecFootnotes.getItemCount())
3131 	{
3132 		m_vecFootnotes.addItem(pFC);
3133 	}
3134 	else
3135 	{
3136 		m_vecFootnotes.insertItemAt(pFC, loc);
3137 	}
3138 	if(pFC)
3139 	{
3140 		pFC->setPage(this);
3141 	}
3142 	_reformat();
3143 	return true;
3144 }
3145 
removeFootnoteContainer(fp_FootnoteContainer * _pFC)3146 void fp_Page::removeFootnoteContainer(fp_FootnoteContainer * _pFC)
3147 {
3148 	UT_sint32 ndx = m_vecFootnotes.findItem(_pFC);
3149 	if(ndx>=0)
3150 	{
3151 		m_vecFootnotes.deleteNthItem(ndx);
3152 		for(ndx=0; ndx < static_cast<UT_sint32>(countFootnoteContainers());ndx++)
3153 		{
3154 			fp_FootnoteContainer * pFC = getNthFootnoteContainer(ndx);
3155 			fl_FootnoteLayout * pFL = static_cast<fl_FootnoteLayout *>(pFC->getSectionLayout());
3156 			pFC->clearScreen();
3157 			pFL->markAllRunsDirty();
3158 		}
3159 		_reformat();
3160 		return;
3161 	}
3162 	return;
3163 }
3164 
3165 
3166 
3167 // Annotation methods
3168 
countAnnotationContainers(void) const3169 UT_sint32 fp_Page::countAnnotationContainers(void) const
3170 {
3171 	return m_vecAnnotations.getItemCount();
3172 }
3173 
findAnnotationContainer(fp_AnnotationContainer * pAC) const3174 UT_sint32 fp_Page::findAnnotationContainer(fp_AnnotationContainer * pAC) const
3175 {
3176 	UT_sint32 i = m_vecAnnotations.findItem(pAC);
3177 	return i;
3178 }
3179 
getNthAnnotationContainer(UT_sint32 n) const3180 fp_AnnotationContainer* fp_Page::getNthAnnotationContainer(UT_sint32 n) const
3181 {
3182 	return m_vecAnnotations.getNthItem(n);
3183 }
3184 
getAnnotationPos(UT_uint32 pid) const3185 UT_sint32 fp_Page::getAnnotationPos(UT_uint32 pid) const
3186 {
3187 	fp_AnnotationContainer * pACon = NULL;
3188 	UT_sint32 i = 0;
3189 	for(i = 0; i< countAnnotationContainers(); i++)
3190 	{
3191 			pACon = getNthAnnotationContainer(i);
3192 			if(!pACon)
3193 				return 0;
3194 			if(pid == pACon->getPID())
3195 				return i;
3196 	}
3197 	return 0;
3198 }
3199 
insertAnnotationContainer(fp_AnnotationContainer * pAC)3200 bool fp_Page::insertAnnotationContainer(fp_AnnotationContainer * pAC)
3201 {
3202 	UT_sint32 i =0;
3203 	UT_sint32 j = findAnnotationContainer(pAC);
3204 	if(j >= 0)
3205 	{
3206 		return false;
3207 	}
3208 	UT_uint32 loc =0;
3209 	UT_sint32 fVal = pAC->getValue();
3210 	fp_AnnotationContainer * pFTemp = NULL;
3211 	for(i=0; i< m_vecAnnotations.getItemCount();i++)
3212 	{
3213 		pFTemp = m_vecAnnotations.getNthItem(i);
3214 		if(fVal < pFTemp->getValue())
3215 		{
3216 			loc = i;
3217 			break;
3218 		}
3219 	}
3220 	if(pFTemp == NULL)
3221 	{
3222 		m_vecAnnotations.addItem(pAC);
3223 	}
3224 	else if( i>= m_vecAnnotations.getItemCount())
3225 	{
3226 		m_vecAnnotations.addItem(pAC);
3227 	}
3228 	else
3229 	{
3230 		m_vecAnnotations.insertItemAt(pAC, loc);
3231 	}
3232 	if(pAC)
3233 	{
3234 		pAC->setPage(this);
3235 	}
3236 	if(getDocLayout()->displayAnnotations())
3237 	{
3238 		_reformat();
3239 	}
3240 	return true;
3241 }
3242 
removeAnnotationContainer(fp_AnnotationContainer * _pAC)3243 void fp_Page::removeAnnotationContainer(fp_AnnotationContainer * _pAC)
3244 {
3245 	UT_sint32 ndx = m_vecAnnotations.findItem(_pAC);
3246 	if(ndx>=0)
3247 	{
3248 		m_vecAnnotations.deleteNthItem(ndx);
3249 		if(getDocLayout()->displayAnnotations())
3250 		{
3251 				for(ndx=0; ndx < static_cast<UT_sint32>(countAnnotationContainers());ndx++)
3252 				{
3253 						fp_AnnotationContainer * pAC = getNthAnnotationContainer(ndx);
3254 						fl_AnnotationLayout * pAL = static_cast<fl_AnnotationLayout *>(pAC->getSectionLayout());
3255 						pAC->clearScreen();
3256 						pAL->markAllRunsDirty();
3257 				}
3258 		}
3259 		_reformat();
3260 		return;
3261 	}
3262 	return;
3263 }
3264