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