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

Generated by: LCOV version 1.10