1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: t -*- */
2 /* AbiWord
3  * Copyright (C) 1998 AbiSource, Inc.
4  * Copyright (C) 2002 Martin Sevior
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301 USA.
20  */
21 
22 #include <string.h>
23 #include <stdlib.h>
24 
25 #include "ut_types.h"
26 #include "ut_string.h"
27 
28 #include "ap_Prefs.h"
29 #include "fl_ContainerLayout.h"
30 #include "fl_FootnoteLayout.h"
31 #include "fl_SectionLayout.h"
32 #include "fl_Layout.h"
33 #include "fl_DocLayout.h"
34 #include "fl_BlockLayout.h"
35 #include "fl_TOCLayout.h"
36 #include "fl_TableLayout.h"
37 #include "fp_TableContainer.h"
38 #include "fp_Page.h"
39 #include "fp_Line.h"
40 #include "fp_Column.h"
41 #include "pd_Document.h"
42 #include "pp_AttrProp.h"
43 #include "pt_Types.h"
44 #include "gr_Graphics.h"
45 #include "fv_View.h"
46 #include "fp_Run.h"
47 #include "ut_debugmsg.h"
48 #include "ut_assert.h"
49 #include "ut_units.h"
50 #include "fl_FrameLayout.h"
51 #include "fp_FrameContainer.h"
52 #include "fl_AutoNum.h"
53 
54 
fl_ContainerLayout(fl_ContainerLayout * pMyLayout,pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP,PTStruxType iStrux,fl_ContainerType iType)55 fl_ContainerLayout::fl_ContainerLayout(fl_ContainerLayout* pMyLayout, pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP, PTStruxType iStrux, fl_ContainerType iType)
56 	: fl_Layout(iStrux, sdh),
57 	  m_iConType(iType),
58 	  m_pMyLayout(pMyLayout),
59 	  m_pPrev(NULL),
60 	  m_pNext(NULL),
61 	  m_pFirstL(NULL),
62 	  m_pLastL(NULL),
63 	  m_pFirstContainer(NULL),
64 	  m_pLastContainer(NULL),
65 	  m_eHidden(FP_VISIBLE),
66 	  m_iFoldedLevel(0)
67 {
68 //	UT_ASSERT(pMyLayout != NULL);
69 	setAttrPropIndex(indexAP);
70 	if(pMyLayout)
71 	{
72 		m_pDoc = pMyLayout->getDocument();
73 	}
74 }
75 
~fl_ContainerLayout()76 fl_ContainerLayout::~fl_ContainerLayout()
77 {
78 #if 1
79 	m_pMyLayout = NULL;
80 	m_pFirstL = NULL;
81 	m_pLastL = NULL;
82 	m_pPrev = NULL;
83 	m_pNext = NULL;
84 	m_pFirstContainer = NULL;
85 	m_pLastContainer = NULL;
86 #endif
87 }
88 
_getPropertiesAP(const PP_AttrProp * & pAP)89 bool fl_ContainerLayout::_getPropertiesAP(const PP_AttrProp*& pAP)
90 {
91 	pAP = NULL;
92 	FPVisibility eVisibility = getAP(pAP);
93 	UT_return_val_if_fail(pAP, false);
94 
95 	setVisibility(eVisibility);
96 
97 	//  Find the folded Level of the strux
98 	lookupFoldedLevel();
99 	if((isHidden() == FP_VISIBLE) && (getFoldedLevel() > 0) && (getLevelInList() > getFoldedLevel()) )
100 	{
101 		xxx_UT_DEBUGMSG(("Table set to hidden folded \n"));
102 		setVisibility(FP_HIDDEN_FOLDED);
103 	}
104 	// evaluate "display" property
105 	// display property
106 	const char* pszDisplay = NULL;
107 	pAP->getProperty("display", (const gchar *&)pszDisplay);
108 	if(isHidden() == FP_VISIBLE && pszDisplay && !strcmp(pszDisplay, "none"))
109 	{
110 		setVisibility(FP_HIDDEN_TEXT);
111 	}
112 
113 	return true;
114 }
115 
lookupProperties(void)116 void fl_ContainerLayout::lookupProperties(void)
117 {
118 	// first of all, call getAP() which will set default visibility
119 	// for us (either visible, or hidden revision)
120 
121 	// other common properties should come here
122 
123 	// this should only implement class-specific properties ...
124 	const PP_AttrProp* pAP;
125 
126 	// assert not needed, since _getPropertiesAP() asserts on failure
127 	if(!_getPropertiesAP(pAP))
128 		return;
129 
130 	_lookupProperties(pAP);
131 }
132 
133 /*!
134     This function looks up only a limited set of properties such as margins.
135     It's purpose is to allow to reformat the document when the view mode changes (in
136     normal view we cannot allow negative margins; the derrived _lookupMarginProperties()
137     needs to handled that in a meaningful way.
138 */
lookupMarginProperties(void)139 void fl_ContainerLayout::lookupMarginProperties(void)
140 {
141 	// first of all, call getAP() which will set default visibility
142 	// for us (either visible, or hidden revision)
143 
144 	// other common properties should come here
145 
146 	// this should only implement class-specific properties ...
147 	const PP_AttrProp* pAP;
148 
149 	// assert not needed, since _getPropertiesAP() asserts on failure
150 	if(!_getPropertiesAP(pAP))
151 		return;
152 
153 	_lookupMarginProperties(pAP);
154 }
155 
156 
157 /*!
158     retrieves AP associated with this layout, corretly processing any
159     revision information;
160 
161     /return return value indicates whether the layout is hidden due to
162     current revision settings or not
163 */
getAP(const PP_AttrProp * & pAP) const164 FPVisibility fl_ContainerLayout::getAP(const PP_AttrProp *& pAP)const
165 {
166 	FL_DocLayout* pDL =	getDocLayout();
167 	UT_return_val_if_fail(pDL,FP_VISIBLE);
168 
169 	FV_View* pView = pDL->getView();
170 	UT_return_val_if_fail(pView,FP_VISIBLE);
171 
172 	UT_uint32 iId  = pView->getRevisionLevel();
173 	bool bShow     = pView->isShowRevisions();
174 	bool bHiddenRevision = false;
175 
176 	getAttrProp(&pAP,NULL,bShow,iId,bHiddenRevision);
177 
178 	if(bHiddenRevision)
179 	{
180 		return FP_HIDDEN_REVISION;
181 	}
182 	else
183 	{
184 		return FP_VISIBLE;
185 	}
186 }
187 
getSpanAP(UT_uint32 blockPos,bool bLeft,const PP_AttrProp * & pSpanAP) const188 void fl_ContainerLayout::getSpanAP(UT_uint32 blockPos, bool bLeft, const PP_AttrProp * &pSpanAP) const
189 {
190 	//first we need to ascertain if this revision is visible
191 	FL_DocLayout* pDL =	getDocLayout();
192 	UT_return_if_fail(pDL);
193 
194 	FV_View* pView = pDL->getView();
195 	UT_return_if_fail(pView);
196 
197 	UT_uint32 iId  = pView->getRevisionLevel();
198 	bool bShow     = pView->isShowRevisions();
199 	bool bHiddenRevision = false;
200 
201 	getSpanAttrProp(blockPos, bLeft, &pSpanAP,NULL,bShow,iId,bHiddenRevision);
202 }
203 
204 
getContainerString(void)205 const char * fl_ContainerLayout::getContainerString(void)
206 {
207 	switch(getContainerType())
208 	{
209 	case FL_CONTAINER_BLOCK:
210 		return "FL_CONTAINER_BLOCK";
211 	case  FL_CONTAINER_DOCSECTION:
212 		return "FL_CONTAINER_DOCSECTION";
213 	case FL_CONTAINER_HDRFTR:
214 		return "FL_CONTAINER_HDRFTR";
215 	case FL_CONTAINER_SHADOW:
216 		return "FL_CONTAINER_SHADOW";
217 	case FL_CONTAINER_FOOTNOTE:
218 		return "FL_CONTAINER_FOOTNOTE";
219 	case FL_CONTAINER_ENDNOTE:
220 		return "FL_CONTAINER_ENDNOTE";
221 	case FL_CONTAINER_MARGINNOTE:
222 		return "FL_CONTAINER_MARGINNOTE";
223 	case FL_CONTAINER_TABLE:
224 		return "FL_CONTAINER_TABLE";
225 	case FL_CONTAINER_CELL:
226 		return "FL_CONTAINER_CELL";
227 	case FL_CONTAINER_FRAME:
228 		return "FL_CONTAINER_FRAME";
229 	case FL_CONTAINER_TOC:
230 		return "FL_CONTAINER_TOC";
231 	case FL_CONTAINER_ANNOTATION:
232 		return "FL_CONTAINER_ANNOTATION";
233 	case FL_CONTAINER_RDFANCHOR:
234 		return "FL_CONTAINER_RDFANCHOR";
235 	default:
236 		return "NOT_IMPLEMENTED";
237 	}
238 	return "NOT IMPLEMENTED";
239 }
240 
241 
242 
243 /*!
244  * Return the value of the attribute keyed by pszName
245  */
getAttribute(const char * pszName) const246 const char*	fl_ContainerLayout::getAttribute(const char * pszName) const
247 {
248 	const PP_AttrProp * pAP = NULL;
249 	getAP(pAP);
250 	UT_return_val_if_fail(pAP, NULL);
251 
252 	const gchar* pszAtt = NULL;
253 	pAP->getAttribute(static_cast<const gchar*>(pszName), pszAtt);
254 
255 	return pszAtt;
256 }
257 
258 /*!
259  * Return the nested List level of this structure.
260  */
getLevelInList(void)261 UT_sint32 fl_ContainerLayout::getLevelInList(void)
262 {
263       fl_BlockLayout * pBList = NULL;
264       if(getContainerType() == FL_CONTAINER_BLOCK)
265       {
266 	   pBList = static_cast<fl_BlockLayout * >(this);
267       }
268       else
269       {
270 	   pBList = getPrevBlockInDocument();
271       }
272       UT_sint32 iLevel = 0;
273       bool bLoop = true;
274       while(pBList && bLoop)
275       {
276 	  while(pBList && !pBList->isListItem())
277 	  {
278 	       pBList = pBList->getPrevBlockInDocument();
279 	  }
280 	  if(pBList == NULL)
281 	  {
282 	       bLoop = false;
283 	       break;
284 	  }
285 	  const PP_AttrProp * pAP = NULL;
286 	  pBList->getAP(pAP);
287 	  const gchar * szLid=NULL;
288 	  UT_uint32 id=0;
289 
290 	  if (!pAP || !pAP->getAttribute(PT_LISTID_ATTRIBUTE_NAME, szLid))
291 	       szLid = NULL;
292 	  if (szLid)
293 	  {
294 	       id = atoi(szLid);
295 
296 	  }
297 	  else
298 	  {
299 		id = 0;
300 	  }
301 	  if(id == 0)
302 	  {
303 	        bLoop = false;
304 	        break;
305 	  }
306 	  PD_Document * pDoc = getDocLayout()->getDocument();
307 	  fl_AutoNum * pAuto = pDoc->getListByID( id);
308 	  if(pAuto->getLastItem() == pBList->getStruxDocHandle())
309 	  {
310 	        if(pAuto->getLastItem() == getStruxDocHandle())
311 		{
312 		     iLevel = pAuto->getLevel();
313 		     bLoop = false;
314 		     break;
315 		}
316 	        iLevel = pAuto->getLevel() -1;
317 		if(iLevel < 0)
318 		{
319 		      iLevel = 0;
320 		}
321 	  }
322 	  else
323 	  {
324 	        if(pBList == this)
325 	        {
326 		      iLevel = pAuto->getLevel();
327 		}
328 		else
329 		{
330 		      iLevel = pAuto->getLevel() + 1;
331 		}
332 	  }
333 	  bLoop = false;
334 	  break;
335       }
336       return iLevel;
337 }
338 /*!
339  * This method returns the folded level of the text.
340  */
getFoldedLevel(void)341 UT_sint32 fl_ContainerLayout::getFoldedLevel(void)
342 {
343 	return m_iFoldedLevel;
344 }
345 
346 
347 /*!
348  * This method returns the ID of the list that is folded.
349  */
getFoldedID(void)350 UT_uint32 fl_ContainerLayout::getFoldedID(void)
351 {
352 	return m_iFoldedID;
353 }
354 
355 /*!
356  * This Method looks up the folded level of the strux.
357  */
lookupFoldedLevel(void)358 void fl_ContainerLayout::lookupFoldedLevel(void)
359 {
360  	const PP_AttrProp* pSectionAP = NULL;
361 
362 	getAP(pSectionAP);
363 
364 	const gchar *pszTEXTFOLDED = NULL;
365 	if(!pSectionAP || !pSectionAP->getProperty("text-folded",pszTEXTFOLDED))
366 	{
367 		m_iFoldedLevel = 0;
368 	}
369 	else
370 	{
371 		m_iFoldedLevel = atoi(pszTEXTFOLDED);
372 	}
373 	xxx_UT_DEBUGMSG(("FOlded Level is %d \n",m_iFoldedLevel));
374     pszTEXTFOLDED = NULL;
375 	if(!pSectionAP || !pSectionAP->getProperty("text-folded-id",pszTEXTFOLDED))
376 	{
377 		m_iFoldedID = 0;
378 	}
379 	else
380 	{
381 		m_iFoldedID = atoi(pszTEXTFOLDED);
382 	}
383 }
384 
385 /*!
386  * This method appends all the text in the current layout to the supplied
387  * GrowBuf.
388  */
appendTextToBuf(UT_GrowBuf & buf) const389 void fl_ContainerLayout::appendTextToBuf(UT_GrowBuf & buf) const
390 {
391 	if(getContainerType() == FL_CONTAINER_BLOCK)
392 	{
393 		const fl_BlockLayout * pBL = static_cast<const fl_BlockLayout *>(this);
394 		pBL->appendTextToBuf(buf);
395 		return;
396 	}
397 	const fl_ContainerLayout * pCL = getFirstLayout();
398 	while(pCL)
399 	{
400 		pCL->appendTextToBuf(buf);
401 		pCL = pCL->getNext();
402 	}
403 }
404 
405 /*!
406  * Set the pointer to the next containerLayout given by pL
407  */
setNext(fl_ContainerLayout * pL)408 void fl_ContainerLayout::setNext(fl_ContainerLayout* pL)
409 {
410 	m_pNext = pL;
411 }
412 
413 /*!
414  * Set the pointer to the previous containerLayout in the linked list
415  * given by pL
416  */
setPrev(fl_ContainerLayout * pL)417 void fl_ContainerLayout::setPrev(fl_ContainerLayout* pL)
418 {
419 	m_pPrev = pL;
420 }
421 
422 /*!
423  * Return the next fl_ContainerLayout in the linked list.
424  */
getNext(void) const425 fl_ContainerLayout * fl_ContainerLayout::getNext(void) const
426 {
427 	return m_pNext;
428 }
429 
430 /*!
431  * Return the previous fl_ContainerLayout in the linked list
432  */
getPrev(void) const433 fl_ContainerLayout * fl_ContainerLayout::getPrev(void) const
434 {
435 	return m_pPrev;
436 }
437 
getDocSectionLayout(void) const438 fl_DocSectionLayout * fl_ContainerLayout::getDocSectionLayout(void) const
439 {
440 	fl_ContainerLayout * pCL = myContainingLayout();
441 	while(pCL!= NULL && ((pCL->getContainerType() != FL_CONTAINER_DOCSECTION) && (pCL->getContainerType() != FL_CONTAINER_HDRFTR)))
442 	{
443 		pCL = pCL->myContainingLayout();
444 	}
445 	if(pCL== NULL)
446 	{
447 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
448 		return NULL;
449 	}
450 	fl_DocSectionLayout * pDSL = NULL;
451 	if(pCL->getContainerType() == FL_CONTAINER_HDRFTR)
452 	{
453 		pDSL = static_cast<fl_HdrFtrSectionLayout *>(pCL)->getDocSectionLayout();
454 	}
455 	else
456 	{
457 		pDSL = static_cast<fl_DocSectionLayout *>(pCL);
458 	}
459 	return pDSL;
460 }
461 
462 /*!
463  * Return the fl_ContainerLayout that "owns" this. Set to NULL for
464  * fl_DocSectionLayout
465  */
myContainingLayout(void) const466 fl_ContainerLayout * fl_ContainerLayout::myContainingLayout(void) const
467 {
468 	return m_pMyLayout;
469 }
470 
471 /*!
472  * If this container is contained by a HdrFtrSectionLayout return it.
473  * Otherwise return
474  * NULL.
475  */
getHdrFtrLayout(void)476 fl_HdrFtrSectionLayout * fl_ContainerLayout::getHdrFtrLayout(void)
477 {
478 	fl_ContainerLayout * pCL = this;
479 	while(pCL && (pCL->getContainerType() != FL_CONTAINER_HDRFTR) &&
480 		  (pCL->getContainerType() != FL_CONTAINER_DOCSECTION))
481 	{
482 		pCL = pCL->myContainingLayout();
483 	}
484 	if(pCL && (pCL->getContainerType() ==  FL_CONTAINER_HDRFTR))
485 	{
486 		return static_cast<fl_HdrFtrSectionLayout *>(pCL);
487 	}
488 	return NULL;
489 }
490 
getDocLayout(void) const491 FL_DocLayout* fl_ContainerLayout::getDocLayout(void) const
492 {
493 	const fl_ContainerLayout * pMyContainer = static_cast<const fl_ContainerLayout *>(this);
494 	while(pMyContainer->getContainerType() != FL_CONTAINER_DOCSECTION && pMyContainer->myContainingLayout())
495 	{
496 		pMyContainer = pMyContainer->myContainingLayout();
497 	}
498 	return static_cast<const fl_DocSectionLayout *>(pMyContainer)->getDocLayout();
499 }
500 
setContainingLayout(fl_ContainerLayout * pL)501 void fl_ContainerLayout::setContainingLayout(fl_ContainerLayout * pL)
502 {
503 //	UT_ASSERT(pL != NULL); // useful for debugging
504 	m_pMyLayout = pL;
505 }
506 
append(pf_Frag_Strux * sdh,PT_AttrPropIndex indexAP,fl_ContainerType iType)507 fl_ContainerLayout * fl_ContainerLayout::append(pf_Frag_Strux* sdh, PT_AttrPropIndex indexAP,fl_ContainerType iType)
508 {
509 	return insert(sdh, m_pLastL, indexAP,iType);
510 }
511 
add(fl_ContainerLayout * pL)512 void fl_ContainerLayout::add(fl_ContainerLayout* pL)
513 {
514 	if (m_pLastL)
515 	{
516 		UT_ASSERT(m_pLastL->getNext() == NULL);
517 
518 		pL->setNext(NULL);
519 		pL->setPrev(m_pLastL);
520 		m_pLastL->setNext(pL);
521 		m_pLastL = pL;
522 	}
523 	else
524 	{
525 		UT_ASSERT(!m_pFirstL);
526 		UT_DEBUGMSG(("add: doing First = Last = NULL \n"));
527 		pL->setNext(NULL);
528 		pL->setPrev(NULL);
529 		m_pFirstL = pL;
530 		m_pLastL = m_pFirstL;
531 	}
532 	pL->setContainingLayout(this);
533 	if(pL->getContainerType() == FL_CONTAINER_BLOCK)
534 	{
535 		UT_ASSERT(getContainerType() != FL_CONTAINER_BLOCK);
536 		static_cast<fl_BlockLayout *>(pL)->setSectionLayout(static_cast<fl_SectionLayout *>(this));
537 	}
538 }
539 
540 
getNextBlockInDocument(void) const541 fl_BlockLayout* fl_ContainerLayout::getNextBlockInDocument(void) const
542 {
543 	fl_ContainerLayout * pNext = getNext();
544 	if(getContainerType() != FL_CONTAINER_BLOCK)
545 	{
546 	  pNext = getFirstLayout();
547 	}
548 	fl_ContainerLayout * pOld = NULL;
549 	UT_uint32 depth = 0;
550 	next_is_null :
551 	if(pNext == NULL)
552 	{
553 		while((pNext == NULL) && ((pOld != NULL) || (depth == 0)))
554 	    {
555 			fl_ContainerLayout * pPrevOld = pOld;
556 			if(depth > 0)
557 			{
558 				pOld = pOld->myContainingLayout();
559 			}
560 			else
561 			{
562 				pOld = myContainingLayout();
563 			}
564 			depth++;
565 			if(pOld != NULL) // HdrFtr's have myContainingLayout == NULL
566 			{
567 				pNext = pOld->getNext();
568 			}
569 			if(pPrevOld == pOld)
570 			{
571 				pOld = NULL;
572 			}
573 		}
574 	}
575 	while(pNext)
576 	{
577 		pOld = pNext;
578 		if(pNext->getContainerType() == FL_CONTAINER_BLOCK)
579 		{
580 			return static_cast<fl_BlockLayout *>(pNext);
581 		}
582 		else if(pNext->getContainerType() == FL_CONTAINER_DOCSECTION)
583 		{
584 			pNext = pNext->getFirstLayout();
585 		}
586 		else if(pNext->getContainerType() == FL_CONTAINER_TABLE)
587 		{
588 			pNext = pNext->getFirstLayout();
589 		}
590 		else if(pNext->getContainerType() == FL_CONTAINER_FRAME)
591 		{
592 			if(pNext->getFirstLayout() == NULL)
593 			{
594 			     pNext = pNext->getNext();
595 			}
596 			else
597 			{
598 			     pNext = pNext->getFirstLayout();
599 			}
600 		}
601 		else if(pNext->getContainerType() == FL_CONTAINER_CELL)
602 		{
603 			pNext = pNext->getFirstLayout();
604 		}
605 		else if(pNext->getContainerType() == FL_CONTAINER_TOC)
606 		{
607 			pNext = pNext->getNext();
608 			if(pNext == NULL)
609 			{
610 				goto next_is_null;
611 			}
612 		}
613 		else if(pNext->getContainerType() == FL_CONTAINER_FOOTNOTE)
614 		{
615 			pNext = pNext->getNext();
616 			if(pNext == NULL)
617 			{
618 				goto next_is_null;
619 			}
620 		}
621 		else if(pNext->getContainerType() == FL_CONTAINER_ANNOTATION)
622 		{
623 			pNext = pNext->getNext();
624 			if(pNext == NULL)
625 			{
626 				goto next_is_null;
627 			}
628 		}
629 		else if(pNext->getContainerType() == FL_CONTAINER_RDFANCHOR)
630 		{
631 			pNext = pNext->getNext();
632 			if(pNext == NULL)
633 			{
634 				goto next_is_null;
635 			}
636 		}
637 		else if(pNext->getContainerType() == FL_CONTAINER_ENDNOTE)
638 		{
639 			pNext = pNext->getNext();
640 			if(pNext == NULL)
641 			{
642 				goto next_is_null;
643 			}
644 		}
645 		else
646 		{
647 			pNext = NULL;
648 			break;
649 		}
650 		if(pNext == NULL)
651 		{
652 				goto next_is_null;
653 		}
654 	}
655 	return NULL;
656 }
657 
getPrevBlockInDocument(void) const658 fl_BlockLayout* fl_ContainerLayout::getPrevBlockInDocument(void) const
659 {
660 	fl_ContainerLayout * pPrev = getPrev();
661 	fl_ContainerLayout * pOld = NULL;
662 	UT_uint32 depth = 0;
663 	if(pPrev == NULL)
664 	{
665 		while((pPrev == NULL) && ((pOld != NULL) || (depth == 0)))
666 	    {
667 			fl_ContainerLayout * pPrevOld = pOld;
668 			if(depth > 0)
669 			{
670 				pOld = pOld->myContainingLayout();
671 			}
672 			else
673 			{
674 				pOld = myContainingLayout();
675 			}
676 			depth++;
677 			if(pOld != NULL) // HdrFtr's can have NULL myContainingLayout's
678 			{
679 				pPrev = pOld->getPrev();
680 			}
681 			if(pPrevOld == pOld )
682 			{
683 				pOld = NULL;
684 			}
685 		}
686 	}
687 	while(pPrev)
688 	{
689 		pOld = pPrev;
690 		if(pPrev->getContainerType() == FL_CONTAINER_BLOCK)
691 		{
692 			return static_cast<fl_BlockLayout *>(pPrev);
693 		}
694 		else if(pPrev->getContainerType() == FL_CONTAINER_DOCSECTION)
695 		{
696 			pPrev = pPrev->getLastLayout();
697 		}
698 		else if(pPrev->getContainerType() == FL_CONTAINER_FRAME)
699 		{
700 			if(pPrev->getLastLayout() == NULL)
701 			{
702 			     pPrev = pPrev->getPrev();
703 			}
704 			else
705 			{
706 			     pPrev = pPrev->getLastLayout();
707 			}
708 		}
709 		else if(pPrev->getContainerType() == FL_CONTAINER_TABLE)
710 		{
711 			pPrev = pPrev->getLastLayout();
712 		}
713 		else if(pPrev->getContainerType() == FL_CONTAINER_CELL)
714 		{
715 			pPrev = pPrev->getLastLayout();
716 		}
717 		else if(pPrev->getContainerType() == FL_CONTAINER_FOOTNOTE)
718 		{
719 			pPrev = pPrev->getLastLayout();
720 		}
721 		else if(pPrev->getContainerType() == FL_CONTAINER_ANNOTATION)
722 		{
723 			pPrev = pPrev->getLastLayout();
724 		}
725 		else if(pPrev->getContainerType() == FL_CONTAINER_RDFANCHOR)
726 		{
727 			pPrev = pPrev->getLastLayout();
728 		}
729 		else if(pPrev->getContainerType() == FL_CONTAINER_TOC)
730 		{
731 			pPrev = pPrev->getLastLayout();
732 		}
733 		else if(pPrev->getContainerType() == FL_CONTAINER_ENDNOTE)
734 		{
735 			pPrev = pPrev->getLastLayout();
736 		}
737 		else
738 		{
739 			pPrev = NULL;
740 			break;
741 		}
742 		if(pPrev == NULL)
743 		{
744 			if(pOld && pOld->myContainingLayout())
745 			{
746 				pPrev = pOld->myContainingLayout()->getPrev();
747 			}
748 		}
749 	}
750 	return NULL;
751 }
752 
753 /*!
754  * Set the pointer to the first Layout in the linked list.
755  */
setFirstLayout(fl_ContainerLayout * pL)756 void fl_ContainerLayout::setFirstLayout(fl_ContainerLayout * pL)
757 {
758 	m_pFirstL = pL;
759 }
760 
761 /*!
762  * Set the pointer to the last Layout in the linked list.
763  */
setLastLayout(fl_ContainerLayout * pL)764 void fl_ContainerLayout::setLastLayout(fl_ContainerLayout * pL)
765 {
766 	m_pLastL = pL;
767 }
768 
769 /*!
770  * Return the pointer to the first layout in the structure.
771  */
getFirstLayout(void) const772 fl_ContainerLayout * fl_ContainerLayout::getFirstLayout(void) const
773 {
774 	return m_pFirstL;
775 }
776 
777 /*!
778  * Return the pointer to the last layout in the structure.
779  */
getLastLayout(void) const780 fl_ContainerLayout * fl_ContainerLayout::getLastLayout(void) const
781 {
782 	return m_pLastL;
783 }
784 
785 
786 /*!
787  * Create a new containerLayout  and insert it into the linked list of
788  * layouts held by this class.
789  * Returns a pointer to the generated ContainerLayout class.
790  */
insert(pf_Frag_Strux * sdh,fl_ContainerLayout * pPrev,PT_AttrPropIndex indexAP,fl_ContainerType iType)791 fl_ContainerLayout * fl_ContainerLayout::insert(pf_Frag_Strux* sdh, fl_ContainerLayout * pPrev, PT_AttrPropIndex indexAP,fl_ContainerType iType)
792 {
793 	fl_ContainerLayout* pL=NULL;
794 	switch (iType)
795 	{
796 	case FL_CONTAINER_BLOCK:
797 		// we have a problem here -- the block needs to be in the list before the consturction is completed
798 		if(getContainerType() ==  FL_CONTAINER_HDRFTR)
799 		{
800 			pL = static_cast<fl_ContainerLayout *>(new fl_BlockLayout(sdh, pPrev, static_cast<fl_SectionLayout *>(this), indexAP,true));
801 		}
802 		else if ((pPrev!= NULL) && (pPrev->getContainerType() == FL_CONTAINER_TABLE))
803 		{
804 			pL = static_cast<fl_ContainerLayout *>(new fl_BlockLayout(sdh,pPrev, static_cast<fl_SectionLayout *>(pPrev->myContainingLayout()), indexAP));
805 		}
806 		else if ((pPrev!= NULL) && (pPrev->getContainerType() == FL_CONTAINER_ANNOTATION))
807 		{
808 			pL = static_cast<fl_ContainerLayout *>(new fl_BlockLayout(sdh,pPrev, static_cast<fl_SectionLayout *>(this), indexAP));
809 			fp_Container * pFirstC = pL->getFirstContainer();
810 			//
811 			// This sets indent for a annotation label.
812 			//
813 			if(pFirstC)
814 			  pFirstC->recalcMaxWidth(true);
815 		}
816 		else if ((pPrev!= NULL) && (pPrev->getContainerType() == FL_CONTAINER_RDFANCHOR))
817 		{
818 			pL = static_cast<fl_ContainerLayout *>(new fl_BlockLayout(sdh,pPrev, static_cast<fl_SectionLayout *>(this), indexAP));
819 		}
820 		else
821 		{
822 			pL = static_cast<fl_ContainerLayout *>(new fl_BlockLayout(sdh, static_cast<fl_BlockLayout *>(pPrev), static_cast<fl_SectionLayout *>(this), indexAP));
823 		}
824 		break;
825 	case FL_CONTAINER_TABLE:
826 		pL = static_cast<fl_ContainerLayout *>(new fl_TableLayout(getDocLayout(),sdh, indexAP, this));
827 		if(pPrev && (pPrev == this))
828 		{
829 		  fl_ContainerLayout * pOldFirst = pPrev->getFirstLayout();
830 		  pPrev->setFirstLayout(pL);
831 		  pL->setNext(pOldFirst);
832 		  if(pOldFirst)
833 		  {
834 		    pOldFirst->setPrev(pL);
835 		  }
836 		  if(pPrev->getLastLayout() == NULL)
837 		  {
838 		    pPrev->setLastLayout(pL);
839 		  }
840 		}
841 		else if (pPrev)
842 		{
843 			pPrev->_insertIntoList(pL);
844 		}
845 //
846 // Now put the Physical Container into the vertical container that contains it.
847 //
848 		{
849 			fp_TableContainer * pTab = static_cast<fp_TableContainer *>(static_cast<fl_TableLayout *>(pL)->getLastContainer());
850 			static_cast<fl_TableLayout *>(pL)->insertTableContainer(static_cast<fp_TableContainer *>(pTab));
851 		}
852 		if(getContainerType() == FL_CONTAINER_CELL)
853 		{
854 			fl_CellLayout * pCell = static_cast<fl_CellLayout *>(this);
855 			pCell->incNumNestedTables();
856 			fl_TableLayout * pTab = static_cast<fl_TableLayout *>(pCell->myContainingLayout());
857 			pTab->incNumNestedTables();
858 		}
859 		break;
860 	case FL_CONTAINER_CELL:
861 		pL = static_cast<fl_ContainerLayout *>(new fl_CellLayout(getDocLayout(),sdh, indexAP, this));
862 		if (pPrev)
863 		{
864 			pPrev->_insertIntoList(pL);
865 		}
866 		else
867 		{
868 			_insertFirst(pL);
869 		}
870 		break;
871 	case FL_CONTAINER_FRAME:
872 	{
873 		pL = static_cast<fl_ContainerLayout *>
874 		  (new fl_FrameLayout(getDocLayout(),
875 				      sdh, indexAP, this));
876 		if (pPrev)
877 		{
878 			while(pPrev && pPrev->getContainerType() != FL_CONTAINER_BLOCK)
879 			{
880 				pPrev = pPrev->getPrev();
881 			}
882 //
883 // Add the frame to the list in te previous block.
884 //
885 			if(pPrev)
886 			{
887 				pPrev->_insertIntoList(pL);
888 				pPrev->addFrame(static_cast<fl_FrameLayout *>(pL));
889 			}
890 		}
891 		break;
892 	}
893 	case FL_CONTAINER_FOOTNOTE:
894 	{
895 		fl_DocSectionLayout * pDSL = getDocSectionLayout();
896 		pL = static_cast<fl_ContainerLayout *>(new fl_FootnoteLayout(getDocLayout(),
897 					  pDSL,
898 					  sdh, indexAP, this));
899 		if (pPrev)
900 			pPrev->_insertIntoList(pL);
901 		break;
902 	}
903 	case FL_CONTAINER_ANNOTATION:
904 	{
905 		fl_DocSectionLayout * pDSL = getDocSectionLayout();
906 		pL = static_cast<fl_ContainerLayout *>(new fl_AnnotationLayout(getDocLayout(),
907 					  pDSL,
908 					  sdh, indexAP, this));
909 		if (pPrev)
910 			pPrev->_insertIntoList(pL);
911 		break;
912 	}
913 	case FL_CONTAINER_TOC:
914 	{
915 		fl_DocSectionLayout * pDSL = getDocSectionLayout();
916 		pL = static_cast<fl_ContainerLayout *>(new fl_TOCLayout(getDocLayout(),
917 					  pDSL,
918 					  sdh, indexAP, this));
919 		if (pPrev)
920 			pPrev->_insertIntoList(pL);
921 		static_cast<fl_TOCLayout *>(pL)->getNewContainer(NULL);
922 		break;
923 	}
924 	case FL_CONTAINER_ENDNOTE:
925 	{
926 		fl_DocSectionLayout * pDSL = getDocSectionLayout();
927 		pL = static_cast<fl_ContainerLayout *>(new fl_EndnoteLayout(getDocLayout(),
928 					  pDSL,
929 					  sdh, indexAP, this));
930 		if (pPrev)
931 			pPrev->_insertIntoList(pL);
932 		break;
933 	}
934 	default:
935 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
936 		break;
937 	}
938 
939 	if (pL == NULL)
940 	{
941 		return pL;
942 	}
943 
944 	if (!m_pLastL)
945 	{
946 		UT_ASSERT(!m_pFirstL);
947 		m_pFirstL = pL;
948 		m_pLastL = pL;
949 	}
950 	else if (m_pLastL == pPrev)
951 	{
952 		m_pLastL = pL;
953 	}
954 	else if (!pPrev)
955 	{
956 		m_pFirstL = pL;
957 	}
958 	if(getContainerType() == FL_CONTAINER_CELL)
959 	{
960 		static_cast<fl_TableLayout *>(myContainingLayout())->setDirty();
961 	}
962 	return pL;
963 }
964 
965 /*!
966    Inserts pL into the containment hierarchy after 'this'.
967    This is actually a general linked list insertion routine.
968 */
_insertIntoList(fl_ContainerLayout * pL)969 void fl_ContainerLayout::_insertIntoList(fl_ContainerLayout * pL)
970 {
971 	fl_ContainerLayout * pNext = getNext();
972 	setNext(pL);
973 
974 	pL->setPrev(this);
975 	pL->setNext(pNext);
976 
977 	if(pNext)
978 		pNext->setPrev(pL);
979 }
980 
981 
982 /*!
983    Inserts pL into the containment hierarchy at First Location;
984 */
_insertFirst(fl_ContainerLayout * pL)985 void fl_ContainerLayout::_insertFirst(fl_ContainerLayout * pL)
986 {
987 	if(m_pFirstL == NULL)
988 	{
989 		m_pFirstL = pL;
990 		pL->setPrev(NULL);
991 		pL->setNext(NULL);
992 		m_pLastL = pL;
993 		return;
994 	}
995 	fl_ContainerLayout * pOldFirst = m_pFirstL;
996 	m_pFirstL = pL;
997 	pL->setNext(pOldFirst);
998 	pL->setPrev(NULL);
999 	pOldFirst->setPrev(pL);
1000 }
1001 
1002 /*!
1003  * Remove a containerLayout class from the linked list held here.
1004  */
remove(fl_ContainerLayout * pL)1005 void fl_ContainerLayout::remove(fl_ContainerLayout * pL)
1006 {
1007 	UT_ASSERT(pL);
1008 	UT_ASSERT(m_pFirstL);
1009 	fl_ContainerLayout* prev = pL->getPrev(); // can be NULL
1010 
1011 	if (prev)
1012 	{
1013 		prev->setNext(pL->getNext());
1014 	}
1015 
1016 	if (pL->getNext())
1017 	{
1018 		pL->getNext()->setPrev(prev);
1019 		if(pL->getContainerType() == FL_CONTAINER_BLOCK)
1020 		{
1021 			UT_ASSERT(getContainerType() != FL_CONTAINER_BLOCK);
1022 			static_cast<fl_BlockLayout *>(pL)->transferListFlags();
1023 		}
1024 		if (pL->getNext()->getContainerType() == FL_CONTAINER_BLOCK)
1025 		{
1026 			fl_BlockLayout* pBNext = static_cast<fl_BlockLayout *>(pL->getNext());
1027 			if (pBNext->hasBorders())
1028 			{
1029 				pBNext->setLineHeightBlockWithBorders(1);
1030 			}
1031 		}
1032 		if (prev && prev->getContainerType() == FL_CONTAINER_BLOCK)
1033 		{
1034 			fl_BlockLayout* pBPrev = static_cast<fl_BlockLayout *>(prev);
1035 			if (pBPrev->hasBorders())
1036 			{
1037 				pBPrev->setLineHeightBlockWithBorders(-1);
1038 			}
1039 		}
1040 	}
1041 
1042 	if (pL == m_pFirstL)
1043 	{
1044 		m_pFirstL = m_pFirstL->getNext();
1045 		if (!m_pFirstL)
1046 		{
1047 			m_pLastL = NULL;
1048 		}
1049 	}
1050 
1051 	if (pL == m_pLastL)
1052 	{
1053 		m_pLastL = m_pLastL->getPrev();
1054 		if (!m_pLastL)
1055 		{
1056 			m_pFirstL = NULL;
1057 		}
1058 	}
1059 	if(getContainerType() != FL_CONTAINER_BLOCK)
1060 	{
1061 	  fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(this);
1062 	  pSL->removeFromUpdate(pL);
1063 	}
1064 	pL->setNext(NULL);
1065 	pL->setPrev(NULL);
1066 	pL->setContainingLayout(NULL);
1067 	if(pL->getContainerType() == FL_CONTAINER_BLOCK)
1068 	{
1069 		UT_ASSERT(getContainerType() != FL_CONTAINER_BLOCK);
1070 		static_cast<fl_BlockLayout *>(pL)->setSectionLayout(NULL);
1071 	}
1072 }
1073 
getFirstContainer() const1074 fp_Container* fl_ContainerLayout::getFirstContainer() const
1075 {
1076 	return m_pFirstContainer;
1077 }
1078 
getLastContainer() const1079 fp_Container* fl_ContainerLayout::getLastContainer() const
1080 {
1081 	return m_pLastContainer;
1082 }
1083 
setFirstContainer(fp_Container * pCon)1084 void fl_ContainerLayout::setFirstContainer(fp_Container * pCon)
1085 {
1086 	if(pCon && getContainerType() == FL_CONTAINER_BLOCK)
1087 	{
1088 		UT_ASSERT(pCon->getContainerType() == FP_CONTAINER_LINE);
1089 	}
1090 	xxx_UT_DEBUGMSG(("Set FirstContainer of %x to %x \n",this,pCon));
1091 	m_pFirstContainer = pCon;
1092 }
1093 
setLastContainer(fp_Container * pCon)1094 void fl_ContainerLayout::setLastContainer(fp_Container * pCon)
1095 {
1096 	xxx_UT_DEBUGMSG(("Set LastContainer of %x to %x \n",this,pCon));
1097 	m_pLastContainer = pCon;
1098 }
1099 
getFirstRun(void) const1100 fp_Run * fl_ContainerLayout::getFirstRun(void) const
1101 {
1102 	if(getContainerType() == FL_CONTAINER_BLOCK)
1103 	{
1104 		const fl_BlockLayout * pBL = static_cast<const fl_BlockLayout *>(this);
1105 		return pBL->getFirstRun();
1106 	}
1107 	else if(getFirstLayout() == NULL)
1108 	{
1109 		return NULL;
1110 	}
1111 	return getFirstLayout()->getFirstRun();
1112 }
1113 
1114 /*!
1115  Get Container's position in document
1116  \param bActualContainerPos When true return block's position. When false
1117 						return position of first run in block
1118  \return Position of Container (or first run in block)
1119  \fixme Split in two functions if called most often with FALSE
1120 */
getPosition(bool bActualBlockPos) const1121 UT_uint32 fl_ContainerLayout::getPosition(bool bActualBlockPos) const
1122 {
1123 	const fl_ContainerLayout * pL = this;
1124 	if(!bActualBlockPos && (getContainerType() != FL_CONTAINER_TOC))
1125 	{
1126 		pL = static_cast<fl_ContainerLayout *>(getNextBlockInDocument());
1127 		if(pL == NULL)
1128 		{
1129 		  PT_DocPosition pos = getDocLayout()->getDocument()->getStruxPosition(getStruxDocHandle());
1130 		  return pos;
1131 		}
1132 		if(pL->getContainerType() == FL_CONTAINER_BLOCK)
1133 		{
1134 			const fl_BlockLayout * pBL = static_cast<const fl_BlockLayout *>(pL);
1135 			return pBL->getPosition(bActualBlockPos);
1136 		}
1137 		return 0;
1138 	}
1139 	PT_DocPosition pos = getDocLayout()->getDocument()->getStruxPosition(getStruxDocHandle());
1140 	return pos;
1141 }
1142 
getHdrFtrSectionLayout(void) const1143 fl_HdrFtrSectionLayout*	fl_ContainerLayout::getHdrFtrSectionLayout(void) const
1144 {
1145 	if(getContainerType() != FL_CONTAINER_SHADOW)
1146 	{
1147 		return NULL;
1148 	}
1149 	const fl_HdrFtrShadow * pHFS = static_cast<const fl_HdrFtrShadow * >(this);
1150 	return pHFS->getHdrFtrSectionLayout();
1151 }
1152 
canContainPoint() const1153 bool fl_ContainerLayout::canContainPoint() const
1154 {
1155 	if(isCollapsed())
1156 		return false;
1157 
1158 	FV_View* pView = getDocLayout()->getView();
1159 	bool bShowHidden = pView->getShowPara();
1160 
1161 	bool bHidden = ((m_eHidden == FP_HIDDEN_TEXT && !bShowHidden)
1162 	              || m_eHidden == FP_HIDDEN_REVISION
1163 		          || m_eHidden == FP_HIDDEN_REVISION_AND_TEXT);
1164 
1165 	if(bHidden)
1166 		return false;
1167 
1168 	if(!_canContainPoint())
1169 		return false;
1170 
1171 	// see if we are not inside a containing layout that cannot contain point
1172 	fl_ContainerLayout * pMyLayout = myContainingLayout();
1173 
1174 	if(!pMyLayout || pMyLayout->getContainerType() == FL_CONTAINER_DOCSECTION)
1175 		return true;
1176 
1177 	return pMyLayout->canContainPoint();
1178 }
1179 
isOnScreen() const1180 bool fl_ContainerLayout::isOnScreen() const
1181 {
1182 	// we check if any of our containers is on screen
1183 	// however, we will not call fp_Container::isOnScreen() to avoid
1184 	// unnecessary overhead
1185 
1186 	if(isCollapsed())
1187 		return false;
1188 
1189 	UT_return_val_if_fail(getDocLayout(),false);
1190 
1191 	FV_View *pView = getDocLayout()->getView();
1192 
1193 	bool bShowHidden = pView && pView->getShowPara();
1194 
1195 	bool bHidden = ((m_eHidden == FP_HIDDEN_TEXT && !bShowHidden)
1196 	              || m_eHidden == FP_HIDDEN_REVISION
1197 		          || m_eHidden == FP_HIDDEN_REVISION_AND_TEXT);
1198 
1199 
1200 	if(bHidden)
1201 		return false;
1202 
1203 	UT_GenericVector<UT_Rect*> vRect;
1204 	UT_GenericVector<fp_Page*> vPages;
1205 
1206 	pView->getVisibleDocumentPagesAndRectangles(vRect, vPages);
1207 
1208 	UT_uint32 iCount = vPages.getItemCount();
1209 
1210 	if(!iCount)
1211 		return false;
1212 
1213 	bool bRet = false;
1214 	fp_Container * pC = getFirstContainer();
1215 
1216 	if(!pC)
1217 		return false;
1218 
1219 	fp_Container *pCEnd = getLastContainer();
1220 
1221 	while(pC)
1222 	{
1223 		fp_Page * pMyPage = pC->getPage();
1224 
1225 		if(pMyPage)
1226 		{
1227 			for(UT_uint32 i = 0; i < iCount; i++)
1228 			{
1229 				fp_Page * pPage = vPages.getNthItem(i);
1230 
1231 				if(pPage == pMyPage)
1232 				{
1233 					UT_Rect r;
1234 					UT_Rect *pR = vRect.getNthItem(i);
1235 
1236 					if(!pC->getPageRelativeOffsets(r))
1237 						break;
1238 
1239 					bRet = r.intersectsRect(pR);
1240 					break;
1241 				}
1242 
1243 			}
1244 		}
1245 
1246 		if(bRet || pC == pCEnd)
1247 			break;
1248 
1249 		pC = static_cast<fp_Container*>(pC->getNext());
1250 	}
1251 
1252 	UT_VECTOR_PURGEALL(UT_Rect*,vRect);
1253 	return bRet;
1254 }
1255 
1256 // Frames stuff
1257 
addFrame(fl_FrameLayout * pFrame)1258 void fl_ContainerLayout::addFrame(fl_FrameLayout * pFrame)
1259 {
1260 	UT_DEBUGMSG(("Adding frame %p to list in container %p \n",pFrame,this));
1261 	UT_sint32 i = m_vecFrames.findItem(pFrame);
1262 	if(i>= 0)
1263 	{
1264 		UT_DEBUGMSG(("Adding already existing frame \n"));
1265 		UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
1266 		return;
1267 	}
1268 	m_vecFrames.addItem(pFrame);
1269 	if (!pFrame->getParentContainer())
1270 	{
1271 		pFrame->setParentContainer(this);
1272 	}
1273 	else
1274 	{
1275 		UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1276 	}
1277 }
1278 
getNumFrames(void) const1279 UT_sint32 fl_ContainerLayout::getNumFrames(void) const
1280 {
1281 	return m_vecFrames.getItemCount();
1282 }
1283 
getNthFrameLayout(UT_sint32 i) const1284 fl_FrameLayout * fl_ContainerLayout::getNthFrameLayout(UT_sint32 i) const
1285 {
1286 	if(i> getNumFrames())
1287 	{
1288 		return NULL;
1289 	}
1290 	return m_vecFrames.getNthItem(i);
1291 }
1292 
1293 
getNthFrameContainer(UT_sint32 i) const1294 fp_FrameContainer * fl_ContainerLayout::getNthFrameContainer(UT_sint32 i) const
1295 {
1296 	if(i> getNumFrames())
1297 	{
1298 		return NULL;
1299 	}
1300 	fl_FrameLayout * pFrame= m_vecFrames.getNthItem(i);
1301 	fp_FrameContainer * pFC = static_cast<fp_FrameContainer *>(pFrame->getFirstContainer());
1302 	return pFC;
1303 }
1304 
removeFrame(fl_FrameLayout * pFrame)1305 bool fl_ContainerLayout::removeFrame(fl_FrameLayout * pFrame)
1306 {
1307 	UT_DEBUGMSG(("Remove Frame %p from this container %p \n",pFrame,this));
1308 	UT_sint32 i = m_vecFrames.findItem(pFrame);
1309 	if(i >= 0)
1310 	{
1311 		m_vecFrames.deleteNthItem(i);
1312 		if (pFrame->getParentContainer() == this)
1313 		{
1314 			pFrame->setParentContainer(NULL);
1315 		}
1316 		return true;
1317 	}
1318 	else
1319 	{
1320 		UT_DEBUGMSG((" Requested Frame not found \n"));
1321 		return false;
1322 	}
1323 }
1324 
1325 
1326 /* This function returns true if the layout contains a footnote layout and false otherwise.
1327    The function returns false if the layout is contained inside a footnote layout.
1328    TODO TODO TODO: Move embedded layouts out of the main fl_Container lists
1329 */
1330 
containsFootnoteLayouts(void) const1331 bool fl_ContainerLayout::containsFootnoteLayouts(void) const
1332 {
1333 	if (getEndStruxDocHandle())
1334 	{
1335 		PT_DocPosition posStart = getDocument()->getStruxPosition(getStruxDocHandle());
1336 		PT_DocPosition posEnd = getDocument()->getStruxPosition(getEndStruxDocHandle());
1337 		return getDocument()->hasEmbedStruxOfTypeInRange(posStart,posEnd,PTX_SectionFootnote);
1338 	}
1339 	// This function has not yet been implemented for layouts that do not have a end strux (blocks, sections)
1340 	UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1341 	return false;
1342 }
1343 
1344 
1345 /* This function returns true if the layout contains a footnote layout and false otherwise.
1346    The function returns false if the layout is contained inside a footnote layout.
1347    TODO TODO TODO: Move embedded layouts out of the main fl_Container lists
1348 */
1349 
containsAnnotationLayouts(void) const1350 bool fl_ContainerLayout::containsAnnotationLayouts(void) const
1351 {
1352 	if (getEndStruxDocHandle())
1353 	{
1354 		PT_DocPosition posStart = getDocument()->getStruxPosition(getStruxDocHandle());
1355 		PT_DocPosition posEnd = getDocument()->getStruxPosition(getEndStruxDocHandle());
1356 		return getDocument()->hasEmbedStruxOfTypeInRange(posStart,posEnd,PTX_SectionAnnotation);
1357 	}
1358 	// This function has not yet been implemented for layouts that do not have a end strux (blocks, sections)
1359 	UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1360 	return false;
1361 }
1362 
1363