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