xref: /aoo41x/main/sw/source/core/undo/untblk.cxx (revision 4d322ebc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <hintids.hxx>
28 #include <fmtanchr.hxx>
29 #include <frmfmt.hxx>
30 #include <doc.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IShellCursorSupplier.hxx>
33 #include <docary.hxx>
34 #include <swundo.hxx>			// fuer die UndoIds
35 #include <pam.hxx>
36 #include <ndtxt.hxx>
37 #include <UndoCore.hxx>
38 #include <rolbck.hxx>
39 #include <redline.hxx>
40 
41 
42 
43 SwUndoInserts::SwUndoInserts( SwUndoId nUndoId, const SwPaM& rPam )
44 	: SwUndo( nUndoId ), SwUndRng( rPam ),
45     pTxtFmtColl( 0 ), pLastNdColl(0), pFrmFmts( 0 ), pRedlData( 0 ),
46 	bSttWasTxtNd( sal_True ), nNdDiff( 0 ), pPos( 0 ), nSetPos( 0 )
47 {
48 	pHistory = new SwHistory;
49 	SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
50 
51 	SwTxtNode* pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
52 	if( pTxtNd )
53 	{
54 		pTxtFmtColl = pTxtNd->GetTxtColl();
55         pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
56                             0, pTxtNd->GetTxt().Len(), false );
57         if( pTxtNd->HasSwAttrSet() )
58             pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
59 
60 		if( !nSttCntnt )	// dann werden Flys mitgenommen !!
61 		{
62 			sal_uInt16 nArrLen = pDoc->GetSpzFrmFmts()->Count();
63 			for( sal_uInt16 n = 0; n < nArrLen; ++n )
64 			{
65 				SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
66                 SwFmtAnchor const*const  pAnchor = &pFmt->GetAnchor();
67                 const SwPosition* pAPos = pAnchor->GetCntntAnchor();
68                 if (pAPos &&
69                     (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
70 					 nSttNode == pAPos->nNode.GetIndex() )
71 				{
72 					if( !pFrmFmts )
73 						pFrmFmts = new SvPtrarr;
74 					pFrmFmts->Insert( pFmt, pFrmFmts->Count() );
75 				}
76 			}
77 		}
78 	}
79 	// Redline beachten
80 	if( pDoc->IsRedlineOn() )
81 	{
82 		pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, pDoc->GetRedlineAuthor() );
83 		SetRedlineMode( pDoc->GetRedlineMode() );
84 	}
85 }
86 
87 // setze den Destination-Bereich nach dem Einlesen.
88 
89 void SwUndoInserts::SetInsertRange( const SwPaM& rPam, sal_Bool bScanFlys,
90 									sal_Bool bSttIsTxtNd )
91 {
92 	const SwPosition* pTmpPos = rPam.End();
93 	nEndNode = pTmpPos->nNode.GetIndex();
94 	nEndCntnt = pTmpPos->nContent.GetIndex();
95 	if( rPam.HasMark() )
96 	{
97 		if( pTmpPos == rPam.GetPoint() )
98 			pTmpPos = rPam.GetMark();
99 		else
100 			pTmpPos = rPam.GetPoint();
101 
102 		nSttNode = pTmpPos->nNode.GetIndex();
103 		nSttCntnt = pTmpPos->nContent.GetIndex();
104 
105 		if( !bSttIsTxtNd )		// wird eine Tabellenselektion eingefuegt,
106 		{
107 			++nSttNode;			// dann stimmt der CopyPam nicht ganz
108 			bSttWasTxtNd = sal_False;
109 		}
110 	}
111 
112 	if( bScanFlys && !nSttCntnt )
113 	{
114 		// dann alle neuen Flys zusammen sammeln !!
115 		SwDoc* pDoc = (SwDoc*)rPam.GetDoc();
116 		sal_uInt16 nFndPos, nArrLen = pDoc->GetSpzFrmFmts()->Count();
117 		for( sal_uInt16 n = 0; n < nArrLen; ++n )
118 		{
119 			SwFrmFmt* pFmt = (*pDoc->GetSpzFrmFmts())[n];
120             SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
121             SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
122             if (pAPos &&
123                 (pAnchor->GetAnchorId() == FLY_AT_PARA) &&
124 				nSttNode == pAPos->nNode.GetIndex() )
125 			{
126 				if( !pFrmFmts ||
127 					USHRT_MAX == ( nFndPos = pFrmFmts->GetPos( pFmt ) ) )
128                 {
129                     ::boost::shared_ptr<SwUndoInsLayFmt> const pFlyUndo(
130                         new SwUndoInsLayFmt(pFmt, 0, 0));
131                     m_FlyUndos.push_back(pFlyUndo);
132                 }
133                 else
134 					pFrmFmts->Remove( nFndPos );
135 			}
136 		}
137 		delete pFrmFmts, pFrmFmts = 0;
138 	}
139 }
140 
141 
142 SwUndoInserts::~SwUndoInserts()
143 {
144 	if( pPos )		// loesche noch den Bereich aus dem UndoNodes Array
145 	{
146 		// Insert speichert den Inhalt in der IconSection
147 		SwNodes& rUNds = pPos->nNode.GetNodes();
148 		if( pPos->nContent.GetIndex() )			// nicht den gesamten Node loeschen
149 		{
150 			SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
151 			ASSERT( pTxtNd, "kein TextNode, aus dem geloescht werden soll" );
152             if( pTxtNd ) // Robust
153             {
154                 pTxtNd->EraseText( pPos->nContent );
155             }
156 			pPos->nNode++;
157 		}
158 		pPos->nContent.Assign( 0, 0 );
159 		rUNds.Delete( pPos->nNode, rUNds.GetEndOfExtras().GetIndex() -
160 									pPos->nNode.GetIndex() );
161 		delete pPos;
162 	}
163 	delete pFrmFmts;
164 	delete pRedlData;
165 }
166 
167 
168 void SwUndoInserts::UndoImpl(::sw::UndoRedoContext & rContext)
169 {
170     SwDoc *const pDoc = & rContext.GetDoc();
171     SwPaM *const pPam = & AddUndoRedoPaM(rContext);
172 
173 	if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
174 		pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
175 
176 	// sind an Point/Mark 2 unterschiedliche TextNodes, dann muss ein
177 	// JoinNext ausgefuehrt werden.
178 	sal_Bool bJoinNext = nSttNode != nEndNode &&
179 				pPam->GetMark()->nNode.GetNode().GetTxtNode() &&
180 				pPam->GetPoint()->nNode.GetNode().GetTxtNode();
181 
182 
183 	// gibts ueberhaupt Inhalt ? (laden von Zeichenvorlagen hat kein Inhalt!)
184 	if( nSttNode != nEndNode || nSttCntnt != nEndCntnt )
185 	{
186 		if( nSttNode != nEndNode )
187 		{
188 			SwTxtNode* pTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
189 			if( pTxtNd && pTxtNd->GetTxt().Len() == nEndCntnt )
190 				pLastNdColl = pTxtNd->GetTxtColl();
191 		}
192 
193 		RemoveIdxFromRange( *pPam, sal_False );
194         SetPaM(*pPam);
195 
196 		// sind Fussnoten oder CntntFlyFrames im Text ??
197 		nSetPos = pHistory->Count();
198 		nNdDiff = pPam->GetMark()->nNode.GetIndex();
199 		DelCntntIndex( *pPam->GetMark(), *pPam->GetPoint() );
200 		nNdDiff -= pPam->GetMark()->nNode.GetIndex();
201 
202 		if( *pPam->GetPoint() != *pPam->GetMark() )
203 		{
204 			pPos = new SwPosition( *pPam->GetPoint() );
205 			MoveToUndoNds( *pPam, &pPos->nNode, &pPos->nContent );
206 
207 			if( !bSttWasTxtNd )
208 				pPam->Move( fnMoveBackward, fnGoCntnt );
209 		}
210 	}
211 
212     if (m_FlyUndos.size())
213     {
214 		sal_uLong nTmp = pPam->GetPoint()->nNode.GetIndex();
215         for (size_t n = m_FlyUndos.size(); 0 < n; --n)
216         {
217             m_FlyUndos[ n-1 ]->UndoImpl(rContext);
218         }
219 		nNdDiff += nTmp - pPam->GetPoint()->nNode.GetIndex();
220 	}
221 
222     SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
223     SwTxtNode* pTxtNode = rIdx.GetNode().GetTxtNode();
224     if( pTxtNode )
225     {
226         if( !pTxtFmtColl )      // falls 0, dann war hier auch kein TextNode,
227         {                       // dann muss dieser geloescht werden,
228             SwNodeIndex aDelIdx( rIdx );
229             rIdx++;
230             SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
231             xub_StrLen nCnt = 0; if( pCNd ) nCnt = pCNd->Len();
232             pPam->GetPoint()->nContent.Assign( pCNd, nCnt );
233             pPam->SetMark();
234             pPam->DeleteMark();
235 
236             RemoveIdxRel( aDelIdx.GetIndex(), *pPam->GetPoint() );
237 
238             pDoc->GetNodes().Delete( aDelIdx, 1 );
239         }
240         else
241         {
242             if( bJoinNext && pTxtNode->CanJoinNext())
243             {
244                 {
245                     RemoveIdxRel( rIdx.GetIndex()+1, SwPosition( rIdx,
246                         SwIndex( pTxtNode, pTxtNode->GetTxt().Len() )));
247                 }
248                 pTxtNode->JoinNext();
249             }
250             // reset all text attributes in the paragraph!
251             pTxtNode->RstAttr( SwIndex(pTxtNode, 0), pTxtNode->Len(), 0, 0, true );
252 
253             // setze alle Attribute im Node zurueck
254             pTxtNode->ResetAllAttr();
255 
256             if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
257                 pTxtFmtColl = (SwTxtFmtColl*)pTxtNode->ChgFmtColl( pTxtFmtColl );
258 
259             pHistory->SetTmpEnd( nSetPos );
260             pHistory->TmpRollback( pDoc, 0, false );
261         }
262     }
263 }
264 
265 void SwUndoInserts::RedoImpl(::sw::UndoRedoContext & rContext)
266 {
267 	// setze noch den Cursor auf den Redo-Bereich
268     SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
269 	SwDoc* pDoc = pPam->GetDoc();
270 	pPam->DeleteMark();
271 	pPam->GetPoint()->nNode = nSttNode - nNdDiff;
272 	SwCntntNode* pCNd = pPam->GetCntntNode();
273 	pPam->GetPoint()->nContent.Assign( pCNd, nSttCntnt );
274 
275 	SwTxtFmtColl* pSavTxtFmtColl = pTxtFmtColl;
276 	if( pTxtFmtColl && pCNd && pCNd->IsTxtNode() )
277 		pSavTxtFmtColl = ((SwTxtNode*)pCNd)->GetTxtColl();
278 
279 	pHistory->SetTmpEnd( nSetPos );
280 
281 	// alte Anfangs-Position fuers Rollback zurueckholen
282 	if( ( nSttNode != nEndNode || nSttCntnt != nEndCntnt ) && pPos )
283 	{
284 		sal_Bool bMvBkwrd = MovePtBackward( *pPam );
285 
286 		// Inhalt wieder einfuegen. (erst pPos abmelden !!)
287 		sal_uLong nMvNd = pPos->nNode.GetIndex();
288 		xub_StrLen nMvCnt = pPos->nContent.GetIndex();
289 		DELETEZ( pPos );
290 		MoveFromUndoNds( *pDoc, nMvNd, nMvCnt, *pPam->GetMark() );
291 		if( bSttWasTxtNd )
292 			MovePtForward( *pPam, bMvBkwrd );
293 		pPam->Exchange();
294 	}
295 
296 	if( USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pTxtFmtColl ))
297 	{
298 		SwTxtNode* pTxtNd = pPam->GetMark()->nNode.GetNode().GetTxtNode();
299 		if( pTxtNd )
300 			pTxtNd->ChgFmtColl( pTxtFmtColl );
301 	}
302 	pTxtFmtColl = pSavTxtFmtColl;
303 
304 	if( pLastNdColl && USHRT_MAX != pDoc->GetTxtFmtColls()->GetPos( pLastNdColl ) &&
305 		pPam->GetPoint()->nNode != pPam->GetMark()->nNode )
306 	{
307 		SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode();
308 		if( pTxtNd )
309 			pTxtNd->ChgFmtColl( pLastNdColl );
310 	}
311 
312     for (size_t n = m_FlyUndos.size(); 0 < n; --n)
313     {
314         m_FlyUndos[ n-1 ]->RedoImpl(rContext);
315     }
316 
317 	pHistory->Rollback( pDoc, nSetPos );
318 
319 	if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
320 	{
321 		RedlineMode_t eOld = pDoc->GetRedlineMode();
322 		pDoc->SetRedlineMode_intern((RedlineMode_t)( eOld & ~nsRedlineMode_t::REDLINE_IGNORE ));
323 		pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ), true);
324 		pDoc->SetRedlineMode_intern( eOld );
325 	}
326 	else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
327 			pDoc->GetRedlineTbl().Count() )
328 		pDoc->SplitRedline( *pPam );
329 }
330 
331 void SwUndoInserts::RepeatImpl(::sw::RepeatContext & rContext)
332 {
333     SwPaM aPam( rContext.GetDoc().GetNodes().GetEndOfContent() );
334 	SetPaM( aPam );
335     SwPaM & rRepeatPaM( rContext.GetRepeatPaM() );
336     aPam.GetDoc()->CopyRange( aPam, *rRepeatPaM.GetPoint(), false );
337 }
338 
339 
340 //////////////////////////////////////////////////////////////////////////
341 
342 SwUndoInsDoc::SwUndoInsDoc( const SwPaM& rPam )
343 	: SwUndoInserts( UNDO_INSDOKUMENT, rPam )
344 {
345 }
346 
347 SwUndoCpyDoc::SwUndoCpyDoc( const SwPaM& rPam )
348 	: SwUndoInserts( UNDO_COPY, rPam )
349 {
350 }
351 
352