Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <editeng/brkitem.hxx>
31 : :
32 : : #include <hintids.hxx>
33 : : #include <fmtpdsc.hxx>
34 : : #include <fmtanchr.hxx>
35 : : #include <fmtcntnt.hxx>
36 : : #include <doc.hxx>
37 : : #include <IDocumentUndoRedo.hxx>
38 : : #include <pam.hxx>
39 : : #include <ndtxt.hxx>
40 : : #include <fldbas.hxx>
41 : : #include <swtable.hxx>
42 : : #include <ddefld.hxx>
43 : : #include <undobj.hxx>
44 : : #include <IMark.hxx>
45 : : #include <mvsave.hxx>
46 : : #include <cellatr.hxx>
47 : : #include <swtblfmt.hxx>
48 : : #include <swddetbl.hxx>
49 : : #include <docary.hxx>
50 : : #include <fmtcnct.hxx>
51 : : #include <redline.hxx>
52 : : #include <paratr.hxx>
53 : : #include <pagedesc.hxx>
54 : : #include <poolfmt.hxx>
55 : : #include <SwNodeNum.hxx>
56 : : #include <set>
57 : : #include <vector>
58 : : #include <boost/foreach.hpp>
59 : :
60 : : #ifdef DBG_UTIL
61 : : #define CHECK_TABLE(t) (t).CheckConsistency();
62 : : #else
63 : : #define CHECK_TABLE(t)
64 : : #endif
65 : :
66 : : namespace
67 : : {
68 : : /*
69 : : The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
70 : : array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
71 : : every node (at least at the moment: 2/08/2006 ), section start and end nodes will not be copied if the corresponding end/start node is outside the copied pam.
72 : : The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
73 : : index inside the pam.
74 : : rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
75 : : of "non-copy" nodes between rPam.Start() and rLastIdx.
76 : : nNewIdx is the new position of interest.
77 : : */
78 : :
79 : 0 : static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
80 : : {
81 : 0 : sal_uLong nStart = rPam.Start()->nNode.GetIndex();
82 : 0 : sal_uLong nEnd = rPam.End()->nNode.GetIndex();
83 [ # # ]: 0 : if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
84 : : {
85 [ # # ]: 0 : do // count "non-copy" nodes
86 : : {
87 : 0 : SwNode& rNode = rLastIdx.GetNode();
88 [ # # # # : 0 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
# # ][ # # ]
[ # # ]
89 : 0 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
90 : 0 : ++rDelCount;
91 : 0 : rLastIdx++;
92 : : }
93 : 0 : while( rLastIdx.GetIndex() < nNewIdx );
94 : : }
95 [ # # ]: 0 : else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
96 : : // no move backward needed
97 : : {
98 [ # # ]: 0 : while( rLastIdx.GetIndex() > nNewIdx )
99 : : {
100 : 0 : SwNode& rNode = rLastIdx.GetNode();
101 [ # # # # : 0 : if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
# # ][ # # ]
[ # # ]
102 : 0 : || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
103 : 0 : --rDelCount;
104 : 0 : rLastIdx--;
105 : : }
106 : : }
107 : 0 : }
108 : :
109 : 0 : static void lcl_SetCpyPos( const SwPosition& rOrigPos,
110 : : const SwPosition& rOrigStt,
111 : : const SwPosition& rCpyStt,
112 : : SwPosition& rChgPos,
113 : : sal_uLong nDelCount )
114 : : {
115 : 0 : sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
116 : 0 : nNdOff -= rOrigStt.nNode.GetIndex();
117 : 0 : nNdOff -= nDelCount;
118 : 0 : xub_StrLen nCntntPos = rOrigPos.nContent.GetIndex();
119 : :
120 : : // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
121 : 0 : rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
122 [ # # ]: 0 : if( !nNdOff )
123 : : {
124 : : // dann nur den Content anpassen
125 [ # # ]: 0 : if( nCntntPos > rOrigStt.nContent.GetIndex() )
126 : 0 : nCntntPos = nCntntPos - rOrigStt.nContent.GetIndex();
127 : : else
128 : 0 : nCntntPos = 0;
129 : 0 : nCntntPos = nCntntPos + rCpyStt.nContent.GetIndex();
130 : : }
131 [ # # ]: 0 : rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
132 : 0 : }
133 : :
134 : : // TODO: use SaveBookmark (from _DelBookmarks)
135 : 18 : static void lcl_CopyBookmarks(const SwPaM& rPam, SwPaM& rCpyPam)
136 : : {
137 : 18 : const SwDoc* pSrcDoc = rPam.GetDoc();
138 : 18 : SwDoc* pDestDoc = rCpyPam.GetDoc();
139 [ + - ]: 18 : const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
140 [ + - ][ + - ]: 18 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
141 : :
142 [ + - ][ + - ]: 18 : const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
143 [ + - ]: 18 : SwPosition* pCpyStt = rCpyPam.Start();
144 : :
145 : : typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
146 [ + - ]: 18 : mark_vector_t vMarksToCopy;
147 [ + - ][ + - ]: 120 : for(IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getMarksBegin();
[ + - ][ + + ]
148 [ + - ]: 60 : ppMark != pSrcMarkAccess->getMarksEnd();
149 : : ppMark++)
150 : : {
151 : 42 : const ::sw::mark::IMark* const pMark = ppMark->get();
152 [ + - ]: 42 : const SwPosition& rMarkStart = pMark->GetMarkStart();
153 [ + - ]: 42 : const SwPosition& rMarkEnd = pMark->GetMarkEnd();
154 : : // only include marks that are in the range and not touching
155 : : // both start and end
156 [ + - ]: 42 : bool bIsNotOnBoundary = pMark->IsExpanded()
157 [ + - ][ + - ]: 30 : ? (rMarkStart != rStt || rMarkEnd != rEnd) // rMarkStart != rMarkEnd
158 [ + + ][ + - ]: 72 : : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ]
159 [ + - ][ + - ]: 42 : if(rMarkStart >= rStt && rMarkEnd <= rEnd && bIsNotOnBoundary)
[ + - ][ + + ]
[ - + ][ - + ]
160 : : {
161 [ # # ]: 0 : vMarksToCopy.push_back(pMark);
162 : : }
163 : : }
164 : : // We have to count the "non-copied" nodes..
165 [ + - ]: 18 : SwNodeIndex aCorrIdx(rStt.nNode);
166 : 18 : sal_uLong nDelCount = 0;
167 [ + - ]: 36 : for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
[ # # + - ]
[ - + ]
168 : 18 : ppMark != vMarksToCopy.end();
169 : : ++ppMark)
170 : : {
171 [ # # ]: 0 : const ::sw::mark::IMark* const pMark = *ppMark;
172 [ # # ]: 0 : SwPaM aTmpPam(*pCpyStt);
173 [ # # ][ # # ]: 0 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
174 [ # # ][ # # ]: 0 : lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
175 [ # # ][ # # ]: 0 : if(pMark->IsExpanded())
176 : : {
177 [ # # ]: 0 : aTmpPam.SetMark();
178 [ # # ][ # # ]: 0 : lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
179 [ # # ][ # # ]: 0 : lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
180 : : }
181 : :
182 [ # # ]: 0 : ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
183 : : aTmpPam,
184 [ # # ]: 0 : pMark->GetName(),
185 [ # # ][ # # ]: 0 : IDocumentMarkAccess::GetType(*pMark));
186 : : // Explicitly try to get exactly the same name as in the source
187 : : // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
188 [ # # ][ # # ]: 0 : pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
[ # # ]
189 : :
190 : : // copying additional attributes for bookmarks or fieldmarks
191 : : ::sw::mark::IBookmark* const pNewBookmark =
192 [ # # ]: 0 : dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
193 [ # # ]: 0 : if(pNewBookmark)
194 : : {
195 [ # # ]: 0 : const ::sw::mark::IBookmark* const pOldBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
196 [ # # ][ # # ]: 0 : pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
197 [ # # ][ # # ]: 0 : pNewBookmark->SetShortName(pOldBookmark->GetShortName());
198 : : }
199 : : ::sw::mark::IFieldmark* const pNewFieldmark =
200 [ # # ]: 0 : dynamic_cast< ::sw::mark::IFieldmark* const >(pNewMark);
201 [ # # ]: 0 : if(pNewFieldmark)
202 : : {
203 [ # # ]: 0 : const ::sw::mark::IFieldmark* const pOldFieldmark = dynamic_cast< const ::sw::mark::IFieldmark* >(pMark);
204 [ # # ][ # # ]: 0 : pNewFieldmark->SetFieldname(pOldFieldmark->GetFieldname());
205 [ # # ][ # # ]: 0 : pNewFieldmark->SetFieldHelptext(pOldFieldmark->GetFieldHelptext());
206 [ # # ]: 0 : ::sw::mark::IFieldmark::parameter_map_t* pNewParams = pNewFieldmark->GetParameters();
207 [ # # ]: 0 : const ::sw::mark::IFieldmark::parameter_map_t* pOldParams = pOldFieldmark->GetParameters();
208 : 0 : ::sw::mark::IFieldmark::parameter_map_t::const_iterator pIt = pOldParams->begin();
209 [ # # ]: 0 : for (; pIt != pOldParams->end(); ++pIt )
210 : : {
211 [ # # ]: 0 : pNewParams->insert( *pIt );
212 : : }
213 : : }
214 : :
215 : : ::sfx2::Metadatable const*const pMetadatable(
216 [ # # ]: 0 : dynamic_cast< ::sfx2::Metadatable const* >(pMark));
217 : : ::sfx2::Metadatable *const pNewMetadatable(
218 [ # # ]: 0 : dynamic_cast< ::sfx2::Metadatable * >(pNewMark));
219 [ # # ][ # # ]: 0 : if (pMetadatable && pNewMetadatable)
220 : : {
221 [ # # ]: 0 : pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
222 : : }
223 [ # # ][ + - ]: 18 : }
[ + - ]
224 : 18 : }
225 : : }
226 : :
227 : : // Structure for the mapping from old and new frame formats to the
228 : : // boxes and lines of a table
229 : : struct _MapTblFrmFmt
230 : : {
231 : : const SwFrmFmt *pOld, *pNew;
232 : 9 : _MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
233 : 9 : : pOld( pOldFmt ), pNew( pNewFmt )
234 : 9 : {}
235 : : };
236 : :
237 : : typedef std::vector<_MapTblFrmFmt> _MapTblFrmFmts;
238 : :
239 : 149 : SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
240 : : {
241 : : // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
242 : : // node with the collection and hard attributes. Normally ist the same
243 : : // node, but if insert a glossary without formatting, then the Attrnode
244 : : // is the prev node of the destionation position in dest. document.
245 : 149 : SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
246 : 149 : SwTxtNode* pCpyAttrNd = pCpyTxtNd;
247 : :
248 : : // Copy the formats to the other document
249 : 149 : SwTxtFmtColl* pColl = 0;
250 [ + + ]: 149 : if( pDoc->IsInsOnlyTextGlossary() )
251 : : {
252 [ + - ]: 4 : SwNodeIndex aIdx( rIdx, -1 );
253 [ + - ]: 4 : if( aIdx.GetNode().IsTxtNode() )
254 : : {
255 : 4 : pCpyAttrNd = aIdx.GetNode().GetTxtNode();
256 : 4 : pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
257 [ + - ]: 4 : }
258 : : }
259 [ + + ]: 149 : if( !pColl )
260 : 145 : pColl = pDoc->CopyTxtColl( *GetTxtColl() );
261 : :
262 : 149 : SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
263 : :
264 : : // METADATA: register copy
265 : 149 : pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
266 : :
267 : : // Copy Attribute/Text
268 [ + + ]: 149 : if( !pCpyAttrNd->HasSwAttrSet() )
269 : : // An AttrSet was added for numbering, so delete it
270 : 107 : pTxtNd->ResetAllAttr();
271 : :
272 : : // if Copy-Textnode unequal to Copy-Attrnode, then copy first
273 : : // the attributes into the new Node.
274 [ + + ]: 149 : if( pCpyAttrNd != pCpyTxtNd )
275 : : {
276 : 4 : pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
277 [ - + ]: 4 : if( pCpyAttrNd->HasSwAttrSet() )
278 : : {
279 [ # # ][ # # ]: 0 : SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
280 [ # # ]: 0 : aSet.ClearItem( RES_PAGEDESC );
281 [ # # ]: 0 : aSet.ClearItem( RES_BREAK );
282 [ # # ][ # # ]: 0 : aSet.CopyToModify( *pTxtNd );
283 : : }
284 : : }
285 : :
286 : : // Is that enough? What about PostIts/Fields/FieldTypes?
287 : : // #i96213# - force copy of all attributes
288 [ + - ]: 149 : pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
289 [ + - ]: 298 : pCpyTxtNd->GetTxt().Len(), true );
290 : :
291 [ - + ]: 149 : if( RES_CONDTXTFMTCOLL == pColl->Which() )
292 : 0 : pTxtNd->ChkCondColl();
293 : :
294 : 149 : return pTxtNd;
295 : : }
296 : :
297 : 9 : static bool lcl_SrchNew( const _MapTblFrmFmt& rMap, const SwFrmFmt** pPara )
298 : : {
299 [ + - ]: 9 : if( rMap.pOld != *pPara )
300 : 9 : return true;
301 : 0 : *pPara = rMap.pNew;
302 : 9 : return false;
303 : : }
304 : :
305 : : struct _CopyTable
306 : : {
307 : : SwDoc* pDoc;
308 : : sal_uLong nOldTblSttIdx;
309 : : _MapTblFrmFmts& rMapArr;
310 : : SwTableLine* pInsLine;
311 : : SwTableBox* pInsBox;
312 : : SwTableNode *pTblNd;
313 : : const SwTable *pOldTable;
314 : :
315 : 3 : _CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
316 : : SwTableNode& rTblNd, const SwTable* pOldTbl )
317 : : : pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
318 : 3 : pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
319 : 3 : {}
320 : : };
321 : :
322 : : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT );
323 : :
324 : 6 : static void lcl_CopyTblBox( SwTableBox* pBox, _CopyTable* pCT )
325 : : {
326 : 6 : SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
327 [ + - ][ + + ]: 15 : for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
[ + - ]
328 [ - + ]: 9 : if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pBoxFmt ) )
329 : 0 : break;
330 [ + - ]: 6 : if( pBoxFmt == pBox->GetFrmFmt() ) // Create a new one?
331 : : {
332 : : const SfxPoolItem* pItem;
333 [ - + # # ]: 6 : if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, sal_False,
[ - + ]
334 [ + - ]: 6 : &pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
335 : : {
336 [ # # ]: 0 : ((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
337 : : }
338 : :
339 [ + - ]: 6 : pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
340 [ + - ]: 6 : pBoxFmt->CopyAttrs( *pBox->GetFrmFmt() );
341 : :
342 [ + - ][ + - ]: 6 : if( pBox->GetSttIdx() )
343 : : {
344 [ + - ]: 6 : SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( sal_False );
345 [ - + ][ # # ]: 6 : if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
[ # # ][ - + ]
346 [ # # ]: 0 : GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
347 : : {
348 : 0 : sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
349 [ # # ]: 0 : sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
350 [ # # ]: 0 : if( nNewIdx != nOldIdx )
351 [ # # ][ # # ]: 0 : pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
[ # # ]
352 : :
353 : : }
354 : : }
355 : :
356 [ + - ]: 6 : pCT->rMapArr.push_back( _MapTblFrmFmt( pBox->GetFrmFmt(), pBoxFmt ) );
357 : : }
358 : :
359 : 6 : sal_uInt16 nLines = pBox->GetTabLines().size();
360 : : SwTableBox* pNewBox;
361 [ - + ]: 6 : if( nLines )
362 [ # # ][ # # ]: 0 : pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
363 : : else
364 : : {
365 : : SwNodeIndex aNewIdx( *pCT->pTblNd,
366 [ + - ][ + - ]: 6 : pBox->GetSttIdx() - pCT->nOldTblSttIdx );
367 : : OSL_ENSURE( aNewIdx.GetNode().IsStartNode(), "Index is not on the start node" );
368 [ + - ][ + - ]: 6 : pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
369 [ + - ][ + - ]: 6 : pNewBox->setRowSpan( pBox->getRowSpan() );
[ + - ]
370 : : }
371 : :
372 [ + - ]: 6 : pCT->pInsLine->GetTabBoxes().push_back( pNewBox );
373 : :
374 [ - + ]: 6 : if( nLines )
375 : : {
376 : 0 : _CopyTable aPara( *pCT );
377 : 0 : aPara.pInsBox = pNewBox;
378 [ # # ][ # # ]: 0 : BOOST_FOREACH( const SwTableLine* pLine, pBox->GetTabLines() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
379 [ # # ]: 0 : lcl_CopyTblLine( pLine, &aPara );
380 : : }
381 [ + - ][ + - ]: 6 : else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
382 : : // In the headline, the paragraphs must match conditional styles
383 [ + - ]: 6 : pNewBox->GetSttNd()->CheckSectionCondColl();
384 : 6 : }
385 : :
386 : 3 : static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT )
387 : : {
388 : 3 : SwTableLineFmt* pLineFmt = (SwTableLineFmt*)pLine->GetFrmFmt();
389 [ + - ][ - + ]: 3 : for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
[ + - ]
390 [ # # ]: 0 : if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pLineFmt ) )
391 : 0 : break;
392 [ + - ]: 3 : if( pLineFmt == pLine->GetFrmFmt() ) // Create a new one?
393 : : {
394 [ + - ]: 3 : pLineFmt = pCT->pDoc->MakeTableLineFmt();
395 [ + - ]: 3 : pLineFmt->CopyAttrs( *pLine->GetFrmFmt() );
396 [ + - ]: 3 : pCT->rMapArr.push_back( _MapTblFrmFmt( pLine->GetFrmFmt(), pLineFmt ) );
397 : : }
398 : : SwTableLine* pNewLine = new SwTableLine( pLineFmt,
399 [ + - ][ + - ]: 3 : pLine->GetTabBoxes().size(), pCT->pInsBox );
400 : : // Insert the new row into the table
401 [ - + ]: 3 : if( pCT->pInsBox )
402 : : {
403 [ # # ]: 0 : pCT->pInsBox->GetTabLines().push_back( pNewLine );
404 : : }
405 : : else
406 : : {
407 [ + - ]: 3 : pCT->pTblNd->GetTable().GetTabLines().push_back( pNewLine );
408 : : }
409 : 3 : pCT->pInsLine = pNewLine;
410 [ + - ][ + + ]: 18 : for( SwTableBoxes::iterator it = ((SwTableLine*)pLine)->GetTabBoxes().begin();
411 : 9 : it != ((SwTableLine*)pLine)->GetTabBoxes().end(); ++it)
412 [ + - ]: 6 : lcl_CopyTblBox(*it, pCT );
413 : 3 : }
414 : :
415 : 3 : SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
416 : : {
417 : : // In which array are we? Nodes? UndoNodes?
418 : 3 : SwNodes& rNds = (SwNodes&)GetNodes();
419 : :
420 : : {
421 [ - + # # ]: 3 : if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
[ - + ][ + - ]
422 [ # # ]: 0 : rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
423 : 0 : return 0;
424 : : }
425 : :
426 : : // Copy the TableFrmFmt
427 [ + - ]: 3 : String sTblName( GetTable().GetFrmFmt()->GetName() );
428 [ + - ]: 3 : if( !pDoc->IsCopyIsMove() )
429 : : {
430 : 3 : const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
431 [ + - ]: 9 : for( sal_uInt16 n = rTblFmts.size(); n; )
432 [ + - ][ + - ]: 6 : if( rTblFmts[ --n ]->GetName() == sTblName )
[ + + ]
433 : : {
434 [ + - ][ + - ]: 3 : sTblName = pDoc->GetUniqueTblName();
[ + - ]
435 : 3 : break;
436 : : }
437 : : }
438 : :
439 [ + - ]: 3 : SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
440 [ + - ]: 3 : pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
441 [ + - ][ + - ]: 3 : SwTableNode* pTblNd = new SwTableNode( rIdx );
442 [ + - ][ + - ]: 3 : SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
443 [ + - ]: 3 : SwNodeIndex aInsPos( *pEndNd );
444 : :
445 : 3 : SwTable& rTbl = (SwTable&)pTblNd->GetTable();
446 [ + - ]: 3 : rTbl.RegisterToFormat( *pTblFmt );
447 : :
448 [ + - ]: 3 : rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
449 : 3 : rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
450 : 3 : rTbl.SetTableModel( GetTable().IsNewModel() );
451 : :
452 : 3 : SwDDEFieldType* pDDEType = 0;
453 [ + - ][ + - ]: 3 : if( IS_TYPE( SwDDETable, &GetTable() ))
[ - + ][ - + ]
[ + - ]
454 : : {
455 : : // We're copying a DDE table
456 : : // Is the field type available in the new document?
457 [ # # ]: 0 : pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
458 [ # # ]: 0 : if( pDDEType->IsDeleted() )
459 [ # # ]: 0 : pDoc->InsDeletedFldType( *pDDEType );
460 : : else
461 [ # # ]: 0 : pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
462 : : OSL_ENSURE( pDDEType, "unknown FieldType" );
463 : :
464 : : // Swap the table pointers in the node
465 [ # # ][ # # ]: 0 : SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
466 [ # # ]: 0 : pTblNd->SetNewTable( pNewTable, sal_False );
467 : : }
468 : : // First copy the content of the tables, we will later assign the
469 : : // boxes/lines and create the frames
470 [ + - ]: 3 : SwNodeRange aRg( *this, +1, *EndOfSectionNode() );
471 : :
472 : : // If there is a table in this table, the table format for the outer table
473 : : // does not seem to be used, because the table does not have any contents yet
474 : : // (see IsUsed). Therefore the inner table gets the same name as the outer table.
475 : : // We have to make sure that the table node of the SwTable is accessible, even
476 : : // without any content in aSortCntBoxes. #i26629#
477 : 3 : pTblNd->GetTable().SetTableNode( pTblNd );
478 [ + - ]: 3 : rNds._Copy( aRg, aInsPos, sal_False );
479 : 3 : pTblNd->GetTable().SetTableNode( 0 );
480 : :
481 : : // Special case for a single box
482 [ - + ]: 3 : if( 1 == GetTable().GetTabSortBoxes().size() )
483 : : {
484 [ # # ]: 0 : aRg.aStart.Assign( *pTblNd, 1 );
485 [ # # ]: 0 : aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
486 [ # # ][ # # ]: 0 : pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
487 : : }
488 : :
489 : : // Delete all frames from the copied area, they will be created
490 : : // during the generation of the table frame
491 [ + - ]: 3 : pTblNd->DelFrms();
492 : :
493 [ + - ]: 3 : _MapTblFrmFmts aMapArr;
494 : 3 : _CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
495 : :
496 [ + - ][ + - ]: 9 : BOOST_FOREACH(const SwTableLine* pLine, GetTable().GetTabLines() )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ]
497 [ + - ]: 3 : lcl_CopyTblLine( pLine, &aPara );
498 : :
499 [ - + ]: 3 : if( pDDEType )
500 [ # # ]: 0 : pDDEType->IncRefCnt();
501 : :
502 : : CHECK_TABLE( GetTable() );
503 [ + - ][ + - ]: 3 : return pTblNd;
[ + - ]
504 : : }
505 : :
506 : 20 : void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
507 : : {
508 : : // Copy the formats into the other document:
509 : : // Special case for PageBreak/PageDesc/ColBrk
510 : 20 : SwDoc* pDestDoc = rDestNd.GetDoc();
511 [ + - ]: 20 : SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
512 : : const SwAttrSet* pSet;
513 : :
514 [ + - ][ + + ]: 20 : if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
515 : : {
516 : : // Special cases for Break-Attributes
517 : : const SfxPoolItem* pAttr;
518 [ + - ][ - + ]: 17 : if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pAttr ) )
519 [ # # ]: 0 : aPgBrkSet.Put( *pAttr );
520 : :
521 [ + - ][ - + ]: 17 : if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pAttr ) )
522 [ # # ]: 17 : aPgBrkSet.Put( *pAttr );
523 : : }
524 : :
525 [ + - ][ + - ]: 20 : rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
526 [ + - ][ + + ]: 20 : if( 0 != ( pSet = GetpSwAttrSet() ) )
527 [ + - ]: 17 : pSet->CopyToModify( rDestNd );
528 : :
529 [ - + ]: 20 : if( aPgBrkSet.Count() )
530 [ # # ][ + - ]: 20 : rDestNd.SetAttr( aPgBrkSet );
531 : 20 : }
532 : :
533 : :
534 : : // Copy method from SwDoc
535 : : // Prevent copying in Flys that are anchored in the area
536 : 21 : sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
537 : : sal_uLong nInsNd )
538 : : {
539 : 21 : const SwFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
540 : :
541 [ + + ]: 90 : for( sal_uInt16 n = 0; n < rFrmFmtTbl.size(); ++n )
542 : : {
543 : 69 : SwFrmFmt const*const pFmt = rFrmFmtTbl[n];
544 : 69 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
545 : 69 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
546 [ + + ][ + + : 279 : if (pAPos &&
+ - + + +
- + - + +
+ + ]
547 : 39 : ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
548 : 39 : (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
549 : 30 : (FLY_AT_FLY == pAnchor->GetAnchorId()) ||
550 : 30 : (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
551 : 39 : nSttNd <= pAPos->nNode.GetIndex() &&
552 : 33 : pAPos->nNode.GetIndex() < nEndNd )
553 : : {
554 : 18 : const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
555 : : SwStartNode* pSNd;
556 [ + + ]: 24 : if( !rCntnt.GetCntntIdx() ||
[ + + - + ]
557 : 6 : 0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
558 : 12 : continue;
559 : :
560 [ + - - + ]: 12 : if( pSNd->GetIndex() < nInsNd &&
[ - + ]
561 : 6 : nInsNd < pSNd->EndOfSectionIndex() )
562 : : // Do not copy !
563 : 0 : return sal_True;
564 : :
565 [ - + ]: 6 : if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
566 : 6 : pSNd->EndOfSectionIndex(), nInsNd ) )
567 : : // Do not copy !
568 : 0 : return sal_True;
569 : : }
570 : : }
571 : :
572 : 21 : return sal_False;
573 : : }
574 : :
575 : 0 : void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
576 : : {
577 : 0 : const SwDoc* pSrcDoc = rPam.GetDoc();
578 : 0 : const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
579 [ # # ]: 0 : if( !rTbl.empty() )
580 : : {
581 : 0 : SwDoc* pDestDoc = rCpyPam.GetDoc();
582 [ # # ][ # # ]: 0 : SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
583 : 0 : SwPaM* pDelPam = 0;
584 [ # # ][ # # ]: 0 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
585 : : // We have to count the "non-copied" nodes
586 : 0 : sal_uLong nDelCount = 0;
587 [ # # ]: 0 : SwNodeIndex aCorrIdx( pStt->nNode );
588 : :
589 : 0 : sal_uInt16 n = 0;
590 [ # # ]: 0 : pSrcDoc->GetRedline( *pStt, &n );
591 [ # # ]: 0 : for( ; n < rTbl.size(); ++n )
592 : : {
593 [ # # ]: 0 : const SwRedline* pRedl = rTbl[ n ];
594 [ # # ][ # # ]: 0 : if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
[ # # ][ # # ]
595 : : {
596 [ # # ][ # # ]: 0 : const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
597 : :
598 [ # # ]: 0 : SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
599 [ # # # ]: 0 : switch( eCmpPos )
600 : : {
601 : : case POS_COLLIDE_END:
602 : : case POS_BEFORE:
603 : : // Pos1 is before Pos2
604 : 0 : break;
605 : :
606 : : case POS_COLLIDE_START:
607 : : case POS_BEHIND:
608 : : // Pos1 is after Pos2
609 : 0 : n = rTbl.size();
610 : 0 : break;
611 : :
612 : : default:
613 : : {
614 [ # # ][ # # ]: 0 : pDelPam = new SwPaM( *pCpyStt, pDelPam );
615 [ # # ][ # # ]: 0 : if( *pStt < *pRStt )
616 : : {
617 [ # # ]: 0 : lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
618 : : lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
619 [ # # ]: 0 : *pDelPam->GetPoint(), nDelCount );
620 : : }
621 [ # # ]: 0 : pDelPam->SetMark();
622 : :
623 [ # # ][ # # ]: 0 : if( *pEnd < *pREnd )
624 [ # # ]: 0 : *pDelPam->GetPoint() = *pCpyEnd;
625 : : else
626 : : {
627 [ # # ]: 0 : lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
628 : : lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
629 [ # # ]: 0 : *pDelPam->GetPoint(), nDelCount );
630 : : }
631 : : }
632 : : }
633 : : }
634 : : }
635 : :
636 [ # # ]: 0 : if( pDelPam )
637 : : {
638 [ # # ]: 0 : RedlineMode_t eOld = pDestDoc->GetRedlineMode();
639 [ # # ]: 0 : pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
640 : :
641 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
642 : :
643 : 0 : do {
644 [ # # ]: 0 : pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
645 [ # # ]: 0 : if( pDelPam->GetNext() == pDelPam )
646 : 0 : break;
647 [ # # ][ # # ]: 0 : delete pDelPam->GetNext();
648 : : } while( sal_True );
649 [ # # ][ # # ]: 0 : delete pDelPam;
650 : :
651 [ # # ][ # # ]: 0 : pDestDoc->SetRedlineMode_intern( eOld );
652 [ # # ]: 0 : }
653 : : }
654 : 0 : }
655 : :
656 : 0 : void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
657 : : {
658 : 0 : SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
659 [ # # ]: 0 : if( !pSrcDoc->GetRedlineTbl().empty() )
660 : : {
661 [ # # ]: 0 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
662 [ # # ]: 0 : SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
663 [ # # ][ # # ]: 0 : lcl_DeleteRedlines( aRgTmp, aCpyTmp );
[ # # ]
664 : : }
665 : 0 : }
666 : :
667 : : // Copy an area into this document or into another document
668 : : bool
669 : 37 : SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
670 : : {
671 : 37 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
672 : :
673 : 37 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
674 [ # # ][ - + ]: 37 : bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
675 : :
676 : : // Catch if there's no copy to do
677 [ + - ][ + + ]: 37 : if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
[ + - ][ + + ]
678 : 9 : return false;
679 : :
680 : : // Prevent copying in Flys that are anchored in the area
681 [ + + ]: 28 : if( pDoc == this )
682 : : {
683 : : // Correct the Start-/EndNode
684 : 18 : sal_uLong nStt = pStt->nNode.GetIndex(),
685 : 18 : nEnd = pEnd->nNode.GetIndex(),
686 : 18 : nDiff = nEnd - nStt +1;
687 : 18 : SwNode* pNd = GetNodes()[ nStt ];
688 [ + + ][ + + ]: 18 : if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
[ + - ]
689 : 3 : ++nStt, --nDiff;
690 [ + - - + ]: 36 : if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
[ - + ]
691 [ + - ][ + - ]: 18 : ((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
[ + - ]
692 : 0 : --nEnd, --nDiff;
693 [ + + - + ]: 33 : if( nDiff &&
[ - + ]
694 : 15 : lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
695 : : {
696 : 0 : return false;
697 : : }
698 : : }
699 : :
700 : 28 : SwPaM* pRedlineRange = 0;
701 [ + - + + : 81 : if( pDoc->IsRedlineOn() ||
- + ][ - + ]
702 : 53 : (!pDoc->IsIgnoreRedline() && !pDoc->GetRedlineTbl().empty() ) )
703 [ # # ]: 0 : pRedlineRange = new SwPaM( rPos );
704 : :
705 : 28 : RedlineMode_t eOld = pDoc->GetRedlineMode();
706 : :
707 : 28 : bool bRet = false;
708 : :
709 [ + + ]: 28 : if( pDoc != this )
710 : : { // ordinary copy
711 : 10 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
712 : : }
713 [ + - ]: 36 : else if( ! ( *pStt <= rPos && rPos < *pEnd &&
714 : 0 : ( pStt->nNode != pEnd->nNode ||
715 [ # # ][ - + : 18 : !pStt->nNode.GetNode().IsTxtNode() )) )
# # # # ]
716 : : {
717 : : // Copy to a position outside of the area, or copy a single TextNode
718 : : // Do an ordinary copy
719 : 18 : bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
720 : : }
721 : : else
722 : : {
723 : : // Copy the area in itself
724 : : // Special case for handling an area with several nodes,
725 : : // or a single node that is not a TextNode
726 : : OSL_ENSURE( this == pDoc, " invalid copy branch!" );
727 : : OSL_FAIL("mst: i thought this could be dead code;"
728 : : "please tell me what you did to get here!");
729 [ # # ]: 0 : pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
730 : :
731 : : // Then copy the area to the underlying document area
732 : : // (with start/end nodes clamped) and move them to
733 : : // the desired position.
734 : :
735 : 0 : SwUndoCpyDoc* pUndo = 0;
736 : : // Save the Undo area
737 [ # # ]: 0 : SwPaM aPam( rPos );
738 [ # # ][ # # ]: 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
[ # # ]
739 : : {
740 [ # # ][ # # ]: 0 : pDoc->GetIDocumentUndoRedo().ClearRedo();
741 [ # # ][ # # ]: 0 : pUndo = new SwUndoCpyDoc( aPam );
742 : : }
743 : :
744 : : {
745 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
746 [ # # ]: 0 : SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
747 [ # # ][ # # ]: 0 : SwNodeIndex( GetNodes().GetEndOfAutotext() ));
[ # # ][ # # ]
748 [ # # ]: 0 : aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
749 : : // copy without Frames
750 [ # # ]: 0 : pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
751 : :
752 [ # # ][ # # ]: 0 : aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
753 [ # # ]: 0 : aPam.SetMark();
754 : : SwCntntNode* pNode =
755 [ # # ][ # # ]: 0 : pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
756 [ # # ]: 0 : pNode->MakeEndIndex( &aPam.GetMark()->nContent );
757 : :
758 [ # # ]: 0 : aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
759 [ # # ][ # # ]: 0 : pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
760 [ # # ]: 0 : pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
761 : : // move to desired position
762 [ # # ]: 0 : pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
763 : :
764 : 0 : pNode = aPam.GetCntntNode();
765 [ # # ]: 0 : *aPam.GetPoint() = rPos; // Move the cursor for Undo
766 [ # # ]: 0 : aPam.SetMark(); // also move the Mark
767 [ # # ]: 0 : aPam.DeleteMark(); // But don't mark any area
768 [ # # ][ # # ]: 0 : pDoc->DeleteSection( pNode ); // Delete the area again
[ # # ]
769 : : }
770 : :
771 : : // if Undo is enabled, store the insertion range
772 [ # # ][ # # ]: 0 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
[ # # ]
773 : : {
774 [ # # ]: 0 : pUndo->SetInsertRange( aPam );
775 [ # # ][ # # ]: 0 : pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
776 : : }
777 : :
778 [ # # ]: 0 : if( pRedlineRange )
779 : : {
780 [ # # ]: 0 : pRedlineRange->SetMark();
781 [ # # ]: 0 : *pRedlineRange->GetPoint() = *aPam.GetPoint();
782 [ # # ]: 0 : *pRedlineRange->GetMark() = *aPam.GetMark();
783 : : }
784 : :
785 [ # # ]: 0 : pDoc->SetModified();
786 [ # # ]: 0 : bRet = true;
787 : : }
788 : :
789 : 28 : pDoc->SetRedlineMode_intern( eOld );
790 [ - + ]: 28 : if( pRedlineRange )
791 : : {
792 [ # # ]: 0 : if( pDoc->IsRedlineOn() )
793 [ # # ]: 0 : pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
794 : : else
795 : 0 : pDoc->SplitRedline( *pRedlineRange );
796 [ # # ]: 0 : delete pRedlineRange;
797 : : }
798 : :
799 : 37 : return bRet;
800 : : }
801 : :
802 : 5 : bool lcl_MarksWholeNode(const SwPaM & rPam)
803 : : {
804 : 5 : bool bResult = false;
805 : 5 : const SwPosition* pStt = rPam.Start();
806 : 5 : const SwPosition* pEnd = rPam.End();
807 : :
808 [ + - ][ + - ]: 5 : if (NULL != pStt && NULL != pEnd)
809 : : {
810 : 5 : const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
811 : 5 : const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
812 : :
813 [ + - + + : 12 : if (NULL != pSttNd && NULL != pEndNd &&
+ - ][ + + ]
[ + - ]
814 : 5 : pStt->nContent.GetIndex() == 0 &&
815 : 2 : pEnd->nContent.GetIndex() == pEndNd->Len())
816 : : {
817 : 2 : bResult = true;
818 : : }
819 : : }
820 : :
821 : 5 : return bResult;
822 : : }
823 : :
824 : : // #i86492#
825 : 0 : bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
826 : : {
827 : 0 : bool bRet = false;
828 : :
829 : 0 : const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
830 : 0 : const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
831 [ # # ]: 0 : if ( pTxtNd && pTxtNd->IsInList() &&
[ # # # # ]
[ # # ][ # # ]
832 : 0 : pEndTxtNd && pEndTxtNd->IsInList() )
833 : : {
834 : 0 : bRet = true;
835 [ # # ][ # # ]: 0 : SwNodeIndex aIdx(rPam.Start()->nNode);
836 : :
837 [ # # ][ # # ]: 0 : do
[ # # ]
838 : : {
839 [ # # ]: 0 : aIdx++;
840 : 0 : pTxtNd = aIdx.GetNode().GetTxtNode();
841 : :
842 [ # # ][ # # ]: 0 : if ( !pTxtNd || !pTxtNd->IsInList() )
[ # # ][ # # ]
843 : : {
844 : 0 : bRet = false;
845 : 0 : break;
846 : : }
847 [ # # ]: 0 : } while ( pTxtNd && pTxtNd != pEndTxtNd );
848 : : }
849 : :
850 : :
851 : 0 : return bRet;
852 : : }
853 : :
854 : 28 : bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
855 : : const bool bMakeNewFrms, const bool bCopyAll,
856 : : SwPaM *const pCpyRange ) const
857 : : {
858 : 28 : SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
859 [ # # ][ - + ]: 28 : const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
860 : :
861 [ + - ]: 28 : SwPosition* pStt = rPam.Start();
862 [ + - ]: 28 : SwPosition* pEnd = rPam.End();
863 : :
864 : : // Catch when there's no copy to do.
865 [ + - ][ + - ]: 46 : if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
[ - + ][ # # ]
[ + + ][ - + ]
[ # # ][ - + ]
866 : : //JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
867 : : //JP 15.11.2001: don't test inclusive the end, ever exclusive
868 [ + - ][ # # ]: 18 : ( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
869 : : {
870 : 0 : return false;
871 : : }
872 : :
873 [ + + ][ + - ]: 28 : const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
[ - + ]
874 : :
875 : : // If Undo is enabled, create the UndoCopy object
876 : 28 : SwUndoCpyDoc* pUndo = 0;
877 [ + - ]: 28 : SwPaM aCpyPam( rPos );
878 : :
879 [ + - ]: 28 : SwTblNumFmtMerge aTNFM( *this, *pDoc );
880 : :
881 [ + - ][ + - ]: 28 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
[ + + ]
882 : : {
883 [ + - ][ + - ]: 6 : pUndo = new SwUndoCpyDoc( aCpyPam );
884 [ + - ][ + - ]: 6 : pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
885 : : }
886 : :
887 [ + - ]: 28 : RedlineMode_t eOld = pDoc->GetRedlineMode();
888 [ + - ]: 28 : pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
889 : :
890 : : // Move the PaM one node back from the insert position, so that
891 : : // the position doesn't get moved
892 [ + - ]: 28 : aCpyPam.SetMark();
893 [ + - ]: 28 : sal_Bool bCanMoveBack = aCpyPam.Move( fnMoveBackward, fnGoCntnt );
894 : : // If the position was shifted from more than one node, an end node has been skipped
895 : 28 : bool bAfterTable = false;
896 [ - + ]: 28 : if ( ( rPos.nNode.GetIndex() - aCpyPam.GetPoint()->nNode.GetIndex() ) > 1 )
897 : : {
898 : : // First go back to the original place
899 [ # # ]: 0 : aCpyPam.GetPoint()->nNode = rPos.nNode;
900 [ # # ]: 0 : aCpyPam.GetPoint()->nContent = rPos.nContent;
901 : :
902 : 0 : bCanMoveBack = false;
903 : 0 : bAfterTable = true;
904 : : }
905 [ + - ]: 28 : if( !bCanMoveBack )
906 [ + - ]: 28 : aCpyPam.GetPoint()->nNode--;
907 : :
908 [ + - ]: 28 : SwNodeRange aRg( pStt->nNode, pEnd->nNode );
909 [ + - ]: 28 : SwNodeIndex aInsPos( rPos.nNode );
910 : 28 : const bool bOneNode = pStt->nNode == pEnd->nNode;
911 : 28 : SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
912 : 28 : SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
913 : 28 : SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
914 : 28 : bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
915 : 20 : ( ( pDestTxtNd && !pDestTxtNd->GetTxt().Len() ) ||
916 [ + - - + ]: 48 : ( !bOneNode && !rPos.nContent.GetIndex() ) );
[ # # ][ # # ]
[ + + ]
917 : 28 : bool bCopyBookmarks = true;
918 : 28 : sal_Bool bStartIsTxtNode = 0 != pSttTxtNd;
919 : :
920 : : // #i104585# copy outline num rule to clipboard (for ASCII filter)
921 [ - + ][ # # ]: 28 : if (pDoc->IsClipBoard() && GetOutlineNumRule())
[ - + ]
922 : : {
923 [ # # ]: 0 : pDoc->SetOutlineNumRule(*GetOutlineNumRule());
924 : : }
925 : :
926 : : // #i86492#
927 : : // Correct the search for a previous list:
928 : : // First search for non-outline numbering list. Then search for non-outline
929 : : // bullet list.
930 : : // Keep also the <ListId> value for possible propagation.
931 [ + - ]: 28 : String aListIdToPropagate;
932 : : const SwNumRule* pNumRuleToPropagate =
933 [ + - ]: 28 : pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
934 [ + - ]: 28 : if ( !pNumRuleToPropagate )
935 : : {
936 : : pNumRuleToPropagate =
937 [ + - ]: 28 : pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
938 : : }
939 : : // #i86492#
940 : : // Do not propagate previous found list, if
941 : : // - destination is an empty paragraph which is not in a list and
942 : : // - source contains at least one paragraph which is not in a list
943 [ - + ]: 28 : if ( pNumRuleToPropagate &&
[ # # # # ]
[ # # ][ # # ]
[ - + ]
944 [ # # ]: 0 : pDestTxtNd && !pDestTxtNd->GetTxt().Len() && !pDestTxtNd->IsInList() &&
945 [ # # ]: 0 : !lcl_ContainsOnlyParagraphsInList( rPam ) )
946 : : {
947 : 0 : pNumRuleToPropagate = 0;
948 : : }
949 : :
950 : : // This do/while block is only there so that we can break out of it!
951 : : do {
952 [ + - ]: 28 : if( pSttTxtNd )
953 : : {
954 : : // Don't copy the beginning completely?
955 [ + + ][ + - ]: 28 : if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
[ + + ][ + + ]
956 : : {
957 [ + - ]: 11 : SwIndex aDestIdx( rPos.nContent );
958 : 11 : sal_Bool bCopyOk = sal_False;
959 [ - + ]: 11 : if( !pDestTxtNd )
960 : : {
961 [ # # ][ # # ]: 0 : if( pStt->nContent.GetIndex() || bOneNode )
[ # # ]
962 [ # # ]: 0 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
963 [ # # ][ # # ]: 0 : pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
964 : : else
965 : : {
966 [ # # ]: 0 : pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
967 : 0 : bCopyOk = sal_True;
968 : : }
969 [ # # ][ # # ]: 0 : aDestIdx.Assign( pDestTxtNd, 0 );
970 : 0 : bCopyCollFmt = true;
971 : : }
972 [ + + ][ - + ]: 11 : else if( !bOneNode || bColumnSel )
973 : : {
974 : 8 : xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
975 : : {
976 [ + - ][ + - ]: 8 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
977 [ + - ][ + - ]: 8 : pDoc->SplitNode( rPos, false );
978 : : }
979 : :
980 [ - + ][ # # ]: 8 : if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
[ # # ][ - + ]
981 : : {
982 : : // after the SplitNode, span the CpyPam correctly again
983 [ # # ]: 0 : aCpyPam.Move( fnMoveBackward, fnGoCntnt );
984 [ # # ]: 0 : aCpyPam.Move( fnMoveBackward, fnGoCntnt );
985 : : }
986 : :
987 [ + - ][ + - ]: 8 : pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
988 [ + - ][ + - ]: 8 : aDestIdx.Assign( pDestTxtNd, pDestTxtNd->GetTxt().Len() );
989 : :
990 : : // Correct the area again
991 [ - + ]: 8 : if( bEndEqualIns )
992 : : {
993 : 0 : sal_Bool bChg = pEnd != rPam.GetPoint();
994 [ # # ]: 0 : if( bChg )
995 : 0 : rPam.Exchange();
996 [ # # ]: 0 : rPam.Move( fnMoveBackward, fnGoCntnt );
997 [ # # ]: 0 : if( bChg )
998 : 0 : rPam.Exchange();
999 : :
1000 [ # # ]: 0 : aRg.aEnd = pEnd->nNode;
1001 : 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1002 : : }
1003 [ + - ][ - + ]: 8 : else if( rPos == *pEnd )
1004 : : {
1005 : : // The end was also moved
1006 [ # # ]: 0 : pEnd->nNode--;
1007 [ # # ][ # # ]: 0 : pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
1008 [ # # ]: 0 : aRg.aEnd = pEnd->nNode;
1009 : 0 : pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1010 : : }
1011 : : }
1012 : :
1013 : : // Safe numrule item at destination.
1014 : : // #i86492# - Safe also <ListId> item of destination.
1015 : 11 : int aNumRuleState = SFX_ITEM_UNKNOWN;
1016 [ + - ]: 11 : SwNumRuleItem aNumRuleItem;
1017 : 11 : int aListIdState = SFX_ITEM_UNKNOWN;
1018 [ + - ][ + - ]: 11 : SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
[ + - ]
1019 : : {
1020 [ + - ]: 11 : const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
1021 [ - + ]: 11 : if (pAttrSet != NULL)
1022 : : {
1023 : 0 : const SfxPoolItem * pItem = NULL;
1024 [ # # ]: 0 : aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1025 [ # # ]: 0 : if (SFX_ITEM_SET == aNumRuleState)
1026 [ # # ]: 0 : aNumRuleItem = *((SwNumRuleItem *) pItem);
1027 : :
1028 : : aListIdState =
1029 [ # # ]: 0 : pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1030 [ # # ]: 0 : if (SFX_ITEM_SET == aListIdState)
1031 : : {
1032 [ # # ]: 0 : aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1033 : : }
1034 : : }
1035 : : }
1036 : :
1037 [ + - ]: 11 : if( !bCopyOk )
1038 : : {
1039 : : const xub_StrLen nCpyLen = ( (bOneNode)
1040 : 3 : ? pEnd->nContent.GetIndex()
1041 : 8 : : pSttTxtNd->GetTxt().Len() )
1042 [ + + ]: 19 : - pStt->nContent.GetIndex();
1043 : : pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
1044 [ + - ]: 11 : pStt->nContent, nCpyLen );
1045 [ - + ]: 11 : if( bEndEqualIns )
1046 [ # # ]: 0 : pEnd->nContent -= nCpyLen;
1047 : : }
1048 : :
1049 [ + + ]: 11 : if( bOneNode )
1050 : : {
1051 [ + - ]: 3 : if( bCopyCollFmt )
1052 : : {
1053 [ + - ]: 3 : pSttTxtNd->CopyCollFmt( *pDestTxtNd );
1054 : :
1055 : : /* If only a part of one paragraph is copied
1056 : : restore the numrule at the destination. */
1057 : : // #i86492# - restore also <ListId> item
1058 [ + - ][ + - ]: 3 : if ( !lcl_MarksWholeNode(rPam) )
1059 : : {
1060 [ - + ]: 3 : if (SFX_ITEM_SET == aNumRuleState)
1061 : : {
1062 [ # # ]: 0 : pDestTxtNd->SetAttr(aNumRuleItem);
1063 : : }
1064 : : else
1065 : : {
1066 [ + - ]: 3 : pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1067 : : }
1068 [ - + ]: 3 : if (SFX_ITEM_SET == aListIdState)
1069 : : {
1070 [ # # ]: 0 : pDestTxtNd->SetAttr(aListIdItem);
1071 : : }
1072 : : else
1073 : : {
1074 [ + - ]: 3 : pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1075 : : }
1076 : : }
1077 : : }
1078 : :
1079 : : break;
1080 : : }
1081 : :
1082 [ + - ][ + - ]: 11 : aRg.aStart++;
[ + + ][ + - ]
[ + + ][ + - ]
[ + + ]
1083 : : }
1084 : : }
1085 [ # # ]: 0 : else if( pDestTxtNd )
1086 : : {
1087 : : // Problems with insertion of table selections into "normal" text solved.
1088 : : // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
1089 : : // the undo operation will try to merge this node after removing the table.
1090 : : // If we didn't split a textnode, the PaM should start at the inserted table node
1091 [ # # ][ # # ]: 0 : if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
1092 : : { // Insertion at the last position of a textnode (empty or not)
1093 [ # # ]: 0 : aInsPos++; // The table will be inserted behind the text node
1094 : : }
1095 [ # # ]: 0 : else if( rPos.nContent.GetIndex() )
1096 : : { // Insertion in the middle of a text node, it has to be split
1097 : : // (and joined from undo)
1098 : 0 : bStartIsTxtNode = sal_True;
1099 : :
1100 : 0 : xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
1101 : : {
1102 [ # # ][ # # ]: 0 : ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
1103 [ # # ][ # # ]: 0 : pDoc->SplitNode( rPos, false );
1104 : : }
1105 : :
1106 [ # # ][ # # ]: 0 : if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
[ # # ][ # # ]
1107 : : {
1108 : : // after the SplitNode, span the CpyPam correctly again
1109 [ # # ]: 0 : aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1110 [ # # ]: 0 : aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1111 : : }
1112 : :
1113 : : // Correct the area again
1114 [ # # ]: 0 : if( bEndEqualIns )
1115 [ # # ]: 0 : aRg.aEnd--;
1116 : : // The end would also be moved
1117 [ # # ][ # # ]: 0 : else if( rPos == *pEnd )
1118 : : {
1119 [ # # ]: 0 : rPos.nNode-=2;
1120 : 0 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1121 [ # # ][ # # ]: 0 : nCntntEnd );
1122 [ # # ]: 0 : rPos.nNode++;
1123 [ # # ]: 0 : aRg.aEnd--;
1124 : : }
1125 : : }
1126 [ # # ]: 0 : else if( bCanMoveBack )
1127 : : { //Insertion at the first position of a text node. It will not be splitted, the table
1128 : : // will be inserted before the text node.
1129 : : // See below, before the SetInsertRange funciton of the undo object will be called,
1130 : : // the CpyPam would be moved to the next content position. This has to be avoided
1131 : : // We want to be moved to the table node itself thus we have to set bCanMoveBack
1132 : : // and to manipulate aCpyPam.
1133 : 0 : bCanMoveBack = false;
1134 [ # # ]: 0 : aCpyPam.GetPoint()->nNode--;
1135 : : }
1136 : : }
1137 : :
1138 : 25 : pDestTxtNd = aInsPos.GetNode().GetTxtNode();
1139 [ + - ]: 25 : if( pEndTxtNd )
1140 : : {
1141 [ + - ]: 25 : SwIndex aDestIdx( rPos.nContent );
1142 [ - + ]: 25 : if( !pDestTxtNd )
1143 : : {
1144 [ # # ]: 0 : pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
1145 [ # # ][ # # ]: 0 : pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
1146 [ # # ][ # # ]: 0 : aDestIdx.Assign( pDestTxtNd, 0 );
1147 [ # # ]: 0 : aInsPos--;
1148 : :
1149 : : // if we have to insert an extra text node
1150 : : // at the destination, this node will be our new destination
1151 : : // (text) node, and thus we set bStartisTxtNode to true. This
1152 : : // will ensure that this node will be deleted during Undo
1153 : : // using JoinNext.
1154 : : OSL_ENSURE( !bStartIsTxtNode, "Oops, undo may be instable now." );
1155 : 0 : bStartIsTxtNode = sal_True;
1156 : : }
1157 : :
1158 : : // Save numrule at destination
1159 : : // #i86492# - Safe also <ListId> item of destination.
1160 : 25 : int aNumRuleState = SFX_ITEM_UNKNOWN;
1161 [ + - ]: 25 : SwNumRuleItem aNumRuleItem;
1162 : 25 : int aListIdState = SFX_ITEM_UNKNOWN;
1163 [ + - ][ + - ]: 25 : SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
[ + - ]
1164 : : {
1165 [ + - ]: 25 : const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
1166 [ - + ]: 25 : if (pAttrSet != NULL)
1167 : : {
1168 : 0 : const SfxPoolItem * pItem = NULL;
1169 : :
1170 : : aNumRuleState =
1171 [ # # ]: 0 : pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1172 [ # # ]: 0 : if (SFX_ITEM_SET == aNumRuleState)
1173 [ # # ]: 0 : aNumRuleItem = *((SwNumRuleItem *) pItem);
1174 : :
1175 : : aListIdState =
1176 [ # # ]: 0 : pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1177 [ # # ]: 0 : if (SFX_ITEM_SET == aListIdState)
1178 [ # # ]: 0 : aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1179 : : }
1180 : : }
1181 : :
1182 : 25 : const bool bEmptyDestNd = 0 == pDestTxtNd->GetTxt().Len();
1183 [ + - ]: 25 : pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
1184 [ + - ][ + - ]: 50 : pEnd->nContent.GetIndex() );
[ + - ]
1185 : :
1186 : : // Also copy all format templates
1187 [ + + ][ + + ]: 25 : if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
[ + - ]
1188 : : {
1189 [ + - ]: 17 : pEndTxtNd->CopyCollFmt( *pDestTxtNd );
1190 : :
1191 [ + + ]: 17 : if ( bOneNode )
1192 : : {
1193 : : /* If only a part of one paragraph is copied
1194 : : restore the numrule at the destination. */
1195 : : // #i86492# - restore also <ListId> item
1196 [ + - ][ - + ]: 2 : if ( !lcl_MarksWholeNode(rPam) )
1197 : : {
1198 [ # # ]: 0 : if (SFX_ITEM_SET == aNumRuleState)
1199 : : {
1200 [ # # ]: 0 : pDestTxtNd->SetAttr(aNumRuleItem);
1201 : : }
1202 : : else
1203 : : {
1204 [ # # ]: 0 : pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1205 : : }
1206 [ # # ]: 0 : if (SFX_ITEM_SET == aListIdState)
1207 : : {
1208 [ # # ]: 0 : pDestTxtNd->SetAttr(aListIdItem);
1209 : : }
1210 : : else
1211 : : {
1212 [ # # ]: 0 : pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1213 : : }
1214 : : }
1215 : : }
1216 [ + - ][ + - ]: 25 : }
[ + - ]
1217 : : }
1218 : :
1219 [ + - ][ + + ]: 25 : if( bCopyAll || aRg.aStart != aRg.aEnd )
[ + + ]
1220 : : {
1221 [ + - ]: 17 : SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
1222 [ + - ][ + + ]: 17 : if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
[ + - ][ + - ]
[ + + ]
1223 : : {
1224 [ + - ][ + - ]: 15 : aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
1225 [ + - ][ - + ]: 15 : if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, sal_False ) )
1226 [ # # ]: 0 : pDestTxtNd->ResetAttr( RES_BREAK );
1227 [ + - ][ - + ]: 15 : if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, sal_False ) )
1228 [ # # ]: 0 : pDestTxtNd->ResetAttr( RES_PAGEDESC );
1229 : : }
1230 : :
1231 [ - + ]: 17 : if( aInsPos == pEnd->nNode )
1232 : : {
1233 [ # # ]: 0 : SwNodeIndex aSaveIdx( aInsPos, -1 );
1234 [ # # ]: 0 : CopyWithFlyInFly( aRg, 0,aInsPos, bMakeNewFrms, sal_False );
1235 [ # # ]: 0 : aSaveIdx++;
1236 [ # # ]: 0 : pEnd->nNode = aSaveIdx;
1237 [ # # ][ # # ]: 0 : pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
[ # # ]
1238 : : }
1239 : : else
1240 [ + - ]: 17 : CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, bMakeNewFrms, sal_False );
1241 : :
1242 : 17 : bCopyBookmarks = false;
1243 : :
1244 : : // Put the breaks back into the first node
1245 [ - + # # ]: 17 : if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
[ # # ][ - + ]
1246 [ # # ]: 0 : aCpyPam.GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode() ) )
1247 : : {
1248 [ # # ]: 0 : pDestTxtNd->SetAttr( aBrkSet );
1249 [ + - ]: 17 : }
1250 : : }
1251 : : } while( sal_False );
1252 : :
1253 : : // Adjust position (in case it was moved / in another node)
1254 : 28 : rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1255 [ + - ][ + - ]: 56 : rPos.nContent.GetIndex() );
1256 : :
1257 [ - + ]: 28 : if( rPos.nNode != aInsPos )
1258 : : {
1259 [ # # ]: 0 : aCpyPam.GetMark()->nNode = aInsPos;
1260 [ # # ][ # # ]: 0 : aCpyPam.GetMark()->nContent.Assign( aCpyPam.GetCntntNode(sal_False), 0 );
1261 [ # # ]: 0 : rPos = *aCpyPam.GetMark();
1262 : : }
1263 : : else
1264 [ + - ]: 28 : *aCpyPam.GetMark() = rPos;
1265 : :
1266 [ + - ]: 28 : if ( !bAfterTable )
1267 [ - + ][ + - ]: 28 : aCpyPam.Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
1268 : : else
1269 : : {
1270 : : // Reset the offset to 0 as it was before the insertion
1271 [ # # ]: 0 : aCpyPam.GetPoint( )->nContent -= aCpyPam.GetPoint( )->nContent;
1272 : :
1273 [ # # ]: 0 : aCpyPam.GetPoint( )->nNode++;
1274 : : // If the next node is a start node, then step back: the start node
1275 : : // has been copied and needs to be in the selection for the undo
1276 [ # # ]: 0 : if ( aCpyPam.GetPoint()->nNode.GetNode().IsStartNode() )
1277 [ # # ]: 0 : aCpyPam.GetPoint( )->nNode--;
1278 : :
1279 : : }
1280 : 28 : aCpyPam.Exchange();
1281 : :
1282 : : // Also copy all bookmarks
1283 [ + - ][ + - ]: 28 : if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() )
[ - + ][ - + ]
[ + + ]
1284 [ # # ]: 0 : lcl_CopyBookmarks( rPam, aCpyPam );
1285 : :
1286 [ - + ]: 28 : if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
1287 [ # # ]: 0 : lcl_DeleteRedlines( rPam, aCpyPam );
1288 : :
1289 : : // If Undo is enabled, store the inserted area
1290 [ + - ][ + - ]: 28 : if (pDoc->GetIDocumentUndoRedo().DoesUndo())
[ + + ]
1291 : : {
1292 [ + - ]: 6 : pUndo->SetInsertRange( aCpyPam, sal_True, bStartIsTxtNode );
1293 : : }
1294 : :
1295 [ - + ]: 28 : if( pCpyRange )
1296 : : {
1297 [ # # ]: 0 : pCpyRange->SetMark();
1298 [ # # ]: 0 : *pCpyRange->GetPoint() = *aCpyPam.GetPoint();
1299 [ # # ]: 0 : *pCpyRange->GetMark() = *aCpyPam.GetMark();
1300 : : }
1301 : :
1302 [ - + ]: 28 : if ( pNumRuleToPropagate )
1303 : : {
1304 : : // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1305 : : pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false,
1306 [ # # ][ # # ]: 0 : aListIdToPropagate, sal_True, true );
[ # # ]
1307 : : }
1308 : :
1309 [ + - ]: 28 : pDoc->SetRedlineMode_intern( eOld );
1310 [ + - ]: 28 : pDoc->SetModified();
1311 : :
1312 [ + - ][ + - ]: 28 : return true;
[ + - ][ + - ]
[ + - ]
1313 : : }
1314 : :
1315 : : // Copy method from SwDoc - "copy Flys in Flys"
1316 : 20 : void SwDoc::CopyWithFlyInFly( const SwNodeRange& rRg, const xub_StrLen nEndContentIndex,
1317 : : const SwNodeIndex& rInsPos, sal_Bool bMakeNewFrms,
1318 : : sal_Bool bDelRedlines, sal_Bool bCopyFlyAtFly ) const
1319 : : {
1320 : 20 : SwDoc* pDest = rInsPos.GetNode().GetDoc();
1321 : :
1322 [ + - ]: 20 : _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
1323 : :
1324 [ + - ]: 20 : SwNodeIndex aSavePos( rInsPos, -1 );
1325 : 20 : sal_Bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
1326 [ + - ][ + - ]: 20 : GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
1327 [ + - ]: 20 : aSavePos++;
1328 [ - + ]: 20 : if( bEndIsEqualEndPos )
1329 [ # # ]: 0 : ((SwNodeIndex&)rRg.aEnd) = aSavePos;
1330 : :
1331 [ + - ]: 20 : aRedlRest.Restore();
1332 : :
1333 : : #if OSL_DEBUG_LEVEL > 0
1334 : : {
1335 : : //JP 17.06.99: Bug 66973 - check count only if the selection is in
1336 : : // the same section or there's no section, because sections that are
1337 : : // not fully selected are not copied.
1338 : : const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
1339 : : SwNodeIndex aTmpI( rRg.aEnd, -1 );
1340 : : const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
1341 : : if( pSSectNd == pESectNd &&
1342 : : !rRg.aStart.GetNode().IsSectionNode() &&
1343 : : !aTmpI.GetNode().IsEndNode() )
1344 : : {
1345 : : OSL_ENSURE( rInsPos.GetIndex() - aSavePos.GetIndex() ==
1346 : : rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
1347 : : "An insufficient number of nodes were copied!" );
1348 : : }
1349 : : }
1350 : : #endif
1351 : :
1352 : : {
1353 [ + - ][ + - ]: 20 : ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
1354 [ + - ][ + - ]: 20 : CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
1355 : : }
1356 : :
1357 [ + - ]: 20 : SwNodeRange aCpyRange( aSavePos, rInsPos );
1358 : :
1359 : : // Also copy all bookmarks
1360 [ + - ][ + - ]: 20 : if( getIDocumentMarkAccess()->getMarksCount() )
[ + + ]
1361 : : {
1362 [ + - ]: 18 : SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
1363 [ + - ]: 18 : SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
1364 : :
1365 [ + - ][ + - ]: 18 : lcl_CopyBookmarks( aRgTmp, aCpyTmp );
[ + - ]
1366 : : }
1367 : :
1368 [ + + ][ + - ]: 20 : if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
[ - + ][ - + ]
1369 [ # # ]: 0 : lcl_DeleteRedlines( rRg, aCpyRange );
1370 : :
1371 [ + - ][ + - ]: 20 : pDest->GetNodes()._DelDummyNodes( aCpyRange );
[ + - ][ + - ]
[ + - ]
1372 : 20 : }
1373 : :
1374 : 0 : void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
1375 : : {
1376 [ # # ][ # # ]: 0 : SwFmtChain aSrc( pSrc->GetChain() );
1377 [ # # ]: 0 : if ( !aSrc.GetNext() )
1378 : : {
1379 [ # # ]: 0 : aSrc.SetNext( pDest );
1380 [ # # ]: 0 : pSrc->SetFmtAttr( aSrc );
1381 : : }
1382 [ # # ][ # # ]: 0 : SwFmtChain aDest( pDest->GetChain() );
1383 [ # # ]: 0 : if ( !aDest.GetPrev() )
1384 : : {
1385 [ # # ]: 0 : aDest.SetPrev( pSrc );
1386 [ # # ]: 0 : pDest->SetFmtAttr( aDest );
1387 [ # # ][ # # ]: 0 : }
1388 : 0 : }
1389 : :
1390 : 134 : void SwDoc::CopyFlyInFlyImpl( const SwNodeRange& rRg,
1391 : : const xub_StrLen nEndContentIndex, const SwNodeIndex& rStartIdx,
1392 : : const bool bCopyFlyAtFly ) const
1393 : : {
1394 : : // First collect all Flys, sort them according to their ordering number,
1395 : : // and then only copy them. This maintains the ordering numbers (which are only
1396 : : // managed in the DrawModel).
1397 : 134 : SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
1398 [ + - ]: 134 : ::std::set< _ZSortFly > aSet;
1399 : 134 : sal_uInt16 nArrLen = GetSpzFrmFmts()->size();
1400 : :
1401 [ + + ]: 203 : for ( sal_uInt16 n = 0; n < nArrLen; ++n )
1402 : : {
1403 [ + - ]: 69 : SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
1404 [ + - ]: 69 : SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
1405 [ + - ]: 69 : SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1406 : 69 : bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
1407 [ + + + - : 165 : if ( pAPos &&
+ + ][ - +
# # # # ]
[ + + + + ]
[ + + ][ + + ]
1408 : : ( bAtCntnt ||
1409 : 18 : (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
1410 : 18 : (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
1411 : 0 : (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
1412 : 0 : ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
1413 [ + - ]: 30 : : ( IsRedlineMove()
1414 : 27 : ? rRg.aStart < pAPos->nNode
1415 [ + - ][ + + ]: 30 : : rRg.aStart <= pAPos->nNode )) &&
1416 : 6 : pAPos->nNode <= rRg.aEnd )
1417 : : {
1418 : : //frames at the last source node are not always copied:
1419 : : //- if the node is empty and is the last node of the document or a table cell
1420 : : // or a text frame then tey have to be copied
1421 : : //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1422 : : //- to-character bound objects are copied if their index is <= nEndContentIndex
1423 : 3 : bool bAdd = false;
1424 [ + - ]: 3 : if( pAPos->nNode < rRg.aEnd )
1425 : 3 : bAdd = true;
1426 [ - + ][ # # ]: 3 : if (!bAdd && !IsRedlineMove()) // fdo#40599: not for redline move
[ # # ][ - + ]
1427 : : {
1428 : 0 : bool bEmptyNode = false;
1429 : 0 : bool bLastNode = false;
1430 : : // is the node empty?
1431 : 0 : const SwNodes& rNodes = pAPos->nNode.GetNodes();
1432 : : SwTxtNode* pTxtNode;
1433 [ # # ]: 0 : if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
1434 : : {
1435 : 0 : bEmptyNode = !pTxtNode->GetTxt().Len();
1436 [ # # ]: 0 : if( bEmptyNode )
1437 : : {
1438 : : //last node information is only necessary to know for the last TextNode
1439 [ # # ]: 0 : SwNodeIndex aTmp( pAPos->nNode );
1440 [ # # ]: 0 : ++aTmp;//goto next node
1441 [ # # ]: 0 : while (aTmp.GetNode().IsEndNode())
1442 : : {
1443 [ # # ]: 0 : if( aTmp == rNodes.GetEndOfContent().GetIndex() )
1444 : : {
1445 : 0 : bLastNode = true;
1446 : 0 : break;
1447 : : }
1448 [ # # ]: 0 : ++aTmp;
1449 [ # # ]: 0 : }
1450 : : }
1451 : : }
1452 [ # # ][ # # ]: 0 : bAdd = bLastNode && bEmptyNode;
1453 [ # # ]: 0 : if( !bAdd )
1454 : : {
1455 [ # # ]: 0 : if( bAtCntnt )
1456 : 0 : bAdd = nEndContentIndex > 0;
1457 : : else
1458 : 0 : bAdd = pAPos->nContent <= nEndContentIndex;
1459 : : }
1460 : : }
1461 [ + - ]: 3 : if( bAdd )
1462 [ + - ][ + - ]: 3 : aSet.insert( _ZSortFly( pFmt, pAnchor, nArrLen + aSet.size() ));
1463 : : }
1464 : : }
1465 : :
1466 : : // Store all copied (and also the newly created) frames in another array.
1467 : : // They are stored as matching the originals, so that we will be later
1468 : : // able to build the chains accordingly.
1469 [ + - ]: 134 : ::std::vector< SwFrmFmt* > aVecSwFrmFmt;
1470 : :
1471 [ + + ]: 137 : for (::std::set< _ZSortFly >::const_iterator it=aSet.begin() ; it != aSet.end(); ++it )
1472 : : {
1473 : : // #i59964#
1474 : : // correct determination of new anchor position
1475 [ + - ]: 3 : SwFmtAnchor aAnchor( *(*it).GetAnchor() );
1476 [ + - ]: 3 : SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
1477 : : // for at-paragraph and at-character anchored objects the new anchor
1478 : : // position can *not* be determined by the difference of the current
1479 : : // anchor position to the start of the copied range, because not
1480 : : // complete selected sections in the copied range aren't copied - see
1481 : : // method <SwNodes::_CopyNodes(..)>.
1482 : : // Thus, the new anchor position in the destination document is found
1483 : : // by counting the text nodes.
1484 [ - + # # ]: 3 : if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
[ + - ]
1485 : 0 : (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
1486 : : {
1487 : : // First, determine number of anchor text node in the copied range.
1488 : : // Note: The anchor text node *have* to be inside the copied range.
1489 : 3 : sal_uLong nAnchorTxtNdNumInRange( 0L );
1490 : 3 : bool bAnchorTxtNdFound( false );
1491 [ + - ]: 3 : SwNodeIndex aIdx( rRg.aStart );
1492 [ + + ][ + - ]: 9 : while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
[ + + ]
1493 : : {
1494 [ + + ]: 6 : if ( aIdx.GetNode().IsTxtNode() )
1495 : : {
1496 : 3 : ++nAnchorTxtNdNumInRange;
1497 [ + - ]: 3 : bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
1498 : : }
1499 : :
1500 [ + - ]: 6 : ++aIdx;
1501 : : }
1502 [ - + ]: 3 : if ( !bAnchorTxtNdFound )
1503 : : {
1504 : : // This case can *not* happen, but to be robust take the first
1505 : : // text node in the destination document.
1506 : : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1507 : 0 : nAnchorTxtNdNumInRange = 1;
1508 : : }
1509 : : // Second, search corresponding text node in destination document
1510 : : // by counting forward from start insert position <rStartIdx> the
1511 : : // determined number of text nodes.
1512 [ + - ]: 3 : aIdx = rStartIdx;
1513 [ + - ]: 3 : SwNodeIndex aAnchorNdIdx( rStartIdx );
1514 : : const SwNode& aEndOfContentNd =
1515 : 3 : aIdx.GetNode().GetNodes().GetEndOfContent();
1516 [ + + + - ]: 15 : while ( nAnchorTxtNdNumInRange > 0 &&
[ + + ]
1517 : 6 : &(aIdx.GetNode()) != &aEndOfContentNd )
1518 : : {
1519 [ + + ]: 6 : if ( aIdx.GetNode().IsTxtNode() )
1520 : : {
1521 : 3 : --nAnchorTxtNdNumInRange;
1522 [ + - ]: 3 : aAnchorNdIdx = aIdx;
1523 : : }
1524 : :
1525 [ + - ]: 6 : ++aIdx;
1526 : : }
1527 [ - + ]: 3 : if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1528 : : {
1529 : : // This case can *not* happen, but to be robust take the first
1530 : : // text node in the destination document.
1531 : : OSL_FAIL( "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1532 [ # # ]: 0 : aAnchorNdIdx = rStartIdx;
1533 [ # # ]: 0 : while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1534 : : {
1535 [ # # ]: 0 : ++aAnchorNdIdx;
1536 : : }
1537 : : }
1538 : : // apply found anchor text node as new anchor position
1539 [ + - ][ + - ]: 3 : pNewPos->nNode = aAnchorNdIdx;
[ + - ]
1540 : : }
1541 : : else
1542 : : {
1543 : 0 : long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
1544 [ # # ]: 0 : SwNodeIndex aIdx( rStartIdx, nOffset );
1545 [ # # ][ # # ]: 0 : pNewPos->nNode = aIdx;
1546 : : }
1547 : : // Set the character bound Flys back at the original character
1548 [ - + # # ]: 3 : if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
[ - + ]
1549 : 0 : pNewPos->nNode.GetNode().IsTxtNode() )
1550 : : {
1551 [ # # ]: 0 : pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
1552 [ # # ][ # # ]: 0 : pNewPos->nContent.GetIndex() );
1553 : : }
1554 : : else
1555 : : {
1556 [ + - ]: 3 : pNewPos->nContent.Assign( 0, 0 );
1557 : : }
1558 : :
1559 : : // Check recursion: copy content in its own frame, then don't copy it.
1560 : 3 : sal_Bool bMakeCpy = sal_True;
1561 [ + - ]: 3 : if( pDest == this )
1562 : : {
1563 [ + - ]: 3 : const SwFmtCntnt& rCntnt = (*it).GetFmt()->GetCntnt();
1564 : : const SwStartNode* pSNd;
1565 [ - + # # : 3 : if( rCntnt.GetCntntIdx() &&
# # # # ]
[ - + ]
1566 : 0 : 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
1567 : 0 : pSNd->GetIndex() < rStartIdx.GetIndex() &&
1568 : 0 : rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
1569 : : {
1570 : 0 : bMakeCpy = sal_False;
1571 [ # # ]: 0 : aSet.erase ( it );
1572 : : }
1573 : : }
1574 : :
1575 : : // Copy the format and set the new anchor
1576 [ + - ]: 3 : if( bMakeCpy )
1577 : 3 : aVecSwFrmFmt.push_back( pDest->CopyLayoutFmt( *(*it).GetFmt(),
1578 [ + - ][ + - ]: 3 : aAnchor, false, true ) );
1579 [ + - ]: 3 : }
1580 : :
1581 : : // Rebuild as much as possible of all chains that are available in the original,
1582 : : OSL_ENSURE( aSet.size() == aVecSwFrmFmt.size(), "Missing new Flys" );
1583 [ + - ]: 134 : if ( aSet.size() == aVecSwFrmFmt.size() )
1584 : : {
1585 : 134 : size_t n = 0;
1586 [ + + ]: 137 : for (::std::set< _ZSortFly >::const_iterator nIt=aSet.begin() ; nIt != aSet.end(); ++nIt, ++n )
1587 : : {
1588 : 3 : const SwFrmFmt *pFmtN = (*nIt).GetFmt();
1589 [ + - ]: 3 : const SwFmtChain &rChain = pFmtN->GetChain();
1590 : 3 : int nCnt = 0 != rChain.GetPrev();
1591 [ - + ]: 3 : nCnt += rChain.GetNext() ? 1: 0;
1592 : 3 : size_t k = 0;
1593 [ + + ]: 6 : for (::std::set< _ZSortFly >::const_iterator kIt=aSet.begin() ; kIt != aSet.end(); ++kIt, ++k )
1594 : : {
1595 : 3 : const SwFrmFmt *pFmtK = (*kIt).GetFmt();
1596 [ - + ]: 3 : if ( rChain.GetPrev() == pFmtK )
1597 : : {
1598 [ # # ]: 0 : ::lcl_ChainFmts( dynamic_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]),
1599 [ # # ][ # # ]: 0 : dynamic_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]) );
[ # # ][ # # ]
1600 : 0 : --nCnt;
1601 : : }
1602 [ - + ]: 3 : else if ( rChain.GetNext() == pFmtK )
1603 : : {
1604 [ # # ]: 0 : ::lcl_ChainFmts( dynamic_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[n]),
1605 [ # # ][ # # ]: 0 : dynamic_cast< SwFlyFrmFmt* >(aVecSwFrmFmt[k]) );
[ # # ][ # # ]
1606 : 0 : --nCnt;
1607 : : }
1608 : : }
1609 : : }
1610 : 134 : }
1611 : 134 : }
1612 : :
1613 : :
1614 : :
1615 : :
1616 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|