1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27
28 #include <MarkManager.hxx>
29 #include <bookmrk.hxx>
30 #include <boost/bind.hpp>
31 #include <cntfrm.hxx>
32 #include <crossrefbookmark.hxx>
33 #include <annotationmark.hxx>
34 #include <dcontact.hxx>
35 #include <doc.hxx>
36 #include <docary.hxx>
37 #include <xmloff/odffields.hxx>
38 #include <editsh.hxx>
39 #include <errhdl.hxx>
40 #include <fmtanchr.hxx>
41 #include <frmfmt.hxx>
42 #include <functional>
43 #include <hintids.hxx>
44 #include <mvsave.hxx>
45 #include <ndtxt.hxx>
46 #include <node.hxx>
47 #include <pam.hxx>
48 #include <redline.hxx>
49 #include <rolbck.hxx>
50 #include <rtl/ustrbuf.hxx>
51 #include <rtl/ustring.hxx>
52 #include <sal/types.h>
53 #include <sortedobjs.hxx>
54 #include <sfx2/linkmgr.hxx>
55 #include <swserv.hxx>
56 #include <swundo.hxx>
57 #include <tools/pstm.hxx>
58 #include <unocrsr.hxx>
59 #include <viscrs.hxx>
60 #include <stdio.h>
61
62
63 using namespace ::sw::mark;
64
65 namespace
66 {
lcl_GreaterThan(const SwPosition & rPos,const SwNodeIndex & rNdIdx,const SwIndex * pIdx)67 static bool lcl_GreaterThan( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
68 {
69 return pIdx != NULL
70 ? ( rPos.nNode > rNdIdx
71 || ( rPos.nNode == rNdIdx
72 && rPos.nContent >= pIdx->GetIndex() ) )
73 : rPos.nNode >= rNdIdx;
74 }
75
lcl_Lower(const SwPosition & rPos,const SwNodeIndex & rNdIdx,const SwIndex * pIdx)76 static bool lcl_Lower( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
77 {
78 return rPos.nNode < rNdIdx
79 || ( pIdx != NULL
80 && rPos.nNode == rNdIdx
81 && rPos.nContent < pIdx->GetIndex() );
82 }
83
lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t & rpFirst,const IDocumentMarkAccess::pMark_t & rpSecond)84 static bool lcl_MarkOrderingByStart(const IDocumentMarkAccess::pMark_t& rpFirst,
85 const IDocumentMarkAccess::pMark_t& rpSecond)
86 {
87 return rpFirst->GetMarkStart() < rpSecond->GetMarkStart();
88 }
89
lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t & rpFirst,const IDocumentMarkAccess::pMark_t & rpSecond)90 static bool lcl_MarkOrderingByEnd(const IDocumentMarkAccess::pMark_t& rpFirst,
91 const IDocumentMarkAccess::pMark_t& rpSecond)
92 {
93 return rpFirst->GetMarkEnd() < rpSecond->GetMarkEnd();
94 }
95
lcl_InsertMarkSorted(IDocumentMarkAccess::container_t & io_vMarks,const IDocumentMarkAccess::pMark_t & pMark)96 static void lcl_InsertMarkSorted(IDocumentMarkAccess::container_t& io_vMarks,
97 const IDocumentMarkAccess::pMark_t& pMark)
98 {
99 io_vMarks.insert(
100 lower_bound(
101 io_vMarks.begin(),
102 io_vMarks.end(),
103 pMark,
104 &lcl_MarkOrderingByStart),
105 pMark);
106 }
107
lcl_PositionFromCntntNode(SwCntntNode * const pCntntNode,const bool bAtEnd=false)108 static inline ::std::auto_ptr<SwPosition> lcl_PositionFromCntntNode(
109 SwCntntNode * const pCntntNode,
110 const bool bAtEnd=false)
111 {
112 ::std::auto_ptr<SwPosition> pResult(new SwPosition(*pCntntNode));
113 pResult->nContent.Assign(pCntntNode, bAtEnd ? pCntntNode->Len() : 0);
114 return pResult;
115 }
116
117 // return a position at the begin of rEnd, if it is a CntntNode
118 // else set it to the begin of the Node after rEnd, if there is one
119 // else set it to the end of the node before rStt
120 // else set it to the CntntNode of the Pos outside the Range
lcl_FindExpelPosition(const SwNodeIndex & rStt,const SwNodeIndex & rEnd,const SwPosition & rOtherPosition)121 static inline ::std::auto_ptr<SwPosition> lcl_FindExpelPosition(
122 const SwNodeIndex& rStt,
123 const SwNodeIndex& rEnd,
124 const SwPosition& rOtherPosition)
125 {
126 SwCntntNode * pNode = rEnd.GetNode().GetCntntNode();
127 bool bPosAtEndOfNode = false;
128 if ( pNode == NULL)
129 {
130 SwNodeIndex aEnd = SwNodeIndex(rEnd);
131 pNode = rEnd.GetNodes().GoNext( &aEnd );
132 bPosAtEndOfNode = false;
133 }
134 if ( pNode == NULL )
135 {
136 SwNodeIndex aStt = SwNodeIndex(rStt);
137 pNode = rStt.GetNodes().GoPrevious(&aStt);
138 bPosAtEndOfNode = true;
139 }
140 if ( pNode != NULL )
141 {
142 return lcl_PositionFromCntntNode( pNode, bPosAtEndOfNode );
143 }
144
145 return ::std::auto_ptr<SwPosition>(new SwPosition(rOtherPosition));
146 };
147
lcl_getMarkAfter(const IDocumentMarkAccess::container_t & rMarks,const SwPosition & rPos)148 static IMark* lcl_getMarkAfter(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
149 {
150 IDocumentMarkAccess::const_iterator_t pMarkAfter = upper_bound(
151 rMarks.begin(),
152 rMarks.end(),
153 rPos,
154 bind(&IMark::StartsAfter, _2, _1)); // finds the first that is starting after
155 if(pMarkAfter == rMarks.end()) return NULL;
156 return pMarkAfter->get();
157 };
158
lcl_getMarkBefore(const IDocumentMarkAccess::container_t & rMarks,const SwPosition & rPos)159 static IMark* lcl_getMarkBefore(const IDocumentMarkAccess::container_t& rMarks, const SwPosition& rPos)
160 {
161 // candidates from which to choose the mark before
162 IDocumentMarkAccess::container_t vCandidates;
163 // no need to consider marks starting after rPos
164 IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
165 rMarks.begin(),
166 rMarks.end(),
167 rPos,
168 bind(&IMark::StartsAfter, _2, _1));
169 vCandidates.reserve(pCandidatesEnd - rMarks.begin());
170 // only marks ending before are candidates
171 remove_copy_if(
172 rMarks.begin(),
173 pCandidatesEnd,
174 back_inserter(vCandidates),
175 boost::bind( ::std::logical_not<bool>(), bind( &IMark::EndsBefore, _1, rPos ) ) );
176 // no candidate left => we are in front of the first mark or there are none
177 if(!vCandidates.size()) return NULL;
178 // return the highest (last) candidate using mark end ordering
179 return max_element(vCandidates.begin(), vCandidates.end(), &lcl_MarkOrderingByEnd)->get();
180 }
181
lcl_FixCorrectedMark(const bool bChangedPos,const bool bChangedOPos,MarkBase * io_pMark)182 static bool lcl_FixCorrectedMark(
183 const bool bChangedPos,
184 const bool bChangedOPos,
185 MarkBase* io_pMark )
186 {
187 if ( IDocumentMarkAccess::GetType(*io_pMark) == IDocumentMarkAccess::ANNOTATIONMARK )
188 {
189 // annotation marks are allowed to span a table cell range.
190 // but trigger sorting to be save
191 return true;
192 }
193
194 if ( ( bChangedPos || bChangedOPos )
195 && io_pMark->IsExpanded()
196 && io_pMark->GetOtherMarkPos().nNode.GetNode().FindTableBoxStartNode() !=
197 io_pMark->GetMarkPos().nNode.GetNode().FindTableBoxStartNode() )
198 {
199 if ( !bChangedOPos )
200 {
201 io_pMark->SetMarkPos( io_pMark->GetOtherMarkPos() );
202 }
203 io_pMark->ClearOtherMarkPos();
204 DdeBookmark * const pDdeBkmk = dynamic_cast< DdeBookmark*>(io_pMark);
205 if ( pDdeBkmk != NULL
206 && pDdeBkmk->IsServer() )
207 {
208 pDdeBkmk->SetRefObject(NULL);
209 }
210 return true;
211 }
212 return false;
213 }
214
lcl_FindMark(IDocumentMarkAccess::container_t & rMarks,const IDocumentMarkAccess::pMark_t & rpMarkToFind)215 static IDocumentMarkAccess::iterator_t lcl_FindMark(
216 IDocumentMarkAccess::container_t& rMarks,
217 const IDocumentMarkAccess::pMark_t& rpMarkToFind)
218 {
219 IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
220 rMarks.begin(), rMarks.end(),
221 rpMarkToFind, &lcl_MarkOrderingByStart);
222 // since there are usually not too many marks on the same start
223 // position, we are not doing a bisect search for the upper bound
224 // but instead start to iterate from pMarkLow directly
225 while(ppCurrentMark != rMarks.end() && **ppCurrentMark == *rpMarkToFind)
226 {
227 if(ppCurrentMark->get() == rpMarkToFind.get())
228 {
229 //OSL_TRACE("found mark named '%s'",
230 // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
231 return ppCurrentMark;
232 }
233 ++ppCurrentMark;
234 }
235 // reached a mark starting on a later start pos or the end of the
236 // vector => not found
237 return rMarks.end();
238 };
239
lcl_FindMarkAtPos(IDocumentMarkAccess::container_t & rMarks,const SwPosition & rPos,const IDocumentMarkAccess::MarkType eType)240 static IDocumentMarkAccess::iterator_t lcl_FindMarkAtPos(
241 IDocumentMarkAccess::container_t& rMarks,
242 const SwPosition& rPos,
243 const IDocumentMarkAccess::MarkType eType)
244 {
245 for(IDocumentMarkAccess::iterator_t ppCurrentMark = lower_bound(
246 rMarks.begin(), rMarks.end(),
247 rPos,
248 bind(&IMark::StartsBefore, _1, _2));
249 ppCurrentMark != rMarks.end();
250 ++ppCurrentMark)
251 {
252 // Once we reach a mark starting after the target pos
253 // we do not need to continue
254 if(ppCurrentMark->get()->StartsAfter(rPos))
255 break;
256 if(IDocumentMarkAccess::GetType(**ppCurrentMark) == eType)
257 {
258 //OSL_TRACE("found mark named '%s'",
259 // ::rtl::OUStringToOString(ppCurrentMark->get()->GetName(), RTL_TEXTENCODING_UTF8).getStr());
260 return ppCurrentMark;
261 }
262 }
263 // reached a mark starting on a later start pos or the end of the
264 // vector => not found
265 return rMarks.end();
266 };
267
lcl_FindMarkByName(const::rtl::OUString & rName,IDocumentMarkAccess::const_iterator_t ppMarksBegin,IDocumentMarkAccess::const_iterator_t ppMarksEnd)268 static IDocumentMarkAccess::const_iterator_t lcl_FindMarkByName(
269 const ::rtl::OUString& rName,
270 IDocumentMarkAccess::const_iterator_t ppMarksBegin,
271 IDocumentMarkAccess::const_iterator_t ppMarksEnd)
272 {
273 return find_if(
274 ppMarksBegin,
275 ppMarksEnd,
276 bind(&::rtl::OUString::equals, bind(&IMark::GetName, _1), rName));
277 }
278
279 #if 0
280 static void lcl_DebugMarks(IDocumentMarkAccess::container_t vMarks)
281 {
282 OSL_TRACE("%d Marks", vMarks.size());
283 for(IDocumentMarkAccess::iterator_t ppMark = vMarks.begin();
284 ppMark != vMarks.end();
285 ppMark++)
286 {
287 IMark* pMark = ppMark->get();
288 ::rtl::OString sName = ::rtl::OUStringToOString(pMark->GetName(), RTL_TEXTENCODING_UTF8);
289 const SwPosition* const pStPos = &pMark->GetMarkStart();
290 const SwPosition* const pEndPos = &pMark->GetMarkEnd();
291 OSL_TRACE("%s %s %d,%d %d,%d",
292 typeid(*pMark).name(),
293 sName.getStr(),
294 pStPos->nNode.GetIndex(),
295 pStPos->nContent.GetIndex(),
296 pEndPos->nNode.GetIndex(),
297 pEndPos->nContent.GetIndex());
298 }
299 };
300 #endif
301 }
302
GetType(const IMark & rBkmk)303 IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk)
304 {
305 const std::type_info* const pMarkTypeInfo = &typeid(rBkmk);
306 // not using dynamic_cast<> here for performance
307 if(*pMarkTypeInfo == typeid(UnoMark))
308 return UNO_BOOKMARK;
309 else if(*pMarkTypeInfo == typeid(DdeBookmark))
310 return DDE_BOOKMARK;
311 else if(*pMarkTypeInfo == typeid(Bookmark))
312 return BOOKMARK;
313 else if(*pMarkTypeInfo == typeid(CrossRefHeadingBookmark))
314 return CROSSREF_HEADING_BOOKMARK;
315 else if(*pMarkTypeInfo == typeid(CrossRefNumItemBookmark))
316 return CROSSREF_NUMITEM_BOOKMARK;
317 else if(*pMarkTypeInfo == typeid(AnnotationMark))
318 return ANNOTATIONMARK;
319 else if(*pMarkTypeInfo == typeid(TextFieldmark))
320 return TEXT_FIELDMARK;
321 else if(*pMarkTypeInfo == typeid(CheckboxFieldmark))
322 return CHECKBOX_FIELDMARK;
323 else if(*pMarkTypeInfo == typeid(NavigatorReminder))
324 return NAVIGATOR_REMINDER;
325 else
326 {
327 OSL_ENSURE(false,
328 "IDocumentMarkAccess::GetType(..)"
329 " - unknown MarkType. This needs to be fixed!");
330 return UNO_BOOKMARK;
331 }
332 }
333
GetCrossRefHeadingBookmarkNamePrefix()334 const ::rtl::OUString& IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()
335 {
336 static const ::rtl::OUString CrossRefHeadingBookmarkNamePrefix = ::rtl::OUString::createFromAscii("__RefHeading__");
337
338 return CrossRefHeadingBookmarkNamePrefix;
339 }
340
IsLegalPaMForCrossRefHeadingBookmark(const SwPaM & rPaM)341 bool SAL_DLLPUBLIC_EXPORT IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( const SwPaM& rPaM )
342 {
343 bool bRet( false );
344
345 bRet = rPaM.Start()->nNode.GetNode().IsTxtNode() &&
346 rPaM.Start()->nContent.GetIndex() == 0 &&
347 ( !rPaM.HasMark() ||
348 ( rPaM.GetMark()->nNode == rPaM.GetPoint()->nNode &&
349 rPaM.End()->nContent.GetIndex() == rPaM.End()->nNode.GetNode().GetTxtNode()->Len() ) );
350
351 return bRet;
352 }
353
354 namespace sw { namespace mark
355 {
MarkManager(SwDoc & rDoc)356 MarkManager::MarkManager(SwDoc& rDoc)
357 : m_vAllMarks()
358 , m_vBookmarks()
359 , m_vFieldmarks()
360 , m_vAnnotationMarks()
361 , m_pDoc(&rDoc)
362 { }
363
364
makeMark(const SwPaM & rPaM,const::rtl::OUString & rName,const IDocumentMarkAccess::MarkType eType)365 ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM,
366 const ::rtl::OUString& rName,
367 const IDocumentMarkAccess::MarkType eType)
368 {
369 #if 0
370 {
371 ::rtl::OString sName = ::rtl::OUStringToOString(rName, RTL_TEXTENCODING_UTF8);
372 const SwPosition* const pPos1 = rPaM.GetPoint();
373 const SwPosition* pPos2 = pPos1;
374 if(rPaM.HasMark())
375 pPos2 = rPaM.GetMark();
376 OSL_TRACE("%s %d,%d %d,%d",
377 sName.getStr(),
378 pPos1->nNode.GetIndex(),
379 pPos1->nContent.GetIndex(),
380 pPos2->nNode.GetIndex(),
381 pPos2->nContent.GetIndex());
382 }
383 #endif
384 // see for example _SaveCntntIdx, Shells
385 OSL_PRECOND(m_vAllMarks.size() < USHRT_MAX,
386 "MarkManager::makeMark(..)"
387 " - more than USHRT_MAX marks are not supported correctly");
388 // There should only be one CrossRefBookmark per Textnode per Type
389 OSL_PRECOND(
390 (eType != CROSSREF_NUMITEM_BOOKMARK && eType != CROSSREF_HEADING_BOOKMARK)
391 || (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.GetPoint(), eType) == m_vBookmarks.end()),
392 "MarkManager::makeMark(..)"
393 " - creating duplicate CrossRefBookmark");
394
395 // create mark
396 MarkBase* pMarkBase = NULL;
397 switch(eType)
398 {
399 case IDocumentMarkAccess::TEXT_FIELDMARK:
400 pMarkBase = new TextFieldmark(rPaM);
401 break;
402 case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
403 pMarkBase = new CheckboxFieldmark(rPaM);
404 break;
405 case IDocumentMarkAccess::NAVIGATOR_REMINDER:
406 pMarkBase = new NavigatorReminder(rPaM);
407 break;
408 case IDocumentMarkAccess::BOOKMARK:
409 pMarkBase = new Bookmark(rPaM, KeyCode(), rName, ::rtl::OUString());
410 break;
411 case IDocumentMarkAccess::DDE_BOOKMARK:
412 pMarkBase = new DdeBookmark(rPaM);
413 break;
414 case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
415 pMarkBase = new CrossRefHeadingBookmark(rPaM, KeyCode(), rName, ::rtl::OUString());
416 break;
417 case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
418 pMarkBase = new CrossRefNumItemBookmark(rPaM, KeyCode(), rName, ::rtl::OUString());
419 break;
420 case IDocumentMarkAccess::UNO_BOOKMARK:
421 pMarkBase = new UnoMark(rPaM);
422 break;
423 case IDocumentMarkAccess::ANNOTATIONMARK:
424 pMarkBase = new AnnotationMark( rPaM, rName );
425 break;
426 }
427 OSL_ENSURE( pMarkBase!=NULL,
428 "MarkManager::makeMark(..)"
429 " - Mark was not created.");
430
431 pMark_t pMark = boost::shared_ptr<IMark>( pMarkBase);
432 if(pMark->GetMarkPos() != pMark->GetMarkStart())
433 pMarkBase->Swap();
434
435 // for performance reasons, we trust UnoMarks to have a (generated) unique name
436 if ( eType != IDocumentMarkAccess::UNO_BOOKMARK )
437 pMarkBase->SetName( getUniqueMarkName( pMarkBase->GetName() ) );
438
439 // register mark
440 lcl_InsertMarkSorted( m_vAllMarks, pMark );
441 switch(eType)
442 {
443 case IDocumentMarkAccess::BOOKMARK:
444 case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
445 case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
446 // if(dynamic_cast<IBookmark*>)
447 lcl_InsertMarkSorted(m_vBookmarks, pMark);
448 break;
449 case IDocumentMarkAccess::TEXT_FIELDMARK:
450 case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
451 // if(dynamic_cast<IFieldmark*>
452 lcl_InsertMarkSorted(m_vFieldmarks, pMark);
453 break;
454 case IDocumentMarkAccess::ANNOTATIONMARK:
455 lcl_InsertMarkSorted( m_vAnnotationMarks, pMark );
456 break;
457 case IDocumentMarkAccess::NAVIGATOR_REMINDER:
458 case IDocumentMarkAccess::DDE_BOOKMARK:
459 case IDocumentMarkAccess::UNO_BOOKMARK:
460 // no special array for these
461 break;
462 }
463 pMarkBase->InitDoc(m_pDoc);
464 #if 0
465 OSL_TRACE("--- makeType ---");
466 OSL_TRACE("Marks");
467 lcl_DebugMarks(m_vAllMarks);
468 OSL_TRACE("Bookmarks");
469 lcl_DebugMarks(m_vBookmarks);
470 OSL_TRACE("Fieldmarks");
471 lcl_DebugMarks(m_vFieldmarks);
472 #endif
473 return pMark.get();
474 }
475
476
makeFieldBookmark(const SwPaM & rPaM,const rtl::OUString & rName,const rtl::OUString & rType)477 ::sw::mark::IFieldmark* MarkManager::makeFieldBookmark(
478 const SwPaM& rPaM,
479 const rtl::OUString& rName,
480 const rtl::OUString& rType )
481 {
482 sw::mark::IMark* pMark =
483 makeMark( rPaM, rName, IDocumentMarkAccess::TEXT_FIELDMARK );
484 sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
485 pFieldMark->SetFieldname( rType );
486
487 return pFieldMark;
488 }
489
490
makeNoTextFieldBookmark(const SwPaM & rPaM,const rtl::OUString & rName,const rtl::OUString & rType)491 ::sw::mark::IFieldmark* MarkManager::makeNoTextFieldBookmark(
492 const SwPaM& rPaM,
493 const rtl::OUString& rName,
494 const rtl::OUString& rType)
495 {
496 sw::mark::IMark* pMark = makeMark( rPaM, rName,
497 IDocumentMarkAccess::CHECKBOX_FIELDMARK );
498 sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark );
499 pFieldMark->SetFieldname( rType );
500
501 return pFieldMark;
502 }
503
504
getMarkForTxtNode(const SwTxtNode & rTxtNode,const IDocumentMarkAccess::MarkType eType)505 ::sw::mark::IMark* MarkManager::getMarkForTxtNode(
506 const SwTxtNode& rTxtNode,
507 const IDocumentMarkAccess::MarkType eType )
508 {
509 SwPosition aPos(rTxtNode);
510 aPos.nContent.Assign(&(const_cast<SwTxtNode&>(rTxtNode)), 0);
511 const iterator_t ppExistingMark = lcl_FindMarkAtPos(m_vBookmarks, aPos, eType);
512 if(ppExistingMark != m_vBookmarks.end())
513 return ppExistingMark->get();
514 const SwPaM aPaM(aPos);
515 return makeMark(aPaM, ::rtl::OUString(), eType);
516 }
517
518
makeAnnotationMark(const SwPaM & rPaM,const::rtl::OUString & rName)519 sw::mark::IMark* MarkManager::makeAnnotationMark(
520 const SwPaM& rPaM,
521 const ::rtl::OUString& rName )
522 {
523 return makeMark( rPaM, rName, IDocumentMarkAccess::ANNOTATIONMARK );
524 }
525
repositionMark(::sw::mark::IMark * const io_pMark,const SwPaM & rPaM)526 void MarkManager::repositionMark(
527 ::sw::mark::IMark* const io_pMark,
528 const SwPaM& rPaM)
529 {
530 OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
531 "<MarkManager::repositionMark(..)>"
532 " - Mark is not in my doc.");
533 MarkBase* const pMarkBase = dynamic_cast< MarkBase* >(io_pMark);
534 pMarkBase->SetMarkPos(*(rPaM.GetPoint()));
535 if(rPaM.HasMark())
536 pMarkBase->SetOtherMarkPos(*(rPaM.GetMark()));
537 else
538 pMarkBase->ClearOtherMarkPos();
539
540 if(pMarkBase->GetMarkPos() != pMarkBase->GetMarkStart())
541 pMarkBase->Swap();
542
543 sortMarks();
544 }
545
546
renameMark(::sw::mark::IMark * io_pMark,const::rtl::OUString & rNewName)547 bool MarkManager::renameMark(
548 ::sw::mark::IMark* io_pMark,
549 const ::rtl::OUString& rNewName )
550 {
551 OSL_PRECOND(io_pMark->GetMarkPos().GetDoc() == m_pDoc,
552 "<MarkManager::repositionMark(..)>"
553 " - Mark is not in my doc.");
554 if ( io_pMark->GetName() == rNewName )
555 return true;
556 if ( findMark(rNewName) != m_vAllMarks.end() )
557 return false;
558 dynamic_cast< ::sw::mark::MarkBase* >(io_pMark)->SetName(rNewName);
559 return true;
560 }
561
562
correctMarksAbsolute(const SwNodeIndex & rOldNode,const SwPosition & rNewPos,const xub_StrLen nOffset)563 void MarkManager::correctMarksAbsolute(
564 const SwNodeIndex& rOldNode,
565 const SwPosition& rNewPos,
566 const xub_StrLen nOffset)
567 {
568 const SwNode* const pOldNode = &rOldNode.GetNode();
569 SwPosition aNewPos(rNewPos);
570 aNewPos.nContent += nOffset;
571 bool isSortingNeeded = false;
572
573 for(iterator_t ppMark = m_vAllMarks.begin();
574 ppMark != m_vAllMarks.end();
575 ppMark++)
576 {
577 ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
578 // is on position ??
579 bool bChangedPos = false;
580 if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
581 {
582 pMark->SetMarkPos(aNewPos);
583 bChangedPos = true;
584 }
585 bool bChangedOPos = false;
586 if (pMark->IsExpanded() &&
587 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
588 {
589 pMark->SetMarkPos(aNewPos);
590 bChangedOPos= true;
591 }
592 // illegal selection? collapse the mark and restore sorting later
593 isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
594 }
595
596 // restore sorting if needed
597 if(isSortingNeeded)
598 sortMarks();
599 #if 0
600 OSL_TRACE("correctMarksAbsolute");
601 lcl_DebugMarks(m_vAllMarks);
602 #endif
603 }
604
605
correctMarksRelative(const SwNodeIndex & rOldNode,const SwPosition & rNewPos,const xub_StrLen nOffset)606 void MarkManager::correctMarksRelative(const SwNodeIndex& rOldNode, const SwPosition& rNewPos, const xub_StrLen nOffset)
607 {
608 const SwNode* const pOldNode = &rOldNode.GetNode();
609 SwPosition aNewPos(rNewPos);
610 aNewPos.nContent += nOffset;
611 bool isSortingNeeded = false;
612
613 for(iterator_t ppMark = m_vAllMarks.begin();
614 ppMark != m_vAllMarks.end();
615 ppMark++)
616 {
617 // is on position ??
618 bool bChangedPos = false, bChangedOPos = false;
619 ::sw::mark::MarkBase* const pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
620 if(&pMark->GetMarkPos().nNode.GetNode() == pOldNode)
621 {
622 SwPosition aNewPosRel(aNewPos);
623 aNewPosRel.nContent += pMark->GetMarkPos().nContent.GetIndex();
624 pMark->SetMarkPos(aNewPosRel);
625 bChangedPos = true;
626 }
627 if(pMark->IsExpanded() &&
628 &pMark->GetOtherMarkPos().nNode.GetNode() == pOldNode)
629 {
630 SwPosition aNewPosRel(aNewPos);
631 aNewPosRel.nContent += pMark->GetOtherMarkPos().nContent.GetIndex();
632 pMark->SetOtherMarkPos(aNewPosRel);
633 bChangedOPos = true;
634 }
635 // illegal selection? collapse the mark and restore sorting later
636 isSortingNeeded |= lcl_FixCorrectedMark(bChangedPos, bChangedOPos, pMark);
637 }
638
639 // restore sorting if needed
640 if(isSortingNeeded)
641 sortMarks();
642 #if 0
643 OSL_TRACE("correctMarksRelative");
644 lcl_DebugMarks(m_vAllMarks);
645 #endif
646 }
647
648
deleteMarks(const SwNodeIndex & rStt,const SwNodeIndex & rEnd,::std::vector<SaveBookmark> * pSaveBkmk,const SwIndex * pSttIdx,const SwIndex * pEndIdx)649 void MarkManager::deleteMarks(
650 const SwNodeIndex& rStt,
651 const SwNodeIndex& rEnd,
652 ::std::vector<SaveBookmark>* pSaveBkmk,
653 const SwIndex* pSttIdx,
654 const SwIndex* pEndIdx )
655 {
656 ::std::vector<const_iterator_t> vMarksToDelete;
657 bool bIsSortingNeeded = false;
658
659 // boolean indicating, if at least one mark has been moved while colleting marks for deletion
660 bool bMarksMoved = false;
661
662 // copy all bookmarks in the move area to a vector storing all position data as offset
663 // reassignment is performed after the move
664 for(iterator_t ppMark = m_vAllMarks.begin();
665 ppMark != m_vAllMarks.end();
666 ppMark++)
667 {
668 // navigator marks should not be moved
669 // TODO: Check if this might make them invalid
670 if(IDocumentMarkAccess::GetType(**ppMark) == NAVIGATOR_REMINDER)
671 continue;
672
673 ::sw::mark::MarkBase* pMark = dynamic_cast< ::sw::mark::MarkBase* >(ppMark->get());
674 // on position ??
675 bool bIsPosInRange = lcl_GreaterThan(pMark->GetMarkPos(), rStt, pSttIdx)
676 && lcl_Lower(pMark->GetMarkPos(), rEnd, pEndIdx);
677 bool bIsOtherPosInRange = pMark->IsExpanded()
678 && lcl_GreaterThan(pMark->GetOtherMarkPos(), rStt, pSttIdx)
679 && lcl_Lower(pMark->GetOtherMarkPos(), rEnd, pEndIdx);
680 // special case: completely in range, touching the end?
681 if ( pEndIdx != NULL
682 && ( ( bIsOtherPosInRange
683 && pMark->GetMarkPos().nNode == rEnd
684 && pMark->GetMarkPos().nContent == *pEndIdx )
685 || ( bIsPosInRange
686 && pMark->IsExpanded()
687 && pMark->GetOtherMarkPos().nNode == rEnd
688 && pMark->GetOtherMarkPos().nContent == *pEndIdx ) ) )
689 {
690 bIsPosInRange = true, bIsOtherPosInRange = true;
691 }
692
693 if ( bIsPosInRange
694 && ( bIsOtherPosInRange
695 || !pMark->IsExpanded() ) )
696 {
697 // completely in range
698
699 bool bDeleteMark = true;
700 {
701 switch ( IDocumentMarkAccess::GetType( *pMark ) )
702 {
703 case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
704 case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
705 // no delete of cross-reference bookmarks, if range is inside one paragraph
706 bDeleteMark = rStt != rEnd;
707 break;
708 case IDocumentMarkAccess::UNO_BOOKMARK:
709 // no delete of UNO mark, if it is not expanded and only touches the start of the range
710 bDeleteMark = bIsOtherPosInRange
711 || pMark->IsExpanded()
712 || pSttIdx == NULL
713 || !( pMark->GetMarkPos().nNode == rStt
714 && pMark->GetMarkPos().nContent == *pSttIdx );
715 break;
716 default:
717 bDeleteMark = true;
718 break;
719 }
720 }
721
722 if ( bDeleteMark )
723 {
724 if ( pSaveBkmk )
725 {
726 pSaveBkmk->push_back( SaveBookmark( true, true, *pMark, rStt, pSttIdx ) );
727 }
728 vMarksToDelete.push_back(ppMark);
729 }
730 }
731 else if ( bIsPosInRange ^ bIsOtherPosInRange )
732 {
733 // the bookmark is partitially in the range
734 // move position of that is in the range out of it
735
736 ::std::auto_ptr< SwPosition > pNewPos;
737 {
738 if ( pEndIdx != NULL )
739 {
740 pNewPos = ::std::auto_ptr< SwPosition >( new SwPosition( rEnd, *pEndIdx ) );
741 }
742 else
743 {
744 pNewPos =
745 lcl_FindExpelPosition( rStt, rEnd, bIsPosInRange ? pMark->GetOtherMarkPos() : pMark->GetMarkPos() );
746 }
747 }
748
749 bool bMoveMark = true;
750 {
751 switch ( IDocumentMarkAccess::GetType( *pMark ) )
752 {
753 case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
754 case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
755 // no move of cross-reference bookmarks, if move occurs inside a certain node
756 bMoveMark = pMark->GetMarkPos().nNode != pNewPos->nNode;
757 break;
758 case IDocumentMarkAccess::ANNOTATIONMARK:
759 // no move of annotation marks, if method is called to collect deleted marks
760 bMoveMark = pSaveBkmk == NULL;
761 break;
762 default:
763 bMoveMark = true;
764 break;
765 }
766 }
767 if ( bMoveMark )
768 {
769 if ( bIsPosInRange )
770 pMark->SetMarkPos(*pNewPos);
771 else
772 pMark->SetOtherMarkPos(*pNewPos);
773 bMarksMoved = true;
774
775 // illegal selection? collapse the mark and restore sorting later
776 bIsSortingNeeded |= lcl_FixCorrectedMark( bIsPosInRange, bIsOtherPosInRange, pMark );
777 }
778 }
779 }
780
781 // If needed, sort mark containers containing subsets of the marks in order to assure sorting.
782 // The sorting is critical for the deletion of a mark as it is searched in these container for deletion.
783 if ( vMarksToDelete.size() > 0 && bMarksMoved )
784 {
785 sortSubsetMarks();
786 }
787 // we just remembered the iterators to delete, so we do not need to search
788 // for the shared_ptr<> (the entry in m_vAllMarks) again
789 // reverse iteration, since erasing an entry invalidates iterators
790 // behind it (the iterators in vMarksToDelete are sorted)
791 for ( ::std::vector< const_iterator_t >::reverse_iterator pppMark = vMarksToDelete.rbegin();
792 pppMark != vMarksToDelete.rend();
793 ++pppMark )
794 {
795 deleteMark(*pppMark);
796 }
797
798 if ( bIsSortingNeeded )
799 {
800 sortMarks();
801 }
802
803 #if 0
804 OSL_TRACE("deleteMarks");
805 lcl_DebugMarks(m_vAllMarks);
806 #endif
807 }
808
809
deleteMark(const const_iterator_t ppMark)810 void MarkManager::deleteMark(const const_iterator_t ppMark)
811 {
812 if(ppMark == m_vAllMarks.end()) return;
813
814 switch(IDocumentMarkAccess::GetType(**ppMark))
815 {
816 case IDocumentMarkAccess::BOOKMARK:
817 case IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK:
818 case IDocumentMarkAccess::CROSSREF_NUMITEM_BOOKMARK:
819 {
820 IDocumentMarkAccess::iterator_t ppBookmark = lcl_FindMark(m_vBookmarks, *ppMark);
821 if ( ppBookmark != m_vBookmarks.end() )
822 {
823 m_vBookmarks.erase(ppBookmark);
824 }
825 else
826 {
827 OSL_ENSURE( false, "<MarkManager::deleteMark(..)> - Bookmark not found in Bookmark container.");
828 }
829 }
830 break;
831
832 case IDocumentMarkAccess::TEXT_FIELDMARK:
833 case IDocumentMarkAccess::CHECKBOX_FIELDMARK:
834 {
835 IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark);
836 if ( ppFieldmark != m_vFieldmarks.end() )
837 {
838 m_vFieldmarks.erase(ppFieldmark);
839 }
840 else
841 {
842 OSL_ENSURE( false, "<MarkManager::deleteMark(..)> - Fieldmark not found in Fieldmark container.");
843 }
844
845 sw::mark::TextFieldmark* pTextFieldmark = dynamic_cast<sw::mark::TextFieldmark*>(ppMark->get());
846 if ( pTextFieldmark )
847 {
848 pTextFieldmark->ReleaseDoc(m_pDoc);
849 }
850
851 }
852 break;
853
854 case IDocumentMarkAccess::ANNOTATIONMARK:
855 {
856 IDocumentMarkAccess::iterator_t ppAnnotationMark = lcl_FindMark(m_vAnnotationMarks, *ppMark);
857 if ( ppAnnotationMark != m_vAnnotationMarks.end() )
858 {
859 m_vAnnotationMarks.erase(ppAnnotationMark);
860 }
861 else
862 {
863 OSL_ENSURE( false, "<MarkManager::deleteMark(..)> - Annotation Mark not found in Annotation Mark container.");
864 }
865 }
866 break;
867
868 case IDocumentMarkAccess::NAVIGATOR_REMINDER:
869 case IDocumentMarkAccess::DDE_BOOKMARK:
870 case IDocumentMarkAccess::UNO_BOOKMARK:
871 // no special marks container
872 break;
873 }
874 DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(ppMark->get());
875 if ( pDdeBookmark )
876 {
877 pDdeBookmark->DeregisterFromDoc(m_pDoc);
878 }
879 // keep a temporary instance of the to-be-deleted mark in order to avoid
880 // recursive deletion of the mark triggered via its destructor.
881 // the temporary hold instance assures that the mark is deleted after the
882 // mark container has been updated. Thus, the mark could not be found anymore
883 // in the mark container by other calls trying to recursively delete the mark.
884 iterator_t aToBeDeletedMarkIter = m_vAllMarks.begin() + (ppMark - m_vAllMarks.begin());
885 pMark_t pToBeDeletedMark = *aToBeDeletedMarkIter;
886 m_vAllMarks.erase( aToBeDeletedMarkIter );
887 }
888
deleteMark(const IMark * const pMark)889 void MarkManager::deleteMark(const IMark* const pMark)
890 {
891 OSL_PRECOND(pMark->GetMarkPos().GetDoc() == m_pDoc,
892 "<MarkManager::repositionMark(..)>"
893 " - Mark is not in my doc.");
894 // finds the last Mark that is starting before pMark
895 // (pMarkLow < pMark)
896 iterator_t pMarkLow =
897 lower_bound(
898 m_vAllMarks.begin(),
899 m_vAllMarks.end(),
900 pMark->GetMarkStart(),
901 bind(&IMark::StartsBefore, _1, _2) );
902 iterator_t pMarkHigh = m_vAllMarks.end();
903 iterator_t pMarkFound =
904 find_if(
905 pMarkLow,
906 pMarkHigh,
907 boost::bind( ::std::equal_to<const IMark*>(), bind(&boost::shared_ptr<IMark>::get, _1), pMark ) );
908 if(pMarkFound != pMarkHigh)
909 deleteMark(pMarkFound);
910 }
911
clearAllMarks()912 void MarkManager::clearAllMarks()
913 {
914 m_vFieldmarks.clear();
915 m_vBookmarks.clear();
916
917 m_vAnnotationMarks.clear();
918
919 #ifdef DEBUG
920 for(iterator_t pBkmk = m_vAllMarks.begin();
921 pBkmk != m_vAllMarks.end();
922 ++pBkmk)
923 OSL_ENSURE( pBkmk->unique(),
924 "<MarkManager::clearAllMarks(..)> - a Bookmark is still in use.");
925 #endif
926 m_vAllMarks.clear();
927 }
928
findMark(const::rtl::OUString & rName) const929 IDocumentMarkAccess::const_iterator_t MarkManager::findMark(const ::rtl::OUString& rName) const
930 {
931 return lcl_FindMarkByName(rName, m_vAllMarks.begin(), m_vAllMarks.end());
932 }
933
findBookmark(const::rtl::OUString & rName) const934 IDocumentMarkAccess::const_iterator_t MarkManager::findBookmark(const ::rtl::OUString& rName) const
935 {
936 return lcl_FindMarkByName(rName, m_vBookmarks.begin(), m_vBookmarks.end());
937 }
938
getAllMarksBegin() const939 IDocumentMarkAccess::const_iterator_t MarkManager::getAllMarksBegin() const
940 { return m_vAllMarks.begin(); }
941
getAllMarksEnd() const942 IDocumentMarkAccess::const_iterator_t MarkManager::getAllMarksEnd() const
943 { return m_vAllMarks.end(); }
944
getAllMarksCount() const945 sal_Int32 MarkManager::getAllMarksCount() const
946 { return m_vAllMarks.size(); }
947
getBookmarksBegin() const948 IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksBegin() const
949 { return m_vBookmarks.begin(); }
950
getBookmarksEnd() const951 IDocumentMarkAccess::const_iterator_t MarkManager::getBookmarksEnd() const
952 { return m_vBookmarks.end(); }
953
getBookmarksCount() const954 sal_Int32 MarkManager::getBookmarksCount() const
955 { return m_vBookmarks.size(); }
956
getFieldmarkFor(const SwPosition & rPos) const957 IFieldmark* MarkManager::getFieldmarkFor(const SwPosition& rPos) const
958 {
959 const_iterator_t pFieldmark = find_if(
960 m_vFieldmarks.begin(),
961 m_vFieldmarks.end( ),
962 bind(&IMark::IsCoveringPosition, _1, rPos));
963 if(pFieldmark == m_vFieldmarks.end()) return NULL;
964 return dynamic_cast<IFieldmark*>(pFieldmark->get());
965 }
966
getFieldmarkAfter(const SwPosition & rPos) const967 IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
968 { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, rPos)); }
969
getFieldmarkBefore(const SwPosition & rPos) const970 IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
971 { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, rPos)); }
972
973
getAnnotationMarksBegin() const974 IDocumentMarkAccess::const_iterator_t MarkManager::getAnnotationMarksBegin() const
975 {
976 return m_vAnnotationMarks.begin();
977 }
978
getAnnotationMarksEnd() const979 IDocumentMarkAccess::const_iterator_t MarkManager::getAnnotationMarksEnd() const
980 {
981 return m_vAnnotationMarks.end();
982 }
983
getAnnotationMarksCount() const984 sal_Int32 MarkManager::getAnnotationMarksCount() const
985 {
986 return m_vAnnotationMarks.size();
987 }
988
findAnnotationMark(const::rtl::OUString & rName) const989 IDocumentMarkAccess::const_iterator_t MarkManager::findAnnotationMark( const ::rtl::OUString& rName ) const
990 {
991 return lcl_FindMarkByName( rName, m_vAnnotationMarks.begin(), m_vAnnotationMarks.end() );
992 }
993
994
getUniqueMarkName(const::rtl::OUString & rName) const995 ::rtl::OUString MarkManager::getUniqueMarkName(const ::rtl::OUString& rName) const
996 {
997 OSL_ENSURE(rName.getLength(),
998 "<MarkManager::getUniqueMarkName(..)> - a name should be proposed");
999 if ( findMark(rName) == getAllMarksEnd() )
1000 {
1001 return rName;
1002 }
1003
1004 ::rtl::OUStringBuffer sBuf;
1005 ::rtl::OUString sTmp;
1006 for(sal_Int32 nCnt = 1; nCnt < SAL_MAX_INT32; nCnt++)
1007 {
1008 sTmp = sBuf.append(rName).append(nCnt).makeStringAndClear();
1009 if ( findMark(sTmp) == getAllMarksEnd() )
1010 {
1011 break;
1012 }
1013 }
1014 return sTmp;
1015 }
1016
assureSortedMarkContainers() const1017 void MarkManager::assureSortedMarkContainers() const
1018 {
1019 const_cast< MarkManager* >(this)->sortMarks();
1020 }
1021
sortSubsetMarks()1022 void MarkManager::sortSubsetMarks()
1023 {
1024 sort(m_vBookmarks.begin(), m_vBookmarks.end(), &lcl_MarkOrderingByStart);
1025 sort(m_vFieldmarks.begin(), m_vFieldmarks.end(), &lcl_MarkOrderingByStart);
1026 sort(m_vAnnotationMarks.begin(), m_vAnnotationMarks.end(), &lcl_MarkOrderingByStart);
1027 }
1028
sortMarks()1029 void MarkManager::sortMarks()
1030 {
1031 sort(m_vAllMarks.begin(), m_vAllMarks.end(), &lcl_MarkOrderingByStart);
1032 sortSubsetMarks();
1033 }
1034
1035 #if OSL_DEBUG_LEVEL > 1
dumpFieldmarks() const1036 void MarkManager::dumpFieldmarks( ) const
1037 {
1038 const_iterator_t pIt = m_vFieldmarks.begin();
1039 for (; pIt != m_vFieldmarks.end( ); pIt++)
1040 {
1041 rtl::OUString str = (*pIt)->ToString();
1042 OSL_TRACE("%s\n",
1043 ::rtl::OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr());
1044 }
1045 }
1046 #endif
1047
1048 }} // namespace ::sw::mark
1049
1050
1051 // old implementation
1052
1053 //SV_IMPL_OP_PTRARR_SORT(SwBookmarks, SwBookmarkPtr)
1054
1055 #define PCURCRSR (_pCurrCrsr)
1056 #define FOREACHPAM_START(pSttCrsr) \
1057 {\
1058 SwPaM *_pStartCrsr = pSttCrsr, *_pCurrCrsr = pSttCrsr; \
1059 do {
1060
1061 #define FOREACHPAM_END() \
1062 } while( (_pCurrCrsr=(SwPaM *)_pCurrCrsr->GetNext()) != _pStartCrsr ); \
1063 }
1064 #define PCURSH ((SwCrsrShell*)_pStartShell)
1065 #define FOREACHSHELL_START( pEShell ) \
1066 {\
1067 ViewShell *_pStartShell = pEShell; \
1068 do { \
1069 if( _pStartShell->IsA( TYPE( SwCrsrShell )) ) \
1070 {
1071
1072 #define FOREACHSHELL_END( pEShell ) \
1073 } \
1074 } while((_pStartShell=(ViewShell*)_pStartShell->GetNext())!= pEShell ); \
1075 }
1076
1077 namespace
1078 {
1079 // Aufbau vom Array: 2 longs,
1080 // 1. Long enthaelt Type und Position im DocArray,
1081 // 2. die ContentPosition
1082 //
1083 // CntntType --
1084 // 0x8000 = Bookmark Pos1
1085 // 0x8001 = Bookmark Pos2
1086 // 0x2000 = Absatzgebundener Rahmen
1087 // 0x2001 = Auto-Absatzgebundener Rahmen, der umgehaengt werden soll
1088 // 0x1000 = Redline Mark
1089 // 0x1001 = Redline Point
1090 // 0x0800 = Crsr aus der CrsrShell Mark
1091 // 0x0801 = Crsr aus der CrsrShell Point
1092 // 0x0400 = UnoCrsr Mark
1093 // 0x0401 = UnoCrsr Point
1094 //
1095
1096 class _SwSaveTypeCountContent
1097 {
1098 union {
1099 struct { sal_uInt16 nType, nCount; } TC;
1100 sal_uLong nTypeCount;
1101 } TYPECOUNT;
1102 xub_StrLen nContent;
1103
1104 public:
_SwSaveTypeCountContent()1105 _SwSaveTypeCountContent() { TYPECOUNT.nTypeCount = 0; nContent = 0; }
_SwSaveTypeCountContent(sal_uInt16 nType)1106 _SwSaveTypeCountContent( sal_uInt16 nType )
1107 {
1108 SetTypeAndCount( nType, 0 );
1109 nContent = 0;
1110 }
_SwSaveTypeCountContent(const SvULongs & rArr,sal_uInt16 & rPos)1111 _SwSaveTypeCountContent( const SvULongs& rArr, sal_uInt16& rPos )
1112 {
1113 TYPECOUNT.nTypeCount = rArr[ rPos++ ];
1114 nContent = static_cast<xub_StrLen>(rArr[ rPos++ ]);
1115 }
Add(SvULongs & rArr)1116 void Add( SvULongs& rArr )
1117 {
1118 rArr.Insert( TYPECOUNT.nTypeCount, rArr.Count() );
1119 rArr.Insert( nContent, rArr.Count() );
1120 }
1121
SetType(sal_uInt16 n)1122 void SetType( sal_uInt16 n ) { TYPECOUNT.TC.nType = n; }
GetType() const1123 sal_uInt16 GetType() const { return TYPECOUNT.TC.nType; }
IncType()1124 void IncType() { ++TYPECOUNT.TC.nType; }
DecType()1125 void DecType() { --TYPECOUNT.TC.nType; }
1126
SetCount(sal_uInt16 n)1127 void SetCount( sal_uInt16 n ) { TYPECOUNT.TC.nCount = n; }
GetCount() const1128 sal_uInt16 GetCount() const { return TYPECOUNT.TC.nCount; }
IncCount()1129 sal_uInt16 IncCount() { return ++TYPECOUNT.TC.nCount; }
DecCount()1130 sal_uInt16 DecCount() { return --TYPECOUNT.TC.nCount; }
1131
SetTypeAndCount(sal_uInt16 nT,sal_uInt16 nC)1132 void SetTypeAndCount( sal_uInt16 nT, sal_uInt16 nC )
1133 { TYPECOUNT.TC.nCount = nC; TYPECOUNT.TC.nType = nT; }
1134
SetContent(xub_StrLen n)1135 void SetContent( xub_StrLen n ) { nContent = n; }
GetContent() const1136 xub_StrLen GetContent() const { return nContent; }
1137 };
1138
1139 // #i59534: If a paragraph will be splitted we have to restore some redline positions
1140 // This help function checks a position compared with a node and an content index
1141
1142 static const int BEFORE_NODE = 0; // Position before the given node index
1143 static const int BEFORE_SAME_NODE = 1; // Same node index but content index before given content index
1144 static const int SAME_POSITION = 2; // Same node index and samecontent index
1145 static const int BEHIND_SAME_NODE = 3; // Same node index but content index behind given content index
1146 static const int BEHIND_NODE = 4; // Position behind the given node index
1147
lcl_RelativePosition(const SwPosition & rPos,sal_uLong nNode,xub_StrLen nCntnt)1148 static int lcl_RelativePosition( const SwPosition& rPos, sal_uLong nNode, xub_StrLen nCntnt )
1149 {
1150 sal_uLong nIndex = rPos.nNode.GetIndex();
1151 int nReturn = BEFORE_NODE;
1152 if( nIndex == nNode )
1153 {
1154 xub_StrLen nCntIdx = rPos.nContent.GetIndex();
1155 if( nCntIdx < nCntnt )
1156 nReturn = BEFORE_SAME_NODE;
1157 else if( nCntIdx == nCntnt )
1158 nReturn = SAME_POSITION;
1159 else
1160 nReturn = BEHIND_SAME_NODE;
1161 }
1162 else if( nIndex > nNode )
1163 nReturn = BEHIND_NODE;
1164 return nReturn;
1165 }
1166
1167
lcl_Greater(const SwPosition & rPos,const SwNodeIndex & rNdIdx,const SwIndex * pIdx)1168 static inline int lcl_Greater( const SwPosition& rPos, const SwNodeIndex& rNdIdx, const SwIndex* pIdx )
1169 {
1170 return rPos.nNode > rNdIdx || ( pIdx && rPos.nNode == rNdIdx && rPos.nContent > pIdx->GetIndex() );
1171 }
1172
lcl_ChkPaM(SvULongs & rSaveArr,sal_uLong nNode,xub_StrLen nCntnt,const SwPaM & rPam,_SwSaveTypeCountContent & rSave,sal_Bool bChkSelDirection)1173 static void lcl_ChkPaM( SvULongs& rSaveArr, sal_uLong nNode, xub_StrLen nCntnt,
1174 const SwPaM& rPam, _SwSaveTypeCountContent& rSave,
1175 sal_Bool bChkSelDirection )
1176 {
1177 // SelektionsRichtung beachten
1178 bool bBound1IsStart = !bChkSelDirection ? sal_True :
1179 ( *rPam.GetPoint() < *rPam.GetMark()
1180 ? rPam.GetPoint() == &rPam.GetBound()
1181 : rPam.GetMark() == &rPam.GetBound());
1182
1183 const SwPosition* pPos = &rPam.GetBound( sal_True );
1184 if( pPos->nNode.GetIndex() == nNode &&
1185 ( bBound1IsStart ? pPos->nContent.GetIndex() < nCntnt
1186 : pPos->nContent.GetIndex() <= nCntnt ))
1187 {
1188 rSave.SetContent( pPos->nContent.GetIndex() );
1189 rSave.Add( rSaveArr );
1190 }
1191
1192 pPos = &rPam.GetBound( sal_False );
1193 if( pPos->nNode.GetIndex() == nNode &&
1194 ( (bBound1IsStart && bChkSelDirection)
1195 ? pPos->nContent.GetIndex() <= nCntnt
1196 : pPos->nContent.GetIndex() < nCntnt ))
1197 {
1198 rSave.SetContent( pPos->nContent.GetIndex() );
1199 rSave.IncType();
1200 rSave.Add( rSaveArr );
1201 rSave.DecType();
1202 }
1203 }
1204
1205 }
1206
1207
1208 // IDocumentMarkAccess for SwDoc
1209
getIDocumentMarkAccess()1210 IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess()
1211 { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1212
getIDocumentMarkAccess() const1213 const IDocumentMarkAccess* SwDoc::getIDocumentMarkAccess() const
1214 { return static_cast< IDocumentMarkAccess* >(pMarkManager.get()); }
1215
1216 // SaveBookmark
1217
SaveBookmark(bool bSavePos,bool bSaveOtherPos,const IMark & rBkmk,const SwNodeIndex & rMvPos,const SwIndex * pIdx)1218 SaveBookmark::SaveBookmark(
1219 bool bSavePos,
1220 bool bSaveOtherPos,
1221 const IMark& rBkmk,
1222 const SwNodeIndex & rMvPos,
1223 const SwIndex* pIdx)
1224 : m_aName(rBkmk.GetName())
1225 , m_aShortName()
1226 , m_aCode()
1227 , m_bSavePos(bSavePos)
1228 , m_bSaveOtherPos(bSaveOtherPos)
1229 , m_eOrigBkmType(IDocumentMarkAccess::GetType(rBkmk))
1230 {
1231 const IBookmark* const pBookmark = dynamic_cast< const IBookmark* >(&rBkmk);
1232 if(pBookmark)
1233 {
1234 m_aShortName = pBookmark->GetShortName();
1235 m_aCode = pBookmark->GetKeyCode();
1236
1237 ::sfx2::Metadatable const*const pMetadatable(
1238 dynamic_cast< ::sfx2::Metadatable const* >(pBookmark));
1239 if (pMetadatable)
1240 {
1241 m_pMetadataUndo = pMetadatable->CreateUndo();
1242 }
1243 }
1244 m_nNode1 = rBkmk.GetMarkPos().nNode.GetIndex();
1245 m_nCntnt1 = rBkmk.GetMarkPos().nContent.GetIndex();
1246
1247 if(m_bSavePos)
1248 {
1249 m_nNode1 -= rMvPos.GetIndex();
1250 if(pIdx && !m_nNode1)
1251 m_nCntnt1 -= pIdx->GetIndex();
1252 }
1253
1254 if(rBkmk.IsExpanded())
1255 {
1256 m_nNode2 = rBkmk.GetOtherMarkPos().nNode.GetIndex();
1257 m_nCntnt2 = rBkmk.GetOtherMarkPos().nContent.GetIndex();
1258
1259 if(m_bSaveOtherPos)
1260 {
1261 m_nNode2 -= rMvPos.GetIndex();
1262 if(pIdx && !m_nNode2)
1263 m_nCntnt2 -= pIdx->GetIndex();
1264 }
1265 }
1266 else
1267 m_nNode2 = ULONG_MAX, m_nCntnt2 = STRING_NOTFOUND;
1268 }
1269
SetInDoc(SwDoc * pDoc,const SwNodeIndex & rNewPos,const SwIndex * pIdx)1270 void SaveBookmark::SetInDoc(
1271 SwDoc* pDoc,
1272 const SwNodeIndex& rNewPos,
1273 const SwIndex* pIdx)
1274 {
1275 SwPaM aPam(rNewPos.GetNode());
1276 if(pIdx)
1277 aPam.GetPoint()->nContent = *pIdx;
1278
1279 if(ULONG_MAX != m_nNode2)
1280 {
1281 aPam.SetMark();
1282
1283 if(m_bSaveOtherPos)
1284 {
1285 aPam.GetMark()->nNode += m_nNode2;
1286 if(pIdx && !m_nNode2)
1287 aPam.GetMark()->nContent += m_nCntnt2;
1288 else
1289 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1290 }
1291 else
1292 {
1293 aPam.GetMark()->nNode = m_nNode2;
1294 aPam.GetMark()->nContent.Assign(aPam.GetCntntNode(sal_False), m_nCntnt2);
1295 }
1296 }
1297
1298 if(m_bSavePos)
1299 {
1300 aPam.GetPoint()->nNode += m_nNode1;
1301
1302 if(pIdx && !m_nNode1)
1303 aPam.GetPoint()->nContent += m_nCntnt1;
1304 else
1305 aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1306 }
1307 else
1308 {
1309 aPam.GetPoint()->nNode = m_nNode1;
1310 aPam.GetPoint()->nContent.Assign(aPam.GetCntntNode(), m_nCntnt1);
1311 }
1312
1313 if(!aPam.HasMark()
1314 || CheckNodesRange(aPam.GetPoint()->nNode, aPam.GetMark()->nNode, sal_True))
1315 {
1316 ::sw::mark::IBookmark* const pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pDoc->getIDocumentMarkAccess()->makeMark(aPam, m_aName, m_eOrigBkmType));
1317 if(pBookmark)
1318 {
1319 pBookmark->SetKeyCode(m_aCode);
1320 pBookmark->SetShortName(m_aShortName);
1321 if (m_pMetadataUndo)
1322 {
1323 ::sfx2::Metadatable * const pMeta(
1324 dynamic_cast< ::sfx2::Metadatable* >(pBookmark));
1325 OSL_ENSURE(pMeta, "metadata undo, but not metadatable?");
1326 if (pMeta)
1327 {
1328 pMeta->RestoreMetadata(m_pMetadataUndo);
1329 }
1330 }
1331 }
1332 }
1333 }
1334
1335
1336 // _DelBookmarks, _{Save,Restore}CntntIdx
1337
_DelBookmarks(const SwNodeIndex & rStt,const SwNodeIndex & rEnd,::std::vector<SaveBookmark> * pSaveBkmk,const SwIndex * pSttIdx,const SwIndex * pEndIdx)1338 void _DelBookmarks(
1339 const SwNodeIndex& rStt,
1340 const SwNodeIndex& rEnd,
1341 ::std::vector<SaveBookmark> * pSaveBkmk,
1342 const SwIndex* pSttIdx,
1343 const SwIndex* pEndIdx)
1344 {
1345 // illegal range ??
1346 if(rStt.GetIndex() > rEnd.GetIndex()
1347 || (rStt == rEnd && (!pSttIdx || pSttIdx->GetIndex() >= pEndIdx->GetIndex())))
1348 return;
1349 SwDoc* const pDoc = rStt.GetNode().GetDoc();
1350
1351 pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, pSttIdx, pEndIdx);
1352
1353 // kopiere alle Redlines, die im Move Bereich stehen in ein
1354 // Array, das alle Angaben auf die Position als Offset speichert.
1355 // Die neue Zuordung erfolgt nach dem Moven.
1356 SwRedlineTbl& rTbl = (SwRedlineTbl&)pDoc->GetRedlineTbl();
1357 for(sal_uInt16 nCnt = 0; nCnt < rTbl.Count(); ++nCnt )
1358 {
1359 // liegt auf der Position ??
1360 SwRedline* pRedl = rTbl[ nCnt ];
1361
1362 SwPosition *pRStt = &pRedl->GetBound(sal_True),
1363 *pREnd = &pRedl->GetBound(sal_False);
1364 if( *pRStt > *pREnd )
1365 {
1366 SwPosition *pTmp = pRStt; pRStt = pREnd, pREnd = pTmp;
1367 }
1368
1369 if( lcl_Greater( *pRStt, rStt, pSttIdx ) && lcl_Lower( *pRStt, rEnd, pEndIdx ))
1370 {
1371 pRStt->nNode = rEnd;
1372 if( pEndIdx )
1373 pRStt->nContent = *pEndIdx;
1374 else
1375 {
1376 sal_Bool bStt = sal_True;
1377 SwCntntNode* pCNd = pRStt->nNode.GetNode().GetCntntNode();
1378 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoNext( &pRStt->nNode )) )
1379 {
1380 bStt = sal_False;
1381 pRStt->nNode = rStt;
1382 if( 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pRStt->nNode )) )
1383 {
1384 pRStt->nNode = pREnd->nNode;
1385 pCNd = pRStt->nNode.GetNode().GetCntntNode();
1386 }
1387 }
1388 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1389 pRStt->nContent.Assign( pCNd, nTmp );
1390 }
1391 }
1392 if( lcl_Greater( *pREnd, rStt, pSttIdx ) && lcl_Lower( *pREnd, rEnd, pEndIdx ))
1393 {
1394 pREnd->nNode = rStt;
1395 if( pSttIdx )
1396 pREnd->nContent = *pSttIdx;
1397 else
1398 {
1399 sal_Bool bStt = sal_False;
1400 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
1401 if( !pCNd && 0 == ( pCNd = pDoc->GetNodes().GoPrevious( &pREnd->nNode )) )
1402 {
1403 bStt = sal_True;
1404 pREnd->nNode = rEnd;
1405 if( 0 == ( pCNd = pDoc->GetNodes().GoNext( &pREnd->nNode )) )
1406 {
1407 pREnd->nNode = pRStt->nNode;
1408 pCNd = pREnd->nNode.GetNode().GetCntntNode();
1409 }
1410 }
1411 xub_StrLen nTmp = bStt ? 0 : pCNd->Len();
1412 pREnd->nContent.Assign( pCNd, nTmp );
1413 }
1414 }
1415 }
1416 }
1417
_SaveCntntIdx(SwDoc * pDoc,sal_uLong nNode,xub_StrLen nCntnt,SvULongs & rSaveArr,sal_uInt8 nSaveFly)1418 void _SaveCntntIdx(SwDoc* pDoc,
1419 sal_uLong nNode,
1420 xub_StrLen nCntnt,
1421 SvULongs& rSaveArr,
1422 sal_uInt8 nSaveFly)
1423 {
1424 // 1. Bookmarks
1425 _SwSaveTypeCountContent aSave;
1426 aSave.SetTypeAndCount( 0x8000, 0 );
1427
1428 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1429 const sal_Int32 nMarksCount = pMarkAccess->getAllMarksCount();
1430 for ( ; aSave.GetCount() < nMarksCount; aSave.IncCount() )
1431 {
1432 bool bMarkPosEqual = false;
1433 const ::sw::mark::IMark* pBkmk = (pMarkAccess->getAllMarksBegin() + aSave.GetCount())->get();
1434 if(pBkmk->GetMarkPos().nNode.GetIndex() == nNode
1435 && pBkmk->GetMarkPos().nContent.GetIndex() <= nCntnt)
1436 {
1437 if(pBkmk->GetMarkPos().nContent.GetIndex() < nCntnt)
1438 {
1439 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1440 aSave.Add(rSaveArr);
1441 }
1442 else // if a bookmark position is equal nCntnt, the other position
1443 bMarkPosEqual = true; // has to decide if it is added to the array
1444 }
1445
1446 if(pBkmk->IsExpanded()
1447 && pBkmk->GetOtherMarkPos().nNode.GetIndex() == nNode
1448 && pBkmk->GetOtherMarkPos().nContent.GetIndex() <= nCntnt)
1449 {
1450 if(bMarkPosEqual)
1451 { // the other position is before, the (main) position is equal
1452 aSave.SetContent(pBkmk->GetMarkPos().nContent.GetIndex());
1453 aSave.Add(rSaveArr);
1454 }
1455 aSave.SetContent(pBkmk->GetOtherMarkPos().nContent.GetIndex());
1456 aSave.IncType();
1457 aSave.Add(rSaveArr);
1458 aSave.DecType();
1459 }
1460 }
1461
1462 // 2. Redlines
1463 aSave.SetTypeAndCount( 0x1000, 0 );
1464 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1465 for( ; aSave.GetCount() < rRedlTbl.Count(); aSave.IncCount() )
1466 {
1467 const SwRedline* pRdl = rRedlTbl[ aSave.GetCount() ];
1468 int nPointPos = lcl_RelativePosition( *pRdl->GetPoint(), nNode, nCntnt );
1469 int nMarkPos = pRdl->HasMark() ? lcl_RelativePosition( *pRdl->GetMark(), nNode, nCntnt ) :
1470 nPointPos;
1471 // #i59534: We have to store the positions inside the same node before the insert position
1472 // and the one at the insert position if the corresponding Point/Mark position is before
1473 // the insert position.
1474 if( nPointPos == BEFORE_SAME_NODE ||
1475 ( nPointPos == SAME_POSITION && nMarkPos < SAME_POSITION ) )
1476 {
1477 aSave.SetContent( pRdl->GetPoint()->nContent.GetIndex() );
1478 aSave.IncType();
1479 aSave.Add( rSaveArr );
1480 aSave.DecType();
1481 }
1482 if( pRdl->HasMark() && ( nMarkPos == BEFORE_SAME_NODE ||
1483 ( nMarkPos == SAME_POSITION && nPointPos < SAME_POSITION ) ) )
1484 {
1485 aSave.SetContent( pRdl->GetMark()->nContent.GetIndex() );
1486 aSave.Add( rSaveArr );
1487 }
1488 }
1489
1490 // 4. Absatzgebundene Objekte
1491 {
1492 SwCntntNode *pNode = pDoc->GetNodes()[nNode]->GetCntntNode();
1493 if( pNode )
1494 {
1495
1496 SwFrm* pFrm = pNode->getLayoutFrm( pDoc->GetCurrentLayout() );
1497 #if OSL_DEBUG_LEVEL > 1
1498 static sal_Bool bViaDoc = sal_False;
1499 if( bViaDoc )
1500 pFrm = NULL;
1501 #endif
1502 if( pFrm ) // gibt es ein Layout? Dann ist etwas billiger...
1503 {
1504 if( pFrm->GetDrawObjs() )
1505 {
1506 const SwSortedObjs& rDObj = *pFrm->GetDrawObjs();
1507 for( sal_uInt32 n = rDObj.Count(); n; )
1508 {
1509 SwAnchoredObject* pObj = rDObj[ --n ];
1510 const SwFrmFmt& rFmt = pObj->GetFrmFmt();
1511 const SwFmtAnchor& rAnchor = rFmt.GetAnchor();
1512 SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1513 if ( pAPos &&
1514 ( ( nSaveFly &&
1515 FLY_AT_PARA == rAnchor.GetAnchorId() ) ||
1516 ( FLY_AT_CHAR == rAnchor.GetAnchorId() ) ) )
1517 {
1518 aSave.SetType( 0x2000 );
1519 aSave.SetContent( pAPos->nContent.GetIndex() );
1520
1521 OSL_ENSURE( nNode == pAPos->nNode.GetIndex(),
1522 "_SaveCntntIdx: Wrong Node-Index" );
1523 if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1524 {
1525 if( nCntnt <= aSave.GetContent() )
1526 {
1527 if( SAVEFLY_SPLIT == nSaveFly )
1528 aSave.IncType(); // = 0x2001;
1529 else
1530 continue;
1531 }
1532 }
1533 aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1534 while( aSave.GetCount() &&
1535 &rFmt != (*pDoc->GetSpzFrmFmts())[
1536 aSave.DecCount() ] )
1537 ; // nothing
1538 OSL_ENSURE( &rFmt == (*pDoc->GetSpzFrmFmts())[
1539 aSave.GetCount() ],
1540 "_SaveCntntIdx: Lost FrameFormat" );
1541 aSave.Add( rSaveArr );
1542 }
1543 }
1544 }
1545 }
1546 else // Schade, kein Layout, dann ist es eben etwas teurer...
1547 {
1548 for( aSave.SetCount( pDoc->GetSpzFrmFmts()->Count() );
1549 aSave.GetCount() ; )
1550 {
1551 SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[
1552 aSave.DecCount() ];
1553 if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
1554 RES_DRAWFRMFMT != pFrmFmt->Which() )
1555 continue;
1556
1557 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
1558 SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1559 if ( pAPos && ( nNode == pAPos->nNode.GetIndex() ) &&
1560 ( FLY_AT_PARA == rAnchor.GetAnchorId() ||
1561 FLY_AT_CHAR == rAnchor.GetAnchorId() ) )
1562 {
1563 aSave.SetType( 0x2000 );
1564 aSave.SetContent( pAPos->nContent.GetIndex() );
1565 if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
1566 {
1567 if( nCntnt <= aSave.GetContent() )
1568 {
1569 if( SAVEFLY_SPLIT == nSaveFly )
1570 aSave.IncType(); // = 0x2001;
1571 else
1572 continue;
1573 }
1574 }
1575 aSave.Add( rSaveArr );
1576 }
1577 }
1578 }
1579 }
1580 }
1581 // 5. CrsrShell
1582 {
1583 SwCrsrShell* pShell = pDoc->GetEditShell();
1584 if( pShell )
1585 {
1586 aSave.SetTypeAndCount( 0x800, 0 );
1587 FOREACHSHELL_START( pShell )
1588 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1589 if( _pStkCrsr )
1590 do {
1591 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *_pStkCrsr,
1592 aSave, sal_False );
1593 aSave.IncCount();
1594 } while ( (_pStkCrsr != 0 ) &&
1595 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1596
1597 FOREACHPAM_START( PCURSH->_GetCrsr() )
1598 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR,
1599 aSave, sal_False );
1600 aSave.IncCount();
1601 FOREACHPAM_END()
1602
1603 FOREACHSHELL_END( pShell )
1604 }
1605 }
1606 // 6. UnoCrsr
1607 {
1608 aSave.SetTypeAndCount( 0x400, 0 );
1609 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1610 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
1611 {
1612 FOREACHPAM_START( rTbl[ n ] )
1613 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1614 aSave.IncCount();
1615 FOREACHPAM_END()
1616
1617 SwUnoTableCrsr* pUnoTblCrsr =
1618 dynamic_cast<SwUnoTableCrsr*>(rTbl[ n ]);
1619 if( pUnoTblCrsr )
1620 {
1621 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1622 lcl_ChkPaM( rSaveArr, nNode, nCntnt, *PCURCRSR, aSave, sal_False );
1623 aSave.IncCount();
1624 FOREACHPAM_END()
1625 }
1626 }
1627 }
1628 }
1629
1630
_RestoreCntntIdx(SwDoc * pDoc,SvULongs & rSaveArr,sal_uLong nNode,xub_StrLen nOffset,sal_Bool bAuto)1631 void _RestoreCntntIdx(SwDoc* pDoc,
1632 SvULongs& rSaveArr,
1633 sal_uLong nNode,
1634 xub_StrLen nOffset,
1635 sal_Bool bAuto)
1636 {
1637 SwCntntNode* pCNd = pDoc->GetNodes()[ nNode ]->GetCntntNode();
1638 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1639 SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1640 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1641 sal_uInt16 n = 0;
1642 while( n < rSaveArr.Count() )
1643 {
1644 _SwSaveTypeCountContent aSave( rSaveArr, n );
1645 SwPosition* pPos = 0;
1646 switch( aSave.GetType() )
1647 {
1648 case 0x8000:
1649 {
1650 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getAllMarksBegin()[aSave.GetCount()].get());
1651 SwPosition aNewPos(pMark->GetMarkPos());
1652 aNewPos.nNode = *pCNd;
1653 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1654 pMark->SetMarkPos(aNewPos);
1655 }
1656 break;
1657 case 0x8001:
1658 {
1659 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getAllMarksBegin()[aSave.GetCount()].get());
1660 SwPosition aNewPos(pMark->GetOtherMarkPos());
1661 aNewPos.nNode = *pCNd;
1662 aNewPos.nContent.Assign(pCNd, aSave.GetContent() + nOffset);
1663 pMark->SetOtherMarkPos(aNewPos);
1664 }
1665 break;
1666 case 0x1001:
1667 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1668 break;
1669 case 0x1000:
1670 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1671 break;
1672 case 0x2000:
1673 {
1674 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1675 const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1676 if( rFlyAnchor.GetCntntAnchor() )
1677 {
1678 SwFmtAnchor aNew( rFlyAnchor );
1679 SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1680 aNewPos.nNode = *pCNd;
1681 if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1682 {
1683 aNewPos.nContent.Assign( pCNd,
1684 aSave.GetContent() + nOffset );
1685 }
1686 else
1687 {
1688 aNewPos.nContent.Assign( 0, 0 );
1689 }
1690 aNew.SetAnchor( &aNewPos );
1691 pFrmFmt->SetFmtAttr( aNew );
1692 }
1693 }
1694 break;
1695 case 0x2001:
1696 if( bAuto )
1697 {
1698 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1699 SfxPoolItem *pAnchor = (SfxPoolItem*)&pFrmFmt->GetAnchor();
1700 pFrmFmt->NotifyClients( pAnchor, pAnchor );
1701 }
1702 break;
1703
1704 case 0x0800:
1705 case 0x0801:
1706 {
1707 sal_uInt16 nCnt = 0;
1708 SwCrsrShell* pShell = pDoc->GetEditShell();
1709 if( pShell )
1710 {
1711 FOREACHSHELL_START( pShell )
1712 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1713 if( _pStkCrsr )
1714 do {
1715 if( aSave.GetCount() == nCnt )
1716 {
1717 pPos = &_pStkCrsr->GetBound( 0x0800 ==
1718 aSave.GetType() );
1719 break;
1720 }
1721 ++nCnt;
1722 } while ( (_pStkCrsr != 0 ) &&
1723 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1724
1725 if( pPos )
1726 break;
1727
1728 FOREACHPAM_START( PCURSH->_GetCrsr() )
1729 if( aSave.GetCount() == nCnt )
1730 {
1731 pPos = &PCURCRSR->GetBound( 0x0800 ==
1732 aSave.GetType() );
1733 break;
1734 }
1735 ++nCnt;
1736 FOREACHPAM_END()
1737 if( pPos )
1738 break;
1739
1740 FOREACHSHELL_END( pShell )
1741 }
1742 }
1743 break;
1744
1745 case 0x0400:
1746 case 0x0401:
1747 {
1748 sal_uInt16 nCnt = 0;
1749 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1750 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1751 {
1752 FOREACHPAM_START( rTbl[ i ] )
1753 if( aSave.GetCount() == nCnt )
1754 {
1755 pPos = &PCURCRSR->GetBound( 0x0400 ==
1756 aSave.GetType() );
1757 break;
1758 }
1759 ++nCnt;
1760 FOREACHPAM_END()
1761 if( pPos )
1762 break;
1763
1764 SwUnoTableCrsr* pUnoTblCrsr =
1765 dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1766 if ( pUnoTblCrsr )
1767 {
1768 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1769 if( aSave.GetCount() == nCnt )
1770 {
1771 pPos = &PCURCRSR->GetBound( 0x0400 ==
1772 aSave.GetType() );
1773 break;
1774 }
1775 ++nCnt;
1776 FOREACHPAM_END()
1777 }
1778 if ( pPos )
1779 break;
1780 }
1781 }
1782 break;
1783 }
1784
1785 if( pPos )
1786 {
1787 pPos->nNode = *pCNd;
1788 pPos->nContent.Assign( pCNd, aSave.GetContent() + nOffset );
1789 }
1790 }
1791 }
1792
_RestoreCntntIdx(SvULongs & rSaveArr,const SwNode & rNd,xub_StrLen nLen,xub_StrLen nChkLen)1793 void _RestoreCntntIdx(SvULongs& rSaveArr,
1794 const SwNode& rNd,
1795 xub_StrLen nLen,
1796 xub_StrLen nChkLen)
1797 {
1798 const SwDoc* pDoc = rNd.GetDoc();
1799 const SwRedlineTbl& rRedlTbl = pDoc->GetRedlineTbl();
1800 const SwSpzFrmFmts* pSpz = pDoc->GetSpzFrmFmts();
1801 const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1802 SwCntntNode* pCNd = (SwCntntNode*)rNd.GetCntntNode();
1803
1804 sal_uInt16 n = 0;
1805 while( n < rSaveArr.Count() )
1806 {
1807 _SwSaveTypeCountContent aSave( rSaveArr, n );
1808 if( aSave.GetContent() >= nChkLen )
1809 rSaveArr[ n-1 ] -= nChkLen;
1810 else
1811 {
1812 SwPosition* pPos = 0;
1813 switch( aSave.GetType() )
1814 {
1815 case 0x8000:
1816 {
1817 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getAllMarksBegin()[aSave.GetCount()].get());
1818 SwPosition aNewPos(pMark->GetMarkPos());
1819 aNewPos.nNode = rNd;
1820 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1821 pMark->SetMarkPos(aNewPos);
1822 }
1823 break;
1824 case 0x8001:
1825 {
1826 MarkBase* pMark = dynamic_cast<MarkBase*>(pMarkAccess->getAllMarksBegin()[aSave.GetCount()].get());
1827 SwPosition aNewPos(pMark->GetOtherMarkPos());
1828 aNewPos.nNode = rNd;
1829 aNewPos.nContent.Assign(pCNd, Min(aSave.GetContent(), nLen));
1830 pMark->SetOtherMarkPos(aNewPos);
1831 }
1832 break;
1833 case 0x1001:
1834 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetPoint();
1835 break;
1836 case 0x1000:
1837 pPos = (SwPosition*)rRedlTbl[ aSave.GetCount() ]->GetMark();
1838 break;
1839 case 0x2000:
1840 case 0x2001:
1841 {
1842 SwFrmFmt *pFrmFmt = (*pSpz)[ aSave.GetCount() ];
1843 const SwFmtAnchor& rFlyAnchor = pFrmFmt->GetAnchor();
1844 if( rFlyAnchor.GetCntntAnchor() )
1845 {
1846 SwFmtAnchor aNew( rFlyAnchor );
1847 SwPosition aNewPos( *rFlyAnchor.GetCntntAnchor() );
1848 aNewPos.nNode = rNd;
1849 if ( FLY_AT_CHAR == rFlyAnchor.GetAnchorId() )
1850 {
1851 aNewPos.nContent.Assign( pCNd, Min(
1852 aSave.GetContent(), nLen ) );
1853 }
1854 else
1855 {
1856 aNewPos.nContent.Assign( 0, 0 );
1857 }
1858 aNew.SetAnchor( &aNewPos );
1859 pFrmFmt->SetFmtAttr( aNew );
1860 }
1861 }
1862 break;
1863
1864 case 0x0800:
1865 case 0x0801:
1866 {
1867 sal_uInt16 nCnt = 0;
1868 SwCrsrShell* pShell = pDoc->GetEditShell();
1869 if( pShell )
1870 {
1871 FOREACHSHELL_START( pShell )
1872 SwPaM *_pStkCrsr = PCURSH->GetStkCrsr();
1873 if( _pStkCrsr )
1874 do {
1875 if( aSave.GetCount() == nCnt )
1876 {
1877 pPos = &_pStkCrsr->GetBound( 0x0800 ==
1878 aSave.GetType() );
1879 break;
1880 }
1881 ++nCnt;
1882 } while ( (_pStkCrsr != 0 ) &&
1883 ((_pStkCrsr=(SwPaM *)_pStkCrsr->GetNext()) != PCURSH->GetStkCrsr()) );
1884
1885 if( pPos )
1886 break;
1887
1888 FOREACHPAM_START( PCURSH->_GetCrsr() )
1889 if( aSave.GetCount() == nCnt )
1890 {
1891 pPos = &PCURCRSR->GetBound( 0x0800 ==
1892 aSave.GetType() );
1893 break;
1894 }
1895 ++nCnt;
1896 FOREACHPAM_END()
1897 if( pPos )
1898 break;
1899
1900 FOREACHSHELL_END( pShell )
1901 }
1902 }
1903 break;
1904
1905 case 0x0400:
1906 case 0x0401:
1907 {
1908 sal_uInt16 nCnt = 0;
1909 const SwUnoCrsrTbl& rTbl = pDoc->GetUnoCrsrTbl();
1910 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
1911 {
1912 FOREACHPAM_START( rTbl[ i ] )
1913 if( aSave.GetCount() == nCnt )
1914 {
1915 pPos = &PCURCRSR->GetBound( 0x0400 ==
1916 aSave.GetType() );
1917 break;
1918 }
1919 ++nCnt;
1920 FOREACHPAM_END()
1921 if( pPos )
1922 break;
1923
1924 SwUnoTableCrsr* pUnoTblCrsr =
1925 dynamic_cast<SwUnoTableCrsr*>(rTbl[ i ]);
1926 if ( pUnoTblCrsr )
1927 {
1928 FOREACHPAM_START( &pUnoTblCrsr->GetSelRing() )
1929 if( aSave.GetCount() == nCnt )
1930 {
1931 pPos = &PCURCRSR->GetBound( 0x0400 ==
1932 aSave.GetType() );
1933 break;
1934 }
1935 ++nCnt;
1936 FOREACHPAM_END()
1937 }
1938 if ( pPos )
1939 break;
1940 }
1941 }
1942 break;
1943 }
1944
1945 if( pPos )
1946 {
1947 pPos->nNode = rNd;
1948 pPos->nContent.Assign( pCNd, Min( aSave.GetContent(), nLen ) );
1949 }
1950 n -= 2;
1951 rSaveArr.Remove( n, 2 );
1952 }
1953 }
1954 }
1955