LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/unocore - unoportenum.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 456 489 93.3 %
Date: 2013-07-09 Functions: 35 40 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <unoport.hxx>
      22             : #include <IMark.hxx>
      23             : // #i81002#
      24             : #include <crossrefbookmark.hxx>
      25             : #include <doc.hxx>
      26             : #include <txatbase.hxx>
      27             : #include <txtatr.hxx>
      28             : #include <ndhints.hxx>
      29             : #include <ndtxt.hxx>
      30             : #include <unocrsr.hxx>
      31             : #include <docary.hxx>
      32             : #include <tox.hxx>
      33             : #include <unomid.h>
      34             : #include <unoparaframeenum.hxx>
      35             : #include <unocrsrhelper.hxx>
      36             : #include <unorefmark.hxx>
      37             : #include <unobookmark.hxx>
      38             : #include <unoredline.hxx>
      39             : #include <unofield.hxx>
      40             : #include <unometa.hxx>
      41             : #include <fmtmeta.hxx>
      42             : #include <fmtanchr.hxx>
      43             : #include <fmtrfmrk.hxx>
      44             : #include <frmfmt.hxx>
      45             : #include <unoidx.hxx>
      46             : #include <unocoll.hxx>
      47             : #include <redline.hxx>
      48             : #include <crsskip.hxx>
      49             : #include <switerator.hxx>
      50             : #include <docufld.hxx>
      51             : #include <fmtfld.hxx>
      52             : #include <osl/mutex.hxx>
      53             : #include <vcl/svapp.hxx>
      54             : #include <comphelper/string.hxx>
      55             : #include <comphelper/servicehelper.hxx>
      56             : #include <cppuhelper/supportsservice.hxx>
      57             : #include <set>
      58             : #include <boost/shared_ptr.hpp>
      59             : #include <algorithm>
      60             : #include <stack>
      61             : 
      62             : 
      63             : using namespace ::com::sun::star;
      64             : using namespace ::com::sun::star::uno;
      65             : using namespace ::com::sun::star::text;
      66             : using namespace ::std;
      67             : 
      68             : typedef ::std::pair< TextRangeList_t * const, SwTxtAttr const * const > PortionList_t;
      69             : typedef ::std::stack< PortionList_t > PortionStack_t;
      70             : 
      71             : static void lcl_CreatePortions(
      72             :     TextRangeList_t & i_rPortions,
      73             :     uno::Reference< text::XText > const& i_xParentText,
      74             :     SwUnoCrsr* pUnoCrsr,
      75             :     FrameDependSortList_t & i_rFrames,
      76             :     const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos );
      77             : 
      78             : namespace
      79             : {
      80             :     static const sal_uInt8 BKM_TYPE_START = 0;
      81             :     static const sal_uInt8 BKM_TYPE_END = 1;
      82             :     static const sal_uInt8 BKM_TYPE_START_END = 2;
      83             : 
      84        1947 :     struct SwXBookmarkPortion_Impl
      85             :     {
      86             :         Reference<XTextContent>     xBookmark;
      87             :         sal_uInt8                       nBkmType;
      88             :         const SwPosition            aPosition;
      89             : 
      90        1947 :         SwXBookmarkPortion_Impl(uno::Reference<text::XTextContent> const& xMark,
      91             :                 const sal_uInt8 nType, SwPosition const& rPosition)
      92             :         : xBookmark ( xMark )
      93             :         , nBkmType  ( nType )
      94        1947 :         , aPosition ( rPosition )
      95             :         {
      96        1947 :         }
      97        9430 :         sal_uLong getIndex ()
      98             :         {
      99        9430 :             return aPosition.nContent.GetIndex();
     100             :         }
     101             :     };
     102             :     typedef boost::shared_ptr < SwXBookmarkPortion_Impl > SwXBookmarkPortion_ImplSharedPtr;
     103             :     struct BookmarkCompareStruct
     104             :     {
     105       18924 :         bool operator () ( const SwXBookmarkPortion_ImplSharedPtr &r1,
     106             :                            const SwXBookmarkPortion_ImplSharedPtr &r2 ) const
     107             :         {
     108             :             // #i16896# for bookmark portions at the same position, the start should
     109             :             // always precede the end. Hence compare positions, and use bookmark type
     110             :             // as tie-breaker for same position.
     111             :             // return ( r1->nIndex   == r2->nIndex )
     112             :             //   ? ( r1->nBkmType <  r2->nBkmType )
     113             :             //   : ( r1->nIndex   <  r2->nIndex );
     114             : 
     115             :             // MTG: 25/11/05: Note that the above code does not correctly handle
     116             :             // the case when one bookmark ends, and another begins in the same
     117             :             // position. When this occurs, the above code will return the
     118             :             // the start of the 2nd bookmark BEFORE the end of the first bookmark
     119             :             // See bug #i58438# for more details. The below code is correct and
     120             :             // fixes both #i58438 and #i16896#
     121       18924 :             return r1->aPosition < r2->aPosition;
     122             :         }
     123             :     };
     124             :     typedef std::multiset < SwXBookmarkPortion_ImplSharedPtr, BookmarkCompareStruct > SwXBookmarkPortion_ImplList;
     125             : 
     126         509 :     static void lcl_FillBookmarkArray(SwDoc& rDoc, SwUnoCrsr& rUnoCrsr, SwXBookmarkPortion_ImplList& rBkmArr)
     127             :     {
     128         509 :         IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
     129         509 :         if(!pMarkAccess->getBookmarksCount())
     130         898 :             return;
     131             : 
     132             :         // no need to consider marks starting after aEndOfPara
     133         120 :         SwPosition aEndOfPara(*rUnoCrsr.GetPoint());
     134         120 :         aEndOfPara.nContent = aEndOfPara.nNode.GetNode().GetTxtNode()->Len();
     135             :         const IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
     136         120 :             pMarkAccess->getBookmarksBegin(),
     137         120 :             pMarkAccess->getBookmarksEnd(),
     138             :             aEndOfPara,
     139         240 :             sw::mark::CompareIMarkStartsAfter()); // finds the first that starts after
     140             : 
     141             :         // search for all bookmarks that start or end in this paragraph
     142         240 :         const SwNodeIndex nOwnNode = rUnoCrsr.GetPoint()->nNode;
     143       10489 :         for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
     144             :             ppMark != pCandidatesEnd;
     145             :             ++ppMark)
     146             :         {
     147       10369 :             ::sw::mark::IMark* const pBkmk = ppMark->get();
     148             :             ::sw::mark::CrossRefBookmark *const pCrossRefMark(
     149       10369 :                     dynamic_cast< ::sw::mark::CrossRefBookmark*>(pBkmk));
     150       10369 :             bool const hasOther = pBkmk->IsExpanded();
     151             : 
     152       10369 :             const SwPosition& rStartPos = pBkmk->GetMarkStart();
     153       10369 :             if(rStartPos.nNode == nOwnNode)
     154             :             {
     155             :                 // #i109272#: cross reference marks: need special handling!
     156          29 :                 sal_uInt8 const nType = (hasOther || pCrossRefMark)
     157        1947 :                     ? BKM_TYPE_START : BKM_TYPE_START_END;
     158             :                 rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
     159             :                     new SwXBookmarkPortion_Impl(
     160             :                             SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
     161         987 :                             nType, rStartPos)));
     162             :             }
     163             : 
     164       10369 :             const SwPosition& rEndPos = pBkmk->GetMarkEnd();
     165       10369 :             if(rEndPos.nNode == nOwnNode)
     166             :             {
     167             :                 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     168         987 :                 auto_ptr<SwPosition> pCrossRefEndPos;
     169             :                 SAL_WNODEPRECATED_DECLARATIONS_POP
     170         987 :                 const SwPosition* pEndPos = NULL;
     171         987 :                 if(hasOther)
     172             :                 {
     173         958 :                     pEndPos = &rEndPos;
     174             :                 }
     175          29 :                 else if (pCrossRefMark)
     176             :                 {
     177             :                     // Crossrefbookmarks only remember the start position but have to span the whole paragraph
     178             :                     SAL_WNODEPRECATED_DECLARATIONS_PUSH
     179           2 :                     pCrossRefEndPos = auto_ptr<SwPosition>(new SwPosition(rEndPos));
     180             :                     SAL_WNODEPRECATED_DECLARATIONS_POP
     181           2 :                     pCrossRefEndPos->nContent = pCrossRefEndPos->nNode.GetNode().GetTxtNode()->Len();
     182           2 :                     pEndPos = pCrossRefEndPos.get();
     183             :                 }
     184         987 :                 if(pEndPos)
     185             :                 {
     186             :                     rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
     187             :                         new SwXBookmarkPortion_Impl(
     188             :                                 SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
     189         960 :                                 BKM_TYPE_END, *pEndPos)));
     190         987 :                 }
     191             :             }
     192         120 :         }
     193             :     }
     194             : }
     195             : 
     196             : namespace
     197             : {
     198             :     class theSwXTextPortionEnumerationUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextPortionEnumerationUnoTunnelId > {};
     199             : }
     200             : 
     201           0 : const uno::Sequence< sal_Int8 > & SwXTextPortionEnumeration::getUnoTunnelId()
     202             : {
     203           0 :     return theSwXTextPortionEnumerationUnoTunnelId::get().getSeq();
     204             : }
     205             : 
     206           0 : sal_Int64 SAL_CALL SwXTextPortionEnumeration::getSomething(
     207             :         const uno::Sequence< sal_Int8 >& rId )
     208             : throw(uno::RuntimeException)
     209             : {
     210           0 :     if( rId.getLength() == 16
     211           0 :         && 0 == memcmp( getUnoTunnelId().getConstArray(),
     212           0 :                                         rId.getConstArray(), 16 ) )
     213             :     {
     214           0 :         return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
     215             :     }
     216           0 :     return 0;
     217             : }
     218             : 
     219           0 : OUString SwXTextPortionEnumeration::getImplementationName()
     220             : throw( RuntimeException )
     221             : {
     222           0 :     return OUString("SwXTextPortionEnumeration");
     223             : }
     224             : 
     225             : sal_Bool
     226           0 : SwXTextPortionEnumeration::supportsService(const OUString& rServiceName)
     227             : throw( RuntimeException )
     228             : {
     229           0 :     return cppu::supportsService(this, rServiceName);
     230             : }
     231             : 
     232           0 : Sequence< OUString > SwXTextPortionEnumeration::getSupportedServiceNames()
     233             : throw( RuntimeException )
     234             : {
     235           0 :     Sequence< OUString > aRet(1);
     236           0 :     OUString* pArray = aRet.getArray();
     237           0 :     pArray[0] = "com.sun.star.text.TextPortionEnumeration";
     238           0 :     return aRet;
     239             : }
     240             : 
     241         509 : SwXTextPortionEnumeration::SwXTextPortionEnumeration(
     242             :         SwPaM& rParaCrsr,
     243             :         uno::Reference< XText > const & xParentText,
     244             :         const sal_Int32 nStart,
     245             :         const sal_Int32 nEnd )
     246         509 :     : m_Portions()
     247             : {
     248             :     SwUnoCrsr* pUnoCrsr =
     249         509 :        rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), false);
     250         509 :     pUnoCrsr->Add(this);
     251             : 
     252             :     OSL_ENSURE(nEnd == -1 || (nStart <= nEnd &&
     253             :         nEnd <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->GetTxt().getLength()),
     254             :             "start or end value invalid!");
     255             : 
     256             :     // find all frames, graphics and OLEs that are bound AT character in para
     257         509 :     FrameDependSortList_t frames;
     258         509 :     ::CollectFrameAtNode(*this, pUnoCrsr->GetPoint()->nNode, frames, true);
     259         509 :     lcl_CreatePortions(m_Portions, xParentText, pUnoCrsr, frames, nStart, nEnd);
     260         509 : }
     261             : 
     262         175 : SwXTextPortionEnumeration::SwXTextPortionEnumeration(
     263             :         SwPaM& rParaCrsr,
     264             :         TextRangeList_t const & rPortions )
     265         175 :     : m_Portions( rPortions )
     266             : {
     267             :     SwUnoCrsr* const pUnoCrsr =
     268         175 :        rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), false);
     269         175 :     pUnoCrsr->Add(this);
     270         175 : }
     271             : 
     272        2052 : SwXTextPortionEnumeration::~SwXTextPortionEnumeration()
     273             : {
     274         684 :     SolarMutexGuard aGuard;
     275             : 
     276         684 :     SwUnoCrsr* pUnoCrsr = GetCursor();
     277         684 :     delete pUnoCrsr;
     278        1368 : }
     279             : 
     280        5533 : sal_Bool SwXTextPortionEnumeration::hasMoreElements()
     281             : throw( uno::RuntimeException )
     282             : {
     283        5533 :     SolarMutexGuard aGuard;
     284             : 
     285        5533 :     return (m_Portions.size() > 0) ? sal_True : sal_False;
     286             : }
     287             : 
     288        5428 : uno::Any SwXTextPortionEnumeration::nextElement()
     289             : throw( container::NoSuchElementException, lang::WrappedTargetException,
     290             :        uno::RuntimeException )
     291             : {
     292        5428 :     SolarMutexGuard aGuard;
     293             : 
     294        5428 :     if (!m_Portions.size())
     295           1 :         throw container::NoSuchElementException();
     296             : 
     297        5427 :     Any any;
     298        5427 :     any <<= m_Portions.front();
     299        5427 :     m_Portions.pop_front();
     300        5428 :     return any;
     301             : }
     302             : 
     303             : typedef ::std::deque< xub_StrLen > FieldMarks_t;
     304             : 
     305             : static void
     306         509 : lcl_FillFieldMarkArray(FieldMarks_t & rFieldMarks, SwUnoCrsr const & rUnoCrsr,
     307             :         const sal_Int32 i_nStartPos)
     308             : {
     309             :     const SwTxtNode * const pTxtNode =
     310         509 :         rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
     311        1018 :     if (!pTxtNode) return;
     312             : 
     313             :     const sal_Unicode fld[] = {
     314         509 :         CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, CH_TXT_ATR_FORMELEMENT, 0 };
     315         509 :     sal_Int32 pos = ::std::max(static_cast<const sal_Int32>(0), i_nStartPos);
     316        1039 :     while ((pos = ::comphelper::string::indexOfAny(pTxtNode->GetTxt(), fld, pos)) != -1)
     317             :     {
     318          21 :         rFieldMarks.push_back(pos);
     319          21 :         ++pos;
     320             :     }
     321             : }
     322             : 
     323             : static uno::Reference<text::XTextRange>
     324          21 : lcl_ExportFieldMark(
     325             :         uno::Reference< text::XText > const & i_xParentText,
     326             :         SwUnoCrsr * const pUnoCrsr,
     327             :         const SwTxtNode * const pTxtNode )
     328             : {
     329          21 :     uno::Reference<text::XTextRange> xRef;
     330          21 :     SwDoc* pDoc = pUnoCrsr->GetDoc();
     331             :     //flr: maybe its a good idea to add a special hint to the hints array and rely on the hint segmentation....
     332          21 :     const xub_StrLen start = pUnoCrsr->Start()->nContent.GetIndex();
     333             :     OSL_ENSURE(pUnoCrsr->End()->nContent.GetIndex() == start,
     334             :                "hmm --- why is this different");
     335             : 
     336          21 :     pUnoCrsr->Right(1, CRSR_SKIP_CHARS, sal_False, sal_False);
     337          21 :     if ( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
     338             :     {
     339             :         OSL_FAIL("cannot move cursor?");
     340           0 :         return 0;
     341             :     }
     342             : 
     343          21 :     const sal_Unicode Char = pTxtNode->GetTxt()[start];
     344          21 :     if (CH_TXT_ATR_FIELDSTART == Char)
     345             :     {
     346          11 :         ::sw::mark::IFieldmark* pFieldmark = NULL;
     347          11 :         if (pDoc)
     348             :         {
     349          11 :             pFieldmark = pDoc->getIDocumentMarkAccess()->
     350          11 :                 getFieldmarkFor(*pUnoCrsr->GetMark());
     351             :         }
     352             :         SwXTextPortion* pPortion = new SwXTextPortion(
     353          11 :             pUnoCrsr, i_xParentText, PORTION_FIELD_START);
     354          11 :         xRef = pPortion;
     355          11 :         if (pPortion && pFieldmark && pDoc)
     356             :         {
     357          11 :             pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     358          11 :             Reference<XTextField> xField;
     359          11 :             const SwFmtFld* pField = SwPostItField::GetByName(pDoc, pFieldmark->GetName());
     360          11 :             if (pField)
     361          10 :                 xField = SwXTextField::CreateXTextField(*pDoc, *pField);
     362          11 :             pPortion->SetTextField(xField);
     363             :         }
     364             :     }
     365          10 :     else if (CH_TXT_ATR_FIELDEND == Char)
     366             :     {
     367           9 :         ::sw::mark::IFieldmark* pFieldmark = NULL;
     368           9 :         if (pDoc)
     369             :         {
     370           9 :             pFieldmark = pDoc->getIDocumentMarkAccess()->
     371           9 :                 getFieldmarkFor(*pUnoCrsr->GetMark());
     372             :         }
     373             :         SwXTextPortion* pPortion = new SwXTextPortion(
     374           9 :             pUnoCrsr, i_xParentText, PORTION_FIELD_END);
     375           9 :         xRef = pPortion;
     376           9 :         if (pPortion && pFieldmark && pDoc)
     377           9 :             pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     378             :     }
     379           1 :     else if (CH_TXT_ATR_FORMELEMENT == Char)
     380             :     {
     381           1 :         ::sw::mark::IFieldmark* pFieldmark = NULL;
     382           1 :         if (pDoc)
     383             :         {
     384           1 :             pFieldmark = pDoc->getIDocumentMarkAccess()->
     385           1 :                 getFieldmarkFor(*pUnoCrsr->GetMark());
     386             :         }
     387             :         SwXTextPortion* pPortion = new SwXTextPortion(
     388           1 :             pUnoCrsr, i_xParentText, PORTION_FIELD_START_END);
     389           1 :         xRef = pPortion;
     390           1 :         if (pPortion && pFieldmark && pDoc)
     391           1 :             pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
     392             :     }
     393             :     else
     394             :     {
     395             :         OSL_FAIL("no fieldmark found?");
     396             :     }
     397          21 :     return xRef;
     398             : }
     399             : 
     400             : static Reference<XTextRange>
     401          46 : lcl_CreateRefMarkPortion(
     402             :     Reference<XText> const& xParent,
     403             :     const SwUnoCrsr * const pUnoCrsr,
     404             :     const SwTxtAttr & rAttr, const bool bEnd)
     405             : {
     406          46 :     SwDoc* pDoc = pUnoCrsr->GetDoc();
     407             :     const SwFmtRefMark& rRefMark =
     408          46 :         static_cast<const SwFmtRefMark&>(rAttr.GetAttr());
     409          46 :     Reference<XTextContent> xContent;
     410          46 :     if (!xContent.is())
     411             :     {
     412          46 :         xContent = new SwXReferenceMark(pDoc, &rRefMark);
     413             :     }
     414             : 
     415          46 :     SwXTextPortion* pPortion = 0;
     416          46 :     if (!bEnd)
     417             :     {
     418          32 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_START);
     419          32 :         pPortion->SetRefMark(xContent);
     420          32 :         pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
     421             :     }
     422             :     else
     423             :     {
     424          14 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_END);
     425          14 :         pPortion->SetRefMark(xContent);
     426             :     }
     427          46 :     return pPortion;
     428             : }
     429             : 
     430             : static void
     431         244 : lcl_InsertRubyPortion(
     432             :     TextRangeList_t & rPortions,
     433             :     Reference<XText> const& xParent,
     434             :     const SwUnoCrsr * const pUnoCrsr,
     435             :     const SwTxtAttr & rAttr, const sal_Bool bEnd)
     436             : {
     437             :     SwXTextPortion* pPortion = new SwXTextPortion(pUnoCrsr,
     438         244 :             static_cast<const SwTxtRuby&>(rAttr), xParent, bEnd);
     439         244 :     rPortions.push_back(pPortion);
     440         244 :     pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
     441         244 : }
     442             : 
     443             : static Reference<XTextRange>
     444          45 : lcl_CreateTOXMarkPortion(
     445             :     Reference<XText> const& xParent,
     446             :     const SwUnoCrsr * const pUnoCrsr,
     447             :     SwTxtAttr & rAttr, const bool bEnd)
     448             : {
     449          45 :     SwDoc* pDoc = pUnoCrsr->GetDoc();
     450          45 :     SwTOXMark & rTOXMark = static_cast<SwTOXMark&>(rAttr.GetAttr());
     451             : 
     452             :     const Reference<XTextContent> xContent(
     453             :         SwXDocumentIndexMark::CreateXDocumentIndexMark(*pDoc,
     454          45 :                     *const_cast<SwTOXType*>(rTOXMark.GetTOXType()), rTOXMark),
     455          45 :         uno::UNO_QUERY);
     456             : 
     457          45 :     SwXTextPortion* pPortion = 0;
     458          45 :     if (!bEnd)
     459             :     {
     460          32 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_START);
     461          32 :         pPortion->SetTOXMark(xContent);
     462          32 :         pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
     463             :     }
     464             :     else
     465             :     {
     466          13 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_END);
     467          13 :         pPortion->SetTOXMark(xContent);
     468             :     }
     469          45 :     return pPortion;
     470             : }
     471             : 
     472             : SAL_WNODEPRECATED_DECLARATIONS_PUSH
     473             : static uno::Reference<text::XTextRange>
     474         175 : lcl_CreateMetaPortion(
     475             :     uno::Reference<text::XText> const& xParent,
     476             :     const SwUnoCrsr * const pUnoCrsr,
     477             :     SwTxtAttr & rAttr, ::std::auto_ptr<TextRangeList_t const> & pPortions)
     478             : {
     479             :     const uno::Reference<rdf::XMetadatable> xMeta( SwXMeta::CreateXMeta(
     480         175 :             *static_cast<SwFmtMeta &>(rAttr.GetAttr()).GetMeta(),
     481         350 :             xParent, pPortions));
     482         175 :     SwXTextPortion * pPortion(0);
     483         175 :     if (RES_TXTATR_META == rAttr.Which())
     484             :     {
     485             :         const uno::Reference<text::XTextContent> xContent(xMeta,
     486         145 :                 uno::UNO_QUERY);
     487         145 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_META);
     488         145 :         pPortion->SetMeta(xContent);
     489             :     }
     490             :     else
     491             :     {
     492          30 :         const uno::Reference<text::XTextField> xField(xMeta, uno::UNO_QUERY);
     493          30 :         pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_FIELD);
     494          30 :         pPortion->SetTextField(xField);
     495             :     }
     496         175 :     return pPortion;
     497             : }
     498             : SAL_WNODEPRECATED_DECLARATIONS_POP
     499             : 
     500             : static void
     501        1918 : lcl_ExportBookmark(
     502             :     TextRangeList_t & rPortions,
     503             :     Reference<XText> const& xParent,
     504             :     const SwUnoCrsr * const pUnoCrsr,
     505             :     SwXBookmarkPortion_ImplList& rBkmArr, const sal_uLong nIndex)
     506             : {
     507        5783 :     for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end();
     508             :           aIter != aEnd; )
     509             :     {
     510        3797 :         SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
     511        3797 :         if ( nIndex > pPtr->getIndex() )
     512             :         {
     513           0 :             rBkmArr.erase( aIter++ );
     514           0 :             continue;
     515             :         }
     516        3797 :         if ( nIndex < pPtr->getIndex() )
     517        1850 :             break;
     518             : 
     519        1947 :         SwXTextPortion* pPortion = 0;
     520        2934 :         if ((BKM_TYPE_START     == pPtr->nBkmType) ||
     521         987 :             (BKM_TYPE_START_END == pPtr->nBkmType))
     522             :         {
     523             :             pPortion =
     524         987 :                 new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_START);
     525         987 :             rPortions.push_back(pPortion);
     526         987 :             pPortion->SetBookmark(pPtr->xBookmark);
     527         987 :             pPortion->SetCollapsed( (BKM_TYPE_START_END == pPtr->nBkmType)
     528         987 :                     ? true : false);
     529             : 
     530             :         }
     531        1947 :         if (BKM_TYPE_END == pPtr->nBkmType)
     532             :         {
     533             :             pPortion =
     534         960 :                 new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_END);
     535         960 :             rPortions.push_back(pPortion);
     536         960 :             pPortion->SetBookmark(pPtr->xBookmark);
     537             :         }
     538        1947 :         rBkmArr.erase( aIter++ );
     539        1947 :     }
     540        1918 : }
     541             : 
     542             : static void
     543         537 : lcl_ExportSoftPageBreak(
     544             :     TextRangeList_t & rPortions,
     545             :     Reference<XText> const& xParent,
     546             :     const SwUnoCrsr * const pUnoCrsr,
     547             :     SwSoftPageBreakList& rBreakArr, const sal_uLong nIndex)
     548             : {
     549        1618 :     for ( SwSoftPageBreakList::iterator aIter = rBreakArr.begin(),
     550         537 :           aEnd = rBreakArr.end();
     551             :           aIter != aEnd; )
     552             :     {
     553         538 :         if ( nIndex > *aIter )
     554             :         {
     555           0 :             rBreakArr.erase( aIter++ );
     556           0 :             continue;
     557             :         }
     558         538 :         if ( nIndex < *aIter )
     559         531 :             break;
     560             : 
     561             :         rPortions.push_back(
     562           7 :             new SwXTextPortion(pUnoCrsr, xParent, PORTION_SOFT_PAGEBREAK) );
     563           7 :         rBreakArr.erase( aIter++ );
     564             :     }
     565         537 : }
     566             : 
     567             : struct SwXRedlinePortion_Impl
     568             : {
     569             :     const SwRedline*    m_pRedline;
     570             :     const bool          m_bStart;
     571             : 
     572          40 :     SwXRedlinePortion_Impl ( const SwRedline* pRed, const bool bIsStart )
     573             :     : m_pRedline(pRed)
     574          40 :     , m_bStart(bIsStart)
     575             :     {
     576          40 :     }
     577             : 
     578         120 :     sal_uLong getRealIndex ()
     579             :     {
     580          60 :         return m_bStart ? m_pRedline->Start()->nContent.GetIndex()
     581         180 :                         : m_pRedline->End()  ->nContent.GetIndex();
     582             :     }
     583             : };
     584             : 
     585             : typedef boost::shared_ptr < SwXRedlinePortion_Impl >
     586             :     SwXRedlinePortion_ImplSharedPtr;
     587             : 
     588             : struct RedlineCompareStruct
     589             : {
     590          80 :     const SwPosition& getPosition ( const SwXRedlinePortion_ImplSharedPtr &r )
     591             :     {
     592          80 :         return *(r->m_bStart ? r->m_pRedline->Start() : r->m_pRedline->End());
     593             :     }
     594             : 
     595          40 :     bool operator () ( const SwXRedlinePortion_ImplSharedPtr &r1,
     596             :                        const SwXRedlinePortion_ImplSharedPtr &r2 )
     597             :     {
     598          40 :         return getPosition ( r1 ) < getPosition ( r2 );
     599             :     }
     600             : };
     601             : 
     602             : typedef std::multiset < SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct >
     603             : SwXRedlinePortion_ImplList;
     604             : 
     605             : static Reference<XTextRange>
     606        1685 : lcl_ExportHints(
     607             :     PortionStack_t & rPortionStack,
     608             :     const Reference<XText> & xParent,
     609             :     SwUnoCrsr * const pUnoCrsr,
     610             :     SwpHints * const pHints,
     611             :     const sal_Int32 i_nStartPos,
     612             :     const sal_Int32 i_nEndPos,
     613             :     const xub_StrLen nCurrentIndex,
     614             :     const bool bRightMoveForbidden,
     615             :     bool & o_rbCursorMoved,
     616             :     sal_Int32 & o_rNextAttrPosition )
     617             : {
     618             :     // if the attribute has a dummy character, then xRef is set (except META)
     619             :     // otherwise, the portion for the attribute is inserted into rPortions!
     620        1685 :     Reference<XTextRange> xRef;
     621        1685 :     SwDoc* pDoc = pUnoCrsr->GetDoc();
     622             :     //search for special text attributes - first some ends
     623        1685 :     sal_uInt16 nEndIndex = 0;
     624        1685 :     sal_uInt16 nNextEnd = 0;
     625       20799 :     while(nEndIndex < pHints->GetEndCount() &&
     626        9676 :         (!pHints->GetEnd(nEndIndex)->GetEnd() ||
     627        3349 :         nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetEnd()))))
     628             :     {
     629        5551 :         if(pHints->GetEnd(nEndIndex)->GetEnd())
     630             :         {
     631        2573 :             SwTxtAttr * const pAttr = pHints->GetEnd(nEndIndex);
     632        2573 :             if (nNextEnd == nCurrentIndex)
     633             :             {
     634         543 :                 const sal_uInt16 nWhich( pAttr->Which() );
     635         543 :                 switch (nWhich)
     636             :                 {
     637             :                     case RES_TXTATR_TOXMARK:
     638             :                     {
     639             :                         Reference<XTextRange> xTmp = lcl_CreateTOXMarkPortion(
     640          13 :                                 xParent, pUnoCrsr, *pAttr, true);
     641          13 :                         rPortionStack.top().first->push_back(xTmp);
     642             :                     }
     643          13 :                     break;
     644             :                     case RES_TXTATR_REFMARK:
     645             :                     {
     646             :                         Reference<XTextRange> xTmp = lcl_CreateRefMarkPortion(
     647          14 :                                 xParent, pUnoCrsr, *pAttr, true);
     648          14 :                         rPortionStack.top().first->push_back(xTmp);
     649             :                     }
     650          14 :                     break;
     651             :                     case RES_TXTATR_CJK_RUBY:
     652             :                        //#i91534# GetEnd() == 0 mixes the order of ruby start/end
     653         122 :                         if( *pAttr->GetEnd() == *pAttr->GetStart())
     654             :                         {
     655           2 :                             lcl_InsertRubyPortion( *rPortionStack.top().first,
     656           2 :                                     xParent, pUnoCrsr, *pAttr, sal_False);
     657             :                         }
     658         122 :                         lcl_InsertRubyPortion( *rPortionStack.top().first,
     659         122 :                                 xParent, pUnoCrsr, *pAttr, sal_True);
     660         122 :                     break;
     661             :                     case RES_TXTATR_META:
     662             :                     case RES_TXTATR_METAFIELD:
     663             :                     {
     664             :                         OSL_ENSURE(*pAttr->GetStart() != *pAttr->GetEnd(),
     665             :                                 "empty meta?");
     666         177 :                         if ((i_nStartPos > 0) &&
     667           1 :                             (*pAttr->GetStart() < i_nStartPos))
     668             :                         {
     669             :                             // force skip pAttr and rest of attribute ends
     670             :                             // at nCurrentIndex
     671             :                             // because they are not contained in the meta pAttr
     672             :                             // and the meta pAttr itself is outside selection!
     673             :                             // (necessary for SwXMeta::createEnumeration)
     674           1 :                             if (*pAttr->GetStart() + 1 == i_nStartPos)
     675             :                             {
     676           1 :                                 nEndIndex = pHints->GetEndCount() - 1;
     677             :                             }
     678           1 :                             break;
     679             :                         }
     680         175 :                         PortionList_t Top = rPortionStack.top();
     681         175 :                         if (Top.second != pAttr)
     682             :                         {
     683             :                             OSL_FAIL("ExportHints: stack error" );
     684             :                         }
     685             :                         else
     686             :                         {
     687             :                             SAL_WNODEPRECATED_DECLARATIONS_PUSH
     688             :                             ::std::auto_ptr<const TextRangeList_t>
     689         175 :                                 pCurrentPortions(Top.first);
     690             :                             SAL_WNODEPRECATED_DECLARATIONS_POP
     691         175 :                             rPortionStack.pop();
     692             :                             const uno::Reference<text::XTextRange> xPortion(
     693             :                                 lcl_CreateMetaPortion(xParent, pUnoCrsr,
     694         350 :                                     *pAttr, pCurrentPortions));
     695         350 :                             rPortionStack.top().first->push_back(xPortion);
     696             :                         }
     697             :                     }
     698         175 :                     break;
     699             :                 }
     700             :             }
     701             :         }
     702        5551 :         nEndIndex++;
     703             :     }
     704             : 
     705             :     // then some starts
     706        1685 :     sal_uInt16 nStartIndex = 0;
     707        1685 :     sal_uInt16 nNextStart = 0;
     708       15091 :     while(nStartIndex < pHints->GetStartCount() &&
     709        6276 :         nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
     710             :     {
     711        5445 :         SwTxtAttr * const pAttr = pHints->GetStart(nStartIndex);
     712        5445 :         sal_uInt16 nAttrWhich = pAttr->Which();
     713        5445 :         if (nNextStart == nCurrentIndex)
     714             :         {
     715         996 :             switch( nAttrWhich )
     716             :             {
     717             :                 case RES_TXTATR_FIELD:
     718          43 :                     if(!bRightMoveForbidden)
     719             :                     {
     720          43 :                         pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
     721          43 :                         if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
     722           0 :                             break;
     723             :                         SwXTextPortion* pPortion;
     724          86 :                         xRef = pPortion = new SwXTextPortion(
     725          86 :                                 pUnoCrsr, xParent, PORTION_FIELD);
     726             :                         Reference<XTextField> const xField =
     727          43 :                             SwXTextField::CreateXTextField(*pDoc, pAttr->GetFld());
     728          43 :                         pPortion->SetTextField(xField);
     729             : 
     730             :                         // If this is a postit field and it has a fieldmark
     731             :                         // associated, set the fieldmark as a bookmark.
     732          43 :                         const SwField* pField = pAttr->GetFld().GetFld();
     733          43 :                         if (pField->Which() == RES_POSTITFLD)
     734             :                         {
     735           9 :                             const SwPostItField* pPostItField = dynamic_cast<const SwPostItField*>(pField);
     736           9 :                             IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
     737           9 :                             IDocumentMarkAccess::const_iterator_t it = pMarkAccess->findMark(pPostItField->GetName());
     738           9 :                             if (it != pMarkAccess->getMarksEnd())
     739           8 :                                 pPortion->SetBookmark(SwXFieldmark::CreateXFieldmark(*pDoc, *it->get()));
     740          43 :                         }
     741             :                     }
     742          43 :                 break;
     743             :                 case RES_TXTATR_FLYCNT   :
     744         354 :                     if(!bRightMoveForbidden)
     745             :                     {
     746         354 :                         pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
     747         354 :                         if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
     748           0 :                             break; // Robust #i81708 content in covered cells
     749         354 :                         pUnoCrsr->Exchange();
     750         708 :                         xRef = new SwXTextPortion(
     751         708 :                                 pUnoCrsr, xParent, PORTION_FRAME);
     752             :                     }
     753         354 :                 break;
     754             :                 case RES_TXTATR_FTN      :
     755             :                 {
     756          20 :                     if(!bRightMoveForbidden)
     757             :                     {
     758          20 :                         pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
     759          20 :                         if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
     760           0 :                             break;
     761             :                         SwXTextPortion* pPortion;
     762          40 :                         xRef = pPortion = new SwXTextPortion(
     763          40 :                                 pUnoCrsr, xParent, PORTION_FOOTNOTE);
     764             :                         Reference<XFootnote> xContent =
     765          20 :                             SwXFootnotes::GetObject(*pDoc, pAttr->GetFtn());
     766          20 :                         pPortion->SetFootnote(xContent);
     767             :                     }
     768             :                 }
     769          20 :                 break;
     770             :                 case RES_TXTATR_TOXMARK:
     771             :                 case RES_TXTATR_REFMARK:
     772             :                 {
     773          64 :                     bool bIsPoint = !(pAttr->GetEnd());
     774          64 :                     if (!bRightMoveForbidden || !bIsPoint)
     775             :                     {
     776          64 :                         if (bIsPoint)
     777             :                         {
     778          37 :                             pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
     779             :                         }
     780             :                         Reference<XTextRange> xTmp =
     781             :                                 (RES_TXTATR_REFMARK == nAttrWhich)
     782             :                             ? lcl_CreateRefMarkPortion(
     783             :                                 xParent, pUnoCrsr, *pAttr, false)
     784             :                             : lcl_CreateTOXMarkPortion(
     785          64 :                                 xParent, pUnoCrsr, *pAttr, false);
     786          64 :                         if (bIsPoint) // consume CH_TXTATR!
     787             :                         {
     788          37 :                             pUnoCrsr->Normalize(false);
     789          37 :                             pUnoCrsr->DeleteMark();
     790          37 :                             xRef = xTmp;
     791             :                         }
     792             :                         else // just insert it
     793             :                         {
     794          27 :                             rPortionStack.top().first->push_back(xTmp);
     795          64 :                         }
     796             :                     }
     797             :                 }
     798          64 :                 break;
     799             :                 case RES_TXTATR_CJK_RUBY:
     800             :                     //#i91534# GetEnd() == 0 mixes the order of ruby start/end
     801         122 :                     if(pAttr->GetEnd() && (*pAttr->GetEnd() != *pAttr->GetStart()))
     802             :                     {
     803         120 :                         lcl_InsertRubyPortion( *rPortionStack.top().first,
     804         240 :                             xParent, pUnoCrsr, *pAttr, sal_False);
     805             :                     }
     806         122 :                 break;
     807             :                 case RES_TXTATR_META:
     808             :                 case RES_TXTATR_METAFIELD:
     809         175 :                     if (*pAttr->GetStart() != *pAttr->GetEnd())
     810             :                     {
     811         175 :                         if (!bRightMoveForbidden)
     812             :                         {
     813         175 :                             pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
     814         175 :                             o_rbCursorMoved = true;
     815             :                             // only if the end is included in selection!
     816         175 :                             if ((i_nEndPos < 0) ||
     817           0 :                                 (*pAttr->GetEnd() <= i_nEndPos))
     818             :                             {
     819             :                                 rPortionStack.push( ::std::make_pair(
     820         175 :                                         new TextRangeList_t, pAttr ));
     821             :                             }
     822             :                         }
     823             :                     }
     824         175 :                 break;
     825             :                 case RES_TXTATR_AUTOFMT:
     826             :                 case RES_TXTATR_INETFMT:
     827             :                 case RES_TXTATR_CHARFMT:
     828         218 :                 break; // these are handled as properties of a "Text" portion
     829             :                 default:
     830             :                     OSL_FAIL("unknown attribute");
     831           0 :                 break;
     832             :             }
     833             :         }
     834        5445 :         nStartIndex++;
     835             :     }
     836             : 
     837        1685 :     if (xRef.is()) // implies that we have moved the cursor
     838             :     {
     839         454 :         o_rbCursorMoved = true;
     840             :     }
     841        1685 :     if (!o_rbCursorMoved)
     842             :     {
     843             :         // search for attribute changes behind the current cursor position
     844             :         // break up at frames, bookmarks, redlines
     845             : 
     846        1056 :         nStartIndex = 0;
     847        1056 :         nNextStart = 0;
     848        8664 :         while(nStartIndex < pHints->GetStartCount() &&
     849        3489 :             nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
     850        3063 :             nStartIndex++;
     851             : 
     852        1056 :         nEndIndex = 0;
     853        1056 :         nNextEnd = 0;
     854        7527 :         while(nEndIndex < pHints->GetEndCount() &&
     855        2998 :             nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd())))
     856        2417 :             nEndIndex++;
     857             : 
     858             :         sal_Int32 nNextPos =
     859         426 :             ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
     860        1198 :             ?   nNextStart  :   nNextEnd;
     861        1056 :         if (nNextPos > nCurrentIndex)
     862             :         {
     863         581 :             o_rNextAttrPosition = nNextPos;
     864             :         }
     865             :     }
     866        1685 :     return xRef;
     867             : }
     868             : 
     869        2622 : static void lcl_MoveCursor( SwUnoCrsr * const pUnoCrsr,
     870             :     const xub_StrLen nCurrentIndex,
     871             :     const sal_Int32 nNextFrameIndex, const sal_Int32 nNextPortionIndex,
     872             :     const sal_Int32 nNextAttrIndex,  const sal_Int32 nNextFieldMarkIndex,
     873             :     const sal_Int32 nEndPos )
     874             : {
     875        2622 :     sal_Int32 nMovePos = pUnoCrsr->GetCntntNode()->Len();
     876             : 
     877        2622 :     if ((nEndPos >= 0) && (nEndPos < nMovePos))
     878             :     {
     879           1 :         nMovePos = nEndPos;
     880             :     }
     881             : 
     882        2622 :     if ((nNextFrameIndex >= 0) && (nNextFrameIndex < nMovePos))
     883             :     {
     884           5 :         nMovePos = nNextFrameIndex;
     885             :     }
     886             : 
     887        2622 :     if ((nNextPortionIndex >= 0) && (nNextPortionIndex < nMovePos))
     888             :     {
     889        1847 :         nMovePos = nNextPortionIndex;
     890             :     }
     891             : 
     892        2622 :     if ((nNextAttrIndex >= 0) && (nNextAttrIndex < nMovePos))
     893             :     {
     894         458 :         nMovePos = nNextAttrIndex;
     895             :     }
     896             : 
     897        2622 :     if ((nNextFieldMarkIndex >= 0) && (nNextFieldMarkIndex < nMovePos))
     898             :     {
     899          19 :         nMovePos = nNextFieldMarkIndex;
     900             :     }
     901             : 
     902        2622 :     if (nMovePos > nCurrentIndex)
     903             :     {
     904             : //          pUnoCrsr->Right(nMovePos - nCurrentIndex);
     905        2622 :         pUnoCrsr->GetPoint()->nContent = static_cast<sal_uInt16>(nMovePos);
     906             :     }
     907        2622 : }
     908             : 
     909             : static void
     910         509 : lcl_FillRedlineArray(SwDoc const & rDoc, SwUnoCrsr const & rUnoCrsr,
     911             :         SwXRedlinePortion_ImplList& rRedArr )
     912             : {
     913         509 :     const SwRedlineTbl& rRedTbl = rDoc.GetRedlineTbl();
     914         509 :     sal_uInt16 nRedTblCount = rRedTbl.size();
     915             : 
     916         509 :     if ( nRedTblCount > 0 )
     917             :     {
     918          20 :         const SwPosition* pStart = rUnoCrsr.GetPoint();
     919          20 :         const SwNodeIndex nOwnNode = pStart->nNode;
     920             : 
     921          48 :         for(sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
     922             :         {
     923          28 :             const SwRedline* pRedline = rRedTbl[nRed];
     924          28 :             const SwPosition* pRedStart = pRedline->Start();
     925          28 :             const SwNodeIndex nRedNode = pRedStart->nNode;
     926          28 :             if ( nOwnNode == nRedNode )
     927             :                 rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
     928          20 :                     new SwXRedlinePortion_Impl ( pRedline, true ) ) );
     929          28 :             if( pRedline->HasMark() && pRedline->End()->nNode == nOwnNode )
     930             :                 rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
     931          20 :                     new SwXRedlinePortion_Impl ( pRedline, false) ) );
     932          48 :        }
     933             :     }
     934         509 : }
     935             : 
     936             : static void
     937         509 : lcl_FillSoftPageBreakArray(
     938             :         SwUnoCrsr const & rUnoCrsr, SwSoftPageBreakList& rBreakArr )
     939             : {
     940             :     const SwTxtNode *pTxtNode =
     941         509 :         rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
     942         509 :     if( pTxtNode )
     943         509 :         pTxtNode->fillSoftPageBreakList( rBreakArr );
     944         509 : }
     945             : 
     946             : static void
     947          60 : lcl_ExportRedline(
     948             :     TextRangeList_t & rPortions,
     949             :     Reference<XText> const& xParent,
     950             :     const SwUnoCrsr * const pUnoCrsr,
     951             :     SwXRedlinePortion_ImplList& rRedlineArr, const sal_uLong nIndex)
     952             : {
     953             : 
     954             :     // MTG: 23/11/05: We want this loop to iterate over all red lines in this
     955             :     // array. We will only insert the ones with index matches
     956         160 :     for ( SwXRedlinePortion_ImplList::iterator aIter = rRedlineArr.begin(), aEnd = rRedlineArr.end();
     957             :           aIter != aEnd; )
     958             :     {
     959          80 :         SwXRedlinePortion_ImplSharedPtr pPtr = (*aIter );
     960          80 :         sal_uLong nRealIndex = pPtr->getRealIndex();
     961             :         // MTG: 23/11/05: If there are elements before nIndex, remove them
     962          80 :         if ( nIndex > nRealIndex )
     963           0 :             rRedlineArr.erase ( aIter++ );
     964             :         // MTG: 23/11/05: If the elements match, and them to the list
     965          80 :         else if ( nIndex == nRealIndex )
     966             :         {
     967             :             rPortions.push_back( new SwXRedlinePortion(
     968          40 :                         *pPtr->m_pRedline, pUnoCrsr, xParent, pPtr->m_bStart));
     969          40 :             rRedlineArr.erase ( aIter++ );
     970             :         }
     971             :         // MTG: 23/11/05: If we've iterated past nIndex, exit the loop
     972             :         else
     973          40 :             break;
     974          40 :     }
     975          60 : }
     976             : 
     977             : static void
     978        3781 : lcl_ExportBkmAndRedline(
     979             :     TextRangeList_t & rPortions,
     980             :     Reference<XText> const & xParent,
     981             :     const SwUnoCrsr * const pUnoCrsr,
     982             :     SwXBookmarkPortion_ImplList& rBkmArr,
     983             :     SwXRedlinePortion_ImplList& rRedlineArr,
     984             :     SwSoftPageBreakList& rBreakArr,
     985             :     const sal_uLong nIndex)
     986             : {
     987        3781 :     if (!rBkmArr.empty())
     988        1918 :         lcl_ExportBookmark(rPortions, xParent, pUnoCrsr, rBkmArr, nIndex);
     989             : 
     990        3781 :     if (!rRedlineArr.empty())
     991          60 :         lcl_ExportRedline(rPortions, xParent, pUnoCrsr, rRedlineArr, nIndex);
     992             : 
     993        3781 :     if (!rBreakArr.empty())
     994         537 :         lcl_ExportSoftPageBreak(rPortions, xParent, pUnoCrsr, rBreakArr, nIndex);
     995        3781 : }
     996             : 
     997             : static sal_Int32
     998        3781 : lcl_ExportFrames(
     999             :     TextRangeList_t & rPortions,
    1000             :     Reference<XText> const & i_xParent,
    1001             :     SwUnoCrsr * const i_pUnoCrsr,
    1002             :     FrameDependSortList_t & i_rFrames,
    1003             :     xub_StrLen const i_nCurrentIndex)
    1004             : {
    1005             :     // find first Frame in (sorted) i_rFrames at current position
    1006        7587 :     while (i_rFrames.size() && (i_rFrames.front().nIndex == i_nCurrentIndex))
    1007             :     // do not check for i_nEnd here; this is done implicity by lcl_MoveCursor
    1008             :     {
    1009             :         const SwModify * const pFrame =
    1010          25 :             i_rFrames.front().pFrameDepend->GetRegisteredIn();
    1011          25 :         if (pFrame) // Frame could be disposed
    1012             :         {
    1013             :             SwXTextPortion* pPortion = new SwXTextPortion(i_pUnoCrsr, i_xParent,
    1014          25 :                 *static_cast<SwFrmFmt*>( const_cast<SwModify*>( pFrame ) ) );
    1015          25 :             rPortions.push_back(pPortion);
    1016             :         }
    1017          25 :         i_rFrames.pop_front();
    1018             :     }
    1019             : 
    1020        3781 :     return i_rFrames.size() ? i_rFrames.front().nIndex : -1;
    1021             : }
    1022             : 
    1023             : static sal_Int32
    1024        2622 : lcl_GetNextIndex(
    1025             :     SwXBookmarkPortion_ImplList const & rBkmArr,
    1026             :     SwXRedlinePortion_ImplList const & rRedlineArr,
    1027             :     SwSoftPageBreakList const & rBreakArr )
    1028             : {
    1029        2622 :     sal_Int32 nRet = -1;
    1030        2622 :     if(!rBkmArr.empty())
    1031             :     {
    1032        1836 :         SwXBookmarkPortion_ImplSharedPtr pPtr = (*rBkmArr.begin());
    1033        1836 :         nRet = pPtr->getIndex();
    1034             :     }
    1035        2622 :     if(!rRedlineArr.empty())
    1036             :     {
    1037          40 :         SwXRedlinePortion_ImplSharedPtr pPtr = (*rRedlineArr.begin());
    1038          40 :         sal_Int32 nTmp = pPtr->getRealIndex();
    1039          40 :         if(nRet < 0 || nTmp < nRet)
    1040          40 :             nRet = nTmp;
    1041             :     }
    1042        2622 :     if(!rBreakArr.empty())
    1043             :     {
    1044         531 :         if(nRet < 0 || *rBreakArr.begin() < static_cast<sal_uInt32>(nRet))
    1045           4 :             nRet = *rBreakArr.begin();
    1046             :     }
    1047        2622 :     return nRet;
    1048             : };
    1049             : 
    1050             : static void
    1051         509 : lcl_CreatePortions(
    1052             :         TextRangeList_t & i_rPortions,
    1053             :         uno::Reference< text::XText > const & i_xParentText,
    1054             :         SwUnoCrsr * const pUnoCrsr,
    1055             :         FrameDependSortList_t & i_rFrames,
    1056             :         const sal_Int32 i_nStartPos,
    1057             :         const sal_Int32 i_nEndPos )
    1058             : {
    1059         509 :     if (!pUnoCrsr)
    1060           0 :         return;
    1061             : 
    1062             :     // set the start if a selection should be exported
    1063         510 :     if ((i_nStartPos > 0) &&
    1064           1 :         (pUnoCrsr->Start()->nContent.GetIndex() != i_nStartPos))
    1065             :     {
    1066           0 :         pUnoCrsr->DeleteMark();
    1067             :         OSL_ENSURE(pUnoCrsr->Start()->nNode.GetNode().GetTxtNode() &&
    1068             :             (i_nStartPos <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->
    1069             :                         GetTxt().getLength()), "Incorrect start position" );
    1070             :         // ??? should this be i_nStartPos - current position ?
    1071             :         pUnoCrsr->Right(static_cast<xub_StrLen>(i_nStartPos),
    1072           0 :                 CRSR_SKIP_CHARS, sal_False, sal_False);
    1073             :     }
    1074             : 
    1075         509 :     FieldMarks_t FieldMarks;
    1076        1018 :     SwXBookmarkPortion_ImplList Bookmarks;
    1077        1018 :     SwXRedlinePortion_ImplList Redlines;
    1078        1018 :     SwSoftPageBreakList SoftPageBreaks;
    1079             : 
    1080         509 :     SwDoc * const pDoc = pUnoCrsr->GetDoc();
    1081         509 :     lcl_FillFieldMarkArray(FieldMarks, *pUnoCrsr, i_nStartPos);
    1082         509 :     lcl_FillBookmarkArray(*pDoc, *pUnoCrsr, Bookmarks);
    1083         509 :     lcl_FillRedlineArray(*pDoc, *pUnoCrsr, Redlines);
    1084         509 :     lcl_FillSoftPageBreakArray(*pUnoCrsr, SoftPageBreaks);
    1085             : 
    1086        1018 :     PortionStack_t PortionStack;
    1087         509 :     PortionStack.push( PortionList_t(&i_rPortions, (const SwTxtAttr *)0) );
    1088             : 
    1089         509 :     bool bAtEnd( false );
    1090        4799 :     while (!bAtEnd) // every iteration consumes at least current character!
    1091             :     {
    1092        3781 :         if (pUnoCrsr->HasMark())
    1093             :         {
    1094        3235 :             pUnoCrsr->Normalize(false);
    1095        3235 :             pUnoCrsr->DeleteMark();
    1096             :         }
    1097             : 
    1098        3781 :         SwTxtNode * const pTxtNode = pUnoCrsr->GetNode()->GetTxtNode();
    1099        3781 :         if (!pTxtNode)
    1100             :         {
    1101             :             OSL_FAIL("lcl_CreatePortions: no TextNode - what now ?");
    1102           0 :             return;
    1103             :         }
    1104             : 
    1105        3781 :         SwpHints * const pHints = pTxtNode->GetpSwpHints();
    1106             :         const xub_StrLen nCurrentIndex =
    1107        3781 :             pUnoCrsr->GetPoint()->nContent.GetIndex();
    1108             :         // this contains the portion which consumes the character in the
    1109             :         // text at nCurrentIndex; i.e. it must be set _once_ per iteration
    1110        3781 :         uno::Reference< XTextRange > xRef;
    1111             : 
    1112        3781 :         SwUnoCursorHelper::SelectPam(*pUnoCrsr, true); // set mark
    1113             : 
    1114             :         const sal_Int32 nFirstFrameIndex =
    1115        3781 :             lcl_ExportFrames( *PortionStack.top().first,
    1116        7562 :                 i_xParentText, pUnoCrsr, i_rFrames, nCurrentIndex);
    1117             : 
    1118        3781 :         lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
    1119        7562 :             pUnoCrsr, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex );
    1120             : 
    1121        3781 :         bool bCursorMoved( false );
    1122        3781 :         sal_Int32 nNextAttrIndex = -1;
    1123             :         // #111716# the cursor must not move right at the
    1124             :         //          end position of a selection!
    1125           3 :         bAtEnd = ((i_nEndPos >= 0) && (nCurrentIndex >= i_nEndPos))
    1126        7561 :               || (nCurrentIndex >= pTxtNode->Len());
    1127        3781 :         if (pHints)
    1128             :         {
    1129             :             // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
    1130        3370 :             xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCrsr,
    1131             :                         pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
    1132        1685 :                         bCursorMoved, nNextAttrIndex);
    1133        1685 :             if (PortionStack.empty())
    1134             :             {
    1135             :                 OSL_FAIL("CreatePortions: stack underflow");
    1136           0 :                 return;
    1137             :             }
    1138             :         }
    1139             : 
    1140        3781 :         if (!xRef.is() && !bCursorMoved)
    1141             :         {
    1142        8947 :             if (!bAtEnd &&
    1143        3196 :                 FieldMarks.size() && (FieldMarks.front() == nCurrentIndex))
    1144             :             {
    1145             :                 // moves cursor
    1146          21 :                 xRef = lcl_ExportFieldMark(i_xParentText, pUnoCrsr, pTxtNode);
    1147          21 :                 FieldMarks.pop_front();
    1148             :             }
    1149             :         }
    1150             :         else
    1151             :         {
    1152             :             OSL_ENSURE(!FieldMarks.size() ||
    1153             :                    (FieldMarks.front() != nCurrentIndex),
    1154             :                    "fieldmark and hint with CH_TXTATR at same pos?");
    1155             :         }
    1156             : 
    1157        3781 :         if (!bAtEnd && !xRef.is() && !bCursorMoved)
    1158             :         {
    1159             :             const sal_Int32 nNextPortionIndex =
    1160        2622 :                 lcl_GetNextIndex(Bookmarks, Redlines, SoftPageBreaks);
    1161             :             const sal_Int32 nNextFieldMarkIndex(
    1162        2622 :                     FieldMarks.size() ? FieldMarks.front() : -1);
    1163             : 
    1164             :             lcl_MoveCursor(pUnoCrsr, nCurrentIndex,
    1165             :                 nFirstFrameIndex, nNextPortionIndex, nNextAttrIndex,
    1166             :                 nNextFieldMarkIndex,
    1167        2622 :                 i_nEndPos);
    1168             : 
    1169        2622 :             xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
    1170             :         }
    1171        1159 :         else if (bAtEnd && !xRef.is() && !pTxtNode->Len())
    1172             :         {
    1173             :             // special case: for an empty paragraph, we better put out a
    1174             :             // text portion because there may be a hyperlink attribute
    1175          38 :             xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
    1176             :         }
    1177             : 
    1178        3781 :         if (xRef.is())
    1179             :         {
    1180        3135 :             PortionStack.top().first->push_back(xRef);
    1181             :         }
    1182        3781 :     }
    1183             : 
    1184             :    OSL_ENSURE((PortionStack.size() == 1) && !PortionStack.top().second,
    1185         509 :             "CreatePortions: stack error" );
    1186             : }
    1187             : 
    1188         684 : void    SwXTextPortionEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
    1189             : {
    1190         684 :     ClientModify(this, pOld, pNew);
    1191         783 : }
    1192             : 
    1193             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10