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