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