1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 /* AbiWord
3 * Copyright (C) 1998 AbiSource, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA.
19 */
20
21
22 // deleteStrux-related functions for class pt_PieceTable.
23
24 #include "ut_types.h"
25 #include "ut_misc.h"
26 #include "ut_assert.h"
27 #include "ut_debugmsg.h"
28 #include "ut_growbuf.h"
29 #include "pt_PieceTable.h"
30 #include "pf_Frag.h"
31 #include "pf_Frag_Strux.h"
32 #include "pf_Frag_Strux_Block.h"
33 #include "pf_Frag_Strux_Section.h"
34 #include "pf_Frag_Text.h"
35 #include "pf_Fragments.h"
36 #include "px_ChangeRecord.h"
37 #include "px_CR_Span.h"
38 #include "px_CR_SpanChange.h"
39 #include "px_CR_Strux.h"
40
41 /****************************************************************/
42 /****************************************************************/
_unlinkStrux(pf_Frag_Strux * pfs,pf_Frag ** ppfEnd,UT_uint32 * pfragOffsetEnd)43 bool pt_PieceTable::_unlinkStrux(pf_Frag_Strux * pfs,
44 pf_Frag ** ppfEnd, UT_uint32 * pfragOffsetEnd)
45 {
46 #if DEBUG
47 if(pfs->getStruxType() == PTX_SectionTable)
48 {
49 UT_DEBUGMSG(("_unlink Strux Table %p \n",pfs));
50 }
51 else if(pfs->getStruxType() == PTX_SectionCell)
52 {
53 UT_DEBUGMSG(("_unlink Strux Cell %p \n",pfs));
54 }
55 else if(pfs->getStruxType() == PTX_EndTable)
56 {
57 UT_DEBUGMSG(("_unlink Strux End Table %p \n",pfs));
58 }
59 else if(pfs->getStruxType() == PTX_EndCell)
60 {
61 UT_DEBUGMSG(("_unlink Strux EndCell %p \n",pfs));
62 }
63 else if(pfs->getStruxType() == PTX_SectionFrame)
64 {
65 UT_DEBUGMSG(("_unlink Strux SectionFrame %p \n",pfs));
66 }
67 else if(pfs->getStruxType() == PTX_EndFrame)
68 {
69 UT_DEBUGMSG(("_unlink Strux EndFrame %p \n",pfs));
70 }
71 else if(pfs->getStruxType() == PTX_Block)
72 {
73 UT_DEBUGMSG(("_unlink Strux Block %p \n",pfs));
74 }
75 else if(pfs->getStruxType() == PTX_Section)
76 {
77 UT_DEBUGMSG(("_unlink Strux Section %p \n",pfs));
78 }
79 else if(pfs->getStruxType() == PTX_SectionHdrFtr)
80 {
81 UT_DEBUGMSG(("_unlink HdrFtr Strux Section %p \n",pfs));
82 }
83 else if(pfs->getStruxType() == PTX_SectionFootnote)
84 {
85 UT_DEBUGMSG(("_unlink Strux SectionFootnote %p \n",pfs));
86 }
87 else if(pfs->getStruxType() == PTX_EndFootnote)
88 {
89 UT_DEBUGMSG(("_unlink Strux EndFootnote %p \n",pfs));
90 }
91 else if(pfs->getStruxType() == PTX_SectionEndnote)
92 {
93 UT_DEBUGMSG(("_unlink Strux SectionEndnote %p \n",pfs));
94 }
95 else if(pfs->getStruxType() == PTX_EndEndnote)
96 {
97 UT_DEBUGMSG(("_unlink Strux EndEndnote %p \n",pfs));
98 }
99 else if(pfs->getStruxType() == PTX_SectionTOC)
100 {
101 UT_DEBUGMSG(("_unlink Strux SectionTOC %p \n",pfs));
102 }
103 else if(pfs->getStruxType() == PTX_EndTOC)
104 {
105 UT_DEBUGMSG(("_unlink Strux EndTOC %p \n",pfs));
106 }
107 // m_pDocument->miniDump(pfs, 2);
108 #endif
109 switch (pfs->getStruxType())
110 {
111 case PTX_Section:
112 case PTX_SectionHdrFtr:
113 case PTX_SectionEndnote:
114 case PTX_SectionTable:
115 case PTX_SectionFrame:
116 case PTX_SectionCell:
117 case PTX_SectionFootnote:
118 case PTX_SectionAnnotation:
119 case PTX_SectionTOC:
120 case PTX_EndCell:
121 case PTX_EndTable:
122 case PTX_EndFootnote:
123 case PTX_EndEndnote:
124 case PTX_EndAnnotation:
125 case PTX_EndFrame:
126 case PTX_EndTOC:
127 return _unlinkStrux_Section(pfs,ppfEnd,pfragOffsetEnd);
128
129 case PTX_Block:
130 return _unlinkStrux_Block(pfs,ppfEnd,pfragOffsetEnd);
131
132 default:
133 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
134 return false;
135 }
136 }
137
_unlinkStrux_Block(pf_Frag_Strux * pfs,pf_Frag ** ppfEnd,UT_uint32 * pfragOffsetEnd)138 bool pt_PieceTable::_unlinkStrux_Block(pf_Frag_Strux * pfs,
139 pf_Frag ** ppfEnd, UT_uint32 * pfragOffsetEnd)
140 {
141 UT_return_val_if_fail (pfs->getStruxType()==PTX_Block,false);
142
143 // unlink this Block strux from the document.
144 // the caller is responsible for deleting pfs.
145
146 if (ppfEnd)
147 *ppfEnd = pfs->getNext();
148 if (pfragOffsetEnd)
149 *pfragOffsetEnd = 0;
150
151 // find the previous strux (either a paragraph or something else).
152
153 pf_Frag_Strux * pfsPrev = NULL;
154 _getStruxFromPosition(pfs->getPos(),&pfsPrev, true); // should that really skip footnotes?
155 UT_return_val_if_fail (pfsPrev, false); // we have a block that's not in a section ??
156 //
157 // Code to prevent a crash. But this should not happen and if it does not everything will
158 // be deleted - Sevior.
159 //
160 if(pfsPrev == NULL)
161 {
162 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
163 UT_DEBUGMSG(("shoudln't happen."));
164 UT_ASSERT(0);
165 return false;
166 }
167
168 switch (pfsPrev->getStruxType())
169 {
170
171 case PTX_Block:
172 // if there is a paragraph before us, we can delete this
173 // paragraph knowing that our content will be assimilated
174 // in to the previous one.
175
176 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
177 return true;
178
179 case PTX_Section:
180 // we are the first paragraph in this section. if we have
181 // content, we cannot be deleted, since there is no one to
182 // inherit our content.
183 UT_DEBUGMSG(("Prev frag is section in delete strux block \n"));
184 if (!_struxIsEmpty(pfs))
185 {
186 // TODO decide if this should assert or just fail...
187 UT_DEBUGMSG(("Cannot delete first paragraph with content.\n"));
188 UT_ASSERT_HARMLESS(0);
189 return false;
190 }
191 //
192 // Check to see if this is the first section of the document.
193 //
194 if(pfsPrev->getPrev() == NULL)
195 {
196 pf_Frag * pfNext = pfs->getNext();
197 if(pfNext == NULL)
198 {
199 //
200 // Cannot delete this because then there will be no page
201 //
202 UT_DEBUGMSG(("Cannot delete only paragraph.\n"));
203 UT_ASSERT_HARMLESS(0);
204 return false;
205 }
206 if(pfNext->getType() == pf_Frag::PFT_Strux)
207 {
208 pf_Frag_Strux * pfsNext = static_cast<pf_Frag_Strux *>(pfNext);
209 if(pfsNext->getStruxType() == PTX_SectionHdrFtr)
210 {
211 //
212 // Cannot delete this because then there will be no page
213 //
214 UT_DEBUGMSG(("Cannot delete only paragraph.\n"));
215 UT_ASSERT_HARMLESS(0);
216 return false;
217 }
218 if(pfsNext->getStruxType() == PTX_SectionFrame)
219 {
220 //
221 // Cannot delete this because then there will be nowhere
222 // for the frame
223 //
224 UT_DEBUGMSG(("Cannot delete becase we need the frame.\n"));
225 UT_ASSERT_HARMLESS(0);
226 return false;
227 }
228 }
229 }
230
231 case PTX_SectionHdrFtr:
232 // we are the first paragraph in this section. if we have
233 // content, we cannot be deleted, since there is no one to
234 // inherit our content.
235
236 if (!_struxIsEmpty(pfs))
237 {
238 // TODO decide if this should assert or just fail...
239 UT_DEBUGMSG(("Cannot delete first paragraph with content.\n"));
240 UT_ASSERT_HARMLESS(0);
241 return false;
242 }
243
244 // no content in this paragraph.
245
246 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
247 return true;
248
249 case PTX_SectionFrame:
250 case PTX_EndFrame:
251 case PTX_SectionTable:
252 case PTX_SectionCell:
253 case PTX_EndCell:
254 case PTX_EndTable:
255 //
256 // deleting tables and cells is a mutlti-step process and we can make no assumptions
257 // along the way.
258 //
259 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
260 return true;
261
262
263 default:
264 UT_ASSERT_HARMLESS(0);
265 return false;
266 }
267 }
268
_unlinkStrux_Section(pf_Frag_Strux * pfs,pf_Frag ** ppfEnd,UT_uint32 * pfragOffsetEnd)269 bool pt_PieceTable::_unlinkStrux_Section(pf_Frag_Strux * pfs,
270 pf_Frag ** ppfEnd, UT_uint32 * pfragOffsetEnd)
271 {
272 UT_return_val_if_fail (pfs->getStruxType()==PTX_Section
273 || pfs->getStruxType()==PTX_SectionHdrFtr
274 || pfs->getStruxType()==PTX_SectionEndnote
275 || pfs->getStruxType()==PTX_SectionTable
276 || pfs->getStruxType()==PTX_SectionFrame
277 || pfs->getStruxType()==PTX_SectionCell
278 || pfs->getStruxType()==PTX_EndCell
279 || pfs->getStruxType()==PTX_EndTable
280 || pfs->getStruxType()==PTX_EndFrame
281 || pfs->getStruxType()==PTX_SectionFootnote
282 || pfs->getStruxType()==PTX_EndFootnote
283 || pfs->getStruxType()==PTX_SectionAnnotation
284 || pfs->getStruxType()==PTX_EndAnnotation
285 || pfs->getStruxType()==PTX_SectionEndnote
286 || pfs->getStruxType()==PTX_EndEndnote
287 || pfs->getStruxType()==PTX_SectionTOC
288 || pfs->getStruxType()==PTX_EndTOC, false );
289
290 // unlink this Section strux from the document.
291 // the caller is responsible for deleting pfs.
292
293 if (ppfEnd)
294 *ppfEnd = pfs->getNext();
295 if (pfragOffsetEnd)
296 *pfragOffsetEnd = 0;
297
298 // find the previous strux (either a paragraph or something else).
299
300 pf_Frag_Strux * pfsPrev = NULL;
301 pf_Frag * pf = pfs->getPrev();
302 while (pf && (!pfsPrev || isFootnote(pf) || isEndFootnote(pf)))
303 {
304 if (pf->getType() == pf_Frag::PFT_Strux)
305 pfsPrev = static_cast<pf_Frag_Strux *> (pf);
306 pf = pf->getPrev();
307 }
308
309 if (!pfsPrev)
310 {
311 // first section in the document cannot be deleted.
312 // TODO decide if this should assesrt or just file...
313 UT_DEBUGMSG(("Cannot delete first section in document.\n"));
314 UT_ASSERT_HARMLESS(0);
315 return false;
316 }
317
318 // delete frag from the embedded_strux list if needed
319 if ((pfs->getStruxType() == PTX_SectionFootnote) ||
320 (pfs->getStruxType() == PTX_SectionEndnote) ||
321 (pfs->getStruxType() == PTX_SectionAnnotation))
322 {
323 bool bNoteRemoved = false;
324 if (!m_embeddedStrux.empty())
325 {
326 std::list<embeddedStrux>::iterator it;
327 for (it = m_embeddedStrux.begin(); it != m_embeddedStrux.end(); ++it)
328 {
329 if ((*it).beginNote == pfs)
330 {
331 m_embeddedStrux.erase(it);
332 bNoteRemoved = true;
333 break;
334 }
335 }
336 }
337 if (!bNoteRemoved)
338 {
339 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
340 }
341 }
342
343 switch (pfsPrev->getStruxType())
344 {
345 case PTX_Block:
346 // if there is a paragraph before us, we can delete this
347 // section knowing that our paragraphs will be assimilated
348 // in to the previous section (that is, the container of
349 // this block).
350
351 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
352 return true;
353 case PTX_SectionTable:
354 //
355 // deleting tables is a multi-step process that can't make assumptions
356 // on a single step
357 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
358 return true;
359 case PTX_SectionFrame:
360 //
361 // deleting Frames is a multi-step process that can't make assumptions
362 // on a single step
363 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
364 return true;
365 case PTX_EndFrame:
366 //
367 // deleting Frames is a multi-step process that can't make assumptions
368 // on a single step
369 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
370 return true;
371
372 case PTX_SectionCell:
373 //
374 // deleting tables is a multi-step process that can't make assumptions
375 // on a single step
376 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
377 return true;
378
379 case PTX_EndCell:
380 //
381 // deleting tables is a multi-step process that can't make assumptions
382 // on a single step
383 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
384 return true;
385
386 case PTX_EndTable:
387 //
388 // deleting tables is a multi-step process that can't make assumptions
389 // on a single step
390 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
391 return true;
392
393 case PTX_SectionEndnote:
394 //
395 // deleting Endnotes is a multi-step process that can't make
396 // assumptions
397 // on a single step
398 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
399 return true;
400
401 case PTX_EndEndnote:
402 //
403 // deleting Endnotes is a multi-step process that can't make
404 // assumptions
405 // on a single step
406 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
407 return true;
408
409
410 case PTX_SectionTOC:
411 //
412 // deleting TOC is a multi-step process that can't make
413 // assumptions
414 // on a single step
415 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
416 return true;
417
418 case PTX_EndTOC:
419 //
420 // deleting TOC is a multi-step process that can't make
421 // assumptions
422 // on a single step
423 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
424 return true;
425
426
427 case PTX_SectionFootnote:
428 //
429 // deleting Footnotes is a multi-step process that can't make
430 // assumptions
431 // on a single step
432 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
433 return true;
434
435 case PTX_EndFootnote:
436 //
437 // deleting Footnotes is a multi-step process that can't make
438 // assumptions
439 // on a single step
440 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
441 return true;
442
443
444
445 case PTX_SectionAnnotation:
446 //
447 // deleting Annotations is a multi-step process that can't make
448 // assumptions
449 // on a single step
450 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
451 return true;
452
453 case PTX_EndAnnotation:
454 //
455 // deleting Annotations is a multi-step process that can't make
456 // assumptions
457 // on a single step
458 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
459 return true;
460
461
462 case PTX_Section:
463 //
464 // We can delete Tables provided there is a block to take it's place later
465 //
466 if((pfs->getStruxType() == PTX_SectionTable) || (pfs->getStruxType() == PTX_EndTable))
467 {
468 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
469 return true;
470 }
471 // there are no blocks (paragraphs) between this section
472 // and the previous section. this is not possible.
473 // TODO decide if this should assert or just fail...
474 UT_DEBUGMSG(("No blocks between sections ??\n"));
475 UT_ASSERT_HARMLESS(0);
476 return false;
477
478
479 case PTX_SectionHdrFtr:
480 if((pfs->getStruxType() == PTX_SectionTable) || (pfs->getStruxType() == PTX_EndTable))
481 {
482 _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
483 return true;
484 }
485 // there are no blocks (paragraphs) between this section
486 // and the previous section. this is not possible.
487 // TODO decide if this should assert or just fail...
488 //
489 // Actually this is OK if it's a hdrFtr that has not been
490 // "realized" yet. Like an even hdrftr that has been defined
491 // but no even pages exist yet.
492 UT_DEBUGMSG(("No blocks between sections ??\n"));
493 // _unlinkFrag(pfs,ppfEnd,pfragOffsetEnd);
494 UT_ASSERT_HARMLESS(0);
495 return false;
496
497 default:
498 UT_ASSERT_HARMLESS(0);
499 return false;
500 }
501 }
502
_deleteStruxWithNotify(PT_DocPosition dpos,pf_Frag_Strux * pfs,pf_Frag ** ppfEnd,UT_uint32 * pfragOffsetEnd,bool bWithRec)503 bool pt_PieceTable::_deleteStruxWithNotify(PT_DocPosition dpos,
504 pf_Frag_Strux * pfs,
505 pf_Frag ** ppfEnd,
506 UT_uint32 * pfragOffsetEnd,
507 bool bWithRec)
508 {
509 UT_return_val_if_fail(pfs, false);
510 PX_ChangeRecord_Strux * pcrs
511 = new PX_ChangeRecord_Strux(PX_ChangeRecord::PXT_DeleteStrux,
512 dpos, pfs->getIndexAP(), pfs->getXID(), pfs->getStruxType());
513 UT_return_val_if_fail (pcrs, false);
514
515 if (!_unlinkStrux(pfs,ppfEnd,pfragOffsetEnd))
516 return false;
517
518 // add record to history. we do not attempt to coalesce these.
519 if (bWithRec)
520 m_history.addChangeRecord(pcrs);
521 m_pDocument->notifyListeners(pfs,pcrs);
522
523 delete pfs;
524
525 return true;
526 }
527
528 /*!
529 * This method scans the piecetAble from the section Frag_strux given looking
530 * for any Header/Footers that belong to the strux. If it finds them, they
531 * are deleted with notifications.
532 \param pf_Frag_Strux_Section pfStruxSec the Section strux that might have headers
533 * or footers belonging to it.
534 * These must be deleted with notification otherwise they won't be recreated on
535 * an undo
536 */
_deleteHdrFtrsFromSectionStruxIfPresent(pf_Frag_Strux_Section * pfStruxSec)537 bool pt_PieceTable::_deleteHdrFtrsFromSectionStruxIfPresent(pf_Frag_Strux_Section * pfStruxSec)
538 {
539 //
540 // Get the index to the Attributes/properties of the section strux to see if
541 // if there is a header defined for this strux.
542 //
543 // FIXME: Handle all the new header/footer types.
544 PT_AttrPropIndex indexAP = pfStruxSec->getIndexAP();
545 const PP_AttrProp * pAP = NULL;
546 getAttrProp(indexAP, &pAP);
547 UT_Vector vecHdrFtr;
548 UT_String HeaderV,HeaderEvenV,HeaderLastV,HeaderFirstV;
549 UT_String FooterV,FooterEvenV,FooterLastV,FooterFirstV;
550 vecHdrFtr.clear();
551 const gchar * szHeaderV = NULL;
552 bool bres = pAP->getAttribute("header",szHeaderV);
553 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
554 {
555 HeaderV = szHeaderV;
556 vecHdrFtr.addItem((void *) HeaderV.c_str());
557 }
558 szHeaderV = NULL;
559 bres = pAP->getAttribute("header-even",szHeaderV);
560 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
561 {
562 HeaderEvenV = szHeaderV;
563 vecHdrFtr.addItem((void *) HeaderEvenV.c_str());
564 }
565 szHeaderV = NULL;
566 bres = pAP->getAttribute("header-last",szHeaderV);
567 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
568 {
569 HeaderLastV = szHeaderV;
570 vecHdrFtr.addItem((void *) HeaderLastV.c_str());
571 }
572 szHeaderV = NULL;
573 bres = pAP->getAttribute("header-first",szHeaderV);
574 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
575 {
576 HeaderFirstV = szHeaderV;
577 vecHdrFtr.addItem((void *) HeaderFirstV.c_str());
578 }
579 szHeaderV = NULL;
580 bres = pAP->getAttribute("footer",szHeaderV);
581 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
582 {
583 FooterV = szHeaderV;
584 vecHdrFtr.addItem((void *) FooterV.c_str());
585 }
586 szHeaderV = NULL;
587 bres = pAP->getAttribute("footer-even",szHeaderV);
588 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
589 {
590 FooterEvenV = szHeaderV;
591 vecHdrFtr.addItem((void *) FooterEvenV.c_str());
592 }
593 szHeaderV = NULL;
594 bres = pAP->getAttribute("footer-last",szHeaderV);
595 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
596 {
597 FooterLastV = szHeaderV;
598 vecHdrFtr.addItem((void *) FooterLastV.c_str());
599 }
600 szHeaderV = NULL;
601 bres = pAP->getAttribute("footer-first",szHeaderV);
602 if(szHeaderV && *szHeaderV && (strcmp(szHeaderV,"0") != 0))
603 {
604 FooterFirstV = szHeaderV;
605 vecHdrFtr.addItem((void *) FooterFirstV.c_str());
606 }
607 UT_sint32 countHdrFtr = vecHdrFtr.getItemCount();
608 UT_DEBUGMSG(("SEVIOR: Deleting HdrFtrs from Document, num Header/Footers %d\n",countHdrFtr));
609 if(0 == countHdrFtr)
610 {
611 return true;
612 }
613 //
614 // This section has a header or footer attribute. Scan the piecetable to see
615 // if there is a header strux somewhere with an ID that matches our section.
616 //
617 pf_Frag * curFrag = NULL;
618 //
619 // Do this loop for all and headers and footers.
620 //
621 UT_sint32 i = 0;
622 for(i=0; i< countHdrFtr; i++)
623 {
624 curFrag = static_cast<pf_Frag *>(pfStruxSec);
625 bool bFoundIt = false;
626 pf_Frag_Strux * curStrux = NULL;
627 while(curFrag != getFragments().getLast() && !bFoundIt)
628 {
629 if(curFrag->getType() == pf_Frag::PFT_Strux)
630 {
631 curStrux = static_cast<pf_Frag_Strux *>(curFrag);
632 if(curStrux->getStruxType() == PTX_SectionHdrFtr)
633 {
634 //
635 // OK we've got a candidate
636 //
637 PT_AttrPropIndex indexAPHdr = curStrux->getIndexAP();
638 const PP_AttrProp * pAPHdr = NULL;
639 getAttrProp(indexAPHdr, &pAPHdr);
640 const gchar * szID = NULL;
641 bres = pAPHdr->getAttribute("id",szID);
642 UT_DEBUGMSG(("SEVIOR: Found candidate id = %s \n",szID));
643 if(bres && (szID != NULL))
644 {
645 //
646 // Look for a match.
647 //
648 szHeaderV = (const char *) vecHdrFtr.getNthItem(i);
649 if(szHeaderV != NULL && strcmp(szHeaderV,szID) == 0)
650 {
651 bFoundIt = true;
652 }
653 }
654 }
655 }
656 curFrag = curFrag->getNext();
657 }
658 if(bFoundIt)
659 {
660 //
661 // This Header belongs to our section. It must be deleted.
662 //
663 _deleteHdrFtrStruxWithNotify(curStrux);
664 }
665 }
666 return true;
667 }
668
669 /*!
670 * This method deletes the Header/Footer from the pieceTable in the order that
671 * will allow an undo to recreate it.
672 */
_deleteHdrFtrStruxWithNotify(pf_Frag_Strux * pfFragStruxHdrFtr)673 void pt_PieceTable::_deleteHdrFtrStruxWithNotify( pf_Frag_Strux * pfFragStruxHdrFtr)
674 {
675 //
676 // First we need the document position of the header/footer strux.
677 //
678 UT_DEBUGMSG(("SEVIOR: Deleting hdrftr \n"));
679 const pf_Frag * pfFrag = NULL;
680 pfFrag = static_cast<pf_Frag *>(pfFragStruxHdrFtr);
681 // TODO HdrFtrPos is unused
682 UT_DebugOnly<PT_DocPosition> HdrFtrPos = getFragPosition(pfFrag);
683 UT_Vector vecFragStrux;
684 UT_DEBUGMSG(("SEVIOR: Deleting hdrftr Strux Pos = %d \n",(PT_DocPosition)HdrFtrPos));
685 //
686 // Now find the first Non-strux frag within this hdrftr
687 //
688 bool bStop = false;
689 bool bIsTable = false;
690 PT_DocPosition posLastStrux = 0;
691 while((pfFrag->getType() == pf_Frag::PFT_Strux) && (pfFrag != getFragments().getLast()) && !bStop)
692 {
693 const pf_Frag_Strux * pfs = static_cast<const pf_Frag_Strux *>(pfFrag);
694 if(pfs != pfFragStruxHdrFtr && (pfs->getStruxType() != PTX_Block))
695 {
696 bStop = true;
697 if(pfs->getStruxType() == PTX_SectionTable)
698 {
699 bIsTable = true;
700 }
701 }
702 else
703 {
704 UT_DEBUGMSG(("Adding strux %p of type %d at Pos %d to strux vector for delete \n",pfs,pfs->getStruxType(),pfs->getPos()));
705 posLastStrux = pfs->getPos();
706 vecFragStrux.addItem((void *) pfFrag);
707 pfFrag = pfFrag->getNext();
708 }
709 }
710 PT_DocPosition TextStartPos = getFragPosition(pfFrag);
711 if(TextStartPos == posLastStrux && !bIsTable)
712 {
713 TextStartPos++;
714 }
715 UT_DEBUGMSG(("SEVIOR: Deleting hdrftr Text Start Pos = %d \n",TextStartPos));
716 //
717 // Now find the end of the text in the header/footer
718 //
719 bool foundEnd = false;
720 while(!foundEnd)
721 {
722 foundEnd = pfFrag == getFragments().getLast();
723 if(!foundEnd && pfFrag->getType() == pf_Frag::PFT_Strux)
724 {
725 const pf_Frag_Strux * pfFragStrux = static_cast<const pf_Frag_Strux *>(pfFrag);
726 foundEnd = ((pfFragStrux->getStruxType() != PTX_Block) &&
727 (pfFragStrux->getStruxType() != PTX_SectionTable) &&
728 (pfFragStrux->getStruxType() != PTX_SectionCell) &&
729 (pfFragStrux->getStruxType() != PTX_EndTable) &&
730 (pfFragStrux->getStruxType() != PTX_EndCell));
731 }
732 if(!foundEnd)
733 {
734 pfFrag = pfFrag->getNext();
735 }
736 }
737 PT_DocPosition TextEndPos = 0;
738 TextEndPos = getFragPosition(pfFrag);
739 if(pfFrag == getFragments().getLast())
740 {
741 TextEndPos = getFragPosition(pfFrag->getPrev()) + pfFrag->getPrev()->getLength();
742 }
743 UT_DEBUGMSG(("SEVIOR: Deleting hdrftr Text End Pos = %d \n",TextEndPos));
744 //
745 // OK delete the text
746 //
747 if(TextEndPos > TextStartPos)
748 {
749 UT_uint32 iRealDeleteCount;
750 deleteSpan(TextStartPos,TextEndPos,NULL,iRealDeleteCount,true);
751 // TODO -- is this right with revisions ???
752 }
753 //
754 // Now delete the struxes at the start.
755 //
756 //
757 UT_uint32 count = vecFragStrux.getItemCount();
758 UT_return_if_fail (count > 0);
759 UT_uint32 i=0;
760 bool bres = false;
761 //
762 // First delete the HdrFtr strux, then delete the blocks, this will enable the
763 // the HdrFtr to be properly recreated on undo (Since it needs blocks to be
764 // present before it can be created.)
765 //
766 bres = _deleteStruxWithNotify(pfFragStruxHdrFtr->getPos(),pfFragStruxHdrFtr,NULL,NULL);
767 for(i=1; i<count; i++)
768 {
769 pf_Frag_Strux * pfs = (pf_Frag_Strux *) vecFragStrux.getNthItem(i);
770 if(static_cast<pf_Frag *>(pfs) == getFragments().getLast())
771 {
772 UT_DEBUGMSG(("Delete Last Strux type %d \n",pfs->getStruxType()));
773 UT_ASSERT_HARMLESS(0);
774 }
775 UT_DEBUGMSG(("Delete Strux at %d strux type is %d \n",pfs->getPos(),pfs->getStruxType()));
776 if(pfs->getStruxType() != PTX_SectionHdrFtr)
777 {
778 bres = _deleteStruxWithNotify(pfs->getPos(),pfs,NULL,NULL);
779 }
780 UT_return_if_fail (bres);
781 }
782 UT_return_if_fail (bres);
783 // deleteSpan(HdrFtrPos,TextStartPos,NULL,true);
784 }
785
786
787
788
789