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