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

Generated by: LCOV version 1.10