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