LCOV - code coverage report
Current view: top level - sw/source/core/doc - docedt.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 185 439 42.1 %
Date: 2014-11-03 Functions: 12 28 42.9 %
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 <fmtanchr.hxx>
      21             : #include <fmtcntnt.hxx>
      22             : #include <txtftn.hxx>
      23             : #include <acorrect.hxx>
      24             : #include <UndoManager.hxx>
      25             : #include <IDocumentRedlineAccess.hxx>
      26             : #include <IDocumentState.hxx>
      27             : #include <IDocumentLayoutAccess.hxx>
      28             : #include <docsh.hxx>
      29             : #include <docary.hxx>
      30             : #include <doctxm.hxx>
      31             : #include <ftnidx.hxx>
      32             : #include <mdiexp.hxx>
      33             : #include <mvsave.hxx>
      34             : #include <redline.hxx>
      35             : #include <rootfrm.hxx>
      36             : #include <splargs.hxx>
      37             : #include <txtfrm.hxx>
      38             : #include <breakit.hxx>
      39             : #include <vcl/layout.hxx>
      40             : #include "comcore.hrc"
      41             : #include "editsh.hxx"
      42             : #include <fmtfld.hxx>
      43             : #include <docufld.hxx>
      44             : #include <unoflatpara.hxx>
      45             : #include <SwGrammarMarkUp.hxx>
      46             : #include <docedt.hxx>
      47             : 
      48             : #include <vector>
      49             : 
      50             : using namespace ::com::sun::star;
      51             : using namespace ::com::sun::star::linguistic2;
      52             : using namespace ::com::sun::star::i18n;
      53             : 
      54             : 
      55          12 : void _RestFlyInRange( _SaveFlyArr & rArr, const SwNodeIndex& rSttIdx,
      56             :                       const SwNodeIndex* pInsertPos )
      57             : {
      58          12 :     SwPosition aPos( rSttIdx );
      59          12 :     for( size_t n = 0; n < rArr.size(); ++n )
      60             :     {
      61             :         // create new anchor
      62           0 :         _SaveFly& rSave = rArr[n];
      63           0 :         SwFrmFmt* pFmt = rSave.pFrmFmt;
      64             : 
      65           0 :         if( rSave.bInsertPosition )
      66             :         {
      67           0 :             if( pInsertPos != NULL )
      68           0 :                 aPos.nNode = *pInsertPos;
      69             :             else
      70           0 :                 aPos.nNode = rSttIdx.GetIndex();
      71             :         }
      72             :         else
      73           0 :             aPos.nNode = rSttIdx.GetIndex() + rSave.nNdDiff;
      74             : 
      75           0 :         aPos.nContent.Assign( 0, 0 );
      76           0 :         SwFmtAnchor aAnchor( pFmt->GetAnchor() );
      77           0 :         aAnchor.SetAnchor( &aPos );
      78           0 :         pFmt->GetDoc()->GetSpzFrmFmts()->push_back( pFmt );
      79           0 :         pFmt->SetFmtAttr( aAnchor );
      80           0 :         SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
      81           0 :         if( pCNd && pCNd->getLayoutFrm( pFmt->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), 0, 0, false ) )
      82           0 :             pFmt->MakeFrms();
      83          12 :     }
      84          12 : }
      85             : 
      86           0 : void _SaveFlyInRange( const SwNodeRange& rRg, _SaveFlyArr& rArr )
      87             : {
      88           0 :     SwFrmFmts& rFmts = *rRg.aStart.GetNode().GetDoc()->GetSpzFrmFmts();
      89           0 :     for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
      90             :     {
      91           0 :         SwFrmFmt *const pFmt = static_cast<SwFrmFmt*>(rFmts[n]);
      92           0 :         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
      93           0 :         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
      94           0 :         if (pAPos &&
      95           0 :             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
      96           0 :              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
      97           0 :             rRg.aStart <= pAPos->nNode && pAPos->nNode < rRg.aEnd )
      98             :         {
      99           0 :             _SaveFly aSave( pAPos->nNode.GetIndex() - rRg.aStart.GetIndex(),
     100           0 :                             pFmt, false );
     101           0 :             rArr.push_back( aSave );
     102           0 :             pFmt->DelFrms();
     103           0 :             rFmts.erase( rFmts.begin() + n-- );
     104             :         }
     105             :     }
     106           0 : }
     107             : 
     108          12 : void _SaveFlyInRange( const SwPaM& rPam, const SwNodeIndex& rInsPos,
     109             :                        _SaveFlyArr& rArr, bool bMoveAllFlys )
     110             : {
     111          12 :     SwFrmFmts& rFmts = *rPam.GetPoint()->nNode.GetNode().GetDoc()->GetSpzFrmFmts();
     112             :     SwFrmFmt* pFmt;
     113             :     const SwFmtAnchor* pAnchor;
     114             : 
     115          12 :     const SwPosition* pPos = rPam.Start();
     116          12 :     const SwNodeIndex& rSttNdIdx = pPos->nNode;
     117          12 :     short nSttOff = (!bMoveAllFlys && rSttNdIdx.GetNode().IsCntntNode() &&
     118          12 :                     pPos->nContent.GetIndex()) ? 1 : 0;
     119             : 
     120          12 :     pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint();
     121          12 :     const SwNodeIndex& rEndNdIdx = pPos->nNode;
     122           0 :     short nOff = ( bMoveAllFlys || ( rEndNdIdx.GetNode().IsCntntNode() &&
     123           0 :                 pPos->nContent == rEndNdIdx.GetNode().GetCntntNode()->Len() ))
     124          12 :                     ? 0 : 1;
     125             : 
     126             :     const SwNodeIndex* pCntntIdx;
     127             : 
     128          12 :     for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
     129             :     {
     130           0 :         bool bInsPos = false;
     131           0 :         pFmt = (SwFrmFmt*)rFmts[n];
     132           0 :         pAnchor = &pFmt->GetAnchor();
     133           0 :         const SwPosition* pAPos = pAnchor->GetCntntAnchor();
     134           0 :         if (pAPos &&
     135           0 :             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
     136           0 :              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
     137             :             // do not move if the InsPos is in the CntntArea of the Fly
     138           0 :             ( 0 == ( pCntntIdx = pFmt->GetCntnt().GetCntntIdx() ) ||
     139           0 :               !( *pCntntIdx < rInsPos &&
     140           0 :                 rInsPos < pCntntIdx->GetNode().EndOfSectionIndex() )) )
     141             :         {
     142           0 :             if( !bMoveAllFlys && rEndNdIdx == pAPos->nNode )
     143             :             {
     144             :                 // Do not touch Anchor, if only a part of the EndNode
     145             :                 // or the whole EndNode is identical with the SttNode
     146           0 :                 if( rSttNdIdx != pAPos->nNode )
     147             :                 {
     148             :                     // Only attach an anchor to the beginning or end
     149           0 :                     SwPosition aPos( rSttNdIdx );
     150           0 :                     SwFmtAnchor aAnchor( *pAnchor );
     151           0 :                     aAnchor.SetAnchor( &aPos );
     152           0 :                     pFmt->SetFmtAttr( aAnchor );
     153             :                 }
     154             :             }
     155           0 :             else if( ( rSttNdIdx.GetIndex() + nSttOff <= pAPos->nNode.GetIndex()
     156           0 :                     && pAPos->nNode.GetIndex() <= rEndNdIdx.GetIndex() - nOff ) ||
     157           0 :                         ( bInsPos = (rInsPos == pAPos->nNode) ))
     158             : 
     159             :             {
     160           0 :                 _SaveFly aSave( pAPos->nNode.GetIndex() - rSttNdIdx.GetIndex(),
     161           0 :                                 pFmt, bInsPos );
     162           0 :                 rArr.push_back( aSave );
     163           0 :                 pFmt->DelFrms();
     164           0 :                 rFmts.erase( rFmts.begin() + n-- );
     165             :             }
     166             :         }
     167             :     }
     168          12 : }
     169             : 
     170             : /// Delete and move all Flys at the paragraph, that are within the selection.
     171             : /// If there is a Fly at the SPoint, it is moved onto the Mark.
     172       14310 : void DelFlyInRange( const SwNodeIndex& rMkNdIdx,
     173             :                     const SwNodeIndex& rPtNdIdx )
     174             : {
     175       14310 :     const bool bDelFwrd = rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex();
     176             : 
     177       14310 :     SwDoc* pDoc = rMkNdIdx.GetNode().GetDoc();
     178       14310 :     SwFrmFmts& rTbl = *pDoc->GetSpzFrmFmts();
     179       93780 :     for ( sal_uInt16 i = rTbl.size(); i; )
     180             :     {
     181       65160 :         SwFrmFmt *pFmt = rTbl[--i];
     182       65160 :         const SwFmtAnchor &rAnch = pFmt->GetAnchor();
     183       65160 :         SwPosition const*const pAPos = rAnch.GetCntntAnchor();
     184      129246 :         if (pAPos &&
     185       80222 :             ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
     186      188242 :              (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
     187             :             ( bDelFwrd
     188       89478 :                 ? rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx
     189         184 :                 : rPtNdIdx <= pAPos->nNode && pAPos->nNode < rMkNdIdx ))
     190             :         {
     191             :             // Only move the Anchor??
     192         814 :             if( rPtNdIdx == pAPos->nNode )
     193             :             {
     194          32 :                 SwFmtAnchor aAnch( pFmt->GetAnchor() );
     195          64 :                 SwPosition aPos( rMkNdIdx );
     196          32 :                 aAnch.SetAnchor( &aPos );
     197          64 :                 pFmt->SetFmtAttr( aAnch );
     198             :             }
     199             :             else
     200             :             {
     201             :                 // If the Fly is deleted, all Flys in it's content have to be deleted too.
     202         782 :                 const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
     203         782 :                 if( rCntnt.GetCntntIdx() )
     204             :                 {
     205         612 :                     DelFlyInRange( *rCntnt.GetCntntIdx(),
     206             :                                     SwNodeIndex( *rCntnt.GetCntntIdx()->
     207        1224 :                                             GetNode().EndOfSectionNode() ));
     208             :                     // Position could have been moved!
     209         612 :                     if( i > rTbl.size() )
     210           0 :                         i = rTbl.size();
     211         612 :                     else if( pFmt != rTbl[i] )
     212           0 :                         i = rTbl.GetPos( pFmt );
     213             :                 }
     214             : 
     215         782 :                 pDoc->getIDocumentLayoutAccess().DelLayoutFmt( pFmt );
     216             : 
     217             :                 // DelLayoutFmt can also trigger the deletion of objects.
     218         782 :                 if( i > rTbl.size() )
     219           0 :                     i = rTbl.size();
     220             :             }
     221             :         }
     222             :     }
     223       14310 : }
     224             : 
     225             : // #i59534: Redo of insertion of multiple text nodes runs into trouble
     226             : // because of unnecessary expanded redlines
     227             : // From now on this class saves the redline positions of all redlines which ends exact at the
     228             : // insert position (node _and_ content index)
     229         954 : _SaveRedlEndPosForRestore::_SaveRedlEndPosForRestore( const SwNodeIndex& rInsIdx, sal_Int32 nCnt )
     230         954 :     : pSavArr( 0 ), pSavIdx( 0 ), nSavCntnt( nCnt )
     231             : {
     232         954 :     SwNode& rNd = rInsIdx.GetNode();
     233         954 :     SwDoc* pDest = rNd.GetDoc();
     234         954 :     if( !pDest->getIDocumentRedlineAccess().GetRedlineTbl().empty() )
     235             :     {
     236             :         sal_uInt16 nFndPos;
     237             :         const SwPosition* pEnd;
     238          24 :         SwPosition aSrcPos( rInsIdx, SwIndex( rNd.GetCntntNode(), nCnt ));
     239          24 :         pDest->getIDocumentRedlineAccess().GetRedline( aSrcPos, &nFndPos );
     240             :         const SwRangeRedline* pRedl;
     241          48 :         while( nFndPos--
     242           6 :               && *( pEnd = ( pRedl = pDest->getIDocumentRedlineAccess().GetRedlineTbl()[ nFndPos ] )->End() ) == aSrcPos
     243          24 :               && *pRedl->Start() < aSrcPos )
     244             :         {
     245           0 :             if( !pSavArr )
     246             :             {
     247           0 :                 pSavArr = new std::vector<SwPosition*>;
     248           0 :                 pSavIdx = new SwNodeIndex( rInsIdx, -1 );
     249             :             }
     250           0 :             pSavArr->push_back( (SwPosition*)pEnd );
     251          24 :         }
     252             :     }
     253         954 : }
     254             : 
     255         954 : _SaveRedlEndPosForRestore::~_SaveRedlEndPosForRestore()
     256             : {
     257         954 :     delete pSavArr;
     258         954 :     delete pSavIdx;
     259         954 : }
     260             : 
     261           0 : void _SaveRedlEndPosForRestore::_Restore()
     262             : {
     263           0 :     ++(*pSavIdx);
     264           0 :     SwCntntNode* pNode = pSavIdx->GetNode().GetCntntNode();
     265             :     // If there's no content node at the remembered position, we will not restore the old position
     266             :     // This may happen if a table (or section?) will be inserted.
     267           0 :     if( pNode )
     268             :     {
     269           0 :         SwPosition aPos( *pSavIdx, SwIndex( pNode, nSavCntnt ));
     270           0 :         for( sal_uInt16 n = pSavArr->size(); n; )
     271           0 :             *(*pSavArr)[ --n ] = aPos;
     272             :     }
     273           0 : }
     274             : 
     275           0 : void SwDoc::SetModified(SwPaM &rPaM)
     276             : {
     277           0 :     SwDataChanged aTmp( rPaM );
     278           0 :     getIDocumentState().SetModified();
     279           0 : }
     280             : 
     281             : /// Convert list of ranges of whichIds to a corresponding list of whichIds
     282        2314 : static std::vector<sal_uInt16> * lcl_RangesToVector(sal_uInt16 * pRanges)
     283             : {
     284        2314 :     std::vector<sal_uInt16> * pResult = new std::vector<sal_uInt16>();
     285             : 
     286        2314 :     int i = 0;
     287        9256 :     while (pRanges[i] != 0)
     288             :     {
     289             :         OSL_ENSURE(pRanges[i+1] != 0, "malformed ranges");
     290             : 
     291      106444 :         for (sal_uInt16 j = pRanges[i]; j < pRanges[i+1]; j++)
     292      101816 :             pResult->push_back(j);
     293             : 
     294        4628 :         i += 2;
     295             :     }
     296             : 
     297        2314 :     return pResult;
     298             : }
     299             : 
     300        9266 : void sw_GetJoinFlags( SwPaM& rPam, bool& rJoinTxt, bool& rJoinPrev )
     301             : {
     302        9266 :     rJoinTxt = false;
     303        9266 :     rJoinPrev = false;
     304        9266 :     if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
     305             :     {
     306        5022 :         const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
     307        5022 :         SwTxtNode *pSttNd = pStt->nNode.GetNode().GetTxtNode();
     308        5022 :         if( pSttNd )
     309             :         {
     310        5018 :             SwTxtNode *pEndNd = pEnd->nNode.GetNode().GetTxtNode();
     311        5018 :             rJoinTxt = 0 != pEndNd;
     312        5018 :             if( rJoinTxt )
     313             :             {
     314        5018 :                 bool bExchange = pStt == rPam.GetPoint();
     315        7462 :                 if( !pStt->nContent.GetIndex() &&
     316        2444 :                     pEndNd->GetTxt().getLength() != pEnd->nContent.GetIndex())
     317         130 :                     bExchange = !bExchange;
     318        5018 :                 if( bExchange )
     319        4860 :                     rPam.Exchange();
     320        5018 :                 rJoinPrev = rPam.GetPoint() == pStt;
     321             :                 OSL_ENSURE( !pStt->nContent.GetIndex() &&
     322             :                     pEndNd->GetTxt().getLength() != pEnd->nContent.GetIndex()
     323             :                     ? rPam.GetPoint()->nNode < rPam.GetMark()->nNode
     324             :                     : rPam.GetPoint()->nNode > rPam.GetMark()->nNode,
     325             :                     "sw_GetJoinFlags");
     326             :             }
     327             :         }
     328             :     }
     329        9266 : }
     330             : 
     331        5018 : void sw_JoinText( SwPaM& rPam, bool bJoinPrev )
     332             : {
     333        5018 :     SwNodeIndex aIdx( rPam.GetPoint()->nNode );
     334        5018 :     SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
     335       10036 :     SwNodeIndex aOldIdx( aIdx );
     336        5018 :     SwTxtNode *pOldTxtNd = pTxtNd;
     337             : 
     338        5018 :     if( pTxtNd && pTxtNd->CanJoinNext( &aIdx ) )
     339             :     {
     340        5018 :         SwDoc* pDoc = rPam.GetDoc();
     341        5018 :         if( bJoinPrev )
     342             :         {
     343             :             // We do not need to handle xmlids in this case, because
     344             :             // it is only invoked if one paragraph is completely empty
     345             :             // (see sw_GetJoinFlags)
     346             :             {
     347             :                 // If PageBreaks are deleted/set, it must not be added to the Undo history!
     348             :                 // Also, deleteing the Node is not added to the Undo histroy!
     349         130 :                 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
     350             : 
     351             :                 /* PageBreaks, PageDesc, ColumnBreaks */
     352             :                 // If we need to change something about the logic to copy the PageBreaks,
     353             :                 // PageDesc, etc. we also have to change SwUndoDelete.
     354             :                 // There, we copy the AUTO PageBreak from the GetMarkNode!
     355             : 
     356             :                 /* The GetMarkNode */
     357         130 :                 if( ( pTxtNd = aIdx.GetNode().GetTxtNode())->HasSwAttrSet() )
     358             :                 {
     359             :                     const SfxPoolItem* pItem;
     360           0 :                     if( SfxItemState::SET == pTxtNd->GetpSwAttrSet()->GetItemState(
     361           0 :                         RES_BREAK, false, &pItem ) )
     362           0 :                         pTxtNd->ResetAttr( RES_BREAK );
     363           0 :                     if( pTxtNd->HasSwAttrSet() &&
     364           0 :                         SfxItemState::SET == pTxtNd->GetpSwAttrSet()->GetItemState(
     365           0 :                         RES_PAGEDESC, false, &pItem ) )
     366           0 :                         pTxtNd->ResetAttr( RES_PAGEDESC );
     367             :                 }
     368             : 
     369             :                 /* The PointNode */
     370         130 :                 if( pOldTxtNd->HasSwAttrSet() )
     371             :                 {
     372             :                     const SfxPoolItem* pItem;
     373           0 :                     SfxItemSet aSet( pDoc->GetAttrPool(), aBreakSetRange );
     374           0 :                     const SfxItemSet* pSet = pOldTxtNd->GetpSwAttrSet();
     375           0 :                     if( SfxItemState::SET == pSet->GetItemState( RES_BREAK,
     376           0 :                         false, &pItem ) )
     377           0 :                         aSet.Put( *pItem );
     378           0 :                     if( SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC,
     379           0 :                         false, &pItem ) )
     380           0 :                         aSet.Put( *pItem );
     381           0 :                     if( aSet.Count() )
     382           0 :                         pTxtNd->SetAttr( aSet );
     383             :                 }
     384         130 :                 pOldTxtNd->FmtToTxtAttr( pTxtNd );
     385             : 
     386         260 :                 const boost::shared_ptr< sw::mark::CntntIdxStore> pCntntStore(sw::mark::CntntIdxStore::Create());
     387         130 :                 pCntntStore->Save( pDoc, aOldIdx.GetIndex(), pOldTxtNd->Len() );
     388             : 
     389         260 :                 SwIndex aAlphaIdx(pTxtNd);
     390         130 :                 pOldTxtNd->CutText( pTxtNd, aAlphaIdx, SwIndex(pOldTxtNd),
     391         260 :                                     pOldTxtNd->Len() );
     392         260 :                 SwPosition aAlphaPos( aIdx, aAlphaIdx );
     393         130 :                 pDoc->CorrRel( rPam.GetPoint()->nNode, aAlphaPos, 0, true );
     394             : 
     395             :                 // move all Bookmarks/TOXMarks
     396         130 :                 if( !pCntntStore->Empty() )
     397           0 :                     pCntntStore->Restore( pDoc, aIdx.GetIndex() );
     398             : 
     399             :                 // If the passed PaM is not in the Crsr ring,
     400             :                 // treat it separately (e.g. when it's being called from AutoFormat)
     401         130 :                 if( pOldTxtNd == rPam.GetBound( true ).nContent.GetIdxReg() )
     402           0 :                     rPam.GetBound( true ) = aAlphaPos;
     403         130 :                 if( pOldTxtNd == rPam.GetBound( false ).nContent.GetIdxReg() )
     404         130 :                     rPam.GetBound( false ) = aAlphaPos;
     405             :             }
     406             :             // delete the Node, at last!
     407         130 :             pDoc->GetNodes().Delete( aOldIdx, 1 );
     408             :         }
     409             :         else
     410             :         {
     411        4888 :             SwTxtNode* pDelNd = aIdx.GetNode().GetTxtNode();
     412        4888 :             if( pTxtNd->Len() )
     413        2574 :                 pDelNd->FmtToTxtAttr( pTxtNd );
     414             :             else
     415             :             {
     416             :                 /* This case was missed:
     417             : 
     418             :                    <something></something>   <-- pTxtNd
     419             :                    <other>ccc</other>        <-- pDelNd
     420             : 
     421             :                    <something> and <other> are paragraph
     422             :                    attributes. The attribute <something> stayed if not
     423             :                    overwritten by an attribute in "ccc". Fixed by
     424             :                    first resetting all character attributes in first
     425             :                    paragraph (pTxtNd).
     426             :                 */
     427             :                 std::vector<sal_uInt16> * pShorts =
     428        2314 :                     lcl_RangesToVector(aCharFmtSetRange);
     429        2314 :                 pTxtNd->ResetAttr(*pShorts);
     430        2314 :                 delete pShorts;
     431             : 
     432        2314 :                 if( pDelNd->HasSwAttrSet() )
     433             :                 {
     434             :                     // only copy the character attributes
     435         260 :                     SfxItemSet aTmpSet( pDoc->GetAttrPool(), aCharFmtSetRange );
     436         260 :                     aTmpSet.Put( *pDelNd->GetpSwAttrSet() );
     437         260 :                     pTxtNd->SetAttr( aTmpSet );
     438             :                 }
     439             :             }
     440             : 
     441        4888 :             pDoc->CorrRel( aIdx, *rPam.GetPoint(), 0, true );
     442             :             // #i100466# adjust given <rPam>, if it does not belong to the cursors
     443        4888 :             if ( pDelNd == rPam.GetBound( true ).nContent.GetIdxReg() )
     444             :             {
     445           0 :                 rPam.GetBound( true ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
     446             :             }
     447        4888 :             if( pDelNd == rPam.GetBound( false ).nContent.GetIdxReg() )
     448             :             {
     449           0 :                 rPam.GetBound( false ) = SwPosition( SwNodeIndex( *pTxtNd ), SwIndex( pTxtNd ) );
     450             :             }
     451        4888 :             pTxtNd->JoinNext();
     452             :         }
     453        5018 :     }
     454        5018 : }
     455             : 
     456           0 : static void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
     457             :     const ModelToViewHelper &rConversionMap )
     458             : {
     459           0 :     if( rTxtNode.IsGrammarCheckDirty() )
     460           0 :         return;
     461           0 :     SwGrammarMarkUp* pWrong = rTxtNode.GetGrammarCheck();
     462           0 :     linguistic2::SingleProofreadingError* pArray = rResult.aErrors.getArray();
     463           0 :     sal_uInt16 i, j = 0;
     464           0 :     if( pWrong )
     465             :     {
     466           0 :         for( i = 0; i < rResult.aErrors.getLength(); ++i )
     467             :         {
     468           0 :             const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
     469           0 :             const sal_Int32 nStart = rConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos;
     470           0 :             const sal_Int32 nEnd = rConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos;
     471           0 :             if( i != j )
     472           0 :                 pArray[j] = pArray[i];
     473           0 :             if( pWrong->LookForEntry( nStart, nEnd ) )
     474           0 :                 ++j;
     475             :         }
     476             :     }
     477           0 :     if( rResult.aErrors.getLength() > j )
     478           0 :         rResult.aErrors.realloc( j );
     479             : }
     480             : 
     481          12 : uno::Any SwDoc::Spell( SwPaM& rPaM,
     482             :                     uno::Reference< XSpellChecker1 >  &xSpeller,
     483             :                     sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
     484             :                     bool bGrammarCheck,
     485             :                     SwConversionArgs *pConvArgs  ) const
     486             : {
     487          12 :     SwPosition* pSttPos = rPaM.Start(), *pEndPos = rPaM.End();
     488             : 
     489          12 :     SwSpellArgs      *pSpellArgs = 0;
     490          12 :     if (pConvArgs)
     491             :     {
     492          12 :         pConvArgs->SetStart(pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent);
     493          12 :         pConvArgs->SetEnd(  pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
     494             :     }
     495             :     else
     496             :         pSpellArgs = new SwSpellArgs( xSpeller,
     497           0 :                             pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
     498           0 :                             pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent,
     499           0 :                             bGrammarCheck );
     500             : 
     501          12 :     sal_uLong nCurrNd = pSttPos->nNode.GetIndex();
     502          12 :     sal_uLong nEndNd = pEndPos->nNode.GetIndex();
     503             : 
     504          12 :     uno::Any aRet;
     505          12 :     if( nCurrNd <= nEndNd )
     506             :     {
     507             :         SwCntntFrm* pCntFrm;
     508          12 :         bool bGoOn = true;
     509          36 :         while( bGoOn )
     510             :         {
     511          12 :             SwNode* pNd = GetNodes()[ nCurrNd ];
     512          12 :             switch( pNd->GetNodeType() )
     513             :             {
     514             :             case ND_TEXTNODE:
     515          12 :                 if( 0 != ( pCntFrm = ((SwTxtNode*)pNd)->getLayoutFrm( getIDocumentLayoutAccess().GetCurrentLayout() )) )
     516             :                 {
     517             :                     // skip protected and hidden Cells and Flys
     518          12 :                     if( pCntFrm->IsProtected() )
     519             :                     {
     520           0 :                         nCurrNd = pNd->EndOfSectionIndex();
     521             :                     }
     522          12 :                     else if( !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
     523             :                     {
     524          12 :                         if( pPageCnt && *pPageCnt && pPageSt )
     525             :                         {
     526          12 :                             sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
     527          12 :                             if( !*pPageSt )
     528             :                             {
     529           8 :                                 *pPageSt = nPageNr;
     530           8 :                                 if( *pPageCnt < *pPageSt )
     531           0 :                                     *pPageCnt = *pPageSt;
     532             :                             }
     533             :                             long nStat;
     534          12 :                             if( nPageNr >= *pPageSt )
     535          12 :                                 nStat = nPageNr - *pPageSt + 1;
     536             :                             else
     537           0 :                                 nStat = nPageNr + *pPageCnt - *pPageSt + 1;
     538          12 :                             ::SetProgressState( nStat, (SwDocShell*)GetDocShell() );
     539             :                         }
     540             :                         //Spell() changes the pSpellArgs in case an error is found
     541          12 :                         sal_Int32 nBeginGrammarCheck = 0;
     542          12 :                         sal_Int32 nEndGrammarCheck = 0;
     543          12 :                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck)
     544             :                         {
     545           0 :                             nBeginGrammarCheck = pSpellArgs->pStartNode == pNd ?  pSpellArgs->pStartIdx->GetIndex() : 0;
     546             :                             // if grammar checking starts inside of a sentence the start position has to be adjusted
     547           0 :                             if( nBeginGrammarCheck )
     548             :                             {
     549           0 :                                 SwIndex aStartIndex( dynamic_cast< SwTxtNode* >( pNd ), nBeginGrammarCheck );
     550           0 :                                 SwPosition aStart( *pNd, aStartIndex );
     551           0 :                                 SwCursor aCrsr(aStart, 0, false);
     552           0 :                                 SwPosition aOrigPos = *aCrsr.GetPoint();
     553           0 :                                 aCrsr.GoSentence( SwCursor::START_SENT );
     554           0 :                                 if( aOrigPos != *aCrsr.GetPoint() )
     555             :                                 {
     556           0 :                                     nBeginGrammarCheck = aCrsr.GetPoint()->nContent.GetIndex();
     557           0 :                                 }
     558             :                             }
     559           0 :                             nEndGrammarCheck = (pSpellArgs->pEndNode == pNd)
     560           0 :                                 ? pSpellArgs->pEndIdx->GetIndex()
     561             :                                 : static_cast<SwTxtNode const*>(pNd)
     562           0 :                                     ->GetTxt().getLength();
     563             :                         }
     564             : 
     565             :                         sal_Int32 nSpellErrorPosition =
     566          12 :                             static_cast<SwTxtNode const*>(pNd)->GetTxt().getLength();
     567          12 :                         if( (!pConvArgs &&
     568          28 :                                 ((SwTxtNode*)pNd)->Spell( pSpellArgs )) ||
     569          12 :                             ( pConvArgs &&
     570          12 :                                 ((SwTxtNode*)pNd)->Convert( *pConvArgs )))
     571             :                         {
     572             :                             // Cancel and remember position
     573           4 :                             pSttPos->nNode = nCurrNd;
     574           4 :                             pEndPos->nNode = nCurrNd;
     575           4 :                             nCurrNd = nEndNd;
     576           4 :                             if( pSpellArgs )
     577           0 :                                 nSpellErrorPosition = pSpellArgs->pStartIdx->GetIndex() > pSpellArgs->pEndIdx->GetIndex() ?
     578           0 :                                             pSpellArgs->pEndIdx->GetIndex() :
     579           0 :                                             pSpellArgs->pStartIdx->GetIndex();
     580             :                         }
     581             : 
     582          12 :                         if( pSpellArgs && pSpellArgs->bIsGrammarCheck )
     583             :                         {
     584           0 :                             uno::Reference< linguistic2::XProofreadingIterator >  xGCIterator( GetGCIterator() );
     585           0 :                             if (xGCIterator.is())
     586             :                             {
     587           0 :                                 uno::Reference< lang::XComponent > xDoc( ((SwDocShell*)GetDocShell())->GetBaseModel(), uno::UNO_QUERY );
     588             :                                 // Expand the string:
     589           0 :                                 const ModelToViewHelper aConversionMap(*(SwTxtNode*)pNd);
     590           0 :                                 OUString aExpandText = aConversionMap.getViewText();
     591             : 
     592             :                                 // get XFlatParagraph to use...
     593           0 :                                 uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *((SwTxtNode*)pNd), aExpandText, aConversionMap );
     594             : 
     595             :                                 // get error position of cursor in XFlatParagraph
     596           0 :                                 linguistic2::ProofreadingResult aResult;
     597             :                                 sal_Int32 nGrammarErrors;
     598           0 :                                 do
     599             :                                 {
     600           0 :                                     aConversionMap.ConvertToViewPosition( nBeginGrammarCheck );
     601           0 :                                     aResult = xGCIterator->checkSentenceAtPosition(
     602           0 :                                             xDoc, xFlatPara, aExpandText, lang::Locale(), nBeginGrammarCheck, -1, -1 );
     603             : 
     604           0 :                                     lcl_syncGrammarError( *((SwTxtNode*)pNd), aResult, aConversionMap );
     605             : 
     606             :                                     // get suggestions to use for the specific error position
     607           0 :                                     nGrammarErrors = aResult.aErrors.getLength();
     608             :                                     // if grammar checking doesn't have any progress then quit
     609           0 :                                     if( aResult.nStartOfNextSentencePosition <= nBeginGrammarCheck )
     610           0 :                                         break;
     611             :                                     // prepare next iteration
     612           0 :                                     nBeginGrammarCheck = aResult.nStartOfNextSentencePosition;
     613             :                                 }
     614           0 :                                 while( nSpellErrorPosition > aResult.nBehindEndOfSentencePosition && !nGrammarErrors && aResult.nBehindEndOfSentencePosition < nEndGrammarCheck );
     615             : 
     616           0 :                                 if( nGrammarErrors > 0 && nSpellErrorPosition >= aResult.nBehindEndOfSentencePosition )
     617             :                                 {
     618           0 :                                     aRet <<= aResult;
     619             :                                     //put the cursor to the current error
     620           0 :                                     const linguistic2::SingleProofreadingError &rError = aResult.aErrors[0];
     621           0 :                                     nCurrNd = pNd->GetIndex();
     622           0 :                                     pSttPos->nNode = nCurrNd;
     623           0 :                                     pEndPos->nNode = nCurrNd;
     624           0 :                                     pSpellArgs->pStartNode = ((SwTxtNode*)pNd);
     625           0 :                                     pSpellArgs->pEndNode = ((SwTxtNode*)pNd);
     626           0 :                                     pSpellArgs->pStartIdx->Assign(((SwTxtNode*)pNd), aConversionMap.ConvertToModelPosition( rError.nErrorStart ).mnPos );
     627           0 :                                     pSpellArgs->pEndIdx->Assign(((SwTxtNode*)pNd), aConversionMap.ConvertToModelPosition( rError.nErrorStart + rError.nErrorLength ).mnPos );
     628           0 :                                     nCurrNd = nEndNd;
     629           0 :                                 }
     630           0 :                             }
     631             :                         }
     632             :                     }
     633             :                 }
     634          12 :                 break;
     635             :             case ND_SECTIONNODE:
     636           0 :                 if( ( ((SwSectionNode*)pNd)->GetSection().IsProtect() ||
     637           0 :                     ((SwSectionNode*)pNd)->GetSection().IsHidden() ) )
     638           0 :                     nCurrNd = pNd->EndOfSectionIndex();
     639           0 :                 break;
     640             :             case ND_ENDNODE:
     641             :                 {
     642           0 :                     break;
     643             :                 }
     644             :             }
     645             : 
     646          12 :             bGoOn = nCurrNd < nEndNd;
     647          12 :             ++nCurrNd;
     648             :         }
     649             :     }
     650             : 
     651          12 :     if( !aRet.hasValue() )
     652             :     {
     653          12 :         if (pConvArgs)
     654          12 :             aRet <<= pConvArgs->aConvText;
     655             :         else
     656           0 :             aRet <<= pSpellArgs->xSpellAlt;
     657             :     }
     658          12 :     delete pSpellArgs;
     659             : 
     660          12 :     return aRet;
     661             : }
     662             : 
     663           0 : class SwHyphArgs : public SwInterHyphInfo
     664             : {
     665             :     const SwNode *pStart;
     666             :     const SwNode *pEnd;
     667             :           SwNode *pNode;
     668             :     sal_uInt16 *pPageCnt;
     669             :     sal_uInt16 *pPageSt;
     670             : 
     671             :     sal_uInt32 nNode;
     672             :     sal_Int32 nPamStart;
     673             :     sal_Int32 nPamLen;
     674             : 
     675             : public:
     676             :     SwHyphArgs( const SwPaM *pPam, const Point &rPoint,
     677             :                 sal_uInt16* pPageCount, sal_uInt16* pPageStart );
     678             :     void SetPam( SwPaM *pPam ) const;
     679           0 :     inline void SetNode( SwNode *pNew ) { pNode = pNew; }
     680             :     inline void SetRange( const SwNode *pNew );
     681           0 :     inline void NextNode() { ++nNode; }
     682           0 :     inline sal_uInt16 *GetPageCnt() { return pPageCnt; }
     683           0 :     inline sal_uInt16 *GetPageSt() { return pPageSt; }
     684             : };
     685             : 
     686           0 : SwHyphArgs::SwHyphArgs( const SwPaM *pPam, const Point &rCrsrPos,
     687             :                          sal_uInt16* pPageCount, sal_uInt16* pPageStart )
     688             :      : SwInterHyphInfo( rCrsrPos ), pNode(0),
     689           0 :      pPageCnt( pPageCount ), pPageSt( pPageStart )
     690             : {
     691             :     // The following constraints have to be met:
     692             :     // 1) there is at least one Selection
     693             :     // 2) SPoint() == Start()
     694             :     OSL_ENSURE( pPam->HasMark(), "SwDoc::Hyphenate: blowing in the wind");
     695             :     OSL_ENSURE( *pPam->GetPoint() <= *pPam->GetMark(),
     696             :             "SwDoc::Hyphenate: New York, New York");
     697             : 
     698           0 :     const SwPosition *pPoint = pPam->GetPoint();
     699           0 :     nNode = pPoint->nNode.GetIndex();
     700             : 
     701             :     // Set start
     702           0 :     pStart = pPoint->nNode.GetNode().GetTxtNode();
     703           0 :     nPamStart = pPoint->nContent.GetIndex();
     704             : 
     705             :     // Set End and Length
     706           0 :     const SwPosition *pMark = pPam->GetMark();
     707           0 :     pEnd = pMark->nNode.GetNode().GetTxtNode();
     708           0 :     nPamLen = pMark->nContent.GetIndex();
     709           0 :     if( pPoint->nNode == pMark->nNode )
     710           0 :         nPamLen = nPamLen - pPoint->nContent.GetIndex();
     711           0 : }
     712             : 
     713           0 : inline void SwHyphArgs::SetRange( const SwNode *pNew )
     714             : {
     715           0 :     nStart = pStart == pNew ? nPamStart : 0;
     716           0 :     nEnd   = pEnd   == pNew ? nPamStart + nPamLen : SAL_MAX_INT32;
     717           0 : }
     718             : 
     719           0 : void SwHyphArgs::SetPam( SwPaM *pPam ) const
     720             : {
     721           0 :     if( !pNode )
     722           0 :         *pPam->GetPoint() = *pPam->GetMark();
     723             :     else
     724             :     {
     725           0 :         pPam->GetPoint()->nNode = nNode;
     726           0 :         pPam->GetPoint()->nContent.Assign( pNode->GetCntntNode(), nWordStart );
     727           0 :         pPam->GetMark()->nNode = nNode;
     728           0 :         pPam->GetMark()->nContent.Assign( pNode->GetCntntNode(),
     729           0 :                                           nWordStart + nWordLen );
     730             :         OSL_ENSURE( nNode == pNode->GetIndex(),
     731             :                 "SwHyphArgs::SetPam: Pam disaster" );
     732             :     }
     733           0 : }
     734             : 
     735             : // Returns sal_True if we can proceed.
     736           0 : static bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
     737             : {
     738             :     // Hyphenate returns true if there is a hyphenation point and sets pPam
     739           0 :     SwTxtNode *pNode = rpNd->GetTxtNode();
     740           0 :     SwHyphArgs *pHyphArgs = (SwHyphArgs*)pArgs;
     741           0 :     if( pNode )
     742             :     {
     743           0 :         SwCntntFrm* pCntFrm = pNode->getLayoutFrm( pNode->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() );
     744           0 :         if( pCntFrm && !((SwTxtFrm*)pCntFrm)->IsHiddenNow() )
     745             :         {
     746           0 :             sal_uInt16 *pPageSt = pHyphArgs->GetPageSt();
     747           0 :             sal_uInt16 *pPageCnt = pHyphArgs->GetPageCnt();
     748           0 :             if( pPageCnt && *pPageCnt && pPageSt )
     749             :             {
     750           0 :                 sal_uInt16 nPageNr = pCntFrm->GetPhyPageNum();
     751           0 :                 if( !*pPageSt )
     752             :                 {
     753           0 :                     *pPageSt = nPageNr;
     754           0 :                     if( *pPageCnt < *pPageSt )
     755           0 :                         *pPageCnt = *pPageSt;
     756             :                 }
     757           0 :                 long nStat = nPageNr >= *pPageSt ? nPageNr - *pPageSt + 1
     758           0 :                                          : nPageNr + *pPageCnt - *pPageSt + 1;
     759           0 :                 ::SetProgressState( nStat, (SwDocShell*)pNode->GetDoc()->GetDocShell() );
     760             :             }
     761           0 :             pHyphArgs->SetRange( rpNd );
     762           0 :             if( pNode->Hyphenate( *pHyphArgs ) )
     763             :             {
     764           0 :                 pHyphArgs->SetNode( rpNd );
     765           0 :                 return false;
     766             :             }
     767             :         }
     768             :     }
     769           0 :     pHyphArgs->NextNode();
     770           0 :     return true;
     771             : }
     772             : 
     773           0 : uno::Reference< XHyphenatedWord >  SwDoc::Hyphenate(
     774             :                             SwPaM *pPam, const Point &rCrsrPos,
     775             :                              sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
     776             : {
     777             :     OSL_ENSURE(this == pPam->GetDoc(), "SwDoc::Hyphenate: strangers in the night");
     778             : 
     779           0 :     if( *pPam->GetPoint() > *pPam->GetMark() )
     780           0 :         pPam->Exchange();
     781             : 
     782           0 :     SwHyphArgs aHyphArg( pPam, rCrsrPos, pPageCnt, pPageSt );
     783           0 :     SwNodeIndex aTmpIdx( pPam->GetMark()->nNode, 1 );
     784           0 :     GetNodes().ForEach( pPam->GetPoint()->nNode, aTmpIdx,
     785           0 :                     lcl_HyphenateNode, &aHyphArg );
     786           0 :     aHyphArg.SetPam( pPam );
     787           0 :     return aHyphArg.GetHyphWord();  // will be set by lcl_HyphenateNode
     788             : }
     789             : 
     790             : // Save the current values to add them as automatic entries to to AutoCorrect.
     791           0 : void SwDoc::SetAutoCorrExceptWord( SwAutoCorrExceptWord* pNew )
     792             : {
     793           0 :     if( pNew != mpACEWord )
     794           0 :         delete mpACEWord;
     795           0 :     mpACEWord = pNew;
     796           0 : }
     797             : 
     798           0 : void SwDoc::DeleteAutoCorrExceptWord()
     799             : {
     800           0 :     delete mpACEWord;
     801           0 :     mpACEWord = 0;
     802           0 : }
     803             : 
     804          16 : void SwDoc::CountWords( const SwPaM& rPaM, SwDocStat& rStat ) const
     805             : {
     806             :     // This is a modified version of SwDoc::TransliterateText
     807          16 :     const SwPosition* pStt = rPaM.Start();
     808          16 :     const SwPosition* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
     809          16 :                                                      : rPaM.GetPoint();
     810             : 
     811          16 :     const sal_uLong nSttNd = pStt->nNode.GetIndex();
     812          16 :     const sal_uLong nEndNd = pEnd->nNode.GetIndex();
     813             : 
     814          16 :     const sal_Int32 nSttCnt = pStt->nContent.GetIndex();
     815          16 :     const sal_Int32 nEndCnt = pEnd->nContent.GetIndex();
     816             : 
     817          16 :     const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
     818          16 :     if( pStt == pEnd && pTNd )                  // no region ?
     819             :     {
     820             :         // do nothing
     821          16 :         return;
     822             :     }
     823             : 
     824          16 :     if( nSttNd != nEndNd )
     825             :     {
     826           0 :         SwNodeIndex aIdx( pStt->nNode );
     827           0 :         if( nSttCnt )
     828             :         {
     829           0 :             ++aIdx;
     830           0 :             if( pTNd )
     831           0 :                 pTNd->CountWords( rStat, nSttCnt, pTNd->GetTxt().getLength() );
     832             :         }
     833             : 
     834           0 :         for( ; aIdx.GetIndex() < nEndNd; ++aIdx )
     835           0 :             if( 0 != ( pTNd = aIdx.GetNode().GetTxtNode() ))
     836           0 :                 pTNd->CountWords( rStat, 0, pTNd->GetTxt().getLength() );
     837             : 
     838           0 :         if( nEndCnt && 0 != ( pTNd = pEnd->nNode.GetNode().GetTxtNode() ))
     839           0 :             pTNd->CountWords( rStat, 0, nEndCnt );
     840             :     }
     841          16 :     else if( pTNd && nSttCnt < nEndCnt )
     842           0 :         pTNd->CountWords( rStat, nSttCnt, nEndCnt );
     843         270 : }
     844             : 
     845             : 
     846             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10