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