1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3  * Copyright (C) 1998 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 <math.h>
23 #include <string.h>
24 
25 #include "fp_Column.h"
26 #include "fp_Page.h"
27 #include "fp_Line.h"
28 #include "fp_TOCContainer.h"
29 #include "fl_SectionLayout.h"
30 #include "gr_DrawArgs.h"
31 #include "fp_TableContainer.h"
32 #include "fp_FootnoteContainer.h"
33 #include "fp_FrameContainer.h"
34 #include "fl_FootnoteLayout.h"
35 #include "fp_Run.h"
36 #include "fl_TOCLayout.h"
37 #include "ut_debugmsg.h"
38 #include "ut_assert.h"
39 #include "fv_View.h"
40 #include "gr_Painter.h"
41 
42 
43 /*!
44   Create container
45   \param iType Container type
46   \param pSectionLayout Section layout type used for this container
47  */
fp_VerticalContainer(FP_ContainerType iType,fl_SectionLayout * pSectionLayout)48 fp_VerticalContainer::fp_VerticalContainer(FP_ContainerType iType, fl_SectionLayout* pSectionLayout) :
49 	fp_Container(iType, pSectionLayout),
50 	m_iRedrawHeight(-1),
51 	m_iWidth(0),
52 	m_iHeight(0),
53 	m_iMaxHeight(0),
54 	m_iX(0),
55 	m_iY(INITIAL_OFFSET),
56 	m_bIntentionallyEmpty(0),
57 	m_imaxContainerHeight(0)
58 {
59 	clearWrappedLines();
60 	UT_ASSERT(getDocSectionLayout());
61 }
62 
63 /*!
64   Destruct container
65   \note The Containers in vector of the container are not
66         destructed. They are owned by the logical hierarchy (i.e.,
67 		the fl_Container classes like fl_BlockLayout), not the physical
68         hierarchy.
69  */
~fp_VerticalContainer()70 fp_VerticalContainer::~fp_VerticalContainer()
71 {
72 }
73 
74 /*!
75   Set width
76   \param iWidth Width of container
77   \todo Should force re-line-break operations on all blocks in the
78         container
79  */
setWidth(UT_sint32 iWidth)80 void fp_VerticalContainer::setWidth(UT_sint32 iWidth)
81 {
82 	if (iWidth == m_iWidth)
83 	{
84 		return;
85 	}
86 	m_iWidth = iWidth;
87 	if(getContainerType() != FP_CONTAINER_COLUMN)
88 	{
89 	    getSectionLayout()->setImageWidth(iWidth);
90 	    getFillType().setWidth(getGraphics(),iWidth);
91 	}
92 
93 	// TODO we really need to force a re-line-break operation on every block herein
94 
95 //	UT_ASSERT(UT_NOT_IMPLEMENTED);
96 }
97 
98 /*!
99  * return a pointer to the current view.
100  */
getView(void) const101 FV_View * fp_VerticalContainer::getView(void) const
102 {
103   fp_Page * pPage = getPage();
104   if(pPage == NULL)
105   {
106     return NULL;
107   }
108   FL_DocLayout * pDL = pPage->getDocLayout();
109   if(pDL == NULL)
110   {
111     return NULL;
112   }
113   return pDL->getView();
114 }
115 /*!
116  Set height
117  \param iHeight Height of container
118  */
setHeight(UT_sint32 iHeight)119 void fp_VerticalContainer::setHeight(UT_sint32 iHeight)
120 {
121 	if (iHeight == m_iHeight)
122 	{
123 		return;
124 	}
125 	if(getContainerType() == FP_CONTAINER_TABLE)
126 	{
127 		fp_TableContainer * pTab = static_cast<fp_TableContainer *>(this);
128 		if(!pTab->isThisBroken())
129 		{
130 			UT_DEBUGMSG(("Unbroken Table container set to %d from %d \n",iHeight,pTab->getHeight()));
131 		}
132 	}
133 	if(getContainerType() == FP_CONTAINER_TOC)
134 	{
135 		fp_TOCContainer * pTOC = static_cast<fp_TOCContainer *>(this);
136 		if(!pTOC->isThisBroken())
137 		{
138 			UT_DEBUGMSG(("Unbroken TOC container set to %d from %d \n",iHeight,pTOC->getHeight()));
139 		}
140 	}
141 	m_iHeight = iHeight;
142 	if(getContainerType() != FP_CONTAINER_COLUMN)
143 	{
144 	  if(getContainerType() == FP_CONTAINER_CELL)
145 	  {
146 	      getSectionLayout()->setImageHeight(getMaxHeight()); // was iHeight
147 	  }
148 	  getFillType().setHeight(getGraphics(),iHeight);
149 	}
150 }
151 
152 /*!
153  Set maximum height
154  \param iMaxHeight Maximum height of container
155  */
setMaxHeight(UT_sint32 iMaxHeight)156 void fp_VerticalContainer::setMaxHeight(UT_sint32 iMaxHeight)
157 {
158 	//UT_ASSERT(iMaxHeight > 0);
159 
160 	if (iMaxHeight == m_iMaxHeight)
161 	{
162 		return;
163 	}
164 
165 	m_iMaxHeight = iMaxHeight;
166 }
167 
168 /*!
169   Get container's X position
170   \return X position
171 */
getX(void) const172 UT_sint32 fp_VerticalContainer::getX(void) const
173 {
174 	return m_iX;
175 }
176 
177 /*!
178   Get container's Y position.
179   \return Y position
180 */
getY(void) const181 UT_sint32 fp_VerticalContainer::getY(void) const
182 {
183 	if(getSectionLayout()->getDocLayout()->getView()  && (getSectionLayout()->getDocLayout()->getView()->getViewMode() != VIEW_PRINT))
184 	{
185 		fl_SectionLayout * pSL = getSectionLayout();
186 		fl_DocSectionLayout * pDSL = NULL;
187 		if(static_cast<fl_ContainerLayout *>(pSL)->getContainerType() == FL_CONTAINER_DOCSECTION)
188 		{
189 			pDSL = static_cast<fl_DocSectionLayout *>(pSL);
190 		}
191 		else
192 		{
193 			pDSL =  static_cast<fl_DocSectionLayout *>(pSL->getDocSectionLayout());
194 		}
195 		if(pSL->getContainerType() == FL_CONTAINER_DOCSECTION)
196 		{
197 			return m_iY - pDSL->getTopMargin();
198 		}
199 		return m_iY;
200 	}
201 	return m_iY;
202 }
203 /*!
204   Get container's Y position. This version checks for a mismatch between view
205  mode and if we're printing.
206   \return Y position
207 */
getY(GR_Graphics * pG) const208 UT_sint32 fp_VerticalContainer::getY(GR_Graphics * pG) const
209 {
210 	if(getSectionLayout()->getDocLayout()->getView()  && (getSectionLayout()->getDocLayout()->getView()->getViewMode() != VIEW_PRINT) && pG->queryProperties(GR_Graphics::DGP_SCREEN))
211 	{
212 		return m_iY - static_cast<fl_DocSectionLayout *>(getSectionLayout())->getTopMargin();
213 	}
214 	return m_iY;
215 }
216 
217 /*!
218  * This method returns the vertical offset due to a table broken
219  * across more than 1 page.
220  */
getYoffsetFromTable(fp_Container * pT,fp_Container * pCell,fp_ContainerObject * pCon)221 UT_sint32 fp_VerticalContainer::getYoffsetFromTable(fp_Container * pT,
222 													fp_Container* pCell,
223 													fp_ContainerObject * pCon)
224 {
225 	fp_TableContainer * pFirstTable = static_cast<fp_TableContainer *>(pT)->getFirstBrokenTable();
226 	fp_TableContainer * pTable = pFirstTable;
227 //	UT_ASSERT(pTable);
228 	UT_sint32 offset = 0;
229 	bool bFound = false;
230 	while(pTable != NULL && !bFound)
231 	{
232 		bFound = pTable->isInBrokenTable(static_cast<fp_CellContainer *>(pCell),static_cast<fp_Container *>(pCon));
233 		if(bFound)
234 		{
235 			offset = -pTable->getYBreak();
236 		}
237 		pTable = static_cast<fp_TableContainer *>(pTable->getNext());
238 	}
239 	return offset;
240 }
241 
242 
243 /*!
244  * This method returns the correct broken table for this line.
245  */
getCorrectBrokenTable(fp_Container * pCon)246 fp_TableContainer * fp_VerticalContainer::getCorrectBrokenTable(fp_Container * pCon)
247 {
248 	xxx_UT_DEBUGMSG(("VerticalContainer: In get Correct proken table \n"));
249 	bool bFound = false;
250 	fp_CellContainer * pCell = NULL;
251 	if(pCon->getContainerType() == FP_CONTAINER_CELL)
252 	{
253 	     pCell = static_cast<fp_CellContainer *>(pCon);
254 	     pCon = pCell->getFirstContainer();
255 	}
256 	else
257 	{
258 	     pCell = static_cast<fp_CellContainer *>(pCon->getContainer());
259 	     if(!pCell)
260 	     {
261 		   return NULL;
262 	     }
263 	}
264 	UT_return_val_if_fail(pCell->getContainerType() == FP_CONTAINER_CELL,NULL);
265 //
266 // OK scan through the broken tables and look for the table that contains this
267 //
268 	fp_Container * pCur = static_cast<fp_Container *>(pCell->getContainer());
269 	UT_return_val_if_fail(pCur->getContainerType() == FP_CONTAINER_TABLE,NULL);
270 	fp_TableContainer * pMasterTab = static_cast<fp_TableContainer *>(pCur);
271 	UT_return_val_if_fail(pMasterTab && pMasterTab->getContainerType() == FP_CONTAINER_TABLE,NULL);
272 	fp_TableContainer * pTab = pMasterTab->getFirstBrokenTable();
273 	bFound = false;
274 	UT_sint32 iCount  =0;
275 	while(pTab && !bFound)
276 	{
277 	        xxx_UT_DEBUGMSG(("getCorrectBrokenTable YBreak %d height %d \n",pTab->getYBreak(),pTab->getHeight()));
278 		if(pTab->isInBrokenTable(pCell,pCon))
279 		{
280 			bFound = true;
281 		}
282 		else
283 		{
284 			pTab = static_cast<fp_TableContainer *>(pTab->getNext());
285 		}
286 		if(!bFound)
287 		{
288 			iCount++;
289 		}
290 	}
291 	if(bFound)
292 	{
293 		xxx_UT_DEBUGMSG(("getCorrect: Found table after %d tries \n",iCount));
294 		xxx_UT_DEBUGMSG(("Container y %d height %d was found in table %d ybreak %d ybottom y %d \n",pCon->getY(),pCon->getHeight(),iCount,pTab->getYBreak(),pTab->getYBottom()));
295 		return  pTab;
296 	}
297 
298 	xxx_UT_DEBUGMSG(("getCorrectBroken: No table found after %d tries, Y of Con \n",iCount,pCon->getY()));
299 	if(pMasterTab)
300 	{
301 //		UT_ASSERT(pMasterTab->getFirstBrokenTable() == NULL);
302 	}
303 	return pMasterTab;
304 }
305 
306 
307 
308 /*!
309  * This method returns the correct broken TOC for this line.
310  */
getCorrectBrokenTOC(fp_Container * pCon)311 fp_TOCContainer * fp_VerticalContainer::getCorrectBrokenTOC(fp_Container * pCon)
312 {
313 	xxx_UT_DEBUGMSG(("VerticalContainer: In get Correct proken TOC \n"));
314 	bool bFound = false;
315 //
316 // OK scan through the broken TOC's and look for the TOC that contains this
317 //
318 	fp_Container * pCur = static_cast<fp_Container *>(pCon->getContainer());
319 	UT_return_val_if_fail(pCur->getContainerType() == FP_CONTAINER_TOC,NULL);
320 	fp_TOCContainer * pMasterTOC = static_cast<fp_TOCContainer *>(pCur);
321 	UT_return_val_if_fail(pMasterTOC && pMasterTOC->getContainerType() == FP_CONTAINER_TOC,NULL);
322 	fp_TOCContainer * pTOC = pMasterTOC->getFirstBrokenTOC();
323 	bFound = false;
324 	UT_sint32 iCount  =0;
325 	while(pTOC && !bFound)
326 	{
327 		if(pTOC->isInBrokenTOC(pCon))
328 		{
329 			bFound = true;
330 		}
331 		else
332 		{
333 			pTOC = static_cast<fp_TOCContainer *>(pTOC->getNext());
334 		}
335 		if(!bFound)
336 		{
337 			iCount++;
338 		}
339 	}
340 	if(bFound)
341 	{
342 		xxx_UT_DEBUGMSG(("getCorrect: Found table after %d tries \n",iCount));
343 		xxx_UT_DEBUGMSG(("Container y %d height %d was found in table %d ybreak %d ybottom y %d \n",pCon->getY(),pCon->getHeight(),iCount,pTab->getYBreak(),pTab->getYBottom()));
344 		return  pTOC;
345 	}
346 	xxx_UT_DEBUGMSG(("getCorrectBrokenTOC: NoTOC found after %d tries, Y of Con \n",iCount,pCon->getY()));
347 	if(pMasterTOC)
348 	{
349 //		UT_ASSERT(pMasterTOC->getFirstBrokenTOC() == NULL);
350 	}
351 	return pMasterTOC;
352 }
353 
354 /*!
355   Get line's offsets relative to this container
356  \param  pContainer Container
357  \retval xoff Container's X offset relative to container
358  \retval yoff Container's Y offset relative to container
359  */
getOffsets(fp_ContainerObject * pContainer,UT_sint32 & xoff,UT_sint32 & yoff)360 void fp_VerticalContainer::getOffsets(fp_ContainerObject* pContainer, UT_sint32& xoff, UT_sint32& yoff)
361 {
362 	fp_ContainerObject * pOrig = pContainer;
363 	UT_sint32 my_xoff = 0;
364 	UT_sint32 my_yoff = 0;
365 	fp_Container * pCon = static_cast<fp_Container *>(this);
366 	fp_Container * pPrev = NULL;
367 	fp_TableContainer * pTab = NULL;
368 	while(pCon && !pCon->isColumnType())
369 	{
370 		my_xoff += pCon->getX();
371 		xxx_UT_DEBUGMSG(("my_xoff = %d pCon %x Type is %s \n",my_xoff,pCon,pCon->getContainerString()));
372 		UT_sint32 iycon = pCon->getY();
373 		my_yoff += iycon;
374 //
375 // Handle offsets from tables broken across pages.
376 //
377 // We detect
378 // line->cell->table->cell->table->cell->table->column
379 //
380 		if(pCon->getContainerType() == FP_CONTAINER_TABLE)
381 		{
382 			fp_VerticalContainer * pVCon= static_cast<fp_VerticalContainer *>(pCon);
383 //
384 // Lines and Cells are actually always in the Master table. To make
385 // Them print on the right pages broken tables are created which
386 // sit in different columns. Here we hijack the recursive search and
387 // move it up the correct broken table line when we come across a cell
388 //
389 			pVCon = getCorrectBrokenTable(static_cast<fp_Container *>(pContainer));
390 			if(pPrev && pPrev->getContainerType() == FP_CONTAINER_CELL)
391 			{
392 				UT_sint32 iTable =  getYoffsetFromTable(pCon,pPrev,pContainer);
393 				my_yoff += iTable;
394 				pTab = static_cast<fp_TableContainer *>(pVCon);
395 				if(pTab->isThisBroken() && (pTab != pTab->getMasterTable()->getFirstBrokenTable()))
396 				{
397 					my_yoff = my_yoff + pVCon->getY() -iycon;
398 				}
399 			}
400 			if(pVCon && pVCon->getContainer() && (pVCon->getContainer()->getContainerType() == FP_CONTAINER_CELL))
401 			{
402 				pContainer = static_cast<fp_Container *>(pVCon);
403 				xxx_UT_DEBUGMSG(("pContainer set to %p height %d \n",pContainer,pContainer->getHeight()));
404 			}
405 			else if(pVCon && (pVCon->getContainer() == NULL))
406 			{
407 			  //
408 			  // Just bail out for now
409 			  //
410 			        return;
411 			}
412 			if(pVCon == NULL)
413 			{
414 			        pCon = NULL;
415 				break;
416 			}
417 			pCon = static_cast<fp_Container *>(pVCon);
418 		}
419 		if(pCon->getContainerType() == FP_CONTAINER_TOC)
420 		{
421 			fp_VerticalContainer * pVCon= static_cast<fp_VerticalContainer *>(pCon);
422 //
423 // Lines and Cells are actually always in the Master table. To make
424 // Them print on the right pages broken tables are created which
425 // sit in different columns. Here we hijack the recursive search and
426 // move it up the correct broken table line when we come across a cell
427 //
428 			pVCon = getCorrectBrokenTOC(static_cast<fp_Container *>(pContainer));
429 			pCon = static_cast<fp_Container *>(pVCon);
430 		}
431 		pPrev = pCon;
432 		pCon = pCon->getContainer();
433 	}
434 	if(pCon && pCon->getContainerType() == FP_CONTAINER_HDRFTR)
435 	{
436 		fl_HdrFtrSectionLayout*	pHFSL = static_cast<fp_HdrFtrContainer *>(pCon)->getHdrFtrSectionLayout();
437 		fp_Page * pPage = getPage();
438 		fl_HdrFtrShadow * pShadowL = NULL;
439 		if(pPage == NULL)
440 		{
441 			pShadowL = pHFSL->getFirstShadow();
442 		}
443 		else
444 		{
445 			pShadowL = pHFSL->findShadow(pPage);
446 		}
447 		if(pShadowL == NULL)
448 		{
449 			return;
450 		}
451 //		UT_ASSERT(pShadowL);
452 		if(pShadowL)
453 		{
454 			pCon = static_cast<fp_Container *>(pShadowL->getFirstContainer());
455 		}
456 		else
457 		{
458 			return;
459 		}
460 	}
461 
462 	UT_sint32 col_x =0;
463 	UT_sint32 col_y =0;
464 	if(pPrev && ((pPrev->getContainerType() == FP_CONTAINER_TABLE) ||
465 				 (pPrev->getContainerType() == FP_CONTAINER_TOC)))
466 	{
467 		if(pCon->getContainerType() == FP_CONTAINER_COLUMN)
468 		{
469 			UT_sint32 col_xV =0;
470 			UT_sint32 col_yV =0;
471 			fp_Column * pCol = static_cast<fp_Column *>(pCon);
472 			pCol->getPage()->getScreenOffsets(pCol, col_xV, col_yV);
473 			pCol =static_cast<fp_Column *>(pCon->getColumn());
474 			pCol->getPage()->getScreenOffsets(pCol, col_x, col_y);
475 			UT_sint32 ydiff = col_yV - col_y;
476 			my_yoff += ydiff;
477 		}
478 		xoff = pCon->getX() + my_xoff + pOrig->getX();
479 		yoff = pCon->getY() + my_yoff + pOrig->getY();
480 		if ((pPrev->getContainerType() == FP_CONTAINER_TOC) &&
481 			(pCon->getContainerType() != FP_CONTAINER_COLUMN_SHADOW))
482 		{
483 			xxx_UT_DEBUGMSG(("Not in shadow final xoff %d \n",xoff));
484 			return;
485 		}
486 	}
487 
488 	if(pCon && pCon->getContainerType() == FP_CONTAINER_COLUMN_SHADOW)
489 	{
490 		xoff = pCon->getX() + my_xoff + pOrig->getX();
491 		yoff = pCon->getY() + my_yoff + pOrig->getY();
492 		xxx_UT_DEBUGMSG(("Offsets in FP_CONTAINER_COLUMN_SHADOW x= %d \n",xoff));
493 		return;
494 	}
495 	if(pCon)
496 	{
497 		xoff = pCon->getX() + my_xoff + pOrig->getX();
498 		yoff = pCon->getY() + my_yoff + pOrig->getY();
499 	}
500 	else
501 	{
502 		xoff = 0;
503 		yoff = 0;
504 	}
505 	if(pCon && pCon->getContainerType() == FP_CONTAINER_FOOTNOTE)
506 	{
507 	        if(getPage() && getView() && (getView()->getViewMode() != VIEW_PRINT))
508 		{
509 		       fl_DocSectionLayout * pDSL = getPage()->getOwningSection();
510 		       yoff -= pDSL->getTopMargin();
511 		}
512 	}
513 	if(pCon && getPage() && (pCon->getContainerType() == FP_CONTAINER_ANNOTATION) &&
514 	   getPage()->getDocLayout()->displayAnnotations())
515 	{
516 	        if(getPage() && getView() && (getView()->getViewMode() != VIEW_PRINT))
517 		{
518 		       fl_DocSectionLayout * pDSL = getPage()->getOwningSection();
519 		       yoff -= pDSL->getTopMargin();
520 		}
521 	}
522 }
523 
524 
525 
526 /*!
527  * return an rectangle that covers this object on the screen
528  * The calling routine is resposible for deleting the returned struct
529  */
getScreenRect(void)530 UT_Rect * fp_VerticalContainer::getScreenRect(void)
531 {
532 	UT_sint32 xoff = 0;
533 	UT_sint32 yoff = 0;
534 	UT_Rect * pRec = NULL;
535 	if(getContainerType() == FP_CONTAINER_FRAME)
536 	{
537 		fp_Page * pPage = getPage();
538 		if(pPage == NULL)
539 		{
540 			return NULL;
541 		}
542 		fp_FrameContainer * pFrameC = static_cast<fp_FrameContainer *>(this);
543 		getView()->getPageScreenOffsets(pPage,xoff,yoff);
544 		xoff += pFrameC->getFullX();
545 		yoff += pFrameC->getFullY();
546 		pRec= new UT_Rect(xoff,yoff,pFrameC->getFullWidth(),pFrameC->getFullHeight());
547 		return pRec;
548 	}
549 	fp_Container * pCon = static_cast<fp_Container *>(fp_Container::getNthCon(0));
550 	if(pCon == NULL)
551 	{
552 		return NULL;
553 	}
554 	getScreenOffsets(pCon,xoff,yoff);
555 	xoff -= pCon->getX();
556 	yoff -= pCon->getY();
557 	pRec= new UT_Rect(xoff,yoff,getWidth(),getHeight());
558 	return pRec;
559 }
560 
561 /*!
562  * Marks Dirty any runs that overlap the supplied rectangle. This rectangle
563  * is relative to the screen.
564  */
markDirtyOverlappingRuns(UT_Rect & recScreen)565 void fp_VerticalContainer::markDirtyOverlappingRuns(UT_Rect & recScreen)
566 {
567 	UT_Rect * pRec = NULL;
568 	pRec = getScreenRect();
569 	if(pRec && recScreen.intersectsRect(pRec))
570 	{
571 		DELETEP(pRec);
572 		UT_sint32 count = countCons();
573 		UT_sint32 i = 0;
574 		for(i = 0; i < count;i++)
575 		{
576 			fp_Container * pCon = static_cast<fp_Container * >(getNthCon(i));
577 			pCon->markDirtyOverlappingRuns(recScreen);
578 		}
579 		return;
580 	}
581 	DELETEP(pRec);
582 }
583 
584 
585 /*!
586   Get Containers' offsets relative to the screen
587  \param  pContainer Container which we want to find the absolute
588                     position of.
589  \retval xoff Container's X offset relative the screen
590  \retval yoff Container's Y offset relative the screen
591  */
getScreenOffsets(fp_ContainerObject * pContainer,UT_sint32 & xoff,UT_sint32 & yoff)592 void fp_VerticalContainer::getScreenOffsets(fp_ContainerObject* pContainer,
593 									UT_sint32& xoff, UT_sint32& yoff)
594 {
595 	fp_ContainerObject * pOrig = pContainer;
596 	UT_sint32 my_xoff =0;
597 	UT_sint32 my_yoff =0;
598 
599 	if((getPage() == NULL) || (pContainer == NULL))
600 	{
601 		xoff = 0;
602 		yoff = 0;
603 		return;
604 	}
605 
606 	fp_Container * pCon = static_cast<fp_Container *>(this);
607 	bool bCell = false;
608 	bool bTable = false;
609 	UT_sint32 xcell = 0;
610 	UT_sint32 ycell = 0;
611 	if((getContainerType() == FP_CONTAINER_TABLE) && (pContainer->getContainerType() == FP_CONTAINER_CELL))
612 	{
613 	        pCon =  static_cast<fp_Container *>(pContainer);
614 	        pContainer = static_cast<fp_CellContainer *>(pContainer)->getNthCon(0);
615 		if(pContainer != NULL)
616 		{
617 		  bCell = true;
618 		  xcell = pContainer->getX();
619 		  ycell = pContainer->getY();
620 		}
621 		else
622 		{
623 		  bTable = true;
624 		  pContainer = pCon;
625 		  pCon = static_cast<fp_Container *>(this);
626 		  my_yoff = getY();
627 		  my_xoff = getX();
628 		}
629 	}
630 	fp_Container * pPrev = NULL;
631 	fp_TableContainer * pTab = NULL;
632 	while(pCon && !pCon->isColumnType() && !bTable)
633 	{
634 		my_xoff += pCon->getX();
635 		xxx_UT_DEBUGMSG(("Screen offsets my_xoff %d pCon %x type %s \n",my_xoff,pCon,pCon->getContainerString()));
636 		UT_sint32 iycon = pCon->getY();
637 		my_yoff += iycon;
638 //
639 // Handle offsets from tables broken across pages.
640 //
641 // We detect
642 // line->cell->table->cell->table->cell->table->column
643 //
644 		if(pCon->getContainerType() == FP_CONTAINER_TABLE)
645 		{
646 			fp_VerticalContainer * pVCon= static_cast<fp_VerticalContainer *>(pCon);
647 //
648 // Lines and Cells are actually always in the Master table. To make
649 // Them print on the right pages broken tables are created which
650 // sit in different columns. Here we put in a recursive search find
651 // the correct broken table line when we come across a cell
652 //
653 // Then we have to get all the offsets right for the broken table.
654 //
655 
656 			pVCon = getCorrectBrokenTable(static_cast<fp_Container *>(pContainer));
657 //
658 // Can happen during loading.
659 //
660 			if(pVCon == NULL)
661 			{
662 				xoff = 0;
663 				yoff = 0;
664 				return;
665 			}
666 			if(pPrev && pPrev->getContainerType() == FP_CONTAINER_CELL)
667 			{
668 				my_yoff += getYoffsetFromTable(pCon,pPrev,pContainer);
669 				pTab = static_cast<fp_TableContainer *>(pVCon);
670 				if(pTab->isThisBroken() && pTab != pTab->getMasterTable()->getFirstBrokenTable())
671 				{
672 					my_yoff = my_yoff + pVCon->getY() -iycon;
673 				}
674 				pCon = static_cast<fp_Container *>(pVCon);
675 			}
676 			else if(pPrev == NULL)
677 			{
678 			        my_yoff = 0;
679 			}
680 			else
681 			{
682 				UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
683 			}
684 			if(pVCon->getContainer()->getContainerType() == FP_CONTAINER_CELL)
685 			{
686 				pContainer = static_cast<fp_ContainerObject *>(pVCon);
687 			}
688 			pCon = static_cast<fp_Container *>(pVCon);
689 		}
690 		if(pCon->getContainerType() == FP_CONTAINER_TOC)
691 		{
692 			fp_VerticalContainer * pVCon= static_cast<fp_VerticalContainer *>(pCon);
693 //
694 // Lines are actually always in the Master table. To make
695 // Them print on the right pages broken tables are created which
696 // sit in different columns. Here we put in a recursive search find
697 // the correct broken table line when we come across a cell
698 //
699 // Then we have to get all the offsets right for the broken table.
700 //
701 
702 			pVCon = getCorrectBrokenTOC(static_cast<fp_Container *>(pContainer));
703 			pCon = static_cast<fp_Container *>(pVCon);
704 		}
705 		pPrev = pCon;
706 		pCon = pCon->getContainer();
707 		if (!pCon)
708 		{
709 			// Can happen during loading
710 			xoff = 0;
711 			yoff = 0;
712 			return;
713 		}
714 	}
715 	UT_return_if_fail(pCon);
716 	UT_sint32 col_x =0;
717 	UT_sint32 col_y =0;
718 	xoff = my_xoff + pOrig->getX();
719 	yoff = my_yoff + pOrig->getY();
720 	if(bCell)
721 	{
722 	        xoff -= xcell;
723 		yoff -= ycell;
724 	}
725 	if (pCon->getContainerType() == FP_CONTAINER_COLUMN)
726 	{
727 		fp_Column * pCol = static_cast<fp_Column *>(pCon);
728 		pCol->getPage()->getScreenOffsets(pCol, col_x, col_y);
729 
730 		xoff += col_x;
731 		yoff += col_y;
732 	}
733 	else if (pCon->getContainerType() == FP_CONTAINER_COLUMN_SHADOW)
734 	{
735 		fp_ShadowContainer * pCol = static_cast<fp_ShadowContainer *>(pCon);
736 		pCol->getPage()->getScreenOffsets(pCol, col_x, col_y);
737 
738 		xoff += col_x;
739 		yoff += col_y;
740 	}
741 	else if(pCon->getContainerType() == FP_CONTAINER_FOOTNOTE)
742 	{
743 		fp_FootnoteContainer * pFC = static_cast<fp_FootnoteContainer *>(pCon);
744 		pFC->getPage()->getScreenOffsets(pFC, col_x, col_y);
745 
746 		xoff += col_x;
747 		yoff += col_y;
748 	        if(pFC->getPage() && getView() && (getView()->getViewMode() != VIEW_PRINT))
749 		{
750 		       fl_DocSectionLayout * pDSL = getPage()->getOwningSection();
751 		       yoff -= pDSL->getTopMargin();
752 		}
753 	}
754 	else if(pCon->getContainerType() == FP_CONTAINER_ANNOTATION)
755 	{
756 		fp_AnnotationContainer * pAC = static_cast<fp_AnnotationContainer *>(pCon);
757 		pAC->getPage()->getScreenOffsets(pAC, col_x, col_y);
758 
759 		xoff += col_x;
760 		yoff += col_y;
761 	        if(pAC->getPage() && getView() && (getView()->getViewMode() != VIEW_PRINT))
762 		{
763 		       fl_DocSectionLayout * pDSL = getPage()->getOwningSection();
764 		       yoff -= pDSL->getTopMargin();
765 		}
766 	}
767 	else if(pCon->getContainerType() == FP_CONTAINER_FRAME)
768 	{
769 		fp_FrameContainer * pFC = static_cast<fp_FrameContainer *>(pCon);
770 		pFC->getPage()->getScreenOffsets(pFC, col_x, col_y);
771 
772 		xoff += col_x;
773 		yoff += col_y;
774 	}
775 	else
776 	{
777 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
778 	}
779 }
780 
781 
782 /*!
783  * remove all contains from this.
784  */
removeAll(void)785 void fp_VerticalContainer::removeAll(void)
786 {
787         UT_sint32 iCount = countCons();
788 	UT_sint32 i = 0;
789 	for(i=0; i< iCount; i++)
790         {
791 	     deleteNthCon(0);
792 	}
793 }
794 /*!
795  Remove line from container
796  \param pContainer Container
797  \param bClear if true clear screen.
798  \note The line is not destructed, as it is owned by the logical
799        hierarchy.
800  */
removeContainer(fp_Container * pContainer,bool bClear)801 void fp_VerticalContainer::removeContainer(fp_Container* pContainer,bool bClear)
802 {
803 	UT_sint32 iCount = countCons();
804 	if(iCount == 0)
805 		return;
806 	UT_sint32 ndx = findCon(pContainer);
807 	UT_ASSERT(ndx >= 0);
808 	if(ndx < 0)
809 	{
810 		return;
811 	}
812 	if(bClear && (pContainer->getContainerType() == FP_CONTAINER_LINE))
813 	{
814 		pContainer->clearScreen();
815 	}
816 	xxx_UT_DEBUGMSG(("Removing Container %x from column %x \n",pContainer,this));
817 	pContainer->setContainer(NULL);
818 	deleteNthCon(ndx);
819 
820 	// don't delete the line here, it's deleted elsewhere.
821 }
822 
823 /*!
824  Insert line at the front/top of the container
825  \param pNewContainer Container
826  */
insertContainer(fp_Container * pNewContainer)827 bool fp_VerticalContainer::insertContainer(fp_Container* pNewContainer)
828 {
829 	UT_return_val_if_fail(pNewContainer,false);
830 	UT_return_val_if_fail((pNewContainer->getContainerType() == FP_CONTAINER_ENDNOTE) || (pNewContainer->getDocSectionLayout() == getDocSectionLayout()),false);
831 	UT_ASSERT(pNewContainer->getContainerType() != FP_CONTAINER_ANNOTATION);
832 	pNewContainer->clearScreen();
833 	xxx_UT_DEBUGMSG(("Insert  Container after CS %x in column %x \n",pNewContainer,this));
834 	insertConAt(pNewContainer, 0);
835 	pNewContainer->setContainer(static_cast<fp_Container *>(this));
836 	pNewContainer->recalcMaxWidth(true);
837 
838 	return true;
839 }
840 
841 /*!
842   Get column gap from page the container is located on
843   \return Column gap
844 */
getColumnGap(void) const845 UT_sint32	fp_VerticalContainer::getColumnGap(void) const
846 {
847 	return getColumn()->getPage()->getColumnGap();
848 }
849 
850 /*!
851  Append line at the end/bottom of the container
852  \param pNewContainer Container
853  */
addContainer(fp_Container * pNewContainer)854 bool fp_VerticalContainer::addContainer(fp_Container* pNewContainer)
855 {
856 	UT_return_val_if_fail(pNewContainer,false);
857 	UT_return_val_if_fail((pNewContainer->getContainerType() == FP_CONTAINER_ENDNOTE) || (pNewContainer->getDocSectionLayout() == getDocSectionLayout()),false);
858 	UT_ASSERT(pNewContainer->getContainerType() != FP_CONTAINER_ANNOTATION);
859 	if(pNewContainer->getContainer() != NULL)
860 	{
861 		pNewContainer->clearScreen();
862 	}
863 	xxx_UT_DEBUGMSG(("Add  Container after CS %x in column %x \n",pNewContainer,this));
864 	addCon(pNewContainer);
865 	pNewContainer->setContainer(this);
866 	pNewContainer->recalcMaxWidth(true);
867 	return true;
868 }
869 
870 /*!
871  Insert line in container after specified line
872  \param pNewContainer   Container to be inserted
873  \param pAfterContainer After this line
874  \todo This function has been hacked to handle the case where
875        pAfterContainer is NULL. That case should not happen. Bad callers
876        should be identified and fixed, and this function should be
877        cleaned up.
878  */
insertContainerAfter(fp_Container * pNewContainer,fp_Container * pAfterContainer)879 bool fp_VerticalContainer::insertContainerAfter(fp_Container*	pNewContainer, fp_Container*	pAfterContainer)
880 {
881 	UT_ASSERT(pAfterContainer);
882 	UT_return_val_if_fail(pNewContainer, false);
883 	UT_return_val_if_fail((pNewContainer->getContainerType() == FP_CONTAINER_ENDNOTE) || (pNewContainer->getDocSectionLayout() == getDocSectionLayout()),false);
884 	UT_ASSERT(pNewContainer->getContainerType() != FP_CONTAINER_ANNOTATION);
885 
886 	UT_sint32 count = countCons();
887 	UT_sint32 ndx = findCon(pAfterContainer);
888 	UT_ASSERT( (count > 0) || (ndx == -1) );
889 
890 	/*
891 	  TODO this routine should not be allowing pAfterContainer to be NULL.
892 	  Right now, we've fixed the symptom, but we really should fix
893 	  the problem.  */
894 	UT_ASSERT(ndx >= 0);
895 	pNewContainer->clearScreen();
896 	if ( (ndx+1) == count )				// append after last line in vector
897 		addCon(pNewContainer);
898 	else if (ndx >= 0)					// append after this item within the vector
899 		insertConAt(pNewContainer, ndx+1);
900 	else
901 	{
902 		// TODO remove this....
903 		insertConAt(pNewContainer, 0);
904 	}
905 
906 	pNewContainer->setContainer(this);
907 	if(pNewContainer->getContainerType() == FP_CONTAINER_LINE)
908 	{
909 		if(static_cast<fp_Line *>(pNewContainer)->isWrapped())
910 		{
911 			return true;
912 		}
913 	}
914 	pNewContainer->recalcMaxWidth(true);
915 
916 	return true;
917 }
918 
919 /*!
920   Clear container content from screen.
921 
922   \fixme Needs to clear outline as well
923 */
clearScreen(void)924 void fp_VerticalContainer::clearScreen(void)
925 {
926 	if(getPage() == NULL)
927 	{
928 		return;
929 	}
930 	if(!getPage()->isOnScreen())
931 	{
932 		return;
933 	}
934 	int count = countCons();
935 	for (int i = 0; i<count; i++)
936 	{
937 		fp_ContainerObject* pContainer = static_cast<fp_ContainerObject*>(getNthCon(i));
938 
939 		pContainer->clearScreen();
940 	}
941 }
942 
943 /*!
944  Draw container outline
945  \param pDA Draw arguments
946  */
_drawBoundaries(dg_DrawArgs * pDA)947 void fp_VerticalContainer::_drawBoundaries(dg_DrawArgs* pDA)
948 {
949     if(pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN))
950 	{
951 		return;
952 	}
953 	UT_return_if_fail(getPage());
954 	UT_return_if_fail(getPage()->getDocLayout()->getView());
955 
956     if(getPage()->getDocLayout()->getView()->getShowPara() && getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN)){
957         UT_sint32 xoffBegin = pDA->xoff - getGraphics()->tlu(1);
958         UT_sint32 yoffBegin = pDA->yoff - getGraphics()->tlu(1);
959         UT_sint32 xoffEnd = pDA->xoff + m_iWidth + getGraphics()->tlu(2);
960         UT_sint32 yoffEnd = pDA->yoff + m_iMaxHeight + getGraphics()->tlu(2);
961 
962 		UT_RGBColor clrShowPara(127,127,127);
963 
964 		GR_Painter painter(getGraphics());
965 
966 		getGraphics()->setColor(clrShowPara);
967 
968         painter.drawLine(xoffBegin, yoffBegin, xoffEnd, yoffBegin);
969         painter.drawLine(xoffBegin, yoffEnd, xoffEnd, yoffEnd);
970         painter.drawLine(xoffBegin, yoffBegin, xoffBegin, yoffEnd);
971         painter.drawLine(xoffEnd, yoffBegin, xoffEnd, yoffEnd);
972     }
973 }
974 
975 /*!
976  * Returns the maximum line height as determined from the layout method
977  * This used by the draw method to determine if a line should be drawn in
978  * a clipping rectangle
979  */
_getMaxContainerHeight(void) const980 UT_sint32 fp_VerticalContainer::_getMaxContainerHeight(void) const
981 {
982 	return m_imaxContainerHeight;
983 }
984 
985 /*!
986  * Set the maximum line Height
987 \param UT_sint32 iLineHeight the largest line height yet found.
988  */
_setMaxContainerHeight(UT_sint32 iLineHeight)989 void fp_VerticalContainer::_setMaxContainerHeight( UT_sint32 iLineHeight)
990 {
991 	m_imaxContainerHeight = iLineHeight;
992 }
993 
994 
validate(void)995 bool fp_VerticalContainer::validate(void)
996 {
997 #if DEBUG
998 	UT_sint32 curTop =0;
999 	UT_sint32 curBot = 0;
1000 	UT_sint32 oldTop = -1;
1001 	UT_sint32 oldBot = -1;
1002 	UT_sint32 i =0;
1003 	bool bValid = true;
1004 	for(i=0; i<countCons();i++)
1005 	{
1006 		fp_ContainerObject* pContainer = static_cast<fp_ContainerObject*>(getNthCon(i));
1007 		curTop = pContainer->getY();
1008 		UT_sint32 iH = pContainer->getHeight();
1009 		if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1010 		{
1011 			fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pContainer);
1012 			iH = pTab->getHeight();
1013 		}
1014 		if(pContainer->getContainerType() == FP_CONTAINER_TOC)
1015 		{
1016 			fp_TOCContainer * pTOC = static_cast<fp_TOCContainer *>(pContainer);
1017 			iH = pTOC->getHeight();
1018 		}
1019 		if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1020 		{
1021 			fp_Line * pLine = static_cast<fp_Line *>(pContainer);
1022 			if(pLine->isSameYAsPrevious())
1023 			{
1024 				continue;
1025 			}
1026 		}
1027 		curBot = curTop + iH;
1028 		UT_ASSERT(oldBot <= curTop);
1029 		if(oldBot > curTop)
1030 		{
1031 			bValid =false;
1032 		}
1033 		UT_ASSERT(curBot >= curTop);
1034 		UT_ASSERT(curTop >=oldTop);
1035 		oldBot = curBot;
1036 		oldTop = curTop;
1037 	}
1038 	return bValid;
1039 #else
1040 	return true;
1041 #endif
1042 }
1043 
1044 
1045 /*!
1046  Draw container content
1047  \param pDA Draw arguments
1048  */
draw(dg_DrawArgs * pDA)1049 void fp_VerticalContainer::draw(dg_DrawArgs* pDA)
1050 {
1051 #if DEBUG
1052 //	validate();
1053 #endif
1054 	const UT_Rect * pClipRect = pDA->pG->getClipRect();
1055 	UT_sint32 ytop = 0, ybot = (UT_sint32)(((UT_uint32)(1<<31)) - 1);
1056 
1057 	if(pClipRect)
1058 	{
1059 		ytop = pClipRect->top;
1060 		ybot = UT_MAX(pClipRect->height,_getMaxContainerHeight())
1061 			+ ytop + pDA->pG->tlu(1);
1062 		xxx_UT_DEBUGMSG(("clipRect height %d \n",pClipRect->height));
1063 	}
1064 
1065 //
1066 // Only draw the lines in the clipping region.
1067 //
1068 	bool bStartedDrawing = false;
1069 	dg_DrawArgs da = *pDA;
1070 	UT_uint32 count = countCons();
1071 	UT_sint32 iCurrHeight = 0;
1072 	xxx_UT_DEBUGMSG(("number of container %d \n",count));
1073 	for (UT_uint32 i = 0; i < count; i++)
1074 	{
1075 		fp_ContainerObject* pContainer = static_cast<fp_ContainerObject*>(getNthCon(i));
1076 		if(pContainer->getY() == INITIAL_OFFSET)
1077 		  continue ; // container is not yet placed
1078 		bool bInTable = false;
1079 		bool bInTOC = false;
1080 
1081 		da.xoff = pDA->xoff + pContainer->getX();
1082 		da.yoff = pDA->yoff + pContainer->getY();
1083 		iCurrHeight = pContainer->getY() + pContainer->getHeight();
1084 		xxx_UT_DEBUGMSG(("iCurrHeight %d | m_iRedrawHeight %d\n", iCurrHeight, m_iRedrawHeight));
1085 		if((m_iRedrawHeight > 0) && (iCurrHeight >  m_iRedrawHeight))
1086 		{
1087 		    da.bDirtyRunsOnly = false;
1088 		}
1089 		xxx_UT_DEBUGMSG(("Draw container %x yoff %d\n",pContainer,da.yoff));
1090 		xxx_UT_DEBUGMSG(("Draw container %x xoff %d\n",pContainer,da.xoff));
1091 #if 0
1092 		if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1093 		{
1094 			fp_Line * pLine = static_cast<fp_Line *>(pContainer);
1095 			if(pLine->isSameYAsPrevious())
1096 			{
1097 				UT_DEBUGMSG((" !!!!!! Same previous!!!!!!!!\n"));
1098 			}
1099 		}
1100 #endif
1101 		if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1102 		{
1103 			fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pContainer);
1104 			if(pTab->isThisBroken())
1105 				da.xoff = pDA->xoff + pTab->getMasterTable()->getX();
1106 
1107 			UT_sint32 iTableBot = da.yoff + pTab->getHeight();
1108 			/* we're in the table if iTableBot < ytop, or table top > ybot */
1109 			bInTable = !(iTableBot < ytop || da.yoff > ybot);
1110 		}
1111 
1112 		if(pContainer->getContainerType() == FP_CONTAINER_TOC)
1113 		{
1114 			fp_TOCContainer * pTOC = static_cast<fp_TOCContainer *>(pContainer);
1115 			xxx_UT_DEBUGMSG(("Draw a TOC getY is %d \n",pContainer->getY()));
1116 			if(pTOC->isThisBroken())
1117 				da.xoff = pDA->xoff + pTOC->getMasterTOC()->getX();
1118 
1119 			UT_sint32 iTOCBot = da.yoff + pTOC->getHeight();
1120 			/* we're in the table if iTableBot < ytop, or table top > ybot */
1121 			bInTOC = !(iTOCBot < ytop || da.yoff > ybot);
1122 		}
1123 
1124 		UT_sint32 sumHeight = pContainer->getHeight() + (ybot-ytop);
1125 		UT_sint32 totDiff;
1126 		if(da.yoff < ytop)
1127 			totDiff = ybot - da.yoff;
1128 		else
1129 			totDiff = da.yoff + pContainer->getHeight() - ytop;
1130 
1131 //		if(bTable || (da.yoff >= ytop && da.yoff <= ybot) || (ydiff >= ytop && ydiff <= ybot))
1132 		if((bInTable || bInTOC) || (totDiff < sumHeight)  || (pClipRect == NULL))
1133 		{
1134 			bStartedDrawing = true;
1135 			pContainer->draw(&da);
1136 		}
1137 		else if(bStartedDrawing)
1138 		{
1139 			// we've started drawing and now we're not, so we're done.
1140 			break;
1141 		}
1142 	}
1143 	m_iRedrawHeight = -1;
1144 	_drawBoundaries(pDA);
1145 }
1146 
1147 /*!
1148   Find document position from X and Y coordinates
1149  \param  x X coordinate
1150  \param  y Y coordinate
1151  \retval pos Document position
1152  \retval bBOL True if position is at begining of line, otherwise false
1153  \retval bEOL True if position is at end of line, otherwise false
1154  */
mapXYToPosition(UT_sint32 x,UT_sint32 y,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool & isTOC)1155 void fp_VerticalContainer::mapXYToPosition(UT_sint32 x, UT_sint32 y, PT_DocPosition& pos,
1156 								   bool& bBOL, bool& bEOL, bool &isTOC)
1157 {
1158 	int count = countCons();
1159 	if(getContainerType() == FP_CONTAINER_TOC)
1160 	{
1161 		fl_TOCLayout * pTOCL = static_cast<fl_TOCLayout *>(getSectionLayout());
1162 		getPage()-> setLastMappedTOC(pTOCL);
1163 		isTOC = true;
1164 	}
1165 	else if(getContainerType() == FP_CONTAINER_COLUMN)
1166 	{
1167 		isTOC = false;
1168 	}
1169 	xxx_UT_DEBUGMSG(("SEVIOR: count cons %d x %d y %d \n",count,x,y));
1170 	if(count == 0)
1171 	{
1172 		xxx_UT_DEBUGMSG(("SEVIOR: In container type %d return with bBOL set \n",getContainerType()));
1173 		if(getContainerType() == FP_CONTAINER_TABLE)
1174 		{
1175 			xxx_UT_DEBUGMSG(("SEVIOR: Table container with no containers \n"));
1176 			return;
1177 		}
1178 		if(getContainerType() == FP_CONTAINER_TOC)
1179 		{
1180 			xxx_UT_DEBUGMSG(("SEVIOR: TOC container with no containers \n"));
1181 			return;
1182 		}
1183 		pos = 2;
1184 		bBOL = true;
1185 		bEOL = true;
1186 		return;
1187 	}
1188 
1189 
1190 	fp_ContainerObject* pContainer = NULL;
1191 	int i = 0;
1192 	// Find first container that contains the point. First has its lower level below the desired Y
1193 	// position. Note that X-positions are completely ignored here.
1194 	UT_sint32 iHeight = 0;
1195 	do
1196 	{
1197 		pContainer = static_cast<fp_ContainerObject*>(getNthCon(i++));
1198 		iHeight = pContainer->getHeight();
1199 		xxx_UT_DEBUGMSG(("SEVIOR: IN column looking at x %d y %d height %d \n",pContainer->getX(),pContainer->getY(),iHeight));
1200 	} while ((i < count)
1201 			 && (y > (pContainer->getY() + iHeight)));
1202 	// Undo the postincrement.
1203 	i--;
1204 	// Now check if the position is actually between the found container
1205 	// and the line before it (ignore check on the top-most line).
1206 	UT_sint32 iUHeight =0;
1207 	if (i > 0 && y < pContainer->getY())
1208 	{
1209 		fp_ContainerObject* pContainerUpper = static_cast<fp_ContainerObject*>(getNthCon(i-1));
1210 		iUHeight = pContainer->getHeight();
1211 
1212 		// Be careful with the signedness here - bug 172 leared us a
1213 		// lesson!
1214 
1215 		// Now pick the line that is closest to the point - or the
1216 		// upper if it's a stalemate.
1217 		if ((pContainer->getY() - y) >= (y - (pContainerUpper->getY() + static_cast<UT_sint32>(iUHeight))))
1218 		{
1219 			pContainer = pContainerUpper;
1220 		}
1221 	}
1222 	if(getContainerType() == FP_CONTAINER_CELL && (i == 0))
1223 	{
1224 	    fp_CellContainer *pCellCon = static_cast<fp_CellContainer *>(this);
1225 	    if((x < getX()) && (pCellCon->getLeftAttach() == 0) )
1226 	    {
1227 		fl_CellLayout * pCL = static_cast<fl_CellLayout *>(getSectionLayout());
1228 		pos = pCL->getPosition(true)+2;
1229 		bBOL = true;
1230 		bEOL = false;
1231 		//		if((pCellCon->getTopAttach() == 0))
1232 		//  pos--;
1233 		return;
1234 	    }
1235 	}
1236 	if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1237 	{
1238 		xxx_UT_DEBUGMSG(("SEVIOR: Looking in a table \n"));
1239 		fp_TableContainer * pTab = static_cast<fp_TableContainer *>(pContainer);
1240 		xxx_UT_DEBUGMSG(("SEVIOR: do map to position for %x \n",pContainer));
1241 		pTab->mapXYToPosition(x - pContainer->getX(),
1242 								y - pContainer->getY() ,
1243 								pos, bBOL, bEOL,isTOC);
1244 	}
1245 	else if(pContainer->getContainerType() == FP_CONTAINER_FRAME)
1246 	{
1247 		fp_FrameContainer * pFrame = static_cast<fp_FrameContainer *>(pContainer);
1248 		fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pFrame->getSectionLayout());
1249 		if(pFL->getFrameType() == FL_FRAME_WRAPPER_IMAGE)
1250 		{
1251 			pos = pFL->getPosition(true);
1252 			return;
1253 		}
1254 		else
1255 		{
1256 			pContainer->mapXYToPosition(x - pContainer->getX(),
1257 										y - pContainer->getY() ,
1258 										pos, bBOL, bEOL,isTOC);
1259 		}
1260 
1261 	}
1262 	else if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1263 	{
1264 //
1265 // Deal with wrapped lines where more than one line can have the same Y
1266 //
1267 		fp_Line * pLine2 = static_cast<fp_Line *>(pContainer);
1268 		if(pLine2->isWrapped())
1269 		{
1270 			fp_Line * pNext = static_cast<fp_Line *>(pLine2->getNext());
1271 			if(pNext && pNext->isSameYAsPrevious())
1272 			{
1273 				fp_ContainerObject *pBest = pContainer;
1274 				UT_sint32 xmin = UT_MIN(abs(pNext->getX() - x),abs(pNext->getX()+pNext->getMaxWidth() -x));
1275 				while(pNext && pNext->isSameYAsPrevious())
1276 				{
1277 					if((pNext->getX() < x) && (x < pNext->getX() + pNext->getMaxWidth()))
1278 					{
1279 						pNext->mapXYToPosition(x - pNext->getX(),
1280 											   y - pNext->getY() ,
1281 											   pos, bBOL, bEOL,isTOC);
1282 						return;
1283 					}
1284 					UT_sint32 xmin1 = UT_MIN(abs(pNext->getX() - x),abs(pNext->getX()+pNext->getMaxWidth() -x));
1285 					if(xmin1 < xmin)
1286 					{
1287 						xmin = xmin1;
1288 						pBest = static_cast<fp_ContainerObject *>(pNext);
1289 					}
1290 					pNext = static_cast<fp_Line *>(pNext->getNext());
1291 				}
1292 				pBest->mapXYToPosition(x - pContainer->getX(),
1293 									   y - pContainer->getY() ,
1294 									   pos, bBOL, bEOL,isTOC);
1295 				return;
1296 			}
1297 			else
1298 			{
1299 				pContainer->mapXYToPosition(x - pContainer->getX(),
1300 											y - pContainer->getY() ,
1301 											pos, bBOL, bEOL,isTOC);
1302 			}
1303 		}
1304 		else if(!pLine2->canContainPoint())
1305 		{
1306 			// lines that cannot contain point are those that are located in blocks that
1307 			// cannot contain point (hidden, collapsed, etc. So we need to find the block
1308 			// that can contain point
1309 			fl_BlockLayout * pBlock = pLine2->getBlock();
1310 			UT_return_if_fail( pBlock );
1311 
1312 			pBlock = pBlock->getNextBlockInDocument();
1313 
1314 			while(pBlock && !pBlock->canContainPoint())
1315 			{
1316 				pBlock = pBlock->getNextBlockInDocument();
1317 			}
1318 
1319 			if(!pBlock)
1320 			{
1321 				// look the other way (reusing pNext, even though it will be previous)
1322 				pBlock = pLine2->getBlock();
1323 
1324 				pBlock = pBlock->getPrevBlockInDocument();
1325 
1326 				while(pBlock && !pBlock->canContainPoint())
1327 				{
1328 					pBlock = pBlock->getPrevBlockInDocument();
1329 				}
1330 
1331 			}
1332 
1333 			if(!pBlock)
1334 			{
1335 				// we are in trouble
1336 				// no blocks that can take point in this document !!!
1337 				// one of the scenarios in which this happens is when the user did ctrl+a -> del
1338 				// in revisions mode or marked everything hidden while fmt marks are not showing
1339 				// If there is a block and it is not visible, we return that block
1340 				// Note that it is difficult to prevent this from happening on the PT level, since
1341 				// just because text is marked as hidden or deleted does not mean it is not
1342 				// visible in a given view.
1343 				fp_Page * pPage = getPage();
1344 				if(pPage && pPage->getDocLayout() && pPage->getDocLayout()->getFirstSection())
1345 				{
1346 					pBlock = pPage->getDocLayout()->getFirstSection()->getFirstBlock();
1347 				}
1348 
1349 				if(!pBlock)
1350 				{
1351 					UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
1352 				}
1353 				else
1354 				{
1355 					fp_Run * pFirstRun = pBlock->getFirstRun();
1356 
1357 					if(pFirstRun)
1358 					{
1359 						fp_Line * pLine = pFirstRun->getLine();
1360 						if(pLine)
1361 						{
1362 							pLine->mapXYToPosition(x - pLine->getX(),
1363 												   y - pLine->getY() ,
1364 												   pos, bBOL, bEOL,isTOC);
1365 						}
1366 
1367 					}
1368 				}
1369 			}
1370 			else
1371 			{
1372 				fp_Run * pFirstRun = pBlock->getFirstRun();
1373 
1374 				if(pFirstRun)
1375 				{
1376 					fp_Line * pVisibleLine = pFirstRun->getLine();
1377 
1378 					if(pVisibleLine)
1379 					{
1380 #if 0
1381 						// !!! This results in an endless loop (bug 7420)
1382 						// get the container that holds this line, so we deal with wrapped
1383 						// lines, etc.
1384 						fp_Container * pVisibleContainer = pVisibleLine->getContainer();
1385 
1386 						pVisibleContainer->mapXYToPosition(x - pContainer->getX(),
1387 													  y - pContainer->getY() ,
1388 													  pos, bBOL, bEOL,isTOC);
1389 
1390 #else
1391 						pVisibleLine->mapXYToPosition(x - pVisibleLine->getX(),
1392 													  y - pVisibleLine->getY() ,
1393 													  pos, bBOL, bEOL,isTOC);
1394 #endif
1395 						return;
1396 					}
1397 
1398 					UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
1399 				}
1400 				else
1401 				{
1402 					UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
1403 				}
1404 			}
1405 		}
1406 
1407 		pContainer->mapXYToPosition(x - pContainer->getX(),
1408 								y - pContainer->getY() ,
1409 									pos, bBOL, bEOL,isTOC);
1410 	}
1411 	else
1412 	{
1413 		xxx_UT_DEBUGMSG(("SEVIOR: do map to position for %x \n",pContainer));
1414 		pContainer->mapXYToPosition(x - pContainer->getX(),
1415 								y - pContainer->getY() ,
1416 									pos, bBOL, bEOL,isTOC);
1417 		xxx_UT_DEBUGMSG(("SEVIOR: Found pos %d in column \n",pos));
1418 	}
1419 }
1420 
1421 /*!
1422  Compute the distance from point to the container's circumference
1423  \param x X coordinate of point
1424  \param y Y coordinate of point
1425  \return Distance between container's circumference and point
1426  */
distanceFromPoint(UT_sint32 x,UT_sint32 y)1427 UT_uint32 fp_VerticalContainer::distanceFromPoint(UT_sint32 x, UT_sint32 y)
1428 {
1429 	UT_sint32 dx;
1430 	UT_sint32 dy;
1431 
1432 	if (x < m_iX)
1433 	{
1434 		dx = m_iX - x;
1435 	}
1436 	else if (x > (m_iX + m_iWidth - getGraphics()->tlu(1)))
1437 	{
1438 		dx = x - (m_iX + m_iWidth - getGraphics()->tlu(1));
1439 	}
1440 	else
1441 	{
1442 		dx = 0;
1443 	}
1444 
1445 	if (y < m_iY)
1446 	{
1447 		dy = m_iY - y;
1448 	}
1449 	else if (y > (m_iY + m_iHeight - getGraphics()->tlu(1)))
1450 	{
1451 		dy = y - (m_iY + m_iHeight - getGraphics()->tlu(1));
1452 	}
1453 	else
1454 	{
1455 		dy = 0;
1456 	}
1457 
1458 	if (dx == 0)
1459 	{
1460 		return dy;
1461 	}
1462 
1463 	if (dy == 0)
1464 	{
1465 		return dx;
1466 	}
1467 
1468 	UT_uint32 dist = (UT_uint32) (sqrt((float)(dx * dx) + (dy * dy)));
1469 
1470 //	UT_ASSERT(dist > 0);
1471 
1472 	return dist;
1473 }
1474 
1475 /*!
1476  Set X position of container
1477  \param iX New X position
1478 
1479  Before the postition of the container is changed, its content is
1480  first cleared from the screen.
1481  */
setX(UT_sint32 iX,bool)1482 void fp_VerticalContainer::setX(UT_sint32 iX, bool /*bDontClearIfNeeded*/)
1483 {
1484 	if (iX == m_iX)
1485 	{
1486 		return;
1487 	}
1488 
1489 	clearScreen();
1490 
1491 	m_iX = iX;
1492 }
1493 
1494 /*!
1495  Set Y position of container
1496  \param iY New Y position
1497 
1498  Before the postition of the container is changed, its content is
1499  first cleared from the screen.
1500  */
setY(UT_sint32 iY)1501 void fp_VerticalContainer::setY(UT_sint32 iY)
1502 {
1503 	if (iY == m_iY)
1504 	{
1505 		return;
1506 	}
1507 	if(m_iY != -99999999)
1508 	{
1509 		clearScreen();
1510 	}
1511 	m_iY = iY;
1512 }
1513 
1514 /*!
1515  Return first line in the container
1516  \return The first line, or NULL if the container is empty
1517  */
getFirstContainer(void) const1518 fp_Container* fp_VerticalContainer::getFirstContainer(void) const
1519 {
1520 	if (countCons() > 0)
1521 	{
1522 		return static_cast<fp_Container*>(getNthCon(0));
1523 	}
1524 	else
1525 	{
1526 		return NULL;
1527 	}
1528 }
1529 
countWrapped(void)1530 UT_sint32  fp_VerticalContainer::countWrapped(void)
1531 {
1532   UT_sint32 nWrapped = 0;
1533   UT_sint32 i = 0;
1534   for(i=0; i<countCons();i++)
1535   {
1536       fp_Container * pCon = static_cast<fp_Container*>(getNthCon(i));
1537       if(pCon->getContainerType() == FP_CONTAINER_LINE)
1538       {
1539 	  fp_Line * pLine = static_cast<fp_Line *>(pCon);
1540 	  xxx_UT_DEBUGMSG(("Line %d MaxWidth %d \n",i,pLine->getMaxWidth()));
1541 	  if(pLine->isWrapped())
1542 	  {
1543 	      nWrapped++;
1544 	  }
1545 	  else if(pLine->isSameYAsPrevious())
1546 	  {
1547 	      nWrapped++;
1548 	  }
1549 	  else if((pLine->getMaxWidth() > 0) && (pLine->getMaxWidth() < getWidth()))
1550 	  {
1551 	      nWrapped++;
1552 
1553 	  }
1554       }
1555   }
1556   return nWrapped;
1557 }
1558 
1559 
1560 /*!
1561  Return last line in the container
1562  \return The last line, or NULL if the container is empty
1563  */
getLastContainer(void) const1564 fp_Container* fp_VerticalContainer::getLastContainer(void) const
1565 {
1566 	UT_uint32 iCount = countCons();
1567 
1568 	if (iCount > 0)
1569 	{
1570 		return static_cast<fp_Container*>(getNthCon(iCount - 1));
1571 	}
1572 	else
1573 	{
1574 		return NULL;
1575 	}
1576 }
1577 
1578 
1579 /*!
1580   Bump Containers from this Container to the next
1581   \param pLastContainerToKeep Last line to keep in this column or NULL for none
1582 */
bumpContainers(fp_ContainerObject * pLastContainerToKeep)1583 void fp_VerticalContainer::bumpContainers(fp_ContainerObject* pLastContainerToKeep)
1584 {
1585 	UT_sint32 ndx = (NULL == pLastContainerToKeep) ? 0 : (findCon(pLastContainerToKeep)+1);
1586 	xxx_UT_DEBUGMSG(("!!!---Bump Containers LastToKeep %x Index %d \n",pLastContainerToKeep,ndx));
1587 	UT_ASSERT(ndx >= 0);
1588 	UT_sint32 i;
1589 	fp_TOCContainer *pTOC2 = NULL;
1590 	fp_VerticalContainer* pNextContainer = static_cast<fp_VerticalContainer*>(getNext());
1591 	UT_return_if_fail(pNextContainer);
1592 	UT_return_if_fail((pNextContainer->getContainerType() == FP_CONTAINER_ENDNOTE) || (pNextContainer->getDocSectionLayout() == getDocSectionLayout()));
1593 	if (pNextContainer->isEmpty())
1594 	{
1595 		for (i=ndx; i< countCons(); i++)
1596 		{
1597 			if(i >= countCons())
1598 			         continue;
1599 			fp_Container* pContainer = static_cast<fp_Container*>(getNthCon(i));
1600 			if(pContainer == NULL)
1601 			        continue;
1602 			pContainer->clearScreen();
1603 //
1604 // Experimental code: FIXME: Might remove after a while - check
1605 // that large tables broken over many pages work fine.
1606 //
1607 #if 1
1608 			if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1609 			{
1610 				fp_TableContainer *pTab = static_cast<fp_TableContainer *>(pContainer);
1611 				if(!pTab->isThisBroken())
1612 				{
1613 					pTab->deleteBrokenTables(true);
1614 				}
1615 			}
1616 			if(pContainer->getContainerType() == FP_CONTAINER_TOC)
1617 			{
1618 				fp_TOCContainer *pTOC = static_cast<fp_TOCContainer *>(pContainer);
1619 				xxx_UT_DEBUGMSG(("Found TOC %x index %d prev %x to bump to Empty Col \n",pTOC,i,pTOC->getPrevContainerInSection()));
1620 				if(!pTOC->isThisBroken())
1621 				{
1622 					pTOC->deleteBrokenTOCs(true);
1623 				}
1624 			}
1625 #endif
1626 			pNextContainer->addContainer(pContainer);
1627 		}
1628 	}
1629 	else
1630 	{
1631 		bool bTOC = false;
1632 		for (i=countCons() - 1; i >= ndx; i--)
1633 		{
1634 			bTOC = false;
1635 			if(i >= countCons())
1636 			         continue;
1637 			fp_Container* pContainer = static_cast<fp_Container*>(getNthCon(i));
1638 			if(pContainer == NULL)
1639 			        continue;
1640 			xxx_UT_DEBUGMSG(("clearScreen on %x in bumpContainers \n",pContainer));
1641 			pContainer->clearScreen();
1642 //
1643 // Experimental code: FIXME: Might remove after a while - check
1644 // that large tables broken over many pages work fine.
1645 //
1646 #if 1
1647 			if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1648 			{
1649 				fp_TableContainer *pTab = static_cast<fp_TableContainer *>(pContainer);
1650 				if(!pTab->isThisBroken())
1651 				{
1652 					pTab->deleteBrokenTables(true);
1653 				}
1654 			}
1655 			if(pContainer->getContainerType() == FP_CONTAINER_TOC)
1656 			{
1657 				pTOC2 = static_cast<fp_TOCContainer *>(pContainer);
1658 				xxx_UT_DEBUGMSG(("Found TOC %x index %d prev %x to bump to filled Col \n",pTOC2,i,pTOC2->getPrevContainerInSection()));
1659 				if(!pTOC2->isThisBroken())
1660 				{
1661 					pTOC2->deleteBrokenTOCs(true);
1662 				}
1663 				bTOC = true;
1664 			}
1665 #endif
1666 			fp_Line * pLine = NULL;
1667 			UT_sint32 iOldMaxWidth = 0;
1668 			if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1669 			{
1670 			    pLine =  static_cast<fp_Line *>(pContainer);
1671 			    iOldMaxWidth = pLine->getMaxWidth();
1672 			}
1673 			pNextContainer->insertContainer(pContainer);
1674 			//
1675 			// Max Line widths can change after a bump. If so
1676 			// we must reformat from the start of the line
1677 			//
1678 			if(pLine && (pLine->getMaxWidth() != iOldMaxWidth))
1679 			{
1680 			    UT_DEBUGMSG(("MaxWidthChanged from container bump \n"));
1681 			    pLine->setReformat();
1682 			}
1683 			if(bTOC)
1684 			{
1685 				//UT_sint32 iTOC = pNextContainer->findCon(pContainer);
1686 				xxx_UT_DEBUGMSG(("TOC insert at location %d in next Container \n",iTOC));
1687 			}
1688 		}
1689 	}
1690 	if(pTOC2)
1691 	{
1692 		//UT_sint32 iTOC = pNextContainer->findCon(pTOC);
1693 		xxx_UT_DEBUGMSG(("TOC Final location %d in next Container \n",iTOC));
1694 	}
1695 	for (i=countCons() - 1; i >= ndx; i--)
1696 	{
1697 		deleteNthCon(i);
1698 	}
1699 }
1700 
1701 
1702 /*!
1703   Create column
1704   \param pSectionLayout Section layout type used for this container
1705 
1706   The section the column is created in specifies the number of column
1707   rows. There is always created columns for all rows at the same
1708   time. The first (left-most) column is the leader.
1709 
1710   \fixme I suspect BIDI does not work with multiple columns since the
1711          leader would then have to be the right-most column.
1712 */
fp_Column(fl_SectionLayout * pSectionLayout)1713 fp_Column::fp_Column(fl_SectionLayout* pSectionLayout) : fp_VerticalContainer(FP_CONTAINER_COLUMN, pSectionLayout),
1714   m_pLeader(NULL),
1715   m_pFollower(NULL),
1716   m_pPage(NULL)
1717 {
1718 }
1719 
~fp_Column()1720 fp_Column::~fp_Column()
1721 {
1722 	xxx_UT_DEBUGMSG(("Deleting Column %x Number containers left %d \n",this,countCons()));
1723 //	UT_ASSERT(countCons() == 0);
1724 }
1725 
1726 /*!
1727  * This method should be called before a docsection collapse since we can't
1728  * be sure that the docsection that owns this column also contains the endnote
1729  * in this column
1730  */
collapseEndnotes(void)1731 void fp_Column::collapseEndnotes(void)
1732 {
1733 	UT_sint32 i = 0;
1734 	for(i=countCons()-1; i>= 0; i--)
1735 	{
1736 		fp_Container * pCon = static_cast<fp_Container *>(getNthCon(i));
1737 		if(pCon->getContainerType() == FP_CONTAINER_ENDNOTE)
1738 		{
1739 			fl_EndnoteLayout * pEL = static_cast<fl_EndnoteLayout *>(pCon->getSectionLayout());
1740 			pEL->collapse();
1741 			UT_sint32 ndx = findCon(pCon);
1742 			if(ndx >= 0)
1743 			{
1744 				justRemoveNthCon(ndx);
1745 			}
1746 		}
1747 	}
1748 }
1749 
1750 
1751 /*!
1752  * Returns true of the column contains a page break.
1753  */
containsPageBreak(void) const1754 bool fp_Column::containsPageBreak(void) const
1755 {
1756     fp_Container * pCon = getLastContainer();
1757     if(pCon && (pCon->getContainerType() ==FP_CONTAINER_LINE))
1758     {
1759 	fp_Line * pLine = static_cast<fp_Line *>(pCon);
1760 	return pLine->containsForcedPageBreak();
1761     }
1762     return false;
1763 }
1764 
setPage(fp_Page * pPage)1765 void fp_Column::setPage(fp_Page * pPage)
1766 {
1767 	if(pPage == NULL)
1768 	{
1769 		getFillType().setParent(NULL);
1770 	}
1771 	else
1772 	{
1773 		getFillType().setParent(&pPage->getFillType());
1774 	}
1775 	m_pPage = pPage;
1776 }
1777 
1778 /* Return the index of the column on its page*/
getColumnIndex(void)1779 UT_sint32 fp_Column::getColumnIndex(void)
1780 {
1781     fp_Page * pPage = getPage();
1782     fl_DocSectionLayout * pSection = getDocSectionLayout();
1783     fp_Column * pCol = NULL;
1784     if (!pPage || !pSection)
1785     {return 0;}
1786     UT_sint32 kmax = static_cast<UT_sint32>(pSection->getNumColumns());
1787     UT_sint32 j;
1788     for(j=0;j<pPage->countColumnLeaders();j++)
1789     {
1790 	pCol = pPage->getNthColumnLeader(j);
1791 	if (pCol && (pCol->getDocSectionLayout() == pSection))
1792 	{
1793 	    UT_sint32 k = 0;
1794 	    while(pCol && k<kmax)
1795 	    {
1796 		if (pCol == this)
1797 		{return k;}
1798 		pCol = static_cast<fp_Column *> (pCol->getNext());
1799 		k++;
1800 	    }
1801 	}
1802     }
1803     return 0;
1804 }
1805 /*!
1806  Draw column outline
1807  \param pDA Draw arguments
1808 
1809  This differs from the container function in that it will use draw the
1810  outline based on the tallest column in the row.
1811 */
_drawBoundaries(dg_DrawArgs * pDA)1812 void fp_Column::_drawBoundaries(dg_DrawArgs* pDA)
1813 {
1814 	if(!pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN))
1815 	{
1816 		return;
1817 	}
1818     if(getPage()->getDocLayout()->getView()->getShowPara() && getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN))
1819     {
1820         getGraphics()->setColor(getPage()->getDocLayout()->getView()->getColorShowPara());
1821         UT_sint32 xoffBegin = pDA->xoff - getGraphics()->tlu(1);
1822         UT_sint32 yoffBegin = pDA->yoff - getGraphics()->tlu(1);
1823         UT_sint32 xoffEnd = pDA->xoff + getWidth() + getGraphics()->tlu(2);
1824 
1825         UT_sint32 iHeight = 0;
1826 		fp_Column* pCol = getLeader();
1827 		if (getPage()->getNthColumnLeader(getPage()->countColumnLeaders()-1) == pCol)
1828 		{
1829 			// If there's no column rows after this one on the page, use max height
1830 			iHeight = getMaxHeight();
1831 		}
1832 		else
1833 		{
1834 			// Find max column height in row
1835 			while (pCol)
1836 			{
1837 				if (pCol->getHeight() > iHeight)
1838 					iHeight = pCol->getHeight();
1839 				pCol = pCol->getFollower();
1840 			}
1841 		}
1842 		UT_sint32 yoffEnd = pDA->yoff + iHeight + getGraphics()->tlu(2);
1843 
1844 		GR_Painter painter(getGraphics());
1845 
1846 		getGraphics()->setLineProperties(getGraphics()->tlu(1),
1847 											GR_Graphics::JOIN_MITER,
1848 											GR_Graphics::CAP_PROJECTING,
1849 											GR_Graphics::LINE_SOLID);
1850 
1851        	painter.drawLine(xoffBegin, yoffBegin, xoffEnd, yoffBegin);
1852 		painter.drawLine(xoffBegin, yoffEnd, xoffEnd, yoffEnd);
1853         painter.drawLine(xoffBegin, yoffBegin, xoffBegin, yoffEnd);
1854         painter.drawLine(xoffEnd, yoffBegin, xoffEnd, yoffEnd);
1855     }
1856 }
1857 
1858 /*!
1859   Layout lines in the column
1860 
1861   This function iterates over the lines in the column and computes
1862   their screen position from their accumulative heights in layout
1863   units.
1864 
1865   Since this code accumulates fractions of the conversion process, the
1866   difference between Y positions of two lines may differ from the
1867   pre-computed height of the upper line. This is due to simple
1868   rounding errors and general lack of precision (screen coordinates
1869   are integer while the computation yields fractions).
1870 
1871   To make XY/position conversion precise, remove the gaps by updating
1872   the line heights. Note that the line heights get updated next time
1873   there's a line lookup - so this does not in any way affect layout,
1874   only the precision of the XY/position conversion code.
1875 
1876   Sevior: I put in the 0.5 to deal with truncation errors and the +1 to deal
1877   with the last line.
1878 
1879   \see fp_Line::setAssignedScreenHeight, fp_Container::recalcHeight
1880 */
layout(void)1881 void fp_Column::layout(void)
1882 {
1883 	clearWrappedLines();
1884 	_setMaxContainerHeight(0);
1885 	UT_sint32 iY = 0, iPrevY2 = 0;
1886 	UT_sint32 iContainerMarginAfter = 0;
1887 	UT_GenericVector<fl_BlockLayout *> vecBlocks;
1888 	fp_Line * pLastLine = NULL;
1889 	fp_Container *pContainer = NULL;
1890 	fp_Container *pPrevContainer = NULL;
1891 	UT_sint32 i  = 0;
1892 	//
1893 	// RedrawHeight makes sure we redraw from whereever a line
1894 	// changes position.
1895 	//
1896 	m_iRedrawHeight = -1;
1897 	for (i=0; i < countCons(); i++)
1898 	{
1899 		pContainer = static_cast<fp_Container*>(getNthCon(i));
1900 
1901 		// ignore footnotes
1902 		if (pContainer->getContainerType() == FP_CONTAINER_FOOTNOTE)
1903 			continue;
1904 		// ignore annotations
1905 		if (pContainer->getContainerType() == FP_CONTAINER_ANNOTATION)
1906 			continue;
1907 
1908 		xxx_UT_DEBUGMSG(("Column Layout: Container %d Container %x Type %d \n",i,pContainer,pContainer->getContainerType()));
1909 //
1910 // Set the location first so the height of a table can be calculated
1911 // and adjusted.
1912 //
1913 		if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1914 		{
1915 //
1916 // Handle case of lines broken around a positioned object with text wrap on
1917 //
1918 			fp_Line * pLine = static_cast<fp_Line *>(pContainer);
1919 			xxx_UT_DEBUGMSG(("Line %x X %d Y %d MaxWidth %d Width %d Height %d \n",pLine,pLine->getX(),pLine->getY(),pLine->getMaxWidth(),pLine->getWidth(),pLine->getHeight()));
1920 			if(pLine->isWrapped())
1921 			{
1922 				addWrappedLine(pLine);
1923 			}
1924 #if 0
1925 			else if((pLine->getMaxWidth() > 0) && (pLine->getMaxWidth() < getWidth()))
1926 			{
1927 				addWrappedLine(pLine);
1928 			}
1929 #endif
1930 			if(pLine->isSameYAsPrevious() && pLine->getPrev())
1931 			{
1932 				UT_sint32 iPrevY = static_cast<fp_Line *>(pLine->getPrev())->getY();
1933 				if(pLine->getY() != iPrevY)
1934 				{
1935 					pLine->clearScreen();
1936 					pLine->setY(iPrevY);
1937 				}
1938 				pPrevContainer = pLine;
1939 				xxx_UT_DEBUGMSG(("Layout: %x SameY container %d getY %d getX %d width %d \n",pLine,i,pLine->getY(),pLine->getX(),pLine->getMaxWidth()));
1940 				continue;
1941 			}
1942 		}
1943 		if(pContainer->getY() != iY)
1944 		{
1945 			pContainer->clearScreen();
1946 			if((m_iRedrawHeight == -1) && (pContainer->getY() > 0))
1947 			  m_iRedrawHeight = pContainer->getY();
1948 
1949 		}
1950 		xxx_UT_DEBUGMSG(("Layout: container %d Height %d setY %d \n",i,iY));
1951 //
1952 // fxime comeback and re-evaluate this
1953 //		UT_ASSERT(iY>=0);
1954 		pContainer->setY(iY);
1955 //		UT_ASSERT(iY == pContainer->getY());
1956 		//UT_ASSERT(pContainer->getY() == iY);
1957 //
1958 // This is to speedup redraws.
1959 //
1960 		fp_TableContainer * pTab = NULL;
1961 		fp_TOCContainer * pTOC = NULL;
1962 		UT_sint32 iHeight = pContainer->getHeight();
1963 		if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
1964 		{
1965 			pTab = static_cast<fp_TableContainer *>(pContainer);
1966 			iHeight = pTab->getHeight();
1967 		}
1968 		if(pContainer->getContainerType() == FP_CONTAINER_TOC)
1969 		{
1970 			pTOC = static_cast<fp_TOCContainer *>(pContainer);
1971 			iHeight = pTOC->getHeight();
1972 			// This is incorrect; if the TOC has been delete in revisions mode, is will
1973 			// have 0 height
1974 			// UT_ASSERT(iHeight > 0);
1975 		}
1976 		else if(pContainer->getContainerType() == FP_CONTAINER_LINE)
1977 		{
1978 			pLastLine = static_cast<fp_Line *>(pContainer);
1979 			iHeight = pLastLine->getHeight();
1980 			UT_sint32 count = vecBlocks.getItemCount();
1981 			if(count == 0)
1982 			{
1983 				vecBlocks.addItem(pLastLine->getBlock());
1984 			}
1985 			else
1986 			{
1987 				if(vecBlocks.getNthItem(count-1) != pLastLine->getBlock())
1988 				{
1989 					vecBlocks.addItem(pLastLine->getBlock());
1990 				}
1991 			}
1992 		}
1993 		if(iHeight > _getMaxContainerHeight())
1994 		{
1995 			_setMaxContainerHeight(iHeight);
1996 		}
1997 		UT_sint32 iContainerHeight = iHeight;
1998 		if(pTab)
1999 		{
2000 			iContainerHeight = pTab->getHeight();
2001 		}
2002 		if(pTOC)
2003 		{
2004 			iContainerHeight = pTOC->getHeight();
2005 		}
2006 		iContainerMarginAfter = pContainer->getMarginAfter();
2007 		xxx_UT_DEBUGMSG(("Layout: container %d Height %d Margin %d setY %d \n",i,iContainerHeight,iContainerMarginAfter,iY));
2008 		//	UT_ASSERT(iContainerHeight > 0);
2009 		// Update height of previous line now we know the gap between
2010 		// it and the current line.
2011 		if (pPrevContainer)
2012 		{
2013 			if(pPrevContainer->getContainerType() == FP_CONTAINER_LINE)
2014 			{
2015 				fp_Line * pLine = static_cast<fp_Line *>(pPrevContainer);
2016 				while(pLine && pLine->isSameYAsPrevious())
2017 				{
2018 					pLine->setAssignedScreenHeight(iY - iPrevY2);
2019 					pLine = static_cast<fp_Line *>(pLine->getPrev());
2020 				}
2021 				if(pLine)
2022 				{
2023 					pLine->setAssignedScreenHeight(iY - iPrevY2);
2024 				}
2025 			}
2026 			else
2027 			{
2028 				xxx_UT_DEBUGMSG(("layout: Assigned screen height %x %d \n",pPrevContainer,iY-iPrevY2));
2029 				pPrevContainer->setAssignedScreenHeight(iY - iPrevY2);
2030 			}
2031 		}
2032 		iPrevY2 = iY;
2033 		iY += iContainerHeight;
2034 		iY += iContainerMarginAfter;
2035 #if DEBUG
2036 		if (iY - iContainerMarginAfter > getMaxHeight())
2037 		{
2038 			UT_DEBUGMSG(("Problem; MaxColHeight: %d present height: %d\n",
2039 						 getMaxHeight(), iY - iContainerMarginAfter));
2040 			UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2041 		}
2042 #endif
2043 		pPrevContainer = pContainer;
2044 	}
2045 	// Correct height position of the last line
2046 	if (pPrevContainer)
2047 	{
2048 		UT_ASSERT((iY - iPrevY2 + getGraphics()->tlu(1)) > 0);
2049 		iY -= iContainerMarginAfter;
2050 		if(pPrevContainer->getContainerType() == FP_CONTAINER_LINE)
2051 		{
2052 			fp_Line * pLine = static_cast<fp_Line *>(pPrevContainer);
2053 			while(pLine && pLine->isSameYAsPrevious())
2054 			{
2055 				pLine->setAssignedScreenHeight(iY - iPrevY2);
2056 				pLine = static_cast<fp_Line *>(pLine->getPrev());
2057 			}
2058 			if(pLine)
2059 			{
2060 				pLine->setAssignedScreenHeight(iY - iPrevY2);
2061 			}
2062 		}
2063 	}
2064 //
2065 // Set the frames on the page
2066 //
2067 	UT_sint32 count = vecBlocks.getItemCount();
2068 	for(i=0; i < count; i++)
2069 	{
2070 		fl_BlockLayout * pBlock = vecBlocks.getNthItem(i);
2071 		if(i < count -1)
2072 		{
2073 			pBlock->setFramesOnPage(NULL);
2074 		}
2075 		else
2076 		{
2077 			pBlock->setFramesOnPage(pLastLine);
2078 		}
2079 	}
2080 //	validate();
2081 
2082 	if (getHeight() == iY)
2083 	{
2084 		return;
2085 	}
2086 
2087 	setHeight(iY);
2088 	getPage()->columnHeightChanged(this);
2089 	fl_DocSectionLayout * pDSL = getPage()->getOwningSection();
2090 	pDSL = pDSL->getNextDocSection();
2091 	while(pDSL)
2092 	{
2093 		pDSL->setNeedsSectionBreak(true,NULL);
2094 		pDSL = pDSL->getNextDocSection();
2095 	}
2096 }
2097 
getMaxHeight(void) const2098 UT_sint32 fp_Column::getMaxHeight(void) const
2099 {
2100 	const fp_VerticalContainer * pVC = static_cast<const fp_VerticalContainer *>(this);
2101 	UT_sint32 iMaxHeight = 0;
2102 	if(!getPage())
2103 	{
2104 		iMaxHeight = pVC->getMaxHeight();
2105 	}
2106 	else
2107 	{
2108 	        iMaxHeight = getPage()->getAvailableHeightForColumn(this);
2109 	}
2110 	//UT_ASSERT(iMaxHeight > 0);
2111 	return iMaxHeight;
2112 }
2113 
getDocSectionLayout(void) const2114 fl_DocSectionLayout* fp_Column::getDocSectionLayout(void) const
2115 {
2116 	UT_ASSERT(getSectionLayout()->getType() == FL_SECTION_DOC ||
2117 			  getSectionLayout()->getType() == FL_SECTION_HDRFTR ||
2118 			  getSectionLayout()->getType() == FL_SECTION_ENDNOTE);
2119 
2120 	return static_cast<fl_DocSectionLayout*>(getSectionLayout());
2121 }
2122 
2123 /*!
2124  * This container is actually to display HdrFtrShadows which are repeated
2125  * for every page in the document. If the text is too high it is clipped to
2126  * to fit in the container. It's up to the user to adjust the height of the
2127  * header/footer region to fit the text.
2128  */
fp_ShadowContainer(UT_sint32 iX,UT_sint32 iY,UT_sint32 iWidth,UT_sint32 iHeight,fl_SectionLayout * pSectionLayout)2129 fp_ShadowContainer::fp_ShadowContainer(UT_sint32 iX,
2130 									   UT_sint32 iY,
2131 									   UT_sint32 iWidth,
2132 									   UT_sint32 iHeight,
2133 									   fl_SectionLayout* pSectionLayout)
2134 	: fp_VerticalContainer(FP_CONTAINER_COLUMN_SHADOW, pSectionLayout)
2135 {
2136 	_setX(iX);
2137 	_setY(iY);
2138 	setWidth(iWidth);
2139 	setHeight(iHeight);
2140 	setMaxHeight(iHeight);
2141    m_bHdrFtrBoxDrawn = false;
2142 }
2143 
~fp_ShadowContainer()2144 fp_ShadowContainer::~fp_ShadowContainer()
2145 {
2146   xxx_UT_DEBUGMSG(("Delete Shadow Container %x from shadow Layout %x \n",this,getSectionLayout()));
2147   getSectionLayout()->setFirstContainer(NULL);
2148 }
2149 
2150 
layout(void)2151 void fp_ShadowContainer::layout(void)
2152 {
2153 	layout(false);
2154 }
2155 
layout(bool bForceLayout)2156 void fp_ShadowContainer::layout(bool bForceLayout)
2157 {
2158 	UT_sint32 iY = 5;
2159 	UT_uint32 iCountContainers = countCons();
2160 	FV_View * pView = getPage()->getDocLayout()->getView();
2161 	bool doLayout = true;
2162 	if(pView)
2163 	{
2164 	    doLayout =	pView->getViewMode() == VIEW_PRINT;
2165 	}
2166 	if(bForceLayout)
2167 	{
2168 		doLayout = true;
2169 	}
2170 	for (UT_uint32 i=0; i < iCountContainers; i++)
2171 	{
2172 		fp_Container* pContainer = static_cast<fp_Container*>(getNthCon(i));
2173 		fp_TableContainer * pTab = NULL;
2174 		fp_TOCContainer * pTOC = NULL;
2175 		if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
2176 		{
2177 			pTab = static_cast<fp_TableContainer *>(pContainer);
2178 			xxx_UT_DEBUGMSG(("Found Table in shadow!!! height = %d \n",pTab->getHeight()));
2179 		}
2180 		else if(pContainer->getContainerType() == FP_CONTAINER_TOC)
2181 		{
2182 			pTOC = static_cast<fp_TOCContainer *>(pContainer);
2183 			UT_DEBUGMSG(("Found TOC in shadow!!!\n"));
2184 		}
2185 //
2186 // FIXME: Implement this one day. Tables in header/footers.
2187 //		if((pTab!= NULL) && !pTab->isThisBroken())
2188 //		{
2189 //			fp_Container * pBroke = static_cast<fp_Container *>(pTab->VBreakAt(0));
2190 //		}
2191 		UT_sint32 iContainerHeight = pContainer->getHeight();
2192 		if(pTab != NULL)
2193 		{
2194 			iContainerHeight = pTab->getHeight();
2195 		}
2196 		if(pTOC != NULL)
2197 		{
2198 			iContainerHeight = pTOC->getHeight();
2199 		}
2200 		UT_sint32 iContainerMarginAfter = pContainer->getMarginAfter();
2201 		UT_sint32 sum = iContainerHeight + iContainerMarginAfter;
2202 		if(((iY + sum) <= (getMaxHeight())) && doLayout)
2203 		{
2204 			pContainer->setY(iY);
2205 		}
2206 		iY += iContainerHeight;
2207 		iY += iContainerMarginAfter;
2208 	}
2209 
2210 	UT_sint32 iNewHeight = iY;
2211 	if (getHeight() == iNewHeight)
2212 	{
2213 		return;
2214 	}
2215 
2216         if(iY <= getMaxHeight())
2217 	{
2218 		setHeight(iNewHeight);
2219 	}
2220 	else
2221 	{
2222 		fl_HdrFtrSectionLayout * pHFSL = getHdrFtrSectionLayout();
2223 		fl_DocSectionLayout * pDSL = pHFSL->getDocSectionLayout();
2224 		bool bHdrFtr = (pHFSL->getHFType() <= FL_HDRFTR_HEADER_LAST);
2225 		if(iNewHeight > getPage()->getHeight()/3)
2226 		{
2227 			iNewHeight = getPage()->getHeight()/3;
2228 		}
2229 		pDSL->setHdrFtrHeightChange(bHdrFtr,iNewHeight+getGraphics()->tlu(3));
2230 		setHeight(getMaxHeight());
2231 	}
2232 }
2233 
2234 /*!
2235  *    get the shadow associated with this hdrftrContainer
2236  */
2237 
getShadow(void)2238 fl_HdrFtrShadow * fp_ShadowContainer::getShadow(void)
2239 {
2240     fl_HdrFtrSectionLayout* pHdrFtrSL = getHdrFtrSectionLayout();
2241 	return  pHdrFtrSL->findShadow( getPage() );
2242 }
2243 
2244 /*!
2245  *  Set the page for this shadow. Also set the fg_FillType parent.
2246  */
2247 
setPage(fp_Page * pPage)2248 void fp_ShadowContainer::setPage(fp_Page *pPage)
2249 {
2250 	m_pPage = pPage;
2251 	if(pPage)
2252 	{
2253 		getFillType().setParent(&pPage->getFillType());
2254 	}
2255 }
2256 
getHdrFtrSectionLayout(void) const2257 fl_HdrFtrSectionLayout* fp_ShadowContainer::getHdrFtrSectionLayout(void) const
2258 {
2259 	UT_ASSERT(getSectionLayout()->getType() == FL_SECTION_HDRFTR);
2260 
2261 	return static_cast<fl_HdrFtrSectionLayout*>(getSectionLayout());
2262 }
2263 
2264 
2265 /*!
2266   Clear container content from screen.
2267 */
clearScreen(void)2268 void fp_ShadowContainer::clearScreen(void)
2269 {
2270 	FV_View * pView = getPage()->getDocLayout()->getView();
2271 	if(pView->getViewMode() !=  VIEW_PRINT)
2272 	{
2273 		UT_DEBUGMSG(("SEVIOR: Attempting to clear Header/Footer in Normal Mode \n"));
2274 		return;
2275 	}
2276 	int count = countCons();
2277 	for (int i = 0; i<count; i++)
2278 	{
2279 		fp_ContainerObject* pContainer = static_cast<fp_ContainerObject*>(getNthCon(i));
2280 
2281 		pContainer->clearScreen();
2282 	}
2283 	clearHdrFtrBoundaries();
2284 }
2285 
2286 
2287 
2288 /*!
2289  Draw container content
2290  \param pDA Draw arguments
2291  */
2292 
draw(dg_DrawArgs * pDA)2293 void fp_ShadowContainer::draw(dg_DrawArgs* pDA)
2294 {
2295 	FV_View * pView = getPage()->getDocLayout()->getView();
2296 	if((pView->getViewMode() !=  VIEW_PRINT) && pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN) )
2297 	{
2298 		UT_DEBUGMSG(("SEVIOR: Attempting to draw Header/Footer in Normal Mode \n"));
2299 		return;
2300 	}
2301 	if((pView->getViewMode() !=  VIEW_PRINT) && pDA->pG->queryProperties(GR_Graphics::DGP_PAPER) )
2302 	{
2303 		layout(true);
2304 	}
2305 
2306 	UT_sint32 count = countCons();
2307 	UT_sint32 iY= 0;
2308 	for (UT_sint32 i = 0; i<count; i++)
2309 	{
2310 		fp_Container* pContainer = static_cast<fp_Container*>(getNthCon(i));
2311 
2312 		dg_DrawArgs da = *pDA;
2313 		da.xoff += pContainer->getX();
2314 		da.yoff += pContainer->getY();
2315 
2316 		UT_sint32 iContainerHeight = pContainer->getHeight();
2317 		UT_sint32 iContainerMarginAfter = pContainer->getMarginAfter();
2318 		iY += iContainerHeight;
2319 		iY += iContainerMarginAfter;
2320 //
2321 // Clip to keep inside header/footer container
2322 //
2323 		if(iY > getMaxHeight())
2324 			break;
2325 		pContainer->draw(&da);
2326 	}
2327     if(pView && pView->isHdrFtrEdit() && pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN) && pView->getEditShadow() == getShadow())
2328 	{
2329 		_drawHdrFtrBoundaries(pDA);
2330 	}
2331 	else
2332 	{
2333         clearHdrFtrBoundaries();
2334 		_drawBoundaries(pDA);
2335 	}
2336 	if((pView->getViewMode() !=  VIEW_PRINT) && pDA->pG->queryProperties(GR_Graphics::DGP_PAPER) )
2337 	{
2338 		layout(false);
2339 	}
2340 }
2341 
2342 /*!
2343  * This method draws a solid box around the currently editted Header/Footer
2344  */
_drawHdrFtrBoundaries(dg_DrawArgs * pDA)2345 void fp_ShadowContainer::_drawHdrFtrBoundaries(dg_DrawArgs * pDA)
2346 {
2347 	if(!pDA->pG->queryProperties(GR_Graphics::DGP_SCREEN))
2348 	{
2349 		return;
2350 	}
2351 	FV_View * pView = getPage()->getDocLayout()->getView();
2352 	if(pView->getViewMode() !=  VIEW_PRINT)
2353 	{
2354 		UT_DEBUGMSG(("SEVIOR: Attempting to draw Header/Footer in Normal Mode \n"));
2355 		return;
2356 	}
2357 //
2358 // Can put this in to speed things up.
2359 //
2360 //	if(m_bHdrFtrBoxDrawn)
2361 //		return;
2362 	UT_RGBColor clrDrawHdrFtr(127,127,127);
2363 	getGraphics()->setLineWidth(getGraphics()->tlu(1));
2364 	getGraphics()->setColor(clrDrawHdrFtr);
2365 //
2366 // These magic numbers stop clearscreens from blanking the lines
2367 //
2368 	m_ixoffBegin = pDA->xoff-2;
2369 	m_iyoffBegin = pDA->yoff+2;
2370 	m_ixoffEnd = pDA->xoff + getWidth() + getGraphics()->tlu(1);
2371 	m_iyoffEnd = pDA->yoff + getMaxHeight() - getGraphics()->tlu(1);
2372 
2373 	GR_Painter painter(getGraphics());
2374 
2375 	painter.drawLine(m_ixoffBegin, m_iyoffBegin, m_ixoffEnd, m_iyoffBegin);
2376 	painter.drawLine(m_ixoffBegin, m_iyoffEnd, m_ixoffEnd, m_iyoffEnd);
2377 	painter.drawLine(m_ixoffBegin, m_iyoffBegin, m_ixoffBegin, m_iyoffEnd);
2378 	painter.drawLine(m_ixoffEnd, m_iyoffBegin, m_ixoffEnd, m_iyoffEnd);
2379 	getGraphics()->setLineWidth(getGraphics()->tlu(1));
2380     m_bHdrFtrBoxDrawn = true;
2381 }
2382 
2383 
2384 /*!
2385  * This method clears the solid box around the curently editted Header/Footer
2386  */
clearHdrFtrBoundaries(void)2387 void fp_ShadowContainer::clearHdrFtrBoundaries(void)
2388 {
2389 	if(!m_bHdrFtrBoxDrawn)
2390 		return;
2391 	const UT_RGBColor * pClr = getPage()->getFillType().getColor();
2392 	getGraphics()->setLineWidth(getGraphics()->tlu(1));
2393 	getGraphics()->setColor(*pClr);
2394 //
2395 // Paint over the previous lines with the page color
2396 //
2397 
2398 	GR_Painter painter(getGraphics());
2399 
2400 	painter.drawLine(m_ixoffBegin, m_iyoffBegin, m_ixoffEnd, m_iyoffBegin);
2401 	painter.drawLine(m_ixoffBegin, m_iyoffEnd, m_ixoffEnd, m_iyoffEnd);
2402 	painter.drawLine(m_ixoffBegin, m_iyoffBegin, m_ixoffBegin, m_iyoffEnd);
2403 	painter.drawLine(m_ixoffEnd, m_iyoffBegin, m_ixoffEnd, m_iyoffEnd);
2404 	getGraphics()->setLineWidth(getGraphics()->tlu(1));
2405 	m_bHdrFtrBoxDrawn = false;
2406 }
2407 
2408 /*!
2409  * Ok this container class is for the hdrftrSectionLayout. It never gets drawn
2410  * on the screen, only the shadows get drawn. The page pointer contains a NULL.
2411  * This makes it possible to format the hdrftrSectionLayout and to do
2412  * editting operations on header/footers like regular text.
2413 \param iwidth width of the page in pixels?? I think.
2414 \param IwidthLayout width of the screen in layout units
2415 \param fl_SectionLayout * pSectionLayout pointer to the
2416        fl_HdrFtrSectionLayout that owns this container.
2417 */
2418 
fp_HdrFtrContainer(UT_sint32 iWidth,fl_SectionLayout * pSectionLayout)2419 fp_HdrFtrContainer::fp_HdrFtrContainer(UT_sint32 iWidth,
2420 									   fl_SectionLayout* pSectionLayout)
2421 	: fp_VerticalContainer(FP_CONTAINER_HDRFTR, pSectionLayout)
2422 {
2423 	_setX(0);
2424 	_setY(0);
2425 	setWidth(iWidth);
2426 	setHeight(0);
2427 }
2428 
~fp_HdrFtrContainer()2429 fp_HdrFtrContainer::~fp_HdrFtrContainer()
2430 {
2431 }
2432 
2433 /*!
2434  * Overloaded layout for VirtualCOntainer. We don't care about the height or
2435  * of the container.
2436  */
2437 
layout(void)2438 void fp_HdrFtrContainer::layout(void)
2439 {
2440 	UT_sint32 iY = 0;
2441 
2442 	UT_uint32 iCountContainers = countCons();
2443 
2444 	for (UT_uint32 i=0; i < iCountContainers; i++)
2445 	{
2446 		fp_Container* pContainer = static_cast<fp_Container*>(getNthCon(i));
2447 		fp_TableContainer * pTab = NULL;
2448 		if(pContainer->getContainerType() == FP_CONTAINER_TABLE)
2449 		{
2450 			pTab = static_cast<fp_TableContainer *>(pContainer);
2451 		}
2452 
2453 		UT_sint32 iContainerHeight = pContainer->getHeight();
2454 		if(pTab)
2455 		{
2456 			iContainerHeight = pTab->getHeight();
2457 		}
2458 		UT_sint32 iContainerMarginAfter = pContainer->getMarginAfter();
2459 
2460 		pContainer->setY(iY);
2461 		iY += iContainerHeight;
2462 		iY += iContainerMarginAfter;
2463 	}
2464 
2465 	UT_sint32 iNewHeight = iY;
2466 
2467 	if (getHeight() == iNewHeight)
2468 	{
2469 		return;
2470 	}
2471 
2472 	setHeight(iNewHeight);
2473 }
2474 
2475 /*!
2476  * Returns a pointer to the HdrFtrSectionLayout that owns this container
2477  */
getHdrFtrSectionLayout(void) const2478 fl_HdrFtrSectionLayout* fp_HdrFtrContainer::getHdrFtrSectionLayout(void) const
2479 {
2480 	UT_ASSERT(getSectionLayout()->getType() == FL_SECTION_HDRFTR);
2481 
2482 	return static_cast<fl_HdrFtrSectionLayout*>(getSectionLayout());
2483 }
2484 
2485 
2486 /*!
2487   Get line's offsets relative to the screen for this method we just return
2488   * -100000 since virtual containers are never drawn.
2489  \param  pContainer Container
2490  \retval xoff Container's X offset relative the screen actually -10000
2491  \retval yoff Container's Y offset relative the screen actually -10000
2492  */
getScreenOffsets(fp_ContainerObject *,UT_sint32 & xoff,UT_sint32 & yoff)2493 void fp_HdrFtrContainer::getScreenOffsets(fp_ContainerObject* /*pContainer*/,
2494 									UT_sint32& xoff, UT_sint32& yoff)
2495 {
2496 	xoff = -100000;
2497 	yoff = -100000;
2498 }
2499 
2500 
2501 /*!
2502   NOP's for clear screen.
2503 */
clearScreen(void)2504 void fp_HdrFtrContainer::clearScreen(void)
2505 {
2506 
2507 }
2508 
2509 /*!
2510  NOP for Draw's
2511  \param pDA Draw arguments
2512  */
draw(dg_DrawArgs *)2513 void fp_HdrFtrContainer::draw(dg_DrawArgs* /*pDA*/)
2514 {
2515 
2516 }
2517