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