LCOV - code coverage report
Current view: top level - sw/source/core/unocore - unotext.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 963 1274 75.6 %
Date: 2015-06-13 12:38:46 Functions: 87 101 86.1 %
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 <stdlib.h>
      21             : 
      22             : #include <memory>
      23             : #include <iostream>
      24             : #include <set>
      25             : #include <utility>
      26             : 
      27             : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
      28             : #include <com/sun/star/text/ControlCharacter.hpp>
      29             : #include <com/sun/star/text/TableColumnSeparator.hpp>
      30             : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
      31             : 
      32             : #include <osl/mutex.hxx>
      33             : #include <vcl/svapp.hxx>
      34             : #include <comphelper/sequence.hxx>
      35             : #include <comphelper/servicehelper.hxx>
      36             : #include <cppuhelper/supportsservice.hxx>
      37             : 
      38             : #include <cmdid.h>
      39             : #include <unotextbodyhf.hxx>
      40             : #include <unotext.hxx>
      41             : #include <unotextrange.hxx>
      42             : #include <unotextcursor.hxx>
      43             : #include <unosection.hxx>
      44             : #include <unobookmark.hxx>
      45             : #include <unorefmark.hxx>
      46             : #include <unoport.hxx>
      47             : #include <unotbl.hxx>
      48             : #include <unoidx.hxx>
      49             : #include <unocoll.hxx>
      50             : #include <unoframe.hxx>
      51             : #include <unofield.hxx>
      52             : #include <unometa.hxx>
      53             : #include <unodraw.hxx>
      54             : #include <unoredline.hxx>
      55             : #include <unomap.hxx>
      56             : #include <unoprnms.hxx>
      57             : #include <unoparagraph.hxx>
      58             : #include <unocrsrhelper.hxx>
      59             : #include <docsh.hxx>
      60             : #include <docary.hxx>
      61             : #include <doc.hxx>
      62             : #include <IDocumentUndoRedo.hxx>
      63             : #include <redline.hxx>
      64             : #include <swundo.hxx>
      65             : #include <section.hxx>
      66             : #include <IMark.hxx>
      67             : #include <fmtanchr.hxx>
      68             : #include <fmtcntnt.hxx>
      69             : #include <crsskip.hxx>
      70             : #include <ndtxt.hxx>
      71             : 
      72             : using namespace ::com::sun::star;
      73             : 
      74             : const sal_Char cInvalidObject[] = "this object is invalid";
      75             : 
      76             : class SwXText::Impl
      77             : {
      78             : 
      79             : public:
      80             :     SwXText &                   m_rThis;
      81             :     SfxItemPropertySet const&   m_rPropSet;
      82             :     const enum CursorType       m_eType;
      83             :     SwDoc *                     m_pDoc;
      84             :     bool                        m_bIsValid;
      85             : 
      86       29242 :     Impl(   SwXText & rThis,
      87             :             SwDoc *const pDoc, const enum CursorType eType)
      88             :         : m_rThis(rThis)
      89       29242 :         , m_rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT))
      90             :         , m_eType(eType)
      91             :         , m_pDoc(pDoc)
      92       58484 :         , m_bIsValid(0 != pDoc)
      93             :     {
      94       29242 :     }
      95             : 
      96             :     uno::Reference< text::XTextRange >
      97             :         finishOrAppendParagraph(
      98             :             const bool bFinish,
      99             :             const uno::Sequence< beans::PropertyValue >&
     100             :                 rCharacterAndParagraphProperties,
     101             :             const uno::Reference< text::XTextRange >& xInsertPosition)
     102             :         throw (lang::IllegalArgumentException, uno::RuntimeException);
     103             : 
     104             :     sal_Int16 ComparePositions(
     105             :             const uno::Reference<text::XTextRange>& xPos1,
     106             :             const uno::Reference<text::XTextRange>& xPos2)
     107             :         throw (lang::IllegalArgumentException, uno::RuntimeException);
     108             : 
     109             :     bool CheckForOwnMember(const SwPaM & rPaM)
     110             :         throw (lang::IllegalArgumentException, uno::RuntimeException);
     111             : 
     112             :     void ConvertCell(
     113             :             const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
     114             :             ::std::vector<SwNodeRange> & rRowNodes,
     115             :             SwNodeRange *const pLastCell,
     116             :             bool & rbExcept);
     117             : 
     118             : };
     119             : 
     120       29242 : SwXText::SwXText(SwDoc *const pDoc, const enum CursorType eType)
     121       29242 :     : m_pImpl( new SwXText::Impl(*this, pDoc, eType) )
     122             : {
     123       29242 : }
     124             : 
     125       29239 : SwXText::~SwXText()
     126             : {
     127       29239 : }
     128             : 
     129       68018 : const SwDoc * SwXText::GetDoc() const
     130             : {
     131       68018 :     return m_pImpl->m_pDoc;
     132             : }
     133      590050 :       SwDoc * SwXText::GetDoc()
     134             : {
     135      590050 :     return m_pImpl->m_pDoc;
     136             : }
     137             : 
     138      200488 : bool SwXText::IsValid() const
     139             : {
     140      200488 :     return m_pImpl->m_bIsValid;
     141             : }
     142             : 
     143          91 : void SwXText::Invalidate()
     144             : {
     145          91 :     m_pImpl->m_bIsValid = false;
     146          91 : }
     147             : 
     148        1017 : void SwXText::SetDoc(SwDoc *const pDoc)
     149             : {
     150             :     OSL_ENSURE(!m_pImpl->m_pDoc || !pDoc,
     151             :         "SwXText::SetDoc: already have a doc?");
     152        1017 :     m_pImpl->m_pDoc = pDoc;
     153        1017 :     m_pImpl->m_bIsValid = (0 != pDoc);
     154        1017 : }
     155             : 
     156             : void
     157           0 : SwXText::PrepareForAttach(uno::Reference< text::XTextRange > &, const SwPaM &)
     158             : {
     159           0 : }
     160             : 
     161       15995 : bool SwXText::CheckForOwnMemberMeta(const SwPaM &, const bool)
     162             :     throw (lang::IllegalArgumentException, uno::RuntimeException)
     163             : {
     164             :     OSL_ENSURE(CURSOR_META != m_pImpl->m_eType, "should not be called!");
     165       15995 :     return false;
     166             : }
     167             : 
     168       68018 : const SwStartNode *SwXText::GetStartNode() const
     169             : {
     170       68018 :     return GetDoc()->GetNodes().GetEndOfContent().StartOfSectionNode();
     171             : }
     172             : 
     173             : uno::Reference< text::XTextCursor >
     174      100061 : SwXText::CreateCursor() throw (uno::RuntimeException)
     175             : {
     176      100061 :     uno::Reference< text::XTextCursor >  xRet;
     177      100061 :     if(IsValid())
     178             :     {
     179      100061 :         SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
     180      100061 :         SwPosition aPos(rNode);
     181             :         xRet = static_cast<text::XWordCursor*>(
     182      100061 :                 new SwXTextCursor(*GetDoc(), this, m_pImpl->m_eType, aPos));
     183      100061 :         xRet->gotoStart(sal_False);
     184             :     }
     185      100061 :     return xRet;
     186             : }
     187             : 
     188             : uno::Any SAL_CALL
     189       43879 : SwXText::queryInterface(const uno::Type& rType) throw (uno::RuntimeException, std::exception)
     190             : {
     191       43879 :     uno::Any aRet;
     192       43879 :     if (rType == cppu::UnoType<text::XText>::get())
     193             :     {
     194       17202 :         aRet <<= uno::Reference< text::XText >(this);
     195             :     }
     196       26677 :     else if (rType == cppu::UnoType<text::XSimpleText>::get())
     197             :     {
     198           3 :         aRet <<= uno::Reference< text::XSimpleText >(this);
     199             :     }
     200       26674 :     else if (rType == cppu::UnoType<text::XTextRange>::get())
     201             :     {
     202        1123 :         aRet <<= uno::Reference< text::XTextRange>(this);
     203             :     }
     204       25551 :     else if (rType == cppu::UnoType<text::XTextRangeCompare>::get())
     205             :     {
     206         350 :         aRet <<= uno::Reference< text::XTextRangeCompare >(this);
     207             :     }
     208       25201 :     else if (rType == cppu::UnoType<lang::XTypeProvider>::get())
     209             :     {
     210           9 :         aRet <<= uno::Reference< lang::XTypeProvider >(this);
     211             :     }
     212       25192 :     else if (rType == cppu::UnoType<text::XRelativeTextContentInsert>::get())
     213             :     {
     214           4 :         aRet <<= uno::Reference< text::XRelativeTextContentInsert >(this);
     215             :     }
     216       25188 :     else if (rType == cppu::UnoType<text::XRelativeTextContentRemove>::get())
     217             :     {
     218           0 :         aRet <<= uno::Reference< text::XRelativeTextContentRemove >(this);
     219             :     }
     220       25188 :     else if (rType == cppu::UnoType<beans::XPropertySet>::get())
     221             :     {
     222         130 :         aRet <<= uno::Reference< beans::XPropertySet >(this);
     223             :     }
     224       25058 :     else if (rType == cppu::UnoType<lang::XUnoTunnel>::get())
     225             :     {
     226        3298 :         aRet <<= uno::Reference< lang::XUnoTunnel >(this);
     227             :     }
     228       21760 :     else if (rType == cppu::UnoType<text::XTextAppendAndConvert>::get())
     229             :     {
     230        7969 :         aRet <<= uno::Reference< text::XTextAppendAndConvert >(this);
     231             :     }
     232       13791 :     else if (rType == cppu::UnoType<text::XTextAppend>::get())
     233             :     {
     234        3654 :         aRet <<= uno::Reference< text::XTextAppend >(this);
     235             :     }
     236       10137 :     else if (rType == cppu::UnoType<text::XTextPortionAppend>::get())
     237             :     {
     238           0 :         aRet <<= uno::Reference< text::XTextPortionAppend >(this);
     239             :     }
     240       10137 :     else if (rType == cppu::UnoType<text::XParagraphAppend>::get())
     241             :     {
     242          41 :         aRet <<= uno::Reference< text::XParagraphAppend >(this);
     243             :     }
     244       10096 :     else if (rType == cppu::UnoType<text::XTextConvert>::get() )
     245             :     {
     246           0 :         aRet <<= uno::Reference< text::XTextConvert >(this);
     247             :     }
     248       10096 :     else if (rType == cppu::UnoType<text::XTextContentAppend>::get())
     249             :     {
     250         452 :         aRet <<= uno::Reference< text::XTextContentAppend >(this);
     251             :     }
     252        9644 :     else if(rType == cppu::UnoType<text::XTextCopy>::get())
     253             :     {
     254         162 :         aRet <<= uno::Reference< text::XTextCopy >( this );
     255             :     }
     256       43879 :     return aRet;
     257             : }
     258             : 
     259             : uno::Sequence< uno::Type > SAL_CALL
     260          19 : SwXText::getTypes() throw (uno::RuntimeException, std::exception)
     261             : {
     262          19 :     uno::Sequence< uno::Type > aRet(12);
     263          19 :     uno::Type* pTypes = aRet.getArray();
     264          19 :     pTypes[0] = cppu::UnoType<text::XText>::get();
     265          19 :     pTypes[1] = cppu::UnoType<text::XTextRangeCompare>::get();
     266          19 :     pTypes[2] = cppu::UnoType<text::XRelativeTextContentInsert>::get();
     267          19 :     pTypes[3] = cppu::UnoType<text::XRelativeTextContentRemove>::get();
     268          19 :     pTypes[4] = cppu::UnoType<lang::XUnoTunnel>::get();
     269          19 :     pTypes[5] = cppu::UnoType<beans::XPropertySet>::get();
     270          19 :     pTypes[6] = cppu::UnoType<text::XTextPortionAppend>::get();
     271          19 :     pTypes[7] = cppu::UnoType<text::XParagraphAppend>::get();
     272          19 :     pTypes[8] = cppu::UnoType<text::XTextContentAppend>::get();
     273          19 :     pTypes[9] = cppu::UnoType<text::XTextConvert>::get();
     274          19 :     pTypes[10] = cppu::UnoType<text::XTextAppend>::get();
     275          19 :     pTypes[11] = cppu::UnoType<text::XTextAppendAndConvert>::get();
     276             : 
     277          19 :     return aRet;
     278             : }
     279             : 
     280             : // belongs the range in the text ? insert it then.
     281             : void SAL_CALL
     282       35088 : SwXText::insertString(const uno::Reference< text::XTextRange >& xTextRange,
     283             :     const OUString& rString, sal_Bool bAbsorb)
     284             : throw (uno::RuntimeException, std::exception)
     285             : {
     286       35088 :     SolarMutexGuard aGuard;
     287             : 
     288       35088 :     if (!xTextRange.is())
     289             :     {
     290           1 :         throw uno::RuntimeException();
     291             :     }
     292       35087 :     if (!GetDoc())
     293             :     {
     294           0 :         throw uno::RuntimeException();
     295             :     }
     296             :     const uno::Reference<lang::XUnoTunnel> xRangeTunnel(xTextRange,
     297       70174 :             uno::UNO_QUERY);
     298             :     SwXTextRange *const pRange =
     299       35087 :         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
     300             :     OTextCursorHelper *const pCursor =
     301       35087 :         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
     302       35087 :     if ((!pRange  || pRange ->GetDoc() != GetDoc()) &&
     303       35087 :         (!pCursor || pCursor->GetDoc() != GetDoc()))
     304             :     {
     305           0 :         throw uno::RuntimeException();
     306             :     }
     307             : 
     308       35087 :     const SwStartNode *const pOwnStartNode = GetStartNode();
     309       70174 :     SwPaM aPam(GetDoc()->GetNodes());
     310       35087 :     const SwPaM * pPam(0);
     311       35087 :     if (pCursor)
     312             :     {
     313       35087 :         pPam = pCursor->GetPaM();
     314             :     }
     315             :     else // pRange
     316             :     {
     317           0 :         if (pRange->GetPositions(aPam))
     318             :         {
     319           0 :             pPam = &aPam;
     320             :         }
     321             :     }
     322       35087 :     if (!pPam)
     323             :     {
     324           0 :         throw uno::RuntimeException();
     325             :     }
     326             : 
     327       35087 :     const SwStartNode* pTmp(pPam->GetNode().StartOfSectionNode());
     328       71305 :     while (pTmp && pTmp->IsSectionNode())
     329             :     {
     330        1131 :         pTmp = pTmp->StartOfSectionNode();
     331             :     }
     332       35087 :     if (!pOwnStartNode || (pOwnStartNode != pTmp))
     333             :     {
     334           0 :         throw uno::RuntimeException();
     335             :     }
     336             : 
     337       35087 :     bool bForceExpandHints( false );
     338       35087 :     if (CURSOR_META == m_pImpl->m_eType)
     339             :     {
     340             :         try
     341             :         {
     342           3 :             bForceExpandHints = CheckForOwnMemberMeta(*pPam, bAbsorb);
     343             :         }
     344           1 :         catch (const lang::IllegalArgumentException& iae)
     345             :         {
     346             :             // stupid method not allowed to throw iae
     347           1 :             throw uno::RuntimeException(iae.Message, 0);
     348             :         }
     349             :     }
     350       35086 :     if (bAbsorb)
     351             :     {
     352             :         //!! scan for CR characters and inserting the paragraph breaks
     353             :         //!! has to be done in the called function.
     354             :         //!! Implemented in SwXTextRange::DeleteAndInsert
     355         292 :         if (pCursor)
     356             :         {
     357             :             SwXTextCursor * const pTextCursor(
     358         292 :                 dynamic_cast<SwXTextCursor*>(pCursor) );
     359         292 :             if (pTextCursor)
     360             :             {
     361         292 :                 pTextCursor->DeleteAndInsert(rString, bForceExpandHints);
     362             :             }
     363             :             else
     364             :             {
     365           0 :                 xTextRange->setString(rString);
     366             :             }
     367             :         }
     368             :         else
     369             :         {
     370           0 :             pRange->DeleteAndInsert(rString, bForceExpandHints);
     371             :         }
     372             :     }
     373             :     else
     374             :     {
     375             :         // create a PaM positioned before the parameter PaM,
     376             :         // so the text is inserted before
     377       34794 :         UnoActionContext aContext(GetDoc());
     378       69588 :         SwPaM aInsertPam(*pPam->Start());
     379       69588 :         ::sw::GroupUndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo());
     380             :         SwUnoCursorHelper::DocInsertStringSplitCR(
     381       69588 :             *GetDoc(), aInsertPam, rString, bForceExpandHints );
     382       35088 :     }
     383       35086 : }
     384             : 
     385             : void SAL_CALL
     386        5546 : SwXText::insertControlCharacter(
     387             :         const uno::Reference< text::XTextRange > & xTextRange,
     388             :         sal_Int16 nControlCharacter, sal_Bool bAbsorb)
     389             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     390             : {
     391        5546 :     SolarMutexGuard aGuard;
     392             : 
     393        5546 :     if (!xTextRange.is())
     394             :     {
     395           1 :         throw lang::IllegalArgumentException();
     396             :     }
     397        5545 :     if (!GetDoc())
     398             :     {
     399           0 :         throw uno::RuntimeException();
     400             :     }
     401             : 
     402       11090 :     SwUnoInternalPaM aPam(*GetDoc());
     403        5545 :     if (!::sw::XTextRangeToSwPaM(aPam, xTextRange))
     404             :     {
     405           0 :         throw uno::RuntimeException();
     406             :     }
     407        5545 :     const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
     408             : 
     409             :     const SwInsertFlags nInsertFlags =
     410             :         bForceExpandHints
     411        5546 :         ? ( SwInsertFlags::FORCEHINTEXPAND | SwInsertFlags::EMPTYEXPAND)
     412       11088 :         : SwInsertFlags::EMPTYEXPAND;
     413             : 
     414        5544 :     if (bAbsorb && aPam.HasMark())
     415             :     {
     416           0 :         m_pImpl->m_pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
     417           0 :         aPam.DeleteMark();
     418             :     }
     419             : 
     420        5544 :     sal_Unicode cIns = 0;
     421        5544 :     switch (nControlCharacter)
     422             :     {
     423             :         case text::ControlCharacter::PARAGRAPH_BREAK :
     424             :             // a table cell now becomes an ordinary text cell!
     425         160 :             m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->nNode);
     426         160 :             m_pImpl->m_pDoc->getIDocumentContentOperations().SplitNode(*aPam.GetPoint(), false);
     427         160 :             break;
     428             :         case text::ControlCharacter::APPEND_PARAGRAPH:
     429             :         {
     430        4807 :             m_pImpl->m_pDoc->ClearBoxNumAttrs(aPam.GetPoint()->nNode);
     431        4807 :             m_pImpl->m_pDoc->getIDocumentContentOperations().AppendTextNode(*aPam.GetPoint());
     432             : 
     433             :             const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
     434        4807 :                     xTextRange, uno::UNO_QUERY);
     435             :             SwXTextRange *const pRange =
     436        4807 :                 ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
     437             :             OTextCursorHelper *const pCursor =
     438             :                 ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(
     439        4807 :                             xRangeTunnel);
     440        4807 :             if (pRange)
     441             :             {
     442           0 :                 pRange->SetPositions(aPam);
     443             :             }
     444        4807 :             else if (pCursor)
     445             :             {
     446        4807 :                 SwPaM *const pCrsr = pCursor->GetPaM();
     447        4807 :                 *pCrsr->GetPoint() = *aPam.GetPoint();
     448        4807 :                 pCrsr->DeleteMark();
     449        4807 :             }
     450             :         }
     451        4807 :         break;
     452         575 :         case text::ControlCharacter::LINE_BREAK:  cIns = 10;              break;
     453           0 :         case text::ControlCharacter::SOFT_HYPHEN: cIns = CHAR_SOFTHYPHEN; break;
     454           2 :         case text::ControlCharacter::HARD_HYPHEN: cIns = CHAR_HARDHYPHEN; break;
     455           0 :         case text::ControlCharacter::HARD_SPACE:  cIns = CHAR_HARDBLANK;  break;
     456             :     }
     457        5544 :     if (cIns)
     458             :     {
     459         577 :         m_pImpl->m_pDoc->getIDocumentContentOperations().InsertString(
     460         577 :                 aPam, OUString(cIns), nInsertFlags);
     461             :     }
     462             : 
     463        5544 :     if (bAbsorb)
     464             :     {
     465             :         const uno::Reference<lang::XUnoTunnel> xRangeTunnel(
     466           0 :                 xTextRange, uno::UNO_QUERY);
     467             :         SwXTextRange *const pRange =
     468           0 :             ::sw::UnoTunnelGetImplementation<SwXTextRange>(xRangeTunnel);
     469             :         OTextCursorHelper *const pCursor =
     470           0 :             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xRangeTunnel);
     471             : 
     472           0 :         SwCursor aCrsr(*aPam.GetPoint(), 0, false);
     473           0 :         SwUnoCursorHelper::SelectPam(aCrsr, true);
     474           0 :         aCrsr.Left(1, CRSR_SKIP_CHARS, false, false);
     475             :         // here, the PaM needs to be moved:
     476           0 :         if (pRange)
     477             :         {
     478           0 :             pRange->SetPositions(aCrsr);
     479             :         }
     480             :         else
     481             :         {
     482           0 :             SwPaM *const pUnoCrsr = pCursor->GetPaM();
     483           0 :             *pUnoCrsr->GetPoint() = *aCrsr.GetPoint();
     484           0 :             if (aCrsr.HasMark())
     485             :             {
     486           0 :                 pUnoCrsr->SetMark();
     487           0 :                 *pUnoCrsr->GetMark() = *aCrsr.GetMark();
     488             :             }
     489             :             else
     490             :             {
     491           0 :                 pUnoCrsr->DeleteMark();
     492             :             }
     493           0 :         }
     494        5546 :     }
     495        5544 : }
     496             : 
     497             : void SAL_CALL
     498       10502 : SwXText::insertTextContent(
     499             :         const uno::Reference< text::XTextRange > & xRange,
     500             :         const uno::Reference< text::XTextContent > & xContent,
     501             :         sal_Bool bAbsorb)
     502             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     503             : {
     504       10502 :     SolarMutexGuard aGuard;
     505             : 
     506       10502 :     if (!xRange.is())
     507             :     {
     508           1 :         lang::IllegalArgumentException aIllegal;
     509           1 :         aIllegal.Message = "first parameter invalid;";
     510           1 :         throw aIllegal;
     511             :     }
     512       10501 :     if (!xContent.is())
     513             :     {
     514           7 :         lang::IllegalArgumentException aIllegal;
     515           7 :         aIllegal.Message = "second parameter invalid";
     516           7 :         throw aIllegal;
     517             :     }
     518       10494 :     if(!GetDoc())
     519             :     {
     520           0 :         uno::RuntimeException aRuntime;
     521           0 :         aRuntime.Message = cInvalidObject;
     522           0 :         throw aRuntime;
     523             :     }
     524             : 
     525       20988 :     SwUnoInternalPaM aPam(*GetDoc());
     526       10494 :     if (!::sw::XTextRangeToSwPaM(aPam, xRange))
     527             :     {
     528           0 :         lang::IllegalArgumentException aIllegal;
     529           0 :         aIllegal.Message = "first parameter invalid";
     530           0 :         throw aIllegal;
     531             :     }
     532             :     // first test if the range is at the right position, then call
     533             :     // xContent->attach
     534       10494 :     const SwStartNode* pOwnStartNode = GetStartNode();
     535       10494 :     SwStartNodeType eSearchNodeType = SwNormalStartNode;
     536       10494 :     switch (m_pImpl->m_eType)
     537             :     {
     538         370 :         case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
     539          64 :         case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
     540          29 :         case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
     541         290 :         case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
     542         364 :         case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
     543             :         //case CURSOR_INVALID:
     544             :         //case CURSOR_BODY:
     545             :         default:
     546        9377 :             break;
     547             :     }
     548             : 
     549             :     const SwStartNode* pTmp =
     550       10494 :         aPam.GetNode().FindSttNodeByType(eSearchNodeType);
     551             : 
     552             :     // ignore SectionNodes
     553       21146 :     while (pTmp && pTmp->IsSectionNode())
     554             :     {
     555         158 :         pTmp = pTmp->StartOfSectionNode();
     556             :     }
     557             :     // if the document starts with a section
     558       20988 :     while (pOwnStartNode->IsSectionNode())
     559             :     {
     560           0 :         pOwnStartNode = pOwnStartNode->StartOfSectionNode();
     561             :     }
     562             :     // this checks if (this) and xRange are in the same text::XText interface
     563       10494 :     if (pOwnStartNode != pTmp)
     564             :     {
     565           0 :         uno::RuntimeException aRunException;
     566           0 :         aRunException.Message = "text interface and cursor not related";
     567           0 :         throw aRunException;
     568             :     }
     569             : 
     570       10494 :     const bool bForceExpandHints(CheckForOwnMemberMeta(aPam, bAbsorb));
     571             : 
     572             :     // special treatment for Contents that do not replace the range, but
     573             :     // instead are "overlaid"
     574             :     const uno::Reference<lang::XUnoTunnel> xContentTunnel(xContent,
     575       10493 :             uno::UNO_QUERY);
     576       10493 :     if (!xContentTunnel.is())
     577             :     {
     578           0 :         lang::IllegalArgumentException aArgException;
     579           0 :         aArgException.Message = "text content does not support lang::XUnoTunnel";
     580           0 :         throw aArgException;
     581             :     }
     582             :     SwXDocumentIndexMark *const pDocumentIndexMark =
     583       10493 :         ::sw::UnoTunnelGetImplementation<SwXDocumentIndexMark>(xContentTunnel);
     584             :     SwXTextSection *const pSection =
     585       10493 :         ::sw::UnoTunnelGetImplementation<SwXTextSection>(xContentTunnel);
     586             :     SwXBookmark *const pBookmark =
     587       10493 :         ::sw::UnoTunnelGetImplementation<SwXBookmark>(xContentTunnel);
     588             :     SwXReferenceMark *const pReferenceMark =
     589       10493 :         ::sw::UnoTunnelGetImplementation<SwXReferenceMark>(xContentTunnel);
     590             :     SwXMeta *const pMeta =
     591       10493 :         ::sw::UnoTunnelGetImplementation<SwXMeta>(xContentTunnel);
     592             :     SwXTextField* pTextField =
     593       10493 :         ::sw::UnoTunnelGetImplementation<SwXTextField>(xContentTunnel);
     594       10493 :     if (pTextField && pTextField->GetServiceId() != SW_SERVICE_FIELDTYPE_ANNOTATION)
     595         655 :         pTextField = 0;
     596             : 
     597        5645 :     const bool bAttribute = pBookmark || pDocumentIndexMark
     598       15996 :         || pSection || pReferenceMark || pMeta || pTextField;
     599             : 
     600       10493 :     if (bAbsorb && !bAttribute)
     601             :     {
     602          11 :         xRange->setString(OUString());
     603             :     }
     604             :     uno::Reference< text::XTextRange > xTempRange =
     605       20986 :         (bAttribute && bAbsorb) ? xRange : xRange->getStart();
     606       10493 :     if (bForceExpandHints)
     607             :     {
     608             :         // if necessary, replace xTempRange with a new SwXTextCursor
     609          20 :         PrepareForAttach(xTempRange, aPam);
     610             :     }
     611       31488 :     xContent->attach(xTempRange);
     612        7666 : }
     613             : 
     614             : void SAL_CALL
     615           4 : SwXText::insertTextContentBefore(
     616             :     const uno::Reference< text::XTextContent>& xNewContent,
     617             :     const uno::Reference< text::XTextContent>& xSuccessor)
     618             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     619             : {
     620           4 :     SolarMutexGuard aGuard;
     621             : 
     622           4 :     if(!GetDoc())
     623             :     {
     624           0 :         uno::RuntimeException aRuntime;
     625           0 :         aRuntime.Message = cInvalidObject;
     626           0 :         throw aRuntime;
     627             :     }
     628             : 
     629             :     const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
     630           8 :             uno::UNO_QUERY);
     631             :     SwXParagraph *const pPara =
     632           4 :             ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
     633           4 :     if (!pPara || !pPara->IsDescriptor() || !xSuccessor.is())
     634             :     {
     635           0 :         throw lang::IllegalArgumentException();
     636             :     }
     637             : 
     638           4 :     bool bRet = false;
     639             :     const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
     640           8 :             uno::UNO_QUERY);
     641             :     SwXTextSection *const pXSection =
     642           4 :             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
     643             :     SwXTextTable *const pXTable =
     644           4 :             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
     645           4 :     SwFrameFormat *const pTableFormat = (pXTable) ? pXTable->GetFrameFormat() : 0;
     646           4 :     SwTextNode * pTextNode = 0;
     647           4 :     if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
     648             :     {
     649           2 :         SwTable *const pTable = SwTable::FindTable( pTableFormat );
     650           2 :         SwTableNode *const pTableNode = pTable->GetTableNode();
     651             : 
     652           2 :         const SwNodeIndex aTableIdx( *pTableNode, -1 );
     653           4 :         SwPosition aBefore(aTableIdx);
     654           2 :         bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore );
     655           4 :         pTextNode = aBefore.nNode.GetNode().GetTextNode();
     656             :     }
     657           4 :     else if (pXSection && pXSection->GetFormat() &&
     658           2 :             pXSection->GetFormat()->GetDoc() == GetDoc())
     659             :     {
     660           2 :         SwSectionFormat *const pSectFormat = pXSection->GetFormat();
     661           2 :         SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
     662             : 
     663           2 :         const SwNodeIndex aSectIdx( *pSectNode, -1 );
     664           4 :         SwPosition aBefore(aSectIdx);
     665           2 :         bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore );
     666           4 :         pTextNode = aBefore.nNode.GetNode().GetTextNode();
     667             :     }
     668           4 :     if (!bRet || !pTextNode)
     669             :     {
     670           0 :         throw lang::IllegalArgumentException();
     671             :     }
     672           8 :     pPara->attachToText(*this, *pTextNode);
     673           4 : }
     674             : 
     675             : void SAL_CALL
     676           4 : SwXText::insertTextContentAfter(
     677             :     const uno::Reference< text::XTextContent>& xNewContent,
     678             :     const uno::Reference< text::XTextContent>& xPredecessor)
     679             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     680             : {
     681           4 :     SolarMutexGuard aGuard;
     682             : 
     683           4 :     if(!GetDoc())
     684             :     {
     685           0 :         throw uno::RuntimeException();
     686             :     }
     687             : 
     688             :     const uno::Reference<lang::XUnoTunnel> xParaTunnel(xNewContent,
     689           8 :             uno::UNO_QUERY);
     690             :     SwXParagraph *const pPara =
     691           4 :             ::sw::UnoTunnelGetImplementation<SwXParagraph>(xParaTunnel);
     692           4 :     if(!pPara || !pPara->IsDescriptor() || !xPredecessor.is())
     693             :     {
     694           0 :         throw lang::IllegalArgumentException();
     695             :     }
     696             : 
     697             :     const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
     698           8 :             uno::UNO_QUERY);
     699             :     SwXTextSection *const pXSection =
     700           4 :             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
     701             :     SwXTextTable *const pXTable =
     702           4 :             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
     703           4 :     SwFrameFormat *const pTableFormat = (pXTable) ? pXTable->GetFrameFormat() : 0;
     704           4 :     bool bRet = false;
     705           4 :     SwTextNode * pTextNode = 0;
     706           4 :     if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
     707             :     {
     708           2 :         SwTable *const pTable = SwTable::FindTable( pTableFormat );
     709           2 :         SwTableNode *const pTableNode = pTable->GetTableNode();
     710             : 
     711           2 :         SwEndNode *const pTableEnd = pTableNode->EndOfSectionNode();
     712           2 :         SwPosition aTableEnd(*pTableEnd);
     713           2 :         bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aTableEnd );
     714           2 :         pTextNode = aTableEnd.nNode.GetNode().GetTextNode();
     715             :     }
     716           4 :     else if (pXSection && pXSection->GetFormat() &&
     717           2 :             pXSection->GetFormat()->GetDoc() == GetDoc())
     718             :     {
     719           2 :         SwSectionFormat *const pSectFormat = pXSection->GetFormat();
     720           2 :         SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
     721           2 :         SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
     722           2 :         SwPosition aEnd(*pEnd);
     723           2 :         bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aEnd );
     724           2 :         pTextNode = aEnd.nNode.GetNode().GetTextNode();
     725             :     }
     726           4 :     if (!bRet || !pTextNode)
     727             :     {
     728           0 :         throw lang::IllegalArgumentException();
     729             :     }
     730           8 :     pPara->attachToText(*this, *pTextNode);
     731           4 : }
     732             : 
     733             : void SAL_CALL
     734           0 : SwXText::removeTextContentBefore(
     735             :     const uno::Reference< text::XTextContent>& xSuccessor)
     736             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     737             : {
     738           0 :     SolarMutexGuard aGuard;
     739             : 
     740           0 :     if(!GetDoc())
     741             :     {
     742           0 :         uno::RuntimeException aRuntime;
     743           0 :         aRuntime.Message = cInvalidObject;
     744           0 :         throw aRuntime;
     745             :     }
     746             : 
     747           0 :     bool bRet = false;
     748             :     const uno::Reference<lang::XUnoTunnel> xSuccTunnel(xSuccessor,
     749           0 :             uno::UNO_QUERY);
     750             :     SwXTextSection *const pXSection =
     751           0 :             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xSuccTunnel);
     752             :     SwXTextTable *const pXTable =
     753           0 :             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xSuccTunnel);
     754           0 :     SwFrameFormat *const pTableFormat = (pXTable) ? pXTable->GetFrameFormat() : 0;
     755           0 :     if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
     756             :     {
     757           0 :         SwTable *const pTable = SwTable::FindTable( pTableFormat );
     758           0 :         SwTableNode *const pTableNode = pTable->GetTableNode();
     759             : 
     760           0 :         const SwNodeIndex aTableIdx( *pTableNode, -1 );
     761           0 :         if(aTableIdx.GetNode().IsTextNode())
     762             :         {
     763           0 :             SwPaM aBefore(aTableIdx);
     764           0 :             bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aBefore );
     765           0 :         }
     766             :     }
     767           0 :     else if (pXSection && pXSection->GetFormat() &&
     768           0 :             pXSection->GetFormat()->GetDoc() == GetDoc())
     769             :     {
     770           0 :         SwSectionFormat *const pSectFormat = pXSection->GetFormat();
     771           0 :         SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
     772             : 
     773           0 :         const SwNodeIndex aSectIdx(  *pSectNode, -1 );
     774           0 :         if(aSectIdx.GetNode().IsTextNode())
     775             :         {
     776           0 :             SwPaM aBefore(aSectIdx);
     777           0 :             bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aBefore );
     778           0 :         }
     779             :     }
     780           0 :     if(!bRet)
     781             :     {
     782           0 :         throw lang::IllegalArgumentException();
     783           0 :     }
     784           0 : }
     785             : 
     786             : void SAL_CALL
     787           0 : SwXText::removeTextContentAfter(
     788             :         const uno::Reference< text::XTextContent>& xPredecessor)
     789             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     790             : {
     791           0 :     SolarMutexGuard aGuard;
     792             : 
     793           0 :     if(!GetDoc())
     794             :     {
     795           0 :         uno::RuntimeException aRuntime;
     796           0 :         aRuntime.Message = cInvalidObject;
     797           0 :         throw aRuntime;
     798             :     }
     799             : 
     800           0 :     bool bRet = false;
     801             :     const uno::Reference<lang::XUnoTunnel> xPredTunnel(xPredecessor,
     802           0 :             uno::UNO_QUERY);
     803             :     SwXTextSection *const pXSection =
     804           0 :             ::sw::UnoTunnelGetImplementation<SwXTextSection>(xPredTunnel);
     805             :     SwXTextTable *const pXTable =
     806           0 :             ::sw::UnoTunnelGetImplementation<SwXTextTable>(xPredTunnel);
     807           0 :     SwFrameFormat *const pTableFormat = (pXTable) ? pXTable->GetFrameFormat() : 0;
     808           0 :     if(pTableFormat && pTableFormat->GetDoc() == GetDoc())
     809             :     {
     810           0 :         SwTable *const pTable = SwTable::FindTable( pTableFormat );
     811           0 :         SwTableNode *const pTableNode = pTable->GetTableNode();
     812           0 :         SwEndNode *const pTableEnd = pTableNode->EndOfSectionNode();
     813             : 
     814           0 :         const SwNodeIndex aTableIdx( *pTableEnd, 1 );
     815           0 :         if(aTableIdx.GetNode().IsTextNode())
     816             :         {
     817           0 :             SwPaM aPaM(aTableIdx);
     818           0 :             bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aPaM );
     819           0 :         }
     820             :     }
     821           0 :     else if (pXSection && pXSection->GetFormat() &&
     822           0 :             pXSection->GetFormat()->GetDoc() == GetDoc())
     823             :     {
     824           0 :         SwSectionFormat *const pSectFormat = pXSection->GetFormat();
     825           0 :         SwSectionNode *const pSectNode = pSectFormat->GetSectionNode();
     826           0 :         SwEndNode *const pEnd = pSectNode->EndOfSectionNode();
     827           0 :         const SwNodeIndex aSectIdx(  *pEnd, 1 );
     828           0 :         if(aSectIdx.GetNode().IsTextNode())
     829             :         {
     830           0 :             SwPaM aAfter(aSectIdx);
     831           0 :             bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( aAfter );
     832           0 :         }
     833             :     }
     834           0 :     if(!bRet)
     835             :     {
     836           0 :         throw lang::IllegalArgumentException();
     837           0 :     }
     838           0 : }
     839             : 
     840             : void SAL_CALL
     841           8 : SwXText::removeTextContent(
     842             :         const uno::Reference< text::XTextContent > & xContent)
     843             : throw (container::NoSuchElementException, uno::RuntimeException, std::exception)
     844             : {
     845             :     // forward: need no solar mutex here
     846           8 :     if(!xContent.is())
     847             :     {
     848           1 :         uno::RuntimeException aRuntime;
     849           1 :         aRuntime.Message = "first parameter invalid";
     850           1 :         throw aRuntime;
     851             :     }
     852           7 :     xContent->dispose();
     853           7 : }
     854             : 
     855             : uno::Reference< text::XText > SAL_CALL
     856        1491 : SwXText::getText() throw (uno::RuntimeException, std::exception)
     857             : {
     858        1491 :     SolarMutexGuard aGuard;
     859             : 
     860        1491 :     const uno::Reference< text::XText > xRet(this);
     861        1491 :     return xRet;
     862             : }
     863             : 
     864             : uno::Reference< text::XTextRange > SAL_CALL
     865         513 : SwXText::getStart() throw (uno::RuntimeException, std::exception)
     866             : {
     867         513 :     SolarMutexGuard aGuard;
     868             : 
     869        1026 :     const uno::Reference< text::XTextCursor > xRef = CreateCursor();
     870         513 :     if(!xRef.is())
     871             :     {
     872           0 :         uno::RuntimeException aRuntime;
     873           0 :         aRuntime.Message = cInvalidObject;
     874           0 :         throw aRuntime;
     875             :     }
     876         513 :     xRef->gotoStart(sal_False);
     877         513 :     const uno::Reference< text::XTextRange > xRet(xRef, uno::UNO_QUERY);
     878        1026 :     return xRet;
     879             : }
     880             : 
     881             : uno::Reference< text::XTextRange > SAL_CALL
     882       59495 : SwXText::getEnd() throw (uno::RuntimeException, std::exception)
     883             : {
     884       59495 :     SolarMutexGuard aGuard;
     885             : 
     886      118990 :     const uno::Reference< text::XTextCursor > xRef = CreateCursor();
     887       59495 :     if(!xRef.is())
     888             :     {
     889           0 :         uno::RuntimeException aRuntime;
     890           0 :         aRuntime.Message = cInvalidObject;
     891           0 :         throw aRuntime;
     892             :     }
     893       59495 :     xRef->gotoEnd(sal_False);
     894       59495 :     const uno::Reference< text::XTextRange >  xRet(xRef, uno::UNO_QUERY);
     895      118990 :     return xRet;
     896             : }
     897             : 
     898         551 : OUString SAL_CALL SwXText::getString() throw (uno::RuntimeException, std::exception)
     899             : {
     900         551 :     SolarMutexGuard aGuard;
     901             : 
     902        1102 :     const uno::Reference< text::XTextCursor > xRet = CreateCursor();
     903         551 :     if(!xRet.is())
     904             :     {
     905           0 :         uno::RuntimeException aRuntime;
     906           0 :         aRuntime.Message = cInvalidObject;
     907           0 :         throw aRuntime;
     908             :     }
     909         551 :     xRet->gotoEnd(sal_True);
     910        1102 :     return xRet->getString();
     911             : }
     912             : 
     913             : void SAL_CALL
     914         248 : SwXText::setString(const OUString& rString) throw (uno::RuntimeException, std::exception)
     915             : {
     916         248 :     SolarMutexGuard aGuard;
     917             : 
     918         248 :     if (!GetDoc())
     919             :     {
     920           0 :         uno::RuntimeException aRuntime;
     921           0 :         aRuntime.Message = cInvalidObject;
     922           0 :         throw aRuntime;
     923             :     }
     924             : 
     925         248 :     const SwStartNode* pStartNode = GetStartNode();
     926         248 :     if (!pStartNode)
     927             :     {
     928           0 :         throw uno::RuntimeException();
     929             :     }
     930             : 
     931         248 :     GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_START, NULL);
     932             :     //insert an empty paragraph at the start and at the end to ensure that
     933             :     //all tables and sections can be removed by the selecting text::XTextCursor
     934         248 :     if (CURSOR_META != m_pImpl->m_eType)
     935             :     {
     936         221 :         SwPosition aStartPos(*pStartNode);
     937         221 :         const SwEndNode* pEnd = pStartNode->EndOfSectionNode();
     938         442 :         SwNodeIndex aEndIdx(*pEnd);
     939         221 :         --aEndIdx;
     940             :         //the inserting of nodes should only be done if really necessary
     941             :         //to prevent #97924# (removes paragraph attributes when setting the text
     942             :         //e.g. of a table cell
     943         221 :         bool bInsertNodes = false;
     944         442 :         SwNodeIndex aStartIdx(*pStartNode);
     945         228 :         do
     946             :         {
     947         228 :             ++aStartIdx;
     948         228 :             SwNode& rCurrentNode = aStartIdx.GetNode();
     949         456 :             if(rCurrentNode.GetNodeType() == ND_SECTIONNODE
     950         228 :                 ||rCurrentNode.GetNodeType() == ND_TABLENODE)
     951             :             {
     952           0 :                 bInsertNodes = true;
     953           0 :                 break;
     954             :             }
     955             :         }
     956             :         while(aStartIdx < aEndIdx);
     957         221 :         if(bInsertNodes)
     958             :         {
     959           0 :             GetDoc()->getIDocumentContentOperations().AppendTextNode( aStartPos );
     960           0 :             SwPosition aEndPos(aEndIdx.GetNode());
     961           0 :             SwPaM aPam(aEndPos);
     962           0 :             GetDoc()->getIDocumentContentOperations().AppendTextNode( *aPam.Start() );
     963         221 :         }
     964             :     }
     965             : 
     966         496 :     const uno::Reference< text::XTextCursor > xRet = CreateCursor();
     967         248 :     if(!xRet.is())
     968             :     {
     969           0 :         GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
     970           0 :         uno::RuntimeException aRuntime;
     971           0 :         aRuntime.Message = cInvalidObject;
     972           0 :         throw aRuntime;
     973             :     }
     974         248 :     xRet->gotoEnd(sal_True);
     975         248 :     xRet->setString(rString);
     976         496 :     GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
     977         248 : }
     978             : 
     979             : //FIXME why is CheckForOwnMember duplicated in some insert methods?
     980             : //  Description: Checks if pRange/pCursor are member of the same text interface.
     981             : //              Only one of the pointers has to be set!
     982         780 : bool SwXText::Impl::CheckForOwnMember(
     983             :     const SwPaM & rPaM)
     984             : throw (lang::IllegalArgumentException, uno::RuntimeException)
     985             : {
     986         780 :     const uno::Reference<text::XTextCursor> xOwnCursor(m_rThis.CreateCursor());
     987             : 
     988        1560 :     const uno::Reference<lang::XUnoTunnel> xTunnel(xOwnCursor, uno::UNO_QUERY);
     989             :     OTextCursorHelper *const pOwnCursor =
     990         780 :             ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xTunnel);
     991             :     OSL_ENSURE(pOwnCursor, "OTextCursorHelper::getUnoTunnelId() ??? ");
     992             :     const SwStartNode* pOwnStartNode =
     993         780 :         pOwnCursor->GetPaM()->GetNode().StartOfSectionNode();
     994         780 :     SwStartNodeType eSearchNodeType = SwNormalStartNode;
     995         780 :     switch (m_eType)
     996             :     {
     997           0 :         case CURSOR_FRAME:      eSearchNodeType = SwFlyStartNode;       break;
     998           8 :         case CURSOR_TBLTEXT:    eSearchNodeType = SwTableBoxStartNode;  break;
     999           4 :         case CURSOR_FOOTNOTE:   eSearchNodeType = SwFootnoteStartNode;  break;
    1000           4 :         case CURSOR_HEADER:     eSearchNodeType = SwHeaderStartNode;    break;
    1001           0 :         case CURSOR_FOOTER:     eSearchNodeType = SwFooterStartNode;    break;
    1002             :         //case CURSOR_INVALID:
    1003             :         //case CURSOR_BODY:
    1004             :         default:
    1005             :             ;
    1006             :     }
    1007             : 
    1008         780 :     const SwNode& rSrcNode = rPaM.GetNode();
    1009         780 :     const SwStartNode* pTmp = rSrcNode.FindSttNodeByType(eSearchNodeType);
    1010             : 
    1011             :     //SectionNodes ueberspringen
    1012        1560 :     while(pTmp && pTmp->IsSectionNode())
    1013             :     {
    1014           0 :         pTmp = pTmp->StartOfSectionNode();
    1015             :     }
    1016             : 
    1017             :     //if the document starts with a section
    1018        1560 :     while(pOwnStartNode->IsSectionNode())
    1019             :     {
    1020           0 :         pOwnStartNode = pOwnStartNode->StartOfSectionNode();
    1021             :     }
    1022             : 
    1023             :     //this checks if (this) and xRange are in the same text::XText interface
    1024        1560 :     return (pOwnStartNode == pTmp);
    1025             : }
    1026             : 
    1027             : sal_Int16
    1028         392 : SwXText::Impl::ComparePositions(
    1029             :     const uno::Reference<text::XTextRange>& xPos1,
    1030             :     const uno::Reference<text::XTextRange>& xPos2)
    1031             : throw (lang::IllegalArgumentException, uno::RuntimeException)
    1032             : {
    1033         392 :     SwUnoInternalPaM aPam1(*m_pDoc);
    1034         784 :     SwUnoInternalPaM aPam2(*m_pDoc);
    1035             : 
    1036         784 :     if (!::sw::XTextRangeToSwPaM(aPam1, xPos1) ||
    1037         392 :         !::sw::XTextRangeToSwPaM(aPam2, xPos2))
    1038             :     {
    1039           0 :         throw lang::IllegalArgumentException();
    1040             :     }
    1041         392 :     if (!CheckForOwnMember(aPam1) || !CheckForOwnMember(aPam2))
    1042             :     {
    1043           4 :         throw lang::IllegalArgumentException();
    1044             :     }
    1045             : 
    1046         388 :     sal_Int16 nCompare = 0;
    1047         388 :     SwPosition const*const pStart1 = aPam1.Start();
    1048         388 :     SwPosition const*const pStart2 = aPam2.Start();
    1049         388 :     if (*pStart1 < *pStart2)
    1050             :     {
    1051         335 :         nCompare = 1;
    1052             :     }
    1053          53 :     else if (*pStart1 > *pStart2)
    1054             :     {
    1055           0 :         nCompare = -1;
    1056             :     }
    1057             :     else
    1058             :     {
    1059             :         OSL_ENSURE(*pStart1 == *pStart2,
    1060             :                 "SwPositions should be equal here");
    1061          53 :         nCompare = 0;
    1062             :     }
    1063             : 
    1064         780 :     return nCompare;
    1065             : }
    1066             : 
    1067             : sal_Int16 SAL_CALL
    1068         388 : SwXText::compareRegionStarts(
    1069             :     const uno::Reference<text::XTextRange>& xRange1,
    1070             :     const uno::Reference<text::XTextRange>& xRange2)
    1071             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1072             : {
    1073         388 :     SolarMutexGuard aGuard;
    1074             : 
    1075         388 :     if (!xRange1.is() || !xRange2.is())
    1076             :     {
    1077           0 :         throw lang::IllegalArgumentException();
    1078             :     }
    1079         776 :     const uno::Reference<text::XTextRange> xStart1 = xRange1->getStart();
    1080         776 :     const uno::Reference<text::XTextRange> xStart2 = xRange2->getStart();
    1081             : 
    1082         776 :     return m_pImpl->ComparePositions(xStart1, xStart2);
    1083             : }
    1084             : 
    1085             : sal_Int16 SAL_CALL
    1086           4 : SwXText::compareRegionEnds(
    1087             :     const uno::Reference<text::XTextRange>& xRange1,
    1088             :     const uno::Reference<text::XTextRange>& xRange2)
    1089             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1090             : {
    1091           4 :     SolarMutexGuard aGuard;
    1092             : 
    1093           4 :     if (!xRange1.is() || !xRange2.is())
    1094             :     {
    1095           0 :         throw lang::IllegalArgumentException();
    1096             :     }
    1097           8 :     uno::Reference<text::XTextRange> xEnd1 = xRange1->getEnd();
    1098           8 :     uno::Reference<text::XTextRange> xEnd2 = xRange2->getEnd();
    1099             : 
    1100           8 :     return m_pImpl->ComparePositions(xEnd1, xEnd2);
    1101             : }
    1102             : 
    1103             : uno::Reference< beans::XPropertySetInfo > SAL_CALL
    1104         132 : SwXText::getPropertySetInfo() throw(uno::RuntimeException, std::exception)
    1105             : {
    1106         132 :     SolarMutexGuard g;
    1107             : 
    1108             :     static uno::Reference< beans::XPropertySetInfo > xInfo =
    1109         132 :         m_pImpl->m_rPropSet.getPropertySetInfo();
    1110         132 :     return xInfo;
    1111             : }
    1112             : 
    1113             : void SAL_CALL
    1114           0 : SwXText::setPropertyValue(const OUString& /*aPropertyName*/,
    1115             :         const uno::Any& /*aValue*/)
    1116             : throw (beans::UnknownPropertyException, beans::PropertyVetoException,
    1117             :     lang::IllegalArgumentException, lang::WrappedTargetException,
    1118             :     uno::RuntimeException, std::exception)
    1119             : {
    1120           0 :     throw lang::IllegalArgumentException();
    1121             : }
    1122             : 
    1123             : uno::Any SAL_CALL
    1124         660 : SwXText::getPropertyValue(
    1125             :     const OUString& rPropertyName)
    1126             : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
    1127             :         uno::RuntimeException, std::exception)
    1128             : {
    1129         660 :     SolarMutexGuard aGuard;
    1130             : 
    1131         660 :     if(!IsValid())
    1132             :     {
    1133           0 :         throw  uno::RuntimeException();
    1134             :     }
    1135             : 
    1136             :     SfxItemPropertySimpleEntry const*const pEntry =
    1137         660 :         m_pImpl->m_rPropSet.getPropertyMap().getByName(rPropertyName);
    1138         660 :     if (!pEntry)
    1139             :     {
    1140           0 :         beans::UnknownPropertyException aExcept;
    1141           0 :         aExcept.Message = "Unknown property: " + rPropertyName;
    1142           0 :         throw aExcept;
    1143             :     }
    1144             : 
    1145         660 :     uno::Any aRet;
    1146         660 :     switch (pEntry->nWID)
    1147             :     {
    1148             : //          no code necessary - the redline is always located at the end node
    1149             : //            case FN_UNO_REDLINE_NODE_START:
    1150             : //            break;
    1151             :         case FN_UNO_REDLINE_NODE_END:
    1152             :         {
    1153         330 :             const SwRedlineTable& rRedTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable();
    1154         330 :             const size_t nRedTableCount = rRedTable.size();
    1155         330 :             if (nRedTableCount > 0)
    1156             :             {
    1157           0 :                 SwStartNode const*const pStartNode = GetStartNode();
    1158           0 :                 const sal_uLong nOwnIndex = pStartNode->EndOfSectionIndex();
    1159           0 :                 for (size_t nRed = 0; nRed < nRedTableCount; ++nRed)
    1160             :                 {
    1161           0 :                     SwRangeRedline const*const pRedline = rRedTable[nRed];
    1162           0 :                     SwPosition const*const pRedStart = pRedline->Start();
    1163           0 :                     const SwNodeIndex nRedNode = pRedStart->nNode;
    1164           0 :                     if (nOwnIndex == nRedNode.GetIndex())
    1165             :                     {
    1166           0 :                         aRet <<= SwXRedlinePortion::CreateRedlineProperties(
    1167           0 :                                 *pRedline, true);
    1168           0 :                         break;
    1169             :                     }
    1170           0 :                 }
    1171             :             }
    1172             :         }
    1173         330 :         break;
    1174             :     }
    1175         660 :     return aRet;
    1176             : }
    1177             : 
    1178             : void SAL_CALL
    1179           0 : SwXText::addPropertyChangeListener(
    1180             :         const OUString& /*rPropertyName*/,
    1181             :         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
    1182             : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
    1183             :     uno::RuntimeException, std::exception)
    1184             : {
    1185             :     OSL_FAIL("SwXText::addPropertyChangeListener(): not implemented");
    1186           0 : }
    1187             : 
    1188             : void SAL_CALL
    1189           0 : SwXText::removePropertyChangeListener(
    1190             :         const OUString& /*rPropertyName*/,
    1191             :         const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/)
    1192             : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
    1193             :     uno::RuntimeException, std::exception)
    1194             : {
    1195             :     OSL_FAIL("SwXText::removePropertyChangeListener(): not implemented");
    1196           0 : }
    1197             : 
    1198             : void SAL_CALL
    1199           0 : SwXText::addVetoableChangeListener(
    1200             :         const OUString& /*rPropertyName*/,
    1201             :         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
    1202             : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
    1203             :     uno::RuntimeException, std::exception)
    1204             : {
    1205             :     OSL_FAIL("SwXText::addVetoableChangeListener(): not implemented");
    1206           0 : }
    1207             : 
    1208             : void SAL_CALL
    1209           0 : SwXText::removeVetoableChangeListener(
    1210             :         const OUString& /*rPropertyName*/,
    1211             :         const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/)
    1212             : throw (beans::UnknownPropertyException, lang::WrappedTargetException,
    1213             :         uno::RuntimeException, std::exception)
    1214             : {
    1215             :     OSL_FAIL("SwXText::removeVetoableChangeListener(): not implemented");
    1216           0 : }
    1217             : 
    1218             : namespace
    1219             : {
    1220             :     class theSwXTextUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextUnoTunnelId > {};
    1221             : }
    1222             : 
    1223       82097 : const uno::Sequence< sal_Int8 > & SwXText::getUnoTunnelId()
    1224             : {
    1225       82097 :     return theSwXTextUnoTunnelId::get().getSeq();
    1226             : }
    1227             : 
    1228             : sal_Int64 SAL_CALL
    1229       12370 : SwXText::getSomething(const uno::Sequence< sal_Int8 >& rId)
    1230             : throw (uno::RuntimeException, std::exception)
    1231             : {
    1232       12370 :     return ::sw::UnoTunnelImpl<SwXText>(rId, this);
    1233             : }
    1234             : 
    1235             : uno::Reference< text::XTextRange > SAL_CALL
    1236       27133 : SwXText::finishParagraph(
    1237             :         const uno::Sequence< beans::PropertyValue > & rProperties)
    1238             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1239             : {
    1240       27133 :     SolarMutexGuard g;
    1241             : 
    1242       27133 :     return m_pImpl->finishOrAppendParagraph(true, rProperties, uno::Reference< text::XTextRange >());
    1243             : }
    1244             : 
    1245             : uno::Reference< text::XTextRange > SAL_CALL
    1246         753 : SwXText::finishParagraphInsert(
    1247             :         const uno::Sequence< beans::PropertyValue > & rProperties,
    1248             :         const uno::Reference< text::XTextRange >& xInsertPosition)
    1249             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1250             : {
    1251         753 :     SolarMutexGuard g;
    1252             : 
    1253         753 :     return m_pImpl->finishOrAppendParagraph(true, rProperties, xInsertPosition);
    1254             : }
    1255             : 
    1256             : uno::Reference< text::XTextRange >
    1257       27886 : SwXText::Impl::finishOrAppendParagraph(
    1258             :         const bool bFinish,
    1259             :         const uno::Sequence< beans::PropertyValue > & rProperties,
    1260             :         const uno::Reference< text::XTextRange >& xInsertPosition)
    1261             :     throw (lang::IllegalArgumentException, uno::RuntimeException)
    1262             : {
    1263       27886 :     if (!m_bIsValid)
    1264             :     {
    1265           1 :         throw  uno::RuntimeException();
    1266             :     }
    1267             : 
    1268       27885 :     const SwStartNode* pStartNode = m_rThis.GetStartNode();
    1269       27885 :     if(!pStartNode)
    1270             :     {
    1271           0 :         throw  uno::RuntimeException();
    1272             :     }
    1273             : 
    1274       27885 :     uno::Reference< text::XTextRange > xRet;
    1275       27885 :     bool bIllegalException = false;
    1276       27885 :     bool bRuntimeException = false;
    1277       55770 :     OUString sMessage;
    1278       27885 :     m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_START , NULL);
    1279             :     // find end node, go backward - don't skip tables because the new
    1280             :     // paragraph has to be the last node
    1281             :     //aPam.Move( fnMoveBackward, fnGoNode );
    1282             :     SwPosition aInsertPosition(
    1283       55770 :             SwNodeIndex( *pStartNode->EndOfSectionNode(), -1 ) );
    1284       55770 :     SwPaM aPam(aInsertPosition);
    1285             :     // If we got a position reference, then the insert point is not the end of
    1286             :     // the document.
    1287       27885 :     if (xInsertPosition.is())
    1288             :     {
    1289         753 :         SwUnoInternalPaM aStartPam(*m_rThis.GetDoc());
    1290         753 :         ::sw::XTextRangeToSwPaM(aStartPam, xInsertPosition);
    1291         753 :         aPam = aStartPam;
    1292         753 :         aPam.SetMark();
    1293             :     }
    1294       27885 :     m_pDoc->getIDocumentContentOperations().AppendTextNode( *aPam.GetPoint() );
    1295             :     // remove attributes from the previous paragraph
    1296       27885 :     m_pDoc->ResetAttrs(aPam);
    1297             :     // in case of finishParagraph the PaM needs to be moved to the
    1298             :     // previous paragraph
    1299       27885 :     if (bFinish)
    1300             :     {
    1301       27885 :         aPam.Move( fnMoveBackward, fnGoNode );
    1302             :     }
    1303             : 
    1304             :     try
    1305             :     {
    1306             :         SfxItemPropertySet const*const pParaPropSet =
    1307       27885 :             aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH);
    1308             : 
    1309       27885 :         SwUnoCursorHelper::SetPropertyValues(aPam, *pParaPropSet, rProperties);
    1310             :     }
    1311          18 :     catch (const lang::IllegalArgumentException& rIllegal)
    1312             :     {
    1313           9 :         sMessage = rIllegal.Message;
    1314           9 :         bIllegalException = true;
    1315             :     }
    1316           0 :     catch (const uno::RuntimeException& rRuntime)
    1317             :     {
    1318           0 :         sMessage = rRuntime.Message;
    1319           0 :         bRuntimeException = true;
    1320             :     }
    1321           0 :     catch (const uno::Exception& rEx)
    1322             :     {
    1323           0 :         sMessage = rEx.Message;
    1324           0 :         bRuntimeException = true;
    1325             :     }
    1326             : 
    1327       27885 :     m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
    1328       27885 :     if (bIllegalException || bRuntimeException)
    1329             :     {
    1330           9 :         m_pDoc->GetIDocumentUndoRedo().Undo();
    1331           0 :         if (bIllegalException)
    1332             :         {
    1333           0 :             lang::IllegalArgumentException aEx;
    1334           0 :             aEx.Message = sMessage;
    1335           0 :             throw aEx;
    1336             :         }
    1337             :         else
    1338             :         {
    1339           0 :             uno::RuntimeException aEx;
    1340           0 :             aEx.Message = sMessage;
    1341           0 :             throw aEx;
    1342             :         }
    1343             :     }
    1344       27876 :     SwTextNode *const pTextNode( aPam.Start()->nNode.GetNode().GetTextNode() );
    1345             :     OSL_ENSURE(pTextNode, "no SwTextNode?");
    1346       27876 :     if (pTextNode)
    1347             :     {
    1348             :         xRet.set(SwXParagraph::CreateXParagraph(*m_pDoc, pTextNode, &m_rThis),
    1349       27876 :                 uno::UNO_QUERY);
    1350             :     }
    1351             : 
    1352       55752 :     return xRet;
    1353             : }
    1354             : 
    1355             : uno::Reference< text::XTextRange > SAL_CALL
    1356       46225 : SwXText::insertTextPortion(
    1357             :         const OUString& rText,
    1358             :         const uno::Sequence< beans::PropertyValue > &
    1359             :             rCharacterAndParagraphProperties,
    1360             :         const uno::Reference<text::XTextRange>& xInsertPosition)
    1361             :     throw (lang::IllegalArgumentException, beans::UnknownPropertyException,
    1362             :            beans::PropertyVetoException,
    1363             :            uno::RuntimeException, std::exception)
    1364             : {
    1365       46225 :     SolarMutexGuard aGuard;
    1366             : 
    1367       46225 :     if(!IsValid())
    1368             :     {
    1369           0 :         throw  uno::RuntimeException();
    1370             :     }
    1371       46225 :     uno::Reference< text::XTextRange > xRet;
    1372       92450 :     const uno::Reference< text::XTextCursor > xTextCursor = CreateCursor();
    1373       46225 :     xTextCursor->gotoRange(xInsertPosition, sal_False);
    1374             : 
    1375             :     const uno::Reference< lang::XUnoTunnel > xRangeTunnel(
    1376       92450 :             xTextCursor, uno::UNO_QUERY_THROW );
    1377             :     SwXTextCursor *const pTextCursor =
    1378       46225 :         ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xRangeTunnel);
    1379             : 
    1380       46225 :     bool bIllegalException = false;
    1381       46225 :     bool bRuntimeException = false;
    1382       92450 :     OUString sMessage;
    1383       46225 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
    1384             : 
    1385       46225 :     auto pCursor(pTextCursor->GetCursor());
    1386       46225 :     m_pImpl->m_pDoc->DontExpandFormat( *pCursor->Start() );
    1387             : 
    1388       46225 :     if (!rText.isEmpty())
    1389             :     {
    1390       46225 :         const sal_Int32 nContentPos = pCursor->GetPoint()->nContent.GetIndex();
    1391             :         SwUnoCursorHelper::DocInsertStringSplitCR(
    1392       46225 :             *m_pImpl->m_pDoc, *pCursor, rText, false);
    1393       46225 :         SwUnoCursorHelper::SelectPam(*pCursor, true);
    1394       46225 :         pCursor->GetPoint()->nContent = nContentPos;
    1395             :     }
    1396             : 
    1397             :     try
    1398             :     {
    1399             :       SfxItemPropertySet const*const pCursorPropSet =
    1400       46225 :           aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR);
    1401             :       SwUnoCursorHelper::SetPropertyValues(*pCursor, *pCursorPropSet,
    1402             :                                            rCharacterAndParagraphProperties,
    1403       46225 :                                            SetAttrMode::NOFORMATATTR);
    1404             :     }
    1405           0 :     catch (const lang::IllegalArgumentException& rIllegal)
    1406             :     {
    1407           0 :         sMessage = rIllegal.Message;
    1408           0 :         bIllegalException = true;
    1409             :     }
    1410           0 :     catch (const uno::RuntimeException& rRuntime)
    1411             :     {
    1412           0 :         sMessage = rRuntime.Message;
    1413           0 :         bRuntimeException = true;
    1414             :     }
    1415       46225 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
    1416       46225 :     if (bIllegalException || bRuntimeException)
    1417             :     {
    1418           0 :         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
    1419           0 :         if (bIllegalException)
    1420             :         {
    1421           0 :             lang::IllegalArgumentException aEx;
    1422           0 :             aEx.Message = sMessage;
    1423           0 :             throw aEx;
    1424             :         }
    1425             :         else
    1426             :         {
    1427           0 :             uno::RuntimeException aEx;
    1428           0 :             aEx.Message = sMessage;
    1429           0 :             throw aEx;
    1430             :         }
    1431             :     }
    1432       46225 :     xRet = new SwXTextRange(*pCursor, this);
    1433       92450 :     return xRet;
    1434             : }
    1435             : 
    1436             : // Append text portions at the end of the last paragraph of the text interface.
    1437             : // Support of import filters.
    1438             : uno::Reference< text::XTextRange > SAL_CALL
    1439       43666 : SwXText::appendTextPortion(
    1440             :         const OUString& rText,
    1441             :         const uno::Sequence< beans::PropertyValue > &
    1442             :             rCharacterAndParagraphProperties)
    1443             : throw (lang::IllegalArgumentException, beans::UnknownPropertyException,
    1444             :        beans::PropertyVetoException, uno::RuntimeException, std::exception)
    1445             : {
    1446             :     // Right now this doesn't need a guard, as it's just calling the insert
    1447             :     // version, that has it already.
    1448       43666 :     uno::Reference<text::XTextRange> xInsertPosition = getEnd();
    1449       43666 :     return insertTextPortion(rText, rCharacterAndParagraphProperties, xInsertPosition);
    1450             : }
    1451             : 
    1452             : // enable inserting/appending text contents like graphic objects, shapes and so on to
    1453             : // support import filters
    1454             : uno::Reference< text::XTextRange > SAL_CALL
    1455        4143 : SwXText::insertTextContentWithProperties(
    1456             :     const uno::Reference< text::XTextContent >& xTextContent,
    1457             :     const uno::Sequence< beans::PropertyValue >&
    1458             :         rCharacterAndParagraphProperties,
    1459             :     const uno::Reference< text::XTextRange >& xInsertPosition)
    1460             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1461             : {
    1462        4143 :     SolarMutexGuard aGuard;
    1463             : 
    1464        4143 :     if (!IsValid())
    1465             :     {
    1466           0 :         throw  uno::RuntimeException();
    1467             :     }
    1468             : 
    1469        4143 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_INSERT, NULL);
    1470             : 
    1471             :     // now attach the text content here
    1472        4143 :     insertTextContent( xInsertPosition, xTextContent, false );
    1473             :     // now apply the properties to the anchor
    1474        1743 :     if (rCharacterAndParagraphProperties.getLength())
    1475             :     {
    1476             :         try
    1477             :         {
    1478         158 :             const sal_Int32 nLen(rCharacterAndParagraphProperties.getLength());
    1479             :             const uno::Reference< beans::XPropertySet > xAnchor(
    1480         158 :                 xTextContent->getAnchor(), uno::UNO_QUERY);
    1481         158 :             if (xAnchor.is())
    1482             :             {
    1483         592 :                 for (sal_Int32 nElement = 0; nElement < nLen; ++nElement)
    1484             :                 {
    1485         434 :                     xAnchor->setPropertyValue(
    1486         434 :                         rCharacterAndParagraphProperties[nElement].Name,
    1487         868 :                         rCharacterAndParagraphProperties[nElement].Value);
    1488             :                 }
    1489         158 :             }
    1490             :         }
    1491           0 :         catch (const uno::Exception& e)
    1492             :         {
    1493           0 :             m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
    1494           0 :             lang::WrappedTargetRuntimeException wrapped;
    1495           0 :             wrapped.TargetException <<= e;
    1496           0 :             throw wrapped;
    1497             :         }
    1498             :     }
    1499        1743 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_INSERT, NULL);
    1500        4143 :     return xInsertPosition;
    1501             : }
    1502             : 
    1503             : uno::Reference< text::XTextRange > SAL_CALL
    1504        4126 : SwXText::appendTextContent(
    1505             :     const uno::Reference< text::XTextContent >& xTextContent,
    1506             :     const uno::Sequence< beans::PropertyValue >&
    1507             :         rCharacterAndParagraphProperties)
    1508             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1509             : {
    1510             :     // Right now this doesn't need a guard, as it's just calling the insert
    1511             :     // version, that has it already.
    1512        4126 :     uno::Reference<text::XTextRange> xInsertPosition = getEnd();
    1513        4126 :     return insertTextContentWithProperties(xTextContent, rCharacterAndParagraphProperties, xInsertPosition);
    1514             : }
    1515             : 
    1516             : // move previously appended paragraphs into a text frames
    1517             : // to support import filters
    1518             : uno::Reference< text::XTextContent > SAL_CALL
    1519         108 : SwXText::convertToTextFrame(
    1520             :     const uno::Reference< text::XTextRange >& xStart,
    1521             :     const uno::Reference< text::XTextRange >& xEnd,
    1522             :     const uno::Sequence< beans::PropertyValue >& rFrameProperties)
    1523             :     throw (lang::IllegalArgumentException, beans::UnknownPropertyException,
    1524             :            beans::PropertyVetoException, uno::RuntimeException, std::exception)
    1525             : {
    1526         108 :     SolarMutexGuard aGuard;
    1527             : 
    1528         108 :     if(!IsValid())
    1529             :     {
    1530           0 :         throw  uno::RuntimeException();
    1531             :     }
    1532         108 :     uno::Reference< text::XTextContent > xRet;
    1533         216 :     SwUnoInternalPaM aStartPam(*GetDoc());
    1534         216 :     std::unique_ptr< SwUnoInternalPaM > pEndPam(new SwUnoInternalPaM(*GetDoc()));
    1535         212 :     if (!::sw::XTextRangeToSwPaM(aStartPam, xStart) ||
    1536         104 :         !::sw::XTextRangeToSwPaM(*pEndPam, xEnd))
    1537             :     {
    1538           4 :         throw lang::IllegalArgumentException();
    1539             :     }
    1540             : 
    1541             :     const uno::Reference<lang::XUnoTunnel> xStartRangeTunnel(xStart,
    1542         208 :             uno::UNO_QUERY);
    1543             :     SwXTextRange *const pStartRange =
    1544         104 :         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xStartRangeTunnel);
    1545             :     const uno::Reference<lang::XUnoTunnel> xEndRangeTunnel(xEnd,
    1546         208 :             uno::UNO_QUERY);
    1547             :     SwXTextRange *const pEndRange   =
    1548         104 :         ::sw::UnoTunnelGetImplementation<SwXTextRange>(xEndRangeTunnel);
    1549             :     // bookmarks have to be removed before the referenced text node
    1550             :     // is deleted in DelFullPara
    1551         104 :     if (pStartRange)
    1552             :     {
    1553         104 :         pStartRange->Invalidate();
    1554             :     }
    1555         104 :     if (pEndRange)
    1556             :     {
    1557          96 :         pEndRange->Invalidate();
    1558             :     }
    1559             : 
    1560         104 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
    1561         104 :     bool bIllegalException = false;
    1562         104 :     bool bRuntimeException = false;
    1563         208 :     OUString sMessage;
    1564         104 :     SwStartNode* pStartStartNode = aStartPam.GetNode().StartOfSectionNode();
    1565         208 :     while (pStartStartNode && pStartStartNode->IsSectionNode())
    1566             :     {
    1567           0 :         pStartStartNode = pStartStartNode->StartOfSectionNode();
    1568             :     }
    1569         104 :     SwStartNode* pEndStartNode = pEndPam->GetNode().StartOfSectionNode();
    1570         208 :     while (pEndStartNode && pEndStartNode->IsSectionNode())
    1571             :     {
    1572           0 :         pEndStartNode = pEndStartNode->StartOfSectionNode();
    1573             :     }
    1574         104 :     bool bParaAfterInserted = false;
    1575         104 :     bool bParaBeforeInserted = false;
    1576         104 :     if (
    1577         134 :         pStartStartNode && pEndStartNode &&
    1578          85 :         (pStartStartNode != pEndStartNode || pStartStartNode != GetStartNode())
    1579             :        )
    1580             :     {
    1581             :         // todo: if the start/end is in a table then insert a paragraph
    1582             :         // before/after, move the start/end nodes, then convert and
    1583             :         // remove the additional paragraphs in the end
    1584          30 :         SwTableNode * pStartTableNode(0);
    1585          30 :         if (pStartStartNode->GetStartNodeType() == SwTableBoxStartNode)
    1586             :         {
    1587          30 :             pStartTableNode = pStartStartNode->FindTableNode();
    1588             :             // Is it the same table start node than the end?
    1589          30 :             SwTableNode *const pEndStartTableNode(pEndStartNode->FindTableNode());
    1590          92 :             while (pEndStartTableNode && pStartTableNode &&
    1591          31 :                    pEndStartTableNode->GetIndex() < pStartTableNode->GetIndex())
    1592             :             {
    1593           1 :                 SwStartNode* pStartStartTableNode = pStartTableNode->StartOfSectionNode();
    1594           1 :                 pStartTableNode = pStartStartTableNode->FindTableNode();
    1595             :             }
    1596             :         }
    1597          30 :         if (pStartTableNode)
    1598             :         {
    1599          30 :             const SwNodeIndex aTableIdx(  *pStartTableNode, -1 );
    1600          60 :             SwPosition aBefore(aTableIdx);
    1601          30 :             bParaBeforeInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore );
    1602          30 :             aStartPam.DeleteMark();
    1603          30 :             *aStartPam.GetPoint() = aBefore;
    1604          60 :             pStartStartNode = aStartPam.GetNode().StartOfSectionNode();
    1605             :         }
    1606          30 :         if (pEndStartNode->GetStartNodeType() == SwTableBoxStartNode)
    1607             :         {
    1608          30 :             SwTableNode *const pEndTableNode = pEndStartNode->FindTableNode();
    1609          30 :             SwEndNode *const pTableEnd = pEndTableNode->EndOfSectionNode();
    1610          30 :             SwPosition aTableEnd(*pTableEnd);
    1611          30 :             bParaAfterInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aTableEnd );
    1612          30 :             pEndPam->DeleteMark();
    1613          30 :             *pEndPam->GetPoint() = aTableEnd;
    1614          30 :             pEndStartNode = pEndPam->GetNode().StartOfSectionNode();
    1615             :         }
    1616             :         // now we should have the positions in the same hierarchy
    1617          60 :         if ((pStartStartNode != pEndStartNode) ||
    1618          30 :             (pStartStartNode != GetStartNode()))
    1619             :         {
    1620             :             // if not - remove the additional paragraphs and throw
    1621           0 :             if (bParaBeforeInserted)
    1622             :             {
    1623           0 :                 SwCursor aDelete(*aStartPam.GetPoint(), 0, false);
    1624           0 :                 *aStartPam.GetPoint() = // park it because node is deleted
    1625           0 :                     SwPosition(GetDoc()->GetNodes().GetEndOfContent());
    1626           0 :                 aDelete.MovePara(fnParaCurr, fnParaStart);
    1627           0 :                 aDelete.SetMark();
    1628           0 :                 aDelete.MovePara(fnParaCurr, fnParaEnd);
    1629           0 :                 GetDoc()->getIDocumentContentOperations().DelFullPara(aDelete);
    1630             :             }
    1631           0 :             if (bParaAfterInserted)
    1632             :             {
    1633           0 :                 SwCursor aDelete(*pEndPam->GetPoint(), 0, false);
    1634           0 :                 *pEndPam->GetPoint() = // park it because node is deleted
    1635           0 :                     SwPosition(GetDoc()->GetNodes().GetEndOfContent());
    1636           0 :                 aDelete.MovePara(fnParaCurr, fnParaStart);
    1637           0 :                 aDelete.SetMark();
    1638           0 :                 aDelete.MovePara(fnParaCurr, fnParaEnd);
    1639           0 :                 GetDoc()->getIDocumentContentOperations().DelFullPara(aDelete);
    1640             :             }
    1641           0 :             throw lang::IllegalArgumentException();
    1642             :         }
    1643             :     }
    1644             : 
    1645             :     // make a selection from aStartPam to a EndPam
    1646             :     // If there is no content in the frame the shape is in
    1647             :     // it gets deleted in the DelFullPara call below,
    1648             :     // In this case insert a tmp text node ( we delete it later )
    1649         208 :     if ( aStartPam.Start()->nNode == pEndPam->Start()->nNode
    1650         104 :     && aStartPam.End()->nNode == pEndPam->End()->nNode )
    1651             :     {
    1652          66 :         SwPosition aEnd(*aStartPam.End());
    1653          66 :         bParaAfterInserted = GetDoc()->getIDocumentContentOperations().AppendTextNode( aEnd );
    1654          66 :         pEndPam->DeleteMark();
    1655          66 :         *pEndPam->GetPoint() = aEnd;
    1656             :     }
    1657         104 :     aStartPam.SetMark();
    1658         104 :     *aStartPam.End() = *pEndPam->End();
    1659         104 :     pEndPam.reset(0);
    1660             : 
    1661             :     // see if there are frames already anchored to this node
    1662         208 :     std::set<OUString> aAnchoredFrames;
    1663             :     // for shapes, we have to work with the SdrObjects, as unique name is not guaranteed in their frame format
    1664         208 :     std::set<const SdrObject*> aAnchoredShapes;
    1665         871 :     for (size_t i = 0; i < m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
    1666             :     {
    1667         767 :         const SwFrameFormat* pFrameFormat = (*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
    1668         767 :         const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
    1669        2331 :         if ((FLY_AT_PARA == rAnchor.GetAnchorId() || FLY_AT_CHAR == rAnchor.GetAnchorId()) &&
    1670        1631 :                 aStartPam.Start()->nNode.GetIndex() <= rAnchor.GetContentAnchor()->nNode.GetIndex() &&
    1671         358 :                 aStartPam.End()->nNode.GetIndex() >= rAnchor.GetContentAnchor()->nNode.GetIndex())
    1672             :         {
    1673          21 :             if (pFrameFormat->Which() == RES_DRAWFRMFMT)
    1674          13 :                 aAnchoredShapes.insert(pFrameFormat->FindSdrObject());
    1675             :             else
    1676           8 :                 aAnchoredFrames.insert(pFrameFormat->GetName());
    1677             :         }
    1678             :     }
    1679             : 
    1680             :     const uno::Reference<text::XTextFrame> xNewFrame(
    1681         208 :             SwXTextFrame::CreateXTextFrame(*m_pImpl->m_pDoc, 0));
    1682         104 :     SwXTextFrame& rNewFrame = dynamic_cast<SwXTextFrame&>(*xNewFrame.get());
    1683         104 :     rNewFrame.SetSelection( aStartPam );
    1684             :     try
    1685             :     {
    1686         104 :         const beans::PropertyValue* pValues = rFrameProperties.getConstArray();
    1687        2494 :         for (sal_Int32 nProp = 0; nProp < rFrameProperties.getLength(); ++nProp)
    1688             :         {
    1689             :             rNewFrame.SwXFrame::setPropertyValue(
    1690        2390 :                     pValues[nProp].Name, pValues[nProp].Value);
    1691             :         }
    1692             : 
    1693             :         {   // has to be in a block to remove the SwIndexes before
    1694             :             // DelFullPara is called
    1695             :             const uno::Reference< text::XTextRange> xInsertTextRange =
    1696         104 :                 new SwXTextRange(aStartPam, this);
    1697         104 :             aStartPam.DeleteMark(); // mark position node may be deleted!
    1698         104 :             rNewFrame.attach( xInsertTextRange );
    1699         104 :             rNewFrame.setName(m_pImpl->m_pDoc->GetUniqueFrameName());
    1700             :         }
    1701             : 
    1702         104 :         SwTextNode *const pTextNode(aStartPam.GetNode().GetTextNode());
    1703             :         OSL_ASSERT(pTextNode);
    1704         104 :         if (!pTextNode || !pTextNode->Len()) // don't remove if it contains text!
    1705             :         {
    1706             :             {   // has to be in a block to remove the SwIndexes before
    1707             :                 // DelFullPara is called
    1708         104 :                 SwPaM aMovePam( aStartPam.GetNode() );
    1709         104 :                 if (aMovePam.Move( fnMoveForward, fnGoContent ))
    1710             :                 {
    1711             :                     // move the anchor to the next paragraph
    1712         103 :                     SwFormatAnchor aNewAnchor(rNewFrame.GetFrameFormat()->GetAnchor());
    1713         103 :                     aNewAnchor.SetAnchor( aMovePam.Start() );
    1714         103 :                     m_pImpl->m_pDoc->SetAttr(
    1715         206 :                         aNewAnchor, *rNewFrame.GetFrameFormat() );
    1716             : 
    1717             :                     // also move frames anchored to us
    1718         971 :                     for (size_t i = 0; i < m_pImpl->m_pDoc->GetSpzFrameFormats()->size(); ++i)
    1719             :                     {
    1720         868 :                         SwFrameFormat* pFrameFormat = (*m_pImpl->m_pDoc->GetSpzFrameFormats())[i];
    1721         868 :                         if (aAnchoredFrames.find(pFrameFormat->GetName()) != aAnchoredFrames.end() || aAnchoredShapes.find(pFrameFormat->FindSdrObject()) != aAnchoredShapes.end())
    1722             :                         {
    1723             :                             // copy the anchor to the next paragraph
    1724          15 :                             SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
    1725          15 :                             aAnchor.SetAnchor(aMovePam.Start());
    1726          15 :                             m_pImpl->m_pDoc->SetAttr(aAnchor, *pFrameFormat);
    1727             :                         }
    1728         103 :                     }
    1729         104 :                 }
    1730             :             }
    1731         104 :             m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(aStartPam);
    1732             :         }
    1733             :     }
    1734           0 :     catch (const lang::IllegalArgumentException& rIllegal)
    1735             :     {
    1736           0 :         sMessage = rIllegal.Message;
    1737           0 :         bIllegalException = true;
    1738             :     }
    1739           0 :     catch (const uno::RuntimeException& rRuntime)
    1740             :     {
    1741           0 :         sMessage = rRuntime.Message;
    1742           0 :         bRuntimeException = true;
    1743             :     }
    1744         104 :     xRet = &rNewFrame;
    1745         104 :     if (bParaBeforeInserted || bParaAfterInserted)
    1746             :     {
    1747             :         const uno::Reference<text::XTextCursor> xFrameTextCursor =
    1748          96 :             rNewFrame.createTextCursor();
    1749             :         const uno::Reference<XUnoTunnel> xTunnel(xFrameTextCursor,
    1750         192 :                 uno::UNO_QUERY);
    1751             :         SwXTextCursor *const pFrameCursor =
    1752          96 :             ::sw::UnoTunnelGetImplementation<SwXTextCursor>(xTunnel);
    1753          96 :         if (bParaBeforeInserted)
    1754             :         {
    1755             :             // todo: remove paragraph before frame
    1756          30 :             m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pFrameCursor->GetPaM());
    1757             :         }
    1758          96 :         if (bParaAfterInserted)
    1759             :         {
    1760          96 :             xFrameTextCursor->gotoEnd(sal_False);
    1761          96 :             if (!bParaBeforeInserted)
    1762          66 :                 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(*pFrameCursor->GetPaM());
    1763             :             else
    1764             :             {
    1765             :                 // In case the frame has a table only, the cursor points to the end of the first cell of the table.
    1766          30 :                 SwPaM aPaM(*pFrameCursor->GetPaM()->GetNode().FindSttNodeByType(SwFlyStartNode)->EndOfSectionNode());
    1767             :                 // Now we have the end of the frame -- the node before that will be the paragraph we want to remove.
    1768          30 :                 --aPaM.GetPoint()->nNode;
    1769          30 :                 m_pImpl->m_pDoc->getIDocumentContentOperations().DelFullPara(aPaM);
    1770             :             }
    1771          96 :         }
    1772             :     }
    1773             : 
    1774         104 :     m_pImpl->m_pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_END, NULL);
    1775         104 :     if (bIllegalException || bRuntimeException)
    1776             :     {
    1777           0 :         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
    1778           0 :         if (bIllegalException)
    1779             :         {
    1780           0 :             lang::IllegalArgumentException aEx;
    1781           0 :             aEx.Message = sMessage;
    1782           0 :             throw aEx;
    1783             :         }
    1784             :         else
    1785             :         {
    1786           0 :             uno::RuntimeException aEx;
    1787           0 :             aEx.Message = sMessage;
    1788           0 :             throw aEx;
    1789             :         }
    1790             :     }
    1791         212 :     return xRet;
    1792             : }
    1793             : 
    1794             : // Move previously imported paragraphs into a new text table.
    1795         234 : struct VerticallyMergedCell
    1796             : {
    1797             :     std::vector<uno::Reference< beans::XPropertySet > > aCells;
    1798             :     sal_Int32                                           nLeftPosition;
    1799             :     bool                                                bOpen;
    1800             : 
    1801          56 :     VerticallyMergedCell(uno::Reference< beans::XPropertySet > const& rxCell,
    1802             :             const sal_Int32 nLeft)
    1803             :         : nLeftPosition( nLeft )
    1804          56 :         , bOpen( true )
    1805             :     {
    1806          56 :         aCells.push_back( rxCell );
    1807          56 :     }
    1808             : };
    1809             : 
    1810             : #define COL_POS_FUZZY 2
    1811             : 
    1812         173 : static bool lcl_SimilarPosition( const sal_Int32 nPos1, const sal_Int32 nPos2 )
    1813             : {
    1814         173 :     return abs( nPos1 - nPos2 ) < COL_POS_FUZZY;
    1815             : }
    1816             : 
    1817        8263 : void SwXText::Impl::ConvertCell(
    1818             :     const uno::Sequence< uno::Reference< text::XTextRange > > & rCell,
    1819             :     ::std::vector<SwNodeRange> & rRowNodes,
    1820             :     SwNodeRange *const pLastCell,
    1821             :     bool & rbExcept)
    1822             : {
    1823        8263 :     if (rCell.getLength() != 2)
    1824             :     {
    1825             :         throw lang::IllegalArgumentException(
    1826             :                 "rCell needs to contain 2 elements",
    1827           1 :                 uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) );
    1828             :     }
    1829        8262 :     const uno::Reference<text::XTextRange> xStartRange = rCell[0];
    1830       16524 :     const uno::Reference<text::XTextRange> xEndRange = rCell[1];
    1831       16524 :     SwUnoInternalPaM aStartCellPam(*m_pDoc);
    1832       16524 :     SwUnoInternalPaM aEndCellPam(*m_pDoc);
    1833             : 
    1834             :     // !!! TODO - PaMs in tables and sections do not work here -
    1835             :     //     the same applies to PaMs in frames !!!
    1836             : 
    1837       16524 :     if (!::sw::XTextRangeToSwPaM(aStartCellPam, xStartRange) ||
    1838        8262 :         !::sw::XTextRangeToSwPaM(aEndCellPam, xEndRange))
    1839             :     {
    1840             :         throw lang::IllegalArgumentException(
    1841             :                 "Start or End range cannot be resolved to a SwPaM",
    1842           0 :                 uno::Reference< text::XTextCopy >( &m_rThis ), sal_Int16( 2 ) );
    1843             :     }
    1844             : 
    1845        8262 :     SwNodeRange aTmpRange(aStartCellPam.Start()->nNode,
    1846       24786 :                           aEndCellPam.End()->nNode);
    1847             :     SwNodeRange * pCorrectedRange =
    1848        8262 :         SwNodes::ExpandRangeForTableBox(aTmpRange);
    1849             : 
    1850        8262 :     if (pCorrectedRange != NULL)
    1851             :     {
    1852          35 :         SwPaM aNewStartPaM(pCorrectedRange->aStart, 0);
    1853          35 :         aStartCellPam = aNewStartPaM;
    1854             : 
    1855          35 :         sal_Int32 nEndLen = 0;
    1856          35 :         SwTextNode * pTextNode = pCorrectedRange->aEnd.GetNode().GetTextNode();
    1857          35 :         if (pTextNode != NULL)
    1858          35 :             nEndLen = pTextNode->Len();
    1859             : 
    1860          70 :         SwPaM aNewEndPaM(pCorrectedRange->aEnd, nEndLen);
    1861          35 :         aEndCellPam = aNewEndPaM;
    1862             : 
    1863          70 :         delete pCorrectedRange;
    1864             :     }
    1865             : 
    1866             :     /** check the nodes between start and end
    1867             :         it is allowed to have pairs of StartNode/EndNodes
    1868             :      */
    1869        8262 :     if (aStartCellPam.Start()->nNode < aEndCellPam.End()->nNode)
    1870             :     {
    1871             :         // increment on each StartNode and decrement on each EndNode
    1872             :         // we must reach zero at the end and must not go below zero
    1873         350 :         long nOpenNodeBlock = 0;
    1874         350 :         SwNodeIndex aCellIndex = aStartCellPam.Start()->nNode;
    1875        5091 :         while (aCellIndex < aEndCellPam.End()->nNode.GetIndex())
    1876             :         {
    1877        4391 :             if (aCellIndex.GetNode().IsStartNode())
    1878             :             {
    1879        1115 :                 ++nOpenNodeBlock;
    1880             :             }
    1881        3276 :             else if (aCellIndex.GetNode().IsEndNode())
    1882             :             {
    1883        1115 :                 --nOpenNodeBlock;
    1884             :             }
    1885        4391 :             if (nOpenNodeBlock < 0)
    1886             :             {
    1887           0 :                 rbExcept = true;
    1888           0 :                 break;
    1889             :             }
    1890        4391 :             ++aCellIndex;
    1891             :         }
    1892         350 :         if (nOpenNodeBlock != 0)
    1893             :         {
    1894           0 :             rbExcept = true;
    1895        8262 :             return;
    1896         350 :         }
    1897             :     }
    1898             : 
    1899             :     /** The vector<vector> NodeRanges has to contain consecutive nodes.
    1900             :         In rTableRanges the ranges don't need to be full paragraphs but
    1901             :         they have to follow each other. To process the ranges they
    1902             :         have to be aligned on paragraph borders by inserting paragraph
    1903             :         breaks. Non-consecutive ranges must initiate an exception.
    1904             :      */
    1905        8262 :     if (!pLastCell) // first cell?
    1906             :     {
    1907             :         // align the beginning - if necessary
    1908         604 :         if (aStartCellPam.Start()->nContent.GetIndex())
    1909             :         {
    1910           0 :             m_pDoc->getIDocumentContentOperations().SplitNode(*aStartCellPam.Start(), false);
    1911             :         }
    1912             :     }
    1913             :     else
    1914             :     {
    1915             :         // check the predecessor
    1916             :         const sal_uLong nStartCellNodeIndex =
    1917        7658 :             aStartCellPam.Start()->nNode.GetIndex();
    1918        7658 :         const sal_uLong nLastNodeEndIndex = pLastCell->aEnd.GetIndex();
    1919        7658 :         if (nLastNodeEndIndex == nStartCellNodeIndex)
    1920             :         {
    1921             :             // same node as predecessor then equal nContent?
    1922           0 :             if (0 != aStartCellPam.Start()->nContent.GetIndex())
    1923             :             {
    1924           0 :                 rbExcept = true;
    1925             :             }
    1926             :             else
    1927             :             {
    1928           0 :                 m_pDoc->getIDocumentContentOperations().SplitNode(*aStartCellPam.Start(), false);
    1929           0 :                 sal_uLong const nNewIndex(aStartCellPam.Start()->nNode.GetIndex());
    1930           0 :                 if (nNewIndex != nStartCellNodeIndex)
    1931             :                 {
    1932             :                     // aStartCellPam now points to the 2nd node
    1933             :                     // the last cell may *also* point to 2nd node now - fix it!
    1934             :                     assert(nNewIndex == nStartCellNodeIndex + 1);
    1935           0 :                     if (pLastCell->aEnd.GetIndex() == nNewIndex)
    1936             :                     {
    1937           0 :                         --pLastCell->aEnd;
    1938           0 :                         if (pLastCell->aStart.GetIndex() == nNewIndex)
    1939             :                         {
    1940           0 :                             --pLastCell->aStart;
    1941             :                         }
    1942             :                     }
    1943             :                 }
    1944             :             }
    1945             :         }
    1946        7658 :         else if (nStartCellNodeIndex == (nLastNodeEndIndex + 1))
    1947             :         {
    1948             :             // next paragraph - now the content index of the new should be 0
    1949             :             // and of the old one should be equal to the text length
    1950             :             // but if it isn't we don't care - the cell is being inserted on
    1951             :             // the node border anyway
    1952             :         }
    1953             :         else
    1954             :         {
    1955           0 :             rbExcept = true;
    1956             :         }
    1957             :     }
    1958             :     // now check if there's a need to insert another paragraph break
    1959       16524 :     if (aEndCellPam.End()->nContent.GetIndex() <
    1960        8262 :             aEndCellPam.End()->nNode.GetNode().GetTextNode()->Len())
    1961             :     {
    1962           0 :         m_pDoc->getIDocumentContentOperations().SplitNode(*aEndCellPam.End(), false);
    1963             :         // take care that the new start/endcell is moved to the right position
    1964             :         // aStartCellPam has to point to the start of the new (previous) node
    1965             :         // aEndCellPam has to point to the end of the new (previous) node
    1966           0 :         aStartCellPam.DeleteMark();
    1967           0 :         aStartCellPam.Move(fnMoveBackward, fnGoNode);
    1968           0 :         aStartCellPam.GetPoint()->nContent = 0;
    1969           0 :         aEndCellPam.DeleteMark();
    1970           0 :         aEndCellPam.Move(fnMoveBackward, fnGoNode);
    1971           0 :         aEndCellPam.GetPoint()->nContent =
    1972           0 :             aEndCellPam.GetNode().GetTextNode()->Len();
    1973             :     }
    1974             : 
    1975             :     assert(aStartCellPam.Start()->nContent.GetIndex() == 0);
    1976             :     assert(aEndCellPam.End()->nContent.GetIndex() == aEndCellPam.End()->nNode.GetNode().GetTextNode()->Len());
    1977        8262 :     SwNodeRange aCellRange(aStartCellPam.Start()->nNode,
    1978       24786 :             aEndCellPam.End()->nNode);
    1979       16524 :     rRowNodes.push_back(aCellRange); // note: invalidates pLastCell!
    1980             : }
    1981             : 
    1982             : typedef uno::Sequence< text::TableColumnSeparator > TableColumnSeparators;
    1983             : 
    1984             : static void
    1985        2930 : lcl_ApplyRowProperties(
    1986             :     uno::Sequence<beans::PropertyValue> const& rRowProperties,
    1987             :     uno::Any const& rRow,
    1988             :     TableColumnSeparators & rRowSeparators)
    1989             : {
    1990        2930 :     uno::Reference< beans::XPropertySet > xRow;
    1991        2930 :     rRow >>= xRow;
    1992        2930 :     const beans::PropertyValue* pProperties = rRowProperties.getConstArray();
    1993       11841 :     for (sal_Int32 nProperty = 0; nProperty < rRowProperties.getLength();
    1994             :          ++nProperty)
    1995             :     {
    1996        8911 :         if ( pProperties[ nProperty ].Name == "TableColumnSeparators" )
    1997             :         {
    1998             :             // add the separators to access the cell's positions
    1999             :             // for vertical merging later
    2000        2896 :             TableColumnSeparators aSeparators;
    2001        2896 :             pProperties[ nProperty ].Value >>= aSeparators;
    2002        2896 :             rRowSeparators = aSeparators;
    2003             :         }
    2004        8911 :         xRow->setPropertyValue(
    2005        8911 :             pProperties[ nProperty ].Name, pProperties[ nProperty ].Value);
    2006        2930 :     }
    2007        2930 : }
    2008             : 
    2009             : #if OSL_DEBUG_LEVEL > 0
    2010             : //-->debug cell properties of all rows
    2011             : static void
    2012             : lcl_DebugCellProperties(
    2013             :     const uno::Sequence< uno::Sequence< uno::Sequence<
    2014             :         beans::PropertyValue > > >& rCellProperties)
    2015             : {
    2016             :     OUString sNames;
    2017             :     for (sal_Int32  nDebugRow = 0; nDebugRow < rCellProperties.getLength();
    2018             :          ++nDebugRow)
    2019             :     {
    2020             :         const uno::Sequence< beans::PropertyValues > aDebugCurrentRow =
    2021             :             rCellProperties[nDebugRow];
    2022             :         sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
    2023             :         (void) nDebugCells;
    2024             :         for (sal_Int32  nDebugCell = 0; nDebugCell < nDebugCells;
    2025             :              ++nDebugCell)
    2026             :         {
    2027             :             const uno::Sequence< beans::PropertyValue >&
    2028             :                 rDebugCellProperties = aDebugCurrentRow[nDebugCell];
    2029             :             const sal_Int32 nDebugCellProperties =
    2030             :                 rDebugCellProperties.getLength();
    2031             :             for (sal_Int32  nDebugProperty = 0;
    2032             :                  nDebugProperty < nDebugCellProperties; ++nDebugProperty)
    2033             :             {
    2034             :                 sNames += rDebugCellProperties[nDebugProperty].Name + "-";
    2035             :             }
    2036             :             sNames += "+";
    2037             :         }
    2038             :         sNames += "|";
    2039             :     }
    2040             :     (void)sNames;
    2041             : }
    2042             : //--<
    2043             : #endif
    2044             : 
    2045             : static void
    2046        8223 : lcl_ApplyCellProperties(
    2047             :     const sal_Int32 nCell,
    2048             :     TableColumnSeparators const& rRowSeparators,
    2049             :     const uno::Sequence< beans::PropertyValue >& rCellProperties,
    2050             :     uno::Reference< uno::XInterface > xCell,
    2051             :     ::std::vector<VerticallyMergedCell> & rMergedCells)
    2052             : {
    2053        8223 :     const sal_Int32 nCellProperties = rCellProperties.getLength();
    2054        8223 :     const uno::Reference< beans::XPropertySet > xCellPS(xCell, uno::UNO_QUERY);
    2055       97600 :     for (sal_Int32 nProperty = 0; nProperty < nCellProperties; ++nProperty)
    2056             :     {
    2057       89377 :         const OUString & rName  = rCellProperties[nProperty].Name;
    2058       89377 :         const uno::Any & rValue = rCellProperties[nProperty].Value;
    2059       89377 :         if ( rName == "VerticalMerge" )
    2060             :         {
    2061             :             // determine left border position
    2062             :             // add the cell to a queue of merged cells
    2063         145 :             bool bMerge = false;
    2064         145 :             rValue >>= bMerge;
    2065         145 :             sal_Int32 nLeftPos = -1;
    2066         145 :             if (!nCell)
    2067             :             {
    2068          92 :                 nLeftPos = 0;
    2069             :             }
    2070          53 :             else if (rRowSeparators.getLength() >= nCell)
    2071             :             {
    2072             :                 const text::TableColumnSeparator* pSeparators =
    2073          53 :                     rRowSeparators.getConstArray();
    2074          53 :                 nLeftPos = pSeparators[nCell - 1].Position;
    2075             :             }
    2076         145 :             if (bMerge)
    2077             :             {
    2078             :                 // 'close' all the cell with the same left position
    2079             :                 // if separate vertical merges in the same column exist
    2080          56 :                 if (rMergedCells.size())
    2081             :                 {
    2082             :                     std::vector<VerticallyMergedCell>::iterator aMergedIter =
    2083          24 :                         rMergedCells.begin();
    2084         108 :                     while (aMergedIter != rMergedCells.end())
    2085             :                     {
    2086         120 :                         if (lcl_SimilarPosition(aMergedIter->nLeftPosition,
    2087          60 :                                     nLeftPos))
    2088             :                         {
    2089          48 :                             aMergedIter->bOpen = false;
    2090             :                         }
    2091          60 :                         ++aMergedIter;
    2092             :                     }
    2093             :                 }
    2094             :                 // add the new group of merged cells
    2095          56 :                 rMergedCells.push_back(VerticallyMergedCell(xCellPS, nLeftPos));
    2096             :             }
    2097             :             else
    2098             :             {
    2099             :                 // find the cell that
    2100             :                 OSL_ENSURE(rMergedCells.size(),
    2101             :                         "the first merged cell is missing");
    2102          89 :                 if (rMergedCells.size())
    2103             :                 {
    2104             :                     std::vector<VerticallyMergedCell>::iterator aMergedIter =
    2105          89 :                         rMergedCells.begin();
    2106             : #if OSL_DEBUG_LEVEL > 0
    2107             :                     bool bDbgFound = false;
    2108             : #endif
    2109         375 :                     while (aMergedIter != rMergedCells.end())
    2110             :                     {
    2111         310 :                         if (aMergedIter->bOpen &&
    2112         113 :                             lcl_SimilarPosition(aMergedIter->nLeftPosition,
    2113         113 :                                 nLeftPos))
    2114             :                         {
    2115          87 :                             aMergedIter->aCells.push_back( xCellPS );
    2116             : #if OSL_DEBUG_LEVEL > 0
    2117             :                             bDbgFound = true;
    2118             : #endif
    2119             :                         }
    2120         197 :                         ++aMergedIter;
    2121             :                     }
    2122             : #if OSL_DEBUG_LEVEL > 0
    2123             :                     OSL_ENSURE( bDbgFound,
    2124             :                             "couldn't find first vertically merged cell" );
    2125             : #endif
    2126             :                 }
    2127             :             }
    2128             :         }
    2129             :         else
    2130             :         {
    2131             :             try
    2132             :             {
    2133       89232 :                 xCellPS->setPropertyValue(rName, rValue);
    2134             :             }
    2135       15514 :             catch (const uno::Exception&)
    2136             :             {
    2137             :                 // Apply the paragraph and char properties to the cell's content
    2138             :                 const uno::Reference< text::XText > xCellText(xCell,
    2139       15514 :                         uno::UNO_QUERY);
    2140             :                 const uno::Reference< text::XTextCursor > xCellCurs =
    2141       31028 :                     xCellText->createTextCursor();
    2142       15514 :                 xCellCurs->gotoStart( sal_False );
    2143       15514 :                 xCellCurs->gotoEnd( sal_True );
    2144             :                 const uno::Reference< beans::XPropertyState >
    2145       31028 :                     xCellTextPropState(xCellCurs, uno::UNO_QUERY);
    2146             :                 try
    2147             :                 {
    2148       15514 :                     const beans::PropertyState state = xCellTextPropState->getPropertyState(rName);
    2149       13872 :                     if (state == beans::PropertyState_DEFAULT_VALUE)
    2150             :                     {
    2151             :                         const uno::Reference< beans::XPropertySet >
    2152       12229 :                             xCellTextProps(xCellCurs, uno::UNO_QUERY);
    2153       12229 :                         xCellTextProps->setPropertyValue(rName, rValue);
    2154             :                     }
    2155             :                 }
    2156        1642 :                 catch (const uno::Exception& e)
    2157             :                 {
    2158             :                     SAL_WARN( "sw.uno", "Exception when getting PropertyState: "
    2159             :                         + rName + ". Message: " + e.Message );
    2160       15514 :                 }
    2161             :             }
    2162             :         }
    2163        8223 :     }
    2164        8223 : }
    2165             : 
    2166             : static void
    2167         603 : lcl_MergeCells(::std::vector<VerticallyMergedCell> & rMergedCells)
    2168             : {
    2169         603 :     if (rMergedCells.size())
    2170             :     {
    2171             :         std::vector<VerticallyMergedCell>::iterator aMergedIter =
    2172          32 :             rMergedCells.begin();
    2173         120 :         while (aMergedIter != rMergedCells.end())
    2174             :         {
    2175             :             sal_Int32 nCellCount =
    2176          56 :                 static_cast<sal_Int32>(aMergedIter->aCells.size());
    2177             :             std::vector<uno::Reference< beans::XPropertySet > >::iterator
    2178          56 :                 aCellIter = aMergedIter->aCells.begin();
    2179          56 :             bool bFirstCell = true;
    2180             :             // the first of the cells gets the number of cells set as RowSpan
    2181             :             // the others get the inverted number of remaining merged cells
    2182             :             // (3,-2,-1)
    2183         255 :             while (aCellIter != aMergedIter->aCells.end())
    2184             :             {
    2185         143 :                 (*aCellIter)->setPropertyValue(
    2186             :                     UNO_NAME_ROW_SPAN,
    2187         143 :                     uno::makeAny(nCellCount));
    2188         143 :                 if (bFirstCell)
    2189             :                 {
    2190          56 :                     nCellCount *= -1;
    2191          56 :                     bFirstCell = false;
    2192             :                 }
    2193         143 :                 ++nCellCount;
    2194         143 :                 ++aCellIter;
    2195             :             }
    2196          56 :             ++aMergedIter;
    2197             :         }
    2198             :     }
    2199         603 : }
    2200             : 
    2201             : uno::Reference< text::XTextTable > SAL_CALL
    2202         605 : SwXText::convertToTable(
    2203             :     const uno::Sequence< uno::Sequence< uno::Sequence<
    2204             :         uno::Reference< text::XTextRange > > > >& rTableRanges,
    2205             :     const uno::Sequence< uno::Sequence< uno::Sequence<
    2206             :         beans::PropertyValue > > >& rCellProperties,
    2207             :     const uno::Sequence< uno::Sequence< beans::PropertyValue > >&
    2208             :         rRowProperties,
    2209             :     const uno::Sequence< beans::PropertyValue >& rTableProperties)
    2210             : throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    2211             : {
    2212         605 :     SolarMutexGuard aGuard;
    2213             : 
    2214         605 :     if(!IsValid())
    2215             :     {
    2216           0 :         throw  uno::RuntimeException();
    2217             :     }
    2218             : 
    2219         605 :     IDocumentRedlineAccess & rIDRA(m_pImpl->m_pDoc->getIDocumentRedlineAccess());
    2220         605 :     if (!IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineMode()))
    2221             :     {
    2222             :         throw uno::RuntimeException(
    2223           0 :             "cannot convertToTable if tracked changes are hidden!");
    2224             :     }
    2225             : 
    2226             :     //at first collect the text ranges as SwPaMs
    2227             :     const uno::Sequence< uno::Sequence< uno::Reference< text::XTextRange > > >*
    2228         605 :         pTableRanges = rTableRanges.getConstArray();
    2229        1210 :     std::vector< std::vector<SwNodeRange> > aTableNodes;
    2230         605 :     bool bExcept = false;
    2231        3549 :     for (sal_Int32 nRow = 0; !bExcept && (nRow < rTableRanges.getLength());
    2232             :             ++nRow)
    2233             :     {
    2234        2945 :         std::vector<SwNodeRange> aRowNodes;
    2235             :         const uno::Sequence< uno::Reference< text::XTextRange > >* pRow =
    2236        2945 :             pTableRanges[nRow].getConstArray();
    2237        2945 :         const sal_Int32 nCells(pTableRanges[nRow].getLength());
    2238             : 
    2239       11207 :         for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
    2240             :         {
    2241             :             SwNodeRange *pLastCell;
    2242        8263 :             if (nCell == 0 && nRow == 0)
    2243             :             {
    2244         604 :                 pLastCell = nullptr;
    2245             :             }
    2246             :             else
    2247             :             {
    2248        7659 :                 std::vector<SwNodeRange>& rRowOfPrevCell = nCell ? aRowNodes : *aTableNodes.rbegin();
    2249        7659 :                 pLastCell = !rRowOfPrevCell.empty() ? &*rRowOfPrevCell.rbegin() : nullptr;
    2250             :             }
    2251        8263 :             m_pImpl->ConvertCell(pRow[nCell], aRowNodes, pLastCell, bExcept);
    2252             :         }
    2253        2944 :         aTableNodes.push_back(aRowNodes);
    2254        2945 :     }
    2255             : 
    2256         604 :     if(bExcept)
    2257             :     {
    2258           0 :         m_pImpl->m_pDoc->GetIDocumentUndoRedo().Undo();
    2259           0 :         throw lang::IllegalArgumentException();
    2260             :     }
    2261             : 
    2262             :     std::vector< TableColumnSeparators >
    2263        1208 :         aRowSeparators(rRowProperties.getLength());
    2264        1208 :     std::vector<VerticallyMergedCell> aMergedCells;
    2265             : 
    2266         604 :     SwTable const*const pTable = m_pImpl->m_pDoc->TextToTable( aTableNodes );
    2267             : 
    2268         604 :     if (!pTable)
    2269           1 :         return uno::Reference< text::XTextTable >();
    2270             : 
    2271             :     uno::Reference<text::XTextTable> const xRet =
    2272        1206 :         SwXTextTable::CreateXTextTable(pTable->GetFrameFormat());
    2273        1206 :     uno::Reference<beans::XPropertySet> const xPrSet(xRet, uno::UNO_QUERY);
    2274             :     // set properties to the table
    2275             :     // catch lang::WrappedTargetException and lang::IndexOutOfBoundsException
    2276             :     try
    2277             :     {
    2278             :         //apply table properties
    2279             :         const beans::PropertyValue* pTableProperties =
    2280         603 :             rTableProperties.getConstArray();
    2281        8394 :         for (sal_Int32 nProperty = 0; nProperty < rTableProperties.getLength();
    2282             :              ++nProperty)
    2283             :         {
    2284             :             try
    2285             :             {
    2286       15582 :                 xPrSet->setPropertyValue( pTableProperties[nProperty].Name,
    2287       15582 :                         pTableProperties[nProperty].Value );
    2288             :             }
    2289        2435 :             catch (const uno::Exception& e)
    2290             :             {
    2291             :                 SAL_WARN( "sw.uno", "Exception when setting property: "
    2292             :                     + pTableProperties[nProperty].Name + ". Message: " + e.Message );
    2293             :             }
    2294             :         }
    2295             : 
    2296             :         //apply row properties
    2297         603 :         const uno::Reference< table::XTableRows >  xRows = xRet->getRows();
    2298             : 
    2299             :         const beans::PropertyValues* pRowProperties =
    2300         603 :             rRowProperties.getConstArray();
    2301        3533 :         for (sal_Int32 nRow = 0; nRow < xRows->getCount(); ++nRow)
    2302             :         {
    2303        2930 :             if( nRow >= rRowProperties.getLength())
    2304             :             {
    2305           0 :                 break;
    2306             :             }
    2307        2930 :             lcl_ApplyRowProperties(pRowProperties[nRow],
    2308        5860 :                 xRows->getByIndex(nRow), aRowSeparators[nRow]);
    2309             :         }
    2310             : 
    2311             : #if OSL_DEBUG_LEVEL > 0
    2312             :         lcl_DebugCellProperties(rCellProperties);
    2313             : #endif
    2314             : 
    2315        1206 :         uno::Reference<table::XCellRange> const xCR(xRet, uno::UNO_QUERY_THROW);
    2316             :         //apply cell properties
    2317        3533 :         for (sal_Int32 nRow = 0; nRow < rCellProperties.getLength(); ++nRow)
    2318             :         {
    2319             :             const uno::Sequence< beans::PropertyValues > aCurrentRow =
    2320        2930 :                 rCellProperties[nRow];
    2321        2930 :             sal_Int32 nCells = aCurrentRow.getLength();
    2322       11153 :             for (sal_Int32  nCell = 0; nCell < nCells; ++nCell)
    2323             :             {
    2324             :                 lcl_ApplyCellProperties(nCell,
    2325        8223 :                     aRowSeparators[nRow], aCurrentRow[nCell],
    2326        8223 :                     xCR->getCellByPosition(nCell, nRow),
    2327       16446 :                     aMergedCells);
    2328             :             }
    2329        2930 :         }
    2330             :         // now that the cell properties are set the vertical merge values
    2331             :         // have to be applied
    2332        1206 :         lcl_MergeCells(aMergedCells);
    2333             :     }
    2334           0 :     catch (const lang::WrappedTargetException&)
    2335             :     {
    2336             :     }
    2337           0 :     catch (const lang::IndexOutOfBoundsException&)
    2338             :     {
    2339             :     }
    2340             : 
    2341             :     assert(SwTable::FindTable(pTable->GetFrameFormat()) == pTable);
    2342             :     assert(pTable->GetFrameFormat() ==
    2343             :             dynamic_cast<SwXTextTable&>(*xRet.get()).GetFrameFormat());
    2344        1208 :     return xRet;
    2345             : }
    2346             : 
    2347             : void SAL_CALL
    2348          81 : SwXText::copyText(
    2349             :     const uno::Reference< text::XTextCopy >& xSource )
    2350             : throw (uno::RuntimeException, std::exception)
    2351             : {
    2352          81 :     SolarMutexGuard aGuard;
    2353             : 
    2354         162 :     uno::Reference< text::XText > const xText(xSource, uno::UNO_QUERY_THROW);
    2355             :     uno::Reference< text::XTextCursor > const xCursor =
    2356         162 :         xText->createTextCursor();
    2357          81 :     xCursor->gotoEnd( sal_True );
    2358             : 
    2359             :     uno::Reference< lang::XUnoTunnel > const xCursorTunnel(xCursor,
    2360         162 :         uno::UNO_QUERY_THROW);
    2361             : 
    2362             :     OTextCursorHelper *const pCursor =
    2363          81 :         ::sw::UnoTunnelGetImplementation<OTextCursorHelper>(xCursorTunnel);
    2364          81 :     if (!pCursor)
    2365             :     {
    2366           0 :         throw uno::RuntimeException();
    2367             :     }
    2368             : 
    2369         162 :     SwNodeIndex rNdIndex( *GetStartNode( ), 1 );
    2370         162 :     SwPosition rPos( rNdIndex );
    2371         162 :     m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange( *pCursor->GetPaM(), rPos, /*bCopyAll=*/false, /*bCheckPos=*/true );
    2372          81 : }
    2373             : 
    2374        2500 : SwXBodyText::SwXBodyText(SwDoc *const pDoc)
    2375        2500 :     : SwXText(pDoc, CURSOR_BODY)
    2376             : {
    2377        2500 : }
    2378             : 
    2379        4994 : SwXBodyText::~SwXBodyText()
    2380             : {
    2381        4994 : }
    2382             : 
    2383             : OUString SAL_CALL
    2384           0 : SwXBodyText::getImplementationName() throw (uno::RuntimeException, std::exception)
    2385             : {
    2386           0 :     return OUString("SwXBodyText");
    2387             : }
    2388             : 
    2389             : static char const*const g_ServicesBodyText[] =
    2390             : {
    2391             :     "com.sun.star.text.Text",
    2392             : };
    2393             : 
    2394             : static const size_t g_nServicesBodyText(
    2395             :     sizeof(g_ServicesBodyText)/sizeof(g_ServicesBodyText[0]));
    2396             : 
    2397           1 : sal_Bool SAL_CALL SwXBodyText::supportsService(const OUString& rServiceName)
    2398             : throw (uno::RuntimeException, std::exception)
    2399             : {
    2400           1 :     return cppu::supportsService(this, rServiceName);
    2401             : }
    2402             : 
    2403             : uno::Sequence< OUString > SAL_CALL
    2404           1 : SwXBodyText::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
    2405             : {
    2406             :     return ::sw::GetSupportedServiceNamesImpl(
    2407           1 :             g_nServicesBodyText, g_ServicesBodyText);
    2408             : }
    2409             : 
    2410             : uno::Any SAL_CALL
    2411        3173 : SwXBodyText::queryAggregation(const uno::Type& rType)
    2412             : throw (uno::RuntimeException, std::exception)
    2413             : {
    2414        3173 :     uno::Any aRet;
    2415        3173 :     if (rType == cppu::UnoType<container::XEnumerationAccess>::get())
    2416             :     {
    2417        2827 :         aRet <<= uno::Reference< container::XEnumerationAccess >(this);
    2418             :     }
    2419         346 :     else if (rType == cppu::UnoType<container::XElementAccess>::get())
    2420             :     {
    2421          10 :         aRet <<= uno::Reference< container::XElementAccess >(this);
    2422             :     }
    2423         336 :     else if (rType == cppu::UnoType<lang::XServiceInfo>::get())
    2424             :     {
    2425           2 :         aRet <<= uno::Reference< lang::XServiceInfo >(this);
    2426             :     }
    2427             :     else
    2428             :     {
    2429         334 :         aRet = SwXText::queryInterface( rType );
    2430             :     }
    2431        3173 :     if(aRet.getValueType() == cppu::UnoType<void>::get())
    2432             :     {
    2433         334 :         aRet = OWeakAggObject::queryAggregation( rType );
    2434             :     }
    2435        3173 :     return aRet;
    2436             : }
    2437             : 
    2438             : uno::Sequence< uno::Type > SAL_CALL
    2439          18 : SwXBodyText::getTypes() throw (uno::RuntimeException, std::exception)
    2440             : {
    2441          18 :     const uno::Sequence< uno::Type > aTypes = SwXBodyText_Base::getTypes();
    2442          36 :     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
    2443          36 :     return ::comphelper::concatSequences(aTypes, aTextTypes);
    2444             : }
    2445             : 
    2446             : uno::Sequence< sal_Int8 > SAL_CALL
    2447           0 : SwXBodyText::getImplementationId() throw (uno::RuntimeException, std::exception)
    2448             : {
    2449           0 :     return css::uno::Sequence<sal_Int8>();
    2450             : }
    2451             : 
    2452             : uno::Any SAL_CALL
    2453       14423 : SwXBodyText::queryInterface(const uno::Type& rType)
    2454             : throw (uno::RuntimeException, std::exception)
    2455             : {
    2456       14423 :     const uno::Any ret = SwXText::queryInterface(rType);
    2457       14423 :     return (ret.getValueType() == cppu::UnoType<void>::get())
    2458             :         ?   SwXBodyText_Base::queryInterface(rType)
    2459       14423 :         :   ret;
    2460             : }
    2461             : 
    2462       31877 : SwXTextCursor * SwXBodyText::CreateTextCursor(const bool bIgnoreTables)
    2463             : {
    2464       31877 :     if(!IsValid())
    2465             :     {
    2466           0 :         return 0;
    2467             :     }
    2468             : 
    2469             :     // the cursor has to skip tables contained in this text
    2470       31877 :     SwPaM aPam(GetDoc()->GetNodes().GetEndOfContent());
    2471       31877 :     aPam.Move( fnMoveBackward, fnGoDoc );
    2472       31877 :     if (!bIgnoreTables)
    2473             :     {
    2474       31877 :         SwTableNode * pTableNode = aPam.GetNode().FindTableNode();
    2475       31877 :         SwContentNode * pCont = 0;
    2476       64711 :         while (pTableNode)
    2477             :         {
    2478         957 :             aPam.GetPoint()->nNode = *pTableNode->EndOfSectionNode();
    2479         957 :             pCont = GetDoc()->GetNodes().GoNext(&aPam.GetPoint()->nNode);
    2480         957 :             pTableNode = pCont->FindTableNode();
    2481             :         }
    2482       31877 :         if (pCont)
    2483             :         {
    2484         949 :             aPam.GetPoint()->nContent.Assign(pCont, 0);
    2485             :         }
    2486             :     }
    2487       31877 :     return new SwXTextCursor(*GetDoc(), this, CURSOR_BODY, *aPam.GetPoint());
    2488             : }
    2489             : 
    2490             : uno::Reference< text::XTextCursor > SAL_CALL
    2491       31877 : SwXBodyText::createTextCursor() throw (uno::RuntimeException, std::exception)
    2492             : {
    2493       31877 :     SolarMutexGuard aGuard;
    2494             : 
    2495             :     const uno::Reference< text::XTextCursor > xRef(
    2496       31877 :             static_cast<text::XWordCursor*>(CreateTextCursor(false)) );
    2497       31877 :     if (!xRef.is())
    2498             :     {
    2499           0 :         uno::RuntimeException aRuntime;
    2500           0 :         aRuntime.Message = cInvalidObject;
    2501           0 :         throw aRuntime;
    2502             :     }
    2503       31877 :     return xRef;
    2504             : }
    2505             : 
    2506             : uno::Reference< text::XTextCursor > SAL_CALL
    2507       13778 : SwXBodyText::createTextCursorByRange(
    2508             :     const uno::Reference< text::XTextRange > & xTextPosition)
    2509             : throw (uno::RuntimeException, std::exception)
    2510             : {
    2511       13778 :     SolarMutexGuard aGuard;
    2512             : 
    2513       13778 :     if(!IsValid())
    2514             :     {
    2515           0 :         uno::RuntimeException aRuntime;
    2516           0 :         aRuntime.Message = cInvalidObject;
    2517           0 :         throw aRuntime;
    2518             :     }
    2519             : 
    2520       13778 :     uno::Reference< text::XTextCursor >  aRef;
    2521       27556 :     SwUnoInternalPaM aPam(*GetDoc());
    2522       13778 :     if (::sw::XTextRangeToSwPaM(aPam, xTextPosition))
    2523             :     {
    2524       13773 :         if ( !aPam.GetNode().GetTextNode() )
    2525           0 :             throw uno::RuntimeException("Invalid text range" );
    2526             : 
    2527       13773 :         SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
    2528             : 
    2529       13773 :         SwStartNode* p1 = aPam.GetNode().StartOfSectionNode();
    2530             :         //document starts with a section?
    2531       29655 :         while(p1->IsSectionNode())
    2532             :         {
    2533        2109 :             p1 = p1->StartOfSectionNode();
    2534             :         }
    2535       13773 :         SwStartNode *const p2 = rNode.StartOfSectionNode();
    2536             : 
    2537       13773 :         if(p1 == p2)
    2538             :         {
    2539             :             aRef = static_cast<text::XWordCursor*>(
    2540       13773 :                     new SwXTextCursor(*GetDoc(), this, CURSOR_BODY,
    2541       13773 :                         *aPam.GetPoint(), aPam.GetMark()));
    2542             :         }
    2543             :     }
    2544       13778 :     if(!aRef.is())
    2545             :     {
    2546             :         throw uno::RuntimeException( "End of content node doesn't have the proper start node",
    2547           5 :                uno::Reference< uno::XInterface >( *this ) );
    2548             :     }
    2549       27551 :     return aRef;
    2550             : }
    2551             : 
    2552             : uno::Reference< container::XEnumeration > SAL_CALL
    2553        2880 : SwXBodyText::createEnumeration()
    2554             : throw (uno::RuntimeException, std::exception)
    2555             : {
    2556        2880 :     SolarMutexGuard aGuard;
    2557             : 
    2558        2880 :     if (!IsValid())
    2559             :     {
    2560           0 :         uno::RuntimeException aRuntime;
    2561           0 :         aRuntime.Message = cInvalidObject;
    2562           0 :         throw aRuntime;
    2563             :     }
    2564             : 
    2565        2880 :     SwNode& rNode = GetDoc()->GetNodes().GetEndOfContent();
    2566        5760 :     SwPosition aPos(rNode);
    2567        5760 :     auto pUnoCursor(GetDoc()->CreateUnoCrsr(aPos, false));
    2568        2880 :     pUnoCursor->Move(fnMoveBackward, fnGoDoc);
    2569        5760 :     return SwXParagraphEnumeration::Create(this, pUnoCursor, CURSOR_BODY);
    2570             : }
    2571             : 
    2572             : uno::Type SAL_CALL
    2573           1 : SwXBodyText::getElementType() throw (uno::RuntimeException, std::exception)
    2574             : {
    2575           1 :     return cppu::UnoType<text::XTextRange>::get();
    2576             : }
    2577             : 
    2578             : sal_Bool SAL_CALL
    2579           1 : SwXBodyText::hasElements() throw (uno::RuntimeException, std::exception)
    2580             : {
    2581           1 :     SolarMutexGuard aGuard;
    2582             : 
    2583           1 :     if (!IsValid())
    2584             :     {
    2585           0 :         uno::RuntimeException aRuntime;
    2586           0 :         aRuntime.Message = cInvalidObject;
    2587           0 :         throw aRuntime;
    2588             :     }
    2589             : 
    2590           1 :     return sal_True;
    2591             : }
    2592             : 
    2593        2942 : class SwXHeadFootText::Impl
    2594             :     : public SwClient
    2595             : {
    2596             : 
    2597             : public:
    2598             : 
    2599             :     bool                        m_bIsHeader;
    2600             : 
    2601        1471 :     Impl(   SwXHeadFootText & /*rThis*/,
    2602             :             SwFrameFormat & rHeadFootFormat, const bool bIsHeader)
    2603             :         : SwClient(& rHeadFootFormat)
    2604        1471 :         , m_bIsHeader(bIsHeader)
    2605             :     {
    2606        1471 :     }
    2607             : 
    2608        9826 :     SwFrameFormat * GetHeadFootFormat() const {
    2609             :         return static_cast<SwFrameFormat*>(
    2610        9826 :                 const_cast<SwModify*>(GetRegisteredIn()));
    2611             :     }
    2612             : 
    2613        7126 :     SwFrameFormat & GetHeadFootFormatOrThrow() {
    2614        7126 :         SwFrameFormat *const pFormat( GetHeadFootFormat() );
    2615        7126 :         if (!pFormat) {
    2616           0 :             throw uno::RuntimeException("SwXHeadFootText: disposed or invalid", 0);
    2617             :         }
    2618        7126 :         return *pFormat;
    2619             :     }
    2620             : protected:
    2621             :     // SwClient
    2622             :     virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew) SAL_OVERRIDE;
    2623             : 
    2624             : };
    2625             : 
    2626         147 : void SwXHeadFootText::Impl::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew)
    2627             : {
    2628         147 :     ClientModify(this, pOld, pNew);
    2629         147 : }
    2630             : 
    2631           0 : bool SwXHeadFootText::IsXHeadFootText(SwClient *const pClient)
    2632             : {
    2633           0 :     return 0 != dynamic_cast<SwXHeadFootText::Impl*>(pClient);
    2634             : }
    2635             : 
    2636             : uno::Reference< text::XText >
    2637        1684 : SwXHeadFootText::CreateXHeadFootText(
    2638             :         SwFrameFormat & rHeadFootFormat, const bool bIsHeader)
    2639             : {
    2640             :     // re-use existing SwXHeadFootText
    2641             :     // #i105557#: do not iterate over the registered clients: race condition
    2642        1684 :     uno::Reference< text::XText > xText(rHeadFootFormat.GetXObject(),
    2643        1684 :             uno::UNO_QUERY);
    2644        1684 :     if (!xText.is())
    2645             :     {
    2646             :         SwXHeadFootText *const pXHFT(
    2647        1471 :                 new SwXHeadFootText(rHeadFootFormat, bIsHeader));
    2648        1471 :         xText.set(pXHFT);
    2649        1471 :         rHeadFootFormat.SetXObject(xText);
    2650             :     }
    2651        1684 :     return xText;
    2652             : }
    2653             : 
    2654        1471 : SwXHeadFootText::SwXHeadFootText(SwFrameFormat & rHeadFootFormat, const bool bIsHeader)
    2655             :     : SwXText(rHeadFootFormat.GetDoc(),
    2656             :             (bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER)
    2657        1471 :     , m_pImpl( new SwXHeadFootText::Impl(*this, rHeadFootFormat, bIsHeader) )
    2658             : {
    2659        1471 : }
    2660             : 
    2661        2942 : SwXHeadFootText::~SwXHeadFootText()
    2662             : {
    2663        2942 : }
    2664             : 
    2665             : OUString SAL_CALL
    2666           2 : SwXHeadFootText::getImplementationName() throw (uno::RuntimeException, std::exception)
    2667             : {
    2668           2 :     return OUString("SwXHeadFootText");
    2669             : }
    2670             : 
    2671             : static char const*const g_ServicesHeadFootText[] =
    2672             : {
    2673             :     "com.sun.star.text.Text",
    2674             : };
    2675             : 
    2676           1 : sal_Bool SAL_CALL SwXHeadFootText::supportsService(const OUString& rServiceName)
    2677             : throw (uno::RuntimeException, std::exception)
    2678             : {
    2679           1 :     return cppu::supportsService(this, rServiceName);
    2680             : }
    2681             : 
    2682             : uno::Sequence< OUString > SAL_CALL
    2683           1 : SwXHeadFootText::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
    2684             : {
    2685             :     return ::sw::GetSupportedServiceNamesImpl(
    2686             :             SAL_N_ELEMENTS(g_ServicesHeadFootText),
    2687           1 :             g_ServicesHeadFootText);
    2688             : }
    2689             : 
    2690        2700 : const SwStartNode *SwXHeadFootText::GetStartNode() const
    2691             : {
    2692        2700 :     const SwStartNode *pSttNd = 0;
    2693        2700 :     SwFrameFormat *const pHeadFootFormat = m_pImpl->GetHeadFootFormat();
    2694        2700 :     if(pHeadFootFormat)
    2695             :     {
    2696        2700 :         const SwFormatContent& rFlyContent = pHeadFootFormat->GetContent();
    2697        2700 :         if( rFlyContent.GetContentIdx() )
    2698             :         {
    2699        2700 :             pSttNd = rFlyContent.GetContentIdx()->GetNode().GetStartNode();
    2700             :         }
    2701             :     }
    2702        2700 :     return pSttNd;
    2703             : }
    2704             : 
    2705             : uno::Reference< text::XTextCursor >
    2706        3156 : SwXHeadFootText::CreateCursor() throw (uno::RuntimeException)
    2707             : {
    2708        3156 :     return createTextCursor();
    2709             : }
    2710             : 
    2711             : uno::Sequence< uno::Type > SAL_CALL
    2712           0 : SwXHeadFootText::getTypes() throw (uno::RuntimeException, std::exception)
    2713             : {
    2714           0 :     const uno::Sequence< uno::Type > aTypes = SwXHeadFootText_Base::getTypes();
    2715           0 :     const uno::Sequence< uno::Type > aTextTypes = SwXText::getTypes();
    2716           0 :     return ::comphelper::concatSequences(aTypes, aTextTypes);
    2717             : }
    2718             : 
    2719             : uno::Sequence< sal_Int8 > SAL_CALL
    2720           0 : SwXHeadFootText::getImplementationId() throw (uno::RuntimeException, std::exception)
    2721             : {
    2722           0 :     return css::uno::Sequence<sal_Int8>();
    2723             : }
    2724             : 
    2725             : uno::Any SAL_CALL
    2726        5809 : SwXHeadFootText::queryInterface(const uno::Type& rType)
    2727             : throw (uno::RuntimeException, std::exception)
    2728             : {
    2729        5809 :     const uno::Any ret = SwXHeadFootText_Base::queryInterface(rType);
    2730        5809 :     return (ret.getValueType() == cppu::UnoType<void>::get())
    2731             :         ?   SwXText::queryInterface(rType)
    2732        5809 :         :   ret;
    2733             : }
    2734             : 
    2735             : uno::Reference< text::XTextCursor > SAL_CALL
    2736        6307 : SwXHeadFootText::createTextCursor() throw (uno::RuntimeException, std::exception)
    2737             : {
    2738        6307 :     SolarMutexGuard aGuard;
    2739             : 
    2740        6307 :     SwFrameFormat & rHeadFootFormat( m_pImpl->GetHeadFootFormatOrThrow() );
    2741             : 
    2742        6307 :     uno::Reference< text::XTextCursor > xRet;
    2743        6307 :     const SwFormatContent& rFlyContent = rHeadFootFormat.GetContent();
    2744        6307 :     const SwNode& rNode = rFlyContent.GetContentIdx()->GetNode();
    2745       12614 :     SwPosition aPos(rNode);
    2746        6307 :     SwXTextCursor *const pXCursor = new SwXTextCursor(*GetDoc(), this,
    2747        6307 :             (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER, aPos);
    2748        6307 :     auto pUnoCrsr(pXCursor->GetCursor());
    2749        6307 :     pUnoCrsr->Move(fnMoveForward, fnGoNode);
    2750             : 
    2751             :     // save current start node to be able to check if there is content
    2752             :     // after the table - otherwise the cursor would be in the body text!
    2753             :     SwStartNode const*const pOwnStartNode = rNode.FindSttNodeByType(
    2754        6307 :             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
    2755             :     // is there a table here?
    2756        6307 :     SwTableNode* pTableNode = pUnoCrsr->GetNode().FindTableNode();
    2757        6307 :     SwContentNode* pCont = 0;
    2758       12705 :     while (pTableNode)
    2759             :     {
    2760          91 :         pUnoCrsr->GetPoint()->nNode = *pTableNode->EndOfSectionNode();
    2761          91 :         pCont = GetDoc()->GetNodes().GoNext(&pUnoCrsr->GetPoint()->nNode);
    2762          91 :         pTableNode = pCont->FindTableNode();
    2763             :     }
    2764        6307 :     if (pCont)
    2765             :     {
    2766          88 :         pUnoCrsr->GetPoint()->nContent.Assign(pCont, 0);
    2767             :     }
    2768             :     SwStartNode const*const pNewStartNode =
    2769        6307 :         pUnoCrsr->GetNode().FindSttNodeByType(
    2770       12614 :             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
    2771        6307 :     if (!pNewStartNode || (pNewStartNode != pOwnStartNode))
    2772             :     {
    2773           0 :         uno::RuntimeException aExcept;
    2774           0 :         aExcept.Message = "no text available";
    2775           0 :         throw aExcept;
    2776             :     }
    2777        6307 :     xRet = static_cast<text::XWordCursor*>(pXCursor);
    2778       12614 :     return xRet;
    2779             : }
    2780             : 
    2781             : uno::Reference< text::XTextCursor > SAL_CALL
    2782         750 : SwXHeadFootText::createTextCursorByRange(
    2783             :     const uno::Reference< text::XTextRange > & xTextPosition)
    2784             : throw (uno::RuntimeException, std::exception)
    2785             : {
    2786         750 :     SolarMutexGuard aGuard;
    2787             : 
    2788         750 :     SwFrameFormat & rHeadFootFormat( m_pImpl->GetHeadFootFormatOrThrow() );
    2789             : 
    2790        1500 :     SwUnoInternalPaM aPam(*GetDoc());
    2791         750 :     if (!::sw::XTextRangeToSwPaM(aPam, xTextPosition))
    2792             :     {
    2793           0 :         uno::RuntimeException aRuntime;
    2794           0 :         aRuntime.Message = cInvalidObject;
    2795           0 :         throw aRuntime;
    2796             :     }
    2797             : 
    2798         750 :     uno::Reference< text::XTextCursor >  xRet;
    2799         750 :     SwNode& rNode = rHeadFootFormat.GetContent().GetContentIdx()->GetNode();
    2800        1500 :     SwPosition aPos(rNode);
    2801        1500 :     SwPaM aHFPam(aPos);
    2802         750 :     aHFPam.Move(fnMoveForward, fnGoNode);
    2803         750 :     SwStartNode *const pOwnStartNode = aHFPam.GetNode().FindSttNodeByType(
    2804        1500 :             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
    2805         750 :     SwStartNode *const p1 = aPam.GetNode().FindSttNodeByType(
    2806        1500 :             (m_pImpl->m_bIsHeader) ? SwHeaderStartNode : SwFooterStartNode);
    2807         750 :     if (p1 == pOwnStartNode)
    2808             :     {
    2809             :         xRet = static_cast<text::XWordCursor*>(
    2810         750 :                 new SwXTextCursor(*GetDoc(), this,
    2811         750 :                     (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER,
    2812        1500 :                     *aPam.GetPoint(), aPam.GetMark()));
    2813             :     }
    2814        1500 :     return xRet;
    2815             : }
    2816             : 
    2817             : uno::Reference< container::XEnumeration > SAL_CALL
    2818          69 : SwXHeadFootText::createEnumeration()
    2819             : throw (uno::RuntimeException, std::exception)
    2820             : {
    2821          69 :     SolarMutexGuard aGuard;
    2822             : 
    2823          69 :     SwFrameFormat & rHeadFootFormat( m_pImpl->GetHeadFootFormatOrThrow() );
    2824             : 
    2825         138 :     uno::Reference< container::XEnumeration >  aRef;
    2826          69 :     const SwFormatContent& rFlyContent = rHeadFootFormat.GetContent();
    2827          69 :     const SwNode& rNode = rFlyContent.GetContentIdx()->GetNode();
    2828         138 :     SwPosition aPos(rNode);
    2829         138 :     auto pUnoCursor(GetDoc()->CreateUnoCrsr(aPos, false));
    2830          69 :     pUnoCursor->Move(fnMoveForward, fnGoNode);
    2831         138 :     return SwXParagraphEnumeration::Create(this, pUnoCursor, (m_pImpl->m_bIsHeader) ? CURSOR_HEADER : CURSOR_FOOTER);
    2832             : }
    2833             : 
    2834             : uno::Type SAL_CALL
    2835           1 : SwXHeadFootText::getElementType() throw (uno::RuntimeException, std::exception)
    2836             : {
    2837           1 :     return cppu::UnoType<text::XTextRange>::get();
    2838             : }
    2839             : 
    2840           1 : sal_Bool SAL_CALL SwXHeadFootText::hasElements() throw (uno::RuntimeException, std::exception)
    2841             : {
    2842           1 :     return sal_True;
    2843         177 : }
    2844             : 
    2845             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11