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

Generated by: LCOV version 1.10