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