xref: /aoo42x/main/sw/source/core/docnode/ndtbl.cxx (revision cdf0e10c)
1 
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 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_sw.hxx"
31 
32 #include <com/sun/star/chart2/XChartDocument.hpp>
33 #include <hintids.hxx>
34 #include <editeng/lrspitem.hxx>
35 #include <editeng/brkitem.hxx>
36 #include <editeng/protitem.hxx>
37 #include <editeng/boxitem.hxx>
38 #include <editeng/shaditem.hxx>
39 #include <fmtfsize.hxx>
40 #include <fmtornt.hxx>
41 #include <fmtfordr.hxx>
42 #include <fmtpdsc.hxx>
43 #include <fmtanchr.hxx>
44 #include <fmtlsplt.hxx>
45 #include <frmatr.hxx>
46 #include <charatr.hxx>
47 #include <cellfrm.hxx>
48 #include <pagefrm.hxx>
49 #include <tabcol.hxx>
50 #include <doc.hxx>
51 #include <IDocumentUndoRedo.hxx>
52 #include <UndoManager.hxx>
53 #include <cntfrm.hxx>
54 #include <pam.hxx>
55 #include <swcrsr.hxx>
56 #include <viscrs.hxx>
57 #include <swtable.hxx>
58 #include <ndtxt.hxx>
59 #include <swundo.hxx>
60 #include <tblsel.hxx>
61 #include <fldbas.hxx>
62 #include <poolfmt.hxx>
63 #include <tabfrm.hxx>
64 #include <UndoCore.hxx>
65 #include <UndoRedline.hxx>
66 #include <UndoDelete.hxx>
67 #include <UndoTable.hxx>
68 #include <hints.hxx>
69 #include <tblafmt.hxx>
70 #include <swcache.hxx>
71 #include <ddefld.hxx>
72 #include <frminf.hxx>
73 #include <cellatr.hxx>
74 #include <swtblfmt.hxx>
75 #include <swddetbl.hxx>
76 #include <mvsave.hxx>
77 #include <docary.hxx>
78 #include <redline.hxx>
79 #include <rolbck.hxx>
80 #include <tblrwcl.hxx>
81 #include <editsh.hxx>
82 #include <txtfrm.hxx>
83 #include <ftnfrm.hxx>
84 #include <section.hxx>
85 #include <frmtool.hxx>
86 #include <node2lay.hxx>
87 #include <comcore.hrc>
88 #include "docsh.hxx"
89 #include <tabcol.hxx>
90 #include <unochart.hxx>
91 #include <node.hxx>
92 #include <ndtxt.hxx>
93 #include <map>
94 #include <algorithm>
95 #include <rootfrm.hxx>
96 #include <fldupde.hxx>
97 #include <switerator.hxx>
98 
99 #ifndef DBG_UTIL
100 #define CHECK_TABLE(t)
101 #else
102 #ifdef DEBUG
103 #define CHECK_TABLE(t) (t).CheckConsistency();
104 #else
105 #define CHECK_TABLE(t)
106 #endif
107 #endif
108 
109 
110 using namespace ::com::sun::star;
111 
112 // #i17764# delete table redlines when modifying the table structure?
113 // #define DEL_TABLE_REDLINES 1
114 
115 const sal_Unicode T2T_PARA = 0x0a;
116 
117 extern void ClearFEShellTabCols();
118 
119 // steht im gctable.cxx
120 extern sal_Bool lcl_GC_Line_Border( const SwTableLine*& , void* pPara );
121 
122 #ifdef DEL_TABLE_REDLINES
123 class lcl_DelRedlines
124 {
125 	SwDoc* pDoc;
126 public:
127 	lcl_DelRedlines( const SwTableNode& rNd, sal_Bool bCheckForOwnRedline );
128 	lcl_DelRedlines( SwPaM& rPam );
129 
130     ~lcl_DelRedlines() { pDoc->EndUndo(UNDO_EMPTY, NULL); }
131 };
132 
133 lcl_DelRedlines::lcl_DelRedlines( SwPaM & rPam) : pDoc( rPam.GetDoc() )
134 {
135     pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
136 	if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
137 		pDoc->AcceptRedline( rPam, true );
138 }
139 #endif
140 
141 void lcl_SetDfltBoxAttr( SwFrmFmt& rFmt, sal_uInt8 nId )
142 {
143 	sal_Bool bTop = sal_False, bBottom = sal_False, bLeft = sal_False, bRight = sal_False;
144 	switch ( nId )
145 	{
146 	case 0:	bTop = bBottom = bLeft = sal_True; 			break;
147 	case 1:	bTop = bBottom = bLeft = bRight = sal_True;	break;
148 	case 2:	bBottom = bLeft = sal_True; 				break;
149 	case 3: bBottom = bLeft = bRight = sal_True; 		break;
150 	}
151 
152     const sal_Bool bHTML = rFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE);
153 	Color aCol( bHTML ? COL_GRAY : COL_BLACK );
154 	SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
155 	if ( bHTML )
156 	{
157 		aLine.SetOutWidth( DEF_DOUBLE_LINE7_OUT );
158 		aLine.SetInWidth ( DEF_DOUBLE_LINE7_IN  );
159 		aLine.SetDistance( DEF_DOUBLE_LINE7_DIST);
160 	}
161     SvxBoxItem aBox(RES_BOX); aBox.SetDistance( 55 );
162 	if ( bTop )
163 		aBox.SetLine( &aLine, BOX_LINE_TOP );
164 	if ( bBottom )
165 		aBox.SetLine( &aLine, BOX_LINE_BOTTOM );
166 	if ( bLeft )
167 		aBox.SetLine( &aLine, BOX_LINE_LEFT );
168 	if ( bRight )
169 		aBox.SetLine( &aLine, BOX_LINE_RIGHT );
170     rFmt.SetFmtAttr( aBox );
171 }
172 
173 void lcl_SetDfltBoxAttr( SwTableBox& rBox, SvPtrarr &rBoxFmtArr, sal_uInt8 nId,
174 							const SwTableAutoFmt* pAutoFmt = 0 )
175 {
176 	SvPtrarr* pArr = (SvPtrarr*)rBoxFmtArr[ nId ];
177 	if( !pArr )
178 	{
179 		pArr = new SvPtrarr;
180 		rBoxFmtArr.Replace( pArr, nId );
181 	}
182 
183 	SwTableBoxFmt* pNewBoxFmt = 0;
184 	SwFrmFmt* pBoxFmt = rBox.GetFrmFmt();
185 	for( sal_uInt16 n = 0; n < pArr->Count(); n += 2 )
186 		if( pArr->GetObject( n ) == pBoxFmt )
187 		{
188 			pNewBoxFmt = (SwTableBoxFmt*)pArr->GetObject( n + 1 );
189 			break;
190 		}
191 
192 	if( !pNewBoxFmt )
193 	{
194 		SwDoc* pDoc = pBoxFmt->GetDoc();
195 		// das Format ist also nicht vorhanden, also neu erzeugen
196 		pNewBoxFmt = pDoc->MakeTableBoxFmt();
197         pNewBoxFmt->SetFmtAttr( pBoxFmt->GetAttrSet().Get( RES_FRM_SIZE ) );
198 
199 		if( pAutoFmt )
200 			pAutoFmt->UpdateToSet( nId, (SfxItemSet&)pNewBoxFmt->GetAttrSet(),
201 									SwTableAutoFmt::UPDATE_BOX,
202 									pDoc->GetNumberFormatter( sal_True ) );
203 		else
204 			::lcl_SetDfltBoxAttr( *pNewBoxFmt, nId );
205 
206 		void* p = pBoxFmt;
207 		pArr->Insert( p, pArr->Count() );
208 		p = pNewBoxFmt;
209 		pArr->Insert( p, pArr->Count() );
210 	}
211 	rBox.ChgFrmFmt( pNewBoxFmt );
212 }
213 
214 SwTableBoxFmt *lcl_CreateDfltBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr,
215 									sal_uInt16 nCols, sal_uInt8 nId )
216 {
217 	if ( !rBoxFmtArr[nId] )
218 	{
219 		SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt();
220 		if( USHRT_MAX != nCols )
221             pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
222 											USHRT_MAX / nCols, 0 ));
223 		::lcl_SetDfltBoxAttr( *pBoxFmt, nId );
224 		rBoxFmtArr.Replace( pBoxFmt, nId );
225 	}
226 	return (SwTableBoxFmt*)rBoxFmtArr[nId];
227 }
228 
229 SwTableBoxFmt *lcl_CreateAFmtBoxFmt( SwDoc &rDoc, SvPtrarr &rBoxFmtArr,
230 									const SwTableAutoFmt& rAutoFmt,
231 									sal_uInt16 nCols, sal_uInt8 nId )
232 {
233 	if( !rBoxFmtArr[nId] )
234 	{
235 		SwTableBoxFmt* pBoxFmt = rDoc.MakeTableBoxFmt();
236 		rAutoFmt.UpdateToSet( nId, (SfxItemSet&)pBoxFmt->GetAttrSet(),
237 								SwTableAutoFmt::UPDATE_BOX,
238 								rDoc.GetNumberFormatter( sal_True ) );
239 		if( USHRT_MAX != nCols )
240             pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
241 											USHRT_MAX / nCols, 0 ));
242 		rBoxFmtArr.Replace( pBoxFmt, nId );
243 	}
244 	return (SwTableBoxFmt*)rBoxFmtArr[nId];
245 }
246 
247 SwTableNode* SwDoc::IsIdxInTbl(const SwNodeIndex& rIdx)
248 {
249 	SwTableNode* pTableNd = 0;
250 	sal_uLong nIndex = rIdx.GetIndex();
251 	do {
252 		SwNode* pNd = (SwNode*)GetNodes()[ nIndex ]->StartOfSectionNode();
253 		if( 0 != ( pTableNd = pNd->GetTableNode() ) )
254 			break;
255 
256 		nIndex = pNd->GetIndex();
257 	} while ( nIndex );
258 	return pTableNd;
259 }
260 
261 
262 // --------------- einfuegen einer neuen Box --------------
263 
264 	// fuege in der Line, vor der InsPos eine neue Box ein.
265 
266 sal_Bool SwNodes::InsBoxen( SwTableNode* pTblNd,
267 						SwTableLine* pLine,
268 						SwTableBoxFmt* pBoxFmt,
269 						SwTxtFmtColl* pTxtColl,
270                         const SfxItemSet* pAutoAttr,
271 						sal_uInt16 nInsPos,
272 						sal_uInt16 nCnt )
273 {
274     if( !nCnt )
275 		return sal_False;
276 	ASSERT( pLine, "keine gueltige Zeile" );
277 
278 	// Index hinter die letzte Box der Line
279 	sal_uLong nIdxPos = 0;
280 	SwTableBox *pPrvBox = 0, *pNxtBox = 0;
281 	if( pLine->GetTabBoxes().Count() )
282 	{
283 		if( nInsPos < pLine->GetTabBoxes().Count() )
284 		{
285 			if( 0 == (pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable(),
286 							pLine->GetTabBoxes()[ nInsPos ] )))
287 				pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() );
288 		}
289 		else if( 0 == ( pNxtBox = pLine->FindNextBox( pTblNd->GetTable(),
290 							pLine->GetTabBoxes()[ nInsPos-1 ] )))
291 				pNxtBox = pLine->FindNextBox( pTblNd->GetTable() );
292 	}
293 	else if( 0 == ( pNxtBox = pLine->FindNextBox( pTblNd->GetTable() )))
294 		pPrvBox = pLine->FindPreviousBox( pTblNd->GetTable() );
295 
296 	if( !pPrvBox && !pNxtBox )
297 	{
298 		sal_Bool bSetIdxPos = sal_True;
299 		if( pTblNd->GetTable().GetTabLines().Count() && !nInsPos )
300 		{
301 			const SwTableLine* pTblLn = pLine;
302 			while( pTblLn->GetUpper() )
303 				pTblLn = pTblLn->GetUpper()->GetUpper();
304 
305 			if( pTblNd->GetTable().GetTabLines()[ 0 ] == pTblLn )
306 			{
307 				// also vor die erste Box der Tabelle
308 				while( ( pNxtBox = pLine->GetTabBoxes()[0])->GetTabLines().Count() )
309 					pLine = pNxtBox->GetTabLines()[0];
310 				nIdxPos = pNxtBox->GetSttIdx();
311 				bSetIdxPos = sal_False;
312 			}
313 		}
314 		if( bSetIdxPos )
315 			// Tabelle ohne irgendeinen Inhalt oder am Ende, also vors Ende
316 			nIdxPos = pTblNd->EndOfSectionIndex();
317 	}
318 	else if( pNxtBox )			// es gibt einen Nachfolger
319 		nIdxPos = pNxtBox->GetSttIdx();
320 	else						// es gibt einen Vorgaenger
321 		nIdxPos = pPrvBox->GetSttNd()->EndOfSectionIndex() + 1;
322 
323 	SwNodeIndex aEndIdx( *this, nIdxPos );
324 	for( sal_uInt16 n = 0; n < nCnt; ++n )
325 	{
326 		SwStartNode* pSttNd = new SwStartNode( aEndIdx, ND_STARTNODE,
327 												SwTableBoxStartNode );
328 		pSttNd->pStartOfSection = pTblNd;
329 		new SwEndNode( aEndIdx, *pSttNd );
330 
331 		pPrvBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
332 
333         SwTableBoxes & rTabBoxes = pLine->GetTabBoxes();
334         sal_uInt16 nRealInsPos = nInsPos + n;
335         if (nRealInsPos > rTabBoxes.Count())
336             nRealInsPos = rTabBoxes.Count();
337 
338         rTabBoxes.C40_INSERT( SwTableBox, pPrvBox, nRealInsPos );
339 
340 		//if( NO_NUMBERING == pTxtColl->GetOutlineLevel()//#outline level,zhaojianwei
341 		if( ! pTxtColl->IsAssignedToListLevelOfOutlineStyle()//<-end,zhaojianwei
342 //FEATURE::CONDCOLL
343 			&& RES_CONDTXTFMTCOLL != pTxtColl->Which()
344 //FEATURE::CONDCOLL
345 		)
346 			new SwTxtNode( SwNodeIndex( *pSttNd->EndOfSectionNode() ),
347 								pTxtColl, pAutoAttr );
348 		else
349 		{
350 			// Outline-Numerierung richtig behandeln !!!
351 			SwTxtNode* pTNd = new SwTxtNode(
352 							SwNodeIndex( *pSttNd->EndOfSectionNode() ),
353 							(SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl(),
354 							pAutoAttr );
355 			pTNd->ChgFmtColl( pTxtColl );
356 		}
357 	}
358 	return sal_True;
359 }
360 
361 // --------------- einfuegen einer neuen Tabelle --------------
362 
363 const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTblOpts,
364                                    const SwPosition& rPos, sal_uInt16 nRows,
365                                    sal_uInt16 nCols, sal_Int16 eAdjust,
366                                    const SwTableAutoFmt* pTAFmt,
367                                    const SvUShorts* pColArr,
368                                    sal_Bool bCalledFromShell,
369                                    sal_Bool bNewModel )
370 {
371     ASSERT( nRows, "Tabelle ohne Zeile?" );
372     ASSERT( nCols, "Tabelle ohne Spalten?" );
373 
374     {
375         // nicht in Fussnoten kopieren !!
376         if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() &&
377             rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
378             return 0;
379 
380         // sollte das ColumnArray die falsche Anzahl haben wird es ignoriert!
381         if( pColArr &&
382             (nCols + ( text::HoriOrientation::NONE == eAdjust ? 2 : 1 )) != pColArr->Count() )
383             pColArr = 0;
384     }
385 
386     String aTblName = GetUniqueTblName();
387 
388     if( GetIDocumentUndoRedo().DoesUndo() )
389     {
390         GetIDocumentUndoRedo().AppendUndo(
391             new SwUndoInsTbl( rPos, nCols, nRows, static_cast<sal_uInt16>(eAdjust),
392                                       rInsTblOpts, pTAFmt, pColArr,
393                                       aTblName));
394     }
395 
396     // fuege erstmal die Nodes ein
397     // hole das Auto-Format fuer die Tabelle
398     SwTxtFmtColl *pBodyColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE ),
399                  *pHeadColl = pBodyColl;
400 
401     sal_Bool bDfltBorders = 0 != ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER );
402 
403     if( (rInsTblOpts.mnInsMode & tabopts::HEADLINE) && (1 != nRows || !bDfltBorders) )
404         pHeadColl = GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN );
405 
406     const sal_uInt16 nRowsToRepeat =
407             tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ?
408             rInsTblOpts.mnRowsToRepeat :
409             0;
410 
411     /* #106283# Save content node to extract FRAMEDIR from. */
412     const SwCntntNode * pCntntNd = rPos.nNode.GetNode().GetCntntNode();
413 
414     /* #109161# If we are called from a shell pass the attrset from
415         pCntntNd (aka the node the table is inserted at) thus causing
416         SwNodes::InsertTable to propagate an adjust item if
417         necessary. */
418     SwTableNode *pTblNd = GetNodes().InsertTable(
419         rPos.nNode,
420         nCols,
421         pBodyColl,
422         nRows,
423         nRowsToRepeat,
424         pHeadColl,
425         bCalledFromShell ? &pCntntNd->GetSwAttrSet() : 0 );
426 
427     // dann erstelle die Box/Line/Table-Struktur
428     SwTableLineFmt* pLineFmt = MakeTableLineFmt();
429     SwTableFmt* pTableFmt = MakeTblFrmFmt( aTblName, GetDfltFrmFmt() );
430 
431     /* #106283# If the node to insert the table at is a context node and has a
432        non-default FRAMEDIR propagate it to the table. */
433     if (pCntntNd)
434     {
435         const SwAttrSet & aNdSet = pCntntNd->GetSwAttrSet();
436         const SfxPoolItem *pItem = NULL;
437 
438         if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
439             && pItem != NULL)
440         {
441             pTableFmt->SetFmtAttr( *pItem );
442         }
443     }
444 
445     //Orientation am Fmt der Table setzen
446     pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) );
447     // alle Zeilen haben die Fill-Order von links nach rechts !
448     pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
449 
450     // die Tabelle bekommt USHRT_MAX als default SSize
451     SwTwips nWidth = USHRT_MAX;
452     if( pColArr )
453     {
454         sal_uInt16 nSttPos = (*pColArr)[ 0 ];
455         sal_uInt16 nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-1)];
456         if( text::HoriOrientation::NONE == eAdjust )
457         {
458             sal_uInt16 nFrmWidth = nLastPos;
459             nLastPos = (*pColArr)[ sal_uInt16(pColArr->Count()-2)];
460             pTableFmt->SetFmtAttr( SvxLRSpaceItem( nSttPos, nFrmWidth - nLastPos, 0, 0, RES_LR_SPACE ) );
461         }
462         nWidth = nLastPos - nSttPos;
463     }
464     else if( nCols )
465     {
466         nWidth /= nCols;
467         nWidth *= nCols; // to avoid rounding problems
468     }
469     pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
470     if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
471         pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False ));
472 
473     // verschiebe ggfs. die harten PageDesc/PageBreak Attribute:
474     SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]
475                             ->GetCntntNode();
476     if( pNextNd && pNextNd->HasSwAttrSet() )
477     {
478         const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet();
479         const SfxPoolItem *pItem;
480         if( SFX_ITEM_SET == pNdSet->GetItemState( RES_PAGEDESC, sal_False,
481             &pItem ) )
482         {
483             pTableFmt->SetFmtAttr( *pItem );
484             pNextNd->ResetAttr( RES_PAGEDESC );
485             pNdSet = pNextNd->GetpSwAttrSet();
486         }
487         if( pNdSet && SFX_ITEM_SET == pNdSet->GetItemState( RES_BREAK, sal_False,
488              &pItem ) )
489         {
490             pTableFmt->SetFmtAttr( *pItem );
491             pNextNd->ResetAttr( RES_BREAK );
492         }
493     }
494 
495     SwTable * pNdTbl = &pTblNd->GetTable();
496     pNdTbl->RegisterToFormat( *pTableFmt );
497 
498     pNdTbl->SetRowsToRepeat( nRowsToRepeat );
499     pNdTbl->SetTableModel( bNewModel );
500 
501     SvPtrarr aBoxFmtArr( 0, 16 );
502     SwTableBoxFmt* pBoxFmt = 0;
503     if( !bDfltBorders && !pTAFmt )
504     {
505         pBoxFmt = MakeTableBoxFmt();
506         pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nCols, 0 ));
507     }
508     else
509     {
510         const sal_uInt16 nBoxArrLen = pTAFmt ? 16 : 4;
511         for( sal_uInt16 i = 0; i < nBoxArrLen; ++i )
512             aBoxFmtArr.Insert( (void*)0, i );
513     }
514     // --> OD 2008-02-25 #refactorlists#
515 //    SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
516     SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
517     // <--
518 
519     SwNodeIndex aNdIdx( *pTblNd, 1 );   // auf den ersten Box-StartNode
520     SwTableLines& rLines = pNdTbl->GetTabLines();
521     for( sal_uInt16 n = 0; n < nRows; ++n )
522     {
523         SwTableLine* pLine = new SwTableLine( pLineFmt, nCols, 0 );
524         rLines.C40_INSERT( SwTableLine, pLine, n );
525         SwTableBoxes& rBoxes = pLine->GetTabBoxes();
526         for( sal_uInt16 i = 0; i < nCols; ++i )
527         {
528             SwTableBoxFmt *pBoxF;
529             if( pTAFmt )
530             {
531                 sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
532                                         ? 12 : (4 * (1 + ((n-1) & 1 )))));
533                 nId = nId + static_cast<sal_uInt8>( !i ? 0 :
534                             ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
535                 pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr, *pTAFmt,
536                                                 nCols, nId );
537 
538                 // ggfs. noch die Absatz/ZeichenAttribute setzen
539                 if( pTAFmt->IsFont() || pTAFmt->IsJustify() )
540                 {
541                     aCharSet.ClearItem();
542                     pTAFmt->UpdateToSet( nId, aCharSet,
543                                         SwTableAutoFmt::UPDATE_CHAR, 0 );
544                     if( aCharSet.Count() )
545                         GetNodes()[ aNdIdx.GetIndex()+1 ]->GetCntntNode()->
546                             SetAttr( aCharSet );
547                 }
548             }
549             else if( bDfltBorders )
550             {
551                 sal_uInt8 nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
552                 pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr, nCols, nBoxId);
553             }
554             else
555                 pBoxF = pBoxFmt;
556 
557             // fuer AutoFormat bei der Eingabe: beim Einfuegen der Tabelle
558             // werden gleich die Spalten gesetzt. Im Array stehen die
559             // Positionen der Spalten!! (nicht deren Breite!)
560             if( pColArr )
561             {
562                 nWidth = (*pColArr)[ sal_uInt16(i + 1) ] - (*pColArr)[ i ];
563                 if( pBoxF->GetFrmSize().GetWidth() != nWidth )
564                 {
565                     if( pBoxF->GetDepends() )       // neues Format erzeugen!
566                     {
567                         SwTableBoxFmt *pNewFmt = MakeTableBoxFmt();
568                         *pNewFmt = *pBoxF;
569                         pBoxF = pNewFmt;
570                     }
571                     pBoxF->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth ));
572                 }
573             }
574 
575             SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine);
576             rBoxes.C40_INSERT( SwTableBox, pBox, i );
577             aNdIdx += 3;        // StartNode, TextNode, EndNode  == 3 Nodes
578         }
579     }
580     // und Frms einfuegen.
581     GetNodes().GoNext( &aNdIdx );      // zum naechsten ContentNode
582     pTblNd->MakeFrms( &aNdIdx );
583 
584     if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
585     {
586         SwPaM aPam( *pTblNd->EndOfSectionNode(), *pTblNd, 1 );
587         if( IsRedlineOn() )
588             AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
589         else
590             SplitRedline( aPam );
591     }
592 
593     SetModified();
594     CHECK_TABLE( *pNdTbl );
595     return pNdTbl;
596 }
597 
598 SwTableNode* SwNodes::InsertTable( const SwNodeIndex& rNdIdx,
599                                    sal_uInt16 nBoxes,
600                                    SwTxtFmtColl* pCntntTxtColl,
601                                    sal_uInt16 nLines,
602                                    sal_uInt16 nRepeat,
603 								   SwTxtFmtColl* pHeadlineTxtColl,
604                                    const SwAttrSet * pAttrSet)
605 {
606 	if( !nBoxes )
607 		return 0;
608 
609 	// wenn Lines angegeben, erzeuge die Matrix aus Lines & Boxen
610 	if( !pHeadlineTxtColl || !nLines )
611 		pHeadlineTxtColl = pCntntTxtColl;
612 
613 	SwTableNode * pTblNd = new SwTableNode( rNdIdx );
614 	SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTblNd );
615 
616 	if( !nLines )		// fuer die FOR-Schleife
617 		++nLines;
618 
619 	SwNodeIndex aIdx( *pEndNd );
620 	SwTxtFmtColl* pTxtColl = pHeadlineTxtColl;
621 	for( sal_uInt16 nL = 0; nL < nLines; ++nL )
622 	{
623 		for( sal_uInt16 nB = 0; nB < nBoxes; ++nB )
624 		{
625 			SwStartNode* pSttNd = new SwStartNode( aIdx, ND_STARTNODE,
626 													SwTableBoxStartNode );
627 			pSttNd->pStartOfSection = pTblNd;
628 
629 			SwTxtNode * pTmpNd = new SwTxtNode( aIdx, pTxtColl );
630 
631             // --> FME 2006-04-13 #i60422# Propagate some more attributes.
632             // Adjustment was done for #109161#
633             const SfxPoolItem* pItem = NULL;
634             if ( NULL != pAttrSet )
635             {
636                 static const sal_uInt16 aPropagateItems[] = {
637                     RES_PARATR_ADJUST,
638                     RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
639                     RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
640                     RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, 0 };
641 
642                 const sal_uInt16* pIdx = aPropagateItems;
643                 while ( *pIdx != 0 )
644                 {
645                     if ( SFX_ITEM_SET != pTmpNd->GetSwAttrSet().GetItemState( *pIdx ) &&
646                          SFX_ITEM_SET == pAttrSet->GetItemState( *pIdx, sal_True, &pItem ) )
647                         static_cast<SwCntntNode *>(pTmpNd)->SetAttr(*pItem);
648                     ++pIdx;
649                 }
650             }
651             // <--
652 
653 			new SwEndNode( aIdx, *pSttNd );
654 		}
655 		if ( nL + 1 >= nRepeat )
656             pTxtColl = pCntntTxtColl;
657 	}
658 	return pTblNd;
659 }
660 
661 
662 //---------------- Text -> Tabelle -----------------------
663 
664 const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTblOpts,
665                                    const SwPaM& rRange, sal_Unicode cCh,
666                                    sal_Int16 eAdjust,
667                                    const SwTableAutoFmt* pTAFmt )
668 {
669 	// pruefe ob in der Selection eine Tabelle liegt
670 	const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
671 	{
672 		sal_uLong nCnt = pStt->nNode.GetIndex();
673 		for( ; nCnt <= pEnd->nNode.GetIndex(); ++nCnt )
674 			if( !GetNodes()[ nCnt ]->IsTxtNode() )
675 				return 0;
676 	}
677 
678 	/* #106283# Save first node in the selection if it is a context node. */
679 	SwCntntNode * pSttCntntNd = pStt->nNode.GetNode().GetCntntNode();
680 
681 	SwPaM aOriginal( *pStt, *pEnd );
682 	pStt = aOriginal.GetMark();
683 	pEnd = aOriginal.GetPoint();
684 
685 #ifdef DEL_TABLE_REDLINES
686 	lcl_DelRedlines aDelRedl( aOriginal );
687 #endif
688 
689 	SwUndoTxtToTbl* pUndo = 0;
690     if( GetIDocumentUndoRedo().DoesUndo() )
691     {
692         GetIDocumentUndoRedo().StartUndo( UNDO_TEXTTOTABLE, NULL );
693         pUndo = new SwUndoTxtToTbl( aOriginal, rInsTblOpts, cCh,
694                     static_cast<sal_uInt16>(eAdjust), pTAFmt );
695         GetIDocumentUndoRedo().AppendUndo( pUndo );
696 
697 		// das Splitten vom TextNode nicht in die Undohistory aufnehmen
698         GetIDocumentUndoRedo().DoUndo( false );
699     }
700 
701 	::PaMCorrAbs( aOriginal, *pEnd );
702 
703 	// sorge dafuer, das der Bereich auf Node-Grenzen liegt
704 	SwNodeRange aRg( pStt->nNode, pEnd->nNode );
705 	if( pStt->nContent.GetIndex() )
706 		SplitNode( *pStt, false );
707 
708 	sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex();
709 	// nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
710 	if( bEndCntnt )
711 	{
712 		if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex()
713 			|| pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
714 		{
715 			SplitNode( *pEnd, false );
716 			((SwNodeIndex&)pEnd->nNode)--;
717 			((SwIndex&)pEnd->nContent).Assign(
718 								pEnd->nNode.GetNode().GetCntntNode(), 0 );
719 			// ein Node und am Ende ??
720 			if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
721 				aRg.aStart--;
722 		}
723 		else
724 			aRg.aEnd++;
725 	}
726 
727 
728 	if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
729 	{
730 		ASSERT( sal_False, "Kein Bereich" );
731 		aRg.aEnd++;
732 	}
733 
734 	// Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
735 	SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
736 
737     GetIDocumentUndoRedo().DoUndo( 0 != pUndo );
738 
739 	// dann erstelle die Box/Line/Table-Struktur
740 	SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt();
741 	SwTableLineFmt* pLineFmt = MakeTableLineFmt();
742 	SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
743 
744 	// alle Zeilen haben die Fill-Order von links nach rechts !
745     pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
746 	// die Tabelle bekommt USHRT_MAX als default SSize
747     pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
748     if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
749         pTableFmt->SetFmtAttr( SwFmtLayoutSplit( sal_False ));
750 
751 	/* #106283# If the first node in the selection is a context node and if it
752        has an item FRAMEDIR set (no default) propagate the item to the
753        replacing table. */
754 	if (pSttCntntNd)
755 	{
756 		const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet();
757 		const SfxPoolItem *pItem = NULL;
758 
759 		if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
760 			&& pItem != NULL)
761 		{
762             pTableFmt->SetFmtAttr( *pItem );
763 		}
764 	}
765 
766     SwTableNode* pTblNd = GetNodes().TextToTable(
767             aRg, cCh, pTableFmt, pLineFmt, pBoxFmt,
768             GetTxtCollFromPool( RES_POOLCOLL_STANDARD ), pUndo );
769 
770 	SwTable * pNdTbl = &pTblNd->GetTable();
771 	ASSERT( pNdTbl, "kein Tabellen-Node angelegt."  )
772 
773     const sal_uInt16 nRowsToRepeat =
774             tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ?
775             rInsTblOpts.mnRowsToRepeat :
776             0;
777     pNdTbl->SetRowsToRepeat( nRowsToRepeat );
778 
779 	sal_Bool bUseBoxFmt = sal_False;
780 	if( !pBoxFmt->GetDepends() )
781 	{
782 		// die Formate an den Boxen haben schon die richtige Size, es darf
783 		// also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
784 		bUseBoxFmt = sal_True;
785         pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() );
786 		delete pBoxFmt;
787         eAdjust = text::HoriOrientation::NONE;
788 	}
789 
790 	//Orientation am Fmt der Table setzen
791     pTableFmt->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust ) );
792     pNdTbl->RegisterToFormat( *pTableFmt );
793 
794     if( pTAFmt || ( rInsTblOpts.mnInsMode & tabopts::DEFAULT_BORDER) )
795 	{
796 		sal_uInt8 nBoxArrLen = pTAFmt ? 16 : 4;
797 		SvPtrarr aBoxFmtArr( nBoxArrLen, 0 );
798 		{
799 			for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
800 				aBoxFmtArr.Insert( (void*)0, i );
801 		}
802 
803         // --> OD 2008-02-25 #refactorlists#
804 //        SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
805         SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
806         // <--
807 		SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
808 
809         SwTableBoxFmt *pBoxF = 0;
810 		SwTableLines& rLines = pNdTbl->GetTabLines();
811 		sal_uInt16 nRows = rLines.Count();
812 		for( sal_uInt16 n = 0; n < nRows; ++n )
813 		{
814 			SwTableBoxes& rBoxes = rLines[ n ]->GetTabBoxes();
815 			sal_uInt16 nCols = rBoxes.Count();
816 			for( sal_uInt16 i = 0; i < nCols; ++i )
817 			{
818 				SwTableBox* pBox = rBoxes[ i ];
819 				sal_Bool bChgSz = sal_False;
820 
821 				if( pTAFmt )
822 				{
823 					sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
824 											? 12 : (4 * (1 + ((n-1) & 1 )))));
825 					nId = nId + static_cast<sal_uInt8>(!i ? 0 :
826                                 ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
827 					if( bUseBoxFmt )
828 						::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId, pTAFmt );
829 					else
830 					{
831 						bChgSz = 0 == aBoxFmtArr[ nId ];
832 						pBoxF = ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr,
833 												*pTAFmt, USHRT_MAX, nId );
834 					}
835 
836 					// ggfs. noch die Absatz/ZeichenAttribute setzen
837 					if( pTAFmt->IsFont() || pTAFmt->IsJustify() )
838 					{
839 						aCharSet.ClearItem();
840 						pTAFmt->UpdateToSet( nId, aCharSet,
841 											SwTableAutoFmt::UPDATE_CHAR, 0 );
842 						if( aCharSet.Count() )
843 						{
844 							sal_uLong nSttNd = pBox->GetSttIdx()+1;
845 							sal_uLong nEndNd = pBox->GetSttNd()->EndOfSectionIndex();
846 							for( ; nSttNd < nEndNd; ++nSttNd )
847 							{
848 								SwCntntNode* pNd = GetNodes()[ nSttNd ]->GetCntntNode();
849 								if( pNd )
850 								{
851 									if( pHistory )
852 									{
853 										SwRegHistory aReg( pNd, *pNd, pHistory );
854 										pNd->SetAttr( aCharSet );
855 									}
856 									else
857 										pNd->SetAttr( aCharSet );
858 								}
859 							}
860 						}
861 					}
862 				}
863 				else
864 				{
865 					sal_uInt8 nId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
866 					if( bUseBoxFmt )
867 						::lcl_SetDfltBoxAttr( *pBox, aBoxFmtArr, nId );
868 					else
869 					{
870 						bChgSz = 0 == aBoxFmtArr[ nId ];
871 						pBoxF = ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr,
872 														USHRT_MAX, nId );
873 					}
874 				}
875 
876 				if( !bUseBoxFmt )
877 				{
878 					if( bChgSz )
879                         pBoxF->SetFmtAttr( pBox->GetFrmFmt()->GetFrmSize() );
880 					pBox->ChgFrmFmt( pBoxF );
881 				}
882 			}
883 		}
884 
885 		if( bUseBoxFmt )
886 		{
887 			for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
888 			{
889 				SvPtrarr* pArr = (SvPtrarr*)aBoxFmtArr[ i ];
890 				delete pArr;
891 			}
892 		}
893 	}
894 
895 	// JP 03.04.97: Inhalt der Boxen auf Zahlen abpruefen
896 	if( IsInsTblFormatNum() )
897 	{
898 		for( sal_uInt16 nBoxes = pNdTbl->GetTabSortBoxes().Count(); nBoxes; )
899 			ChkBoxNumFmt( *pNdTbl->GetTabSortBoxes()[ --nBoxes ], sal_False );
900 	}
901 
902 	sal_uLong nIdx = pTblNd->GetIndex();
903 	aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
904 
905 	{
906 		SwPaM& rTmp = (SwPaM&)rRange;	// Point immer an den Anfang
907 		rTmp.DeleteMark();
908 		rTmp.GetPoint()->nNode = *pTblNd;
909 		SwCntntNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode );
910 		rTmp.GetPoint()->nContent.Assign( pCNd, 0 );
911 	}
912 
913 	if( pUndo )
914     {
915         GetIDocumentUndoRedo().EndUndo( UNDO_TEXTTOTABLE, NULL );
916     }
917 
918 	SetModified();
919 	SetFieldsDirty(true, NULL, 0);
920 	return pNdTbl;
921 }
922 
923 SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh,
924 									SwTableFmt* pTblFmt,
925 									SwTableLineFmt* pLineFmt,
926 									SwTableBoxFmt* pBoxFmt,
927 									SwTxtFmtColl* pTxtColl,
928 									SwUndoTxtToTbl* pUndo )
929 {
930 	if( rRange.aStart >= rRange.aEnd )
931 		return 0;
932 
933 	SwTableNode * pTblNd = new SwTableNode( rRange.aStart );
934 	new SwEndNode( rRange.aEnd, *pTblNd );
935 
936 	SwDoc* pDoc = GetDoc();
937 	SvUShorts aPosArr( 0, 16 );
938 	SwTable * pTable = &pTblNd->GetTable();
939 	SwTableLine* pLine;
940 	SwTableBox* pBox;
941 	sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
942 
943 	SwNodeIndex aSttIdx( *pTblNd, 1 );
944 	SwNodeIndex aEndIdx( rRange.aEnd, -1 );
945 	for( nLines = 0, nBoxes = 0;
946 		aSttIdx.GetIndex() < aEndIdx.GetIndex();
947 		aSttIdx += 2, nLines++, nBoxes = 0 )
948 	{
949 		SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
950 		ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" );
951 
952 		if( !nLines && 0x0b == cCh )
953 		{
954 			cCh = 0x09;
955 
956 			// JP 28.10.96: vom 1. Node die Positionen des Trenners besorgen,
957 			//				damit die Boxen entsprechend eingestellt werden
958 			SwTxtFrmInfo aFInfo( (SwTxtFrm*)pTxtNd->getLayoutFrm( pTxtNd->GetDoc()->GetCurrentLayout() ) );
959 			if( aFInfo.IsOneLine() )		// nur dann sinnvoll!
960 			{
961 				const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
962 				for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt )
963                 {
964 					if( *pTxt == cCh )
965 					{
966 						aPosArr.Insert( static_cast<sal_uInt16>(
967                                         aFInfo.GetCharPos( nChPos+1, sal_False )),
968 										aPosArr.Count() );
969 					}
970                 }
971 
972 				aPosArr.Insert( /*aFInfo.GetFrm()->Frm().Left() +*/
973                                 static_cast<sal_uInt16>(aFInfo.GetFrm()->IsVertical() ?
974                                 aFInfo.GetFrm()->Prt().Bottom() :
975                                 aFInfo.GetFrm()->Prt().Right()),
976 								aPosArr.Count() );
977 			}
978 		}
979 
980 		// die alten Frames loeschen, es werden neue erzeugt
981 		pTxtNd->DelFrms();
982 
983 		// PageBreaks/PageDesc/ColBreak rausschmeissen.
984         const SfxItemSet* pSet = pTxtNd->GetpSwAttrSet();
985 		if( pSet )
986 		{
987 // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle
988 // erfolgen, denn sonst stehen sie falsch in der History !!!
989 //			SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory );
990 			const SfxPoolItem* pItem;
991 			if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) )
992 			{
993 				if( !nLines )
994                     pTblFmt->SetFmtAttr( *pItem );
995                 pTxtNd->ResetAttr( RES_BREAK );
996                 pSet = pTxtNd->GetpSwAttrSet();
997 			}
998 
999 			if( pSet && SFX_ITEM_SET == pSet->GetItemState(
1000 				RES_PAGEDESC, sal_False, &pItem ) &&
1001 				((SwFmtPageDesc*)pItem)->GetPageDesc() )
1002 			{
1003 				if( !nLines )
1004                     pTblFmt->SetFmtAttr( *pItem );
1005                 pTxtNd->ResetAttr( RES_PAGEDESC );
1006 			}
1007 		}
1008 
1009 		// setze den bei allen TextNode in der Tabelle den TableNode
1010 		// als StartNode
1011 		pTxtNd->pStartOfSection = pTblNd;
1012 
1013 		pLine = new SwTableLine( pLineFmt, 1, 0 );
1014 		pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines );
1015 
1016 		SwStartNode* pSttNd;
1017 		SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd ));
1018 
1019 		SvULongs aBkmkArr( 15, 15 );
1020 		_SaveCntntIdx( pDoc, aSttIdx.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr );
1021 
1022 		const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
1023 
1024 		if( T2T_PARA != cCh )
1025 			for( xub_StrLen nChPos = 0; *pTxt; ++nChPos, ++pTxt )
1026 				if( *pTxt == cCh )
1027 				{
1028 					aCntPos.nContent = nChPos;
1029                     SwCntntNode* pNewNd = pTxtNd->SplitCntntNode( aCntPos );
1030 
1031 					if( aBkmkArr.Count() )
1032 						_RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos,
1033 											nChPos + 1 );
1034 
1035 					// Trennzeichen loeschen und SuchString korrigieren
1036                     pTxtNd->EraseText( aCntPos.nContent, 1 );
1037 					pTxt = pTxtNd->GetTxt().GetBuffer();
1038 					nChPos = 0;
1039 					--nChPos, --pTxt;           // for the ++ in the for loop !!!
1040 
1041 					// setze bei allen TextNodes in der Tabelle den TableNode
1042 					// als StartNode
1043 					const SwNodeIndex aTmpIdx( aCntPos.nNode, -1 );
1044 					pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
1045 												SwTableBoxStartNode );
1046 					new SwEndNode( aCntPos.nNode, *pSttNd );
1047 					pNewNd->pStartOfSection = pSttNd;
1048 
1049 					// Section der Box zuweisen
1050 					pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
1051 					pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
1052 				}
1053 
1054 		// und jetzt den letzten Teil-String
1055 		if( aBkmkArr.Count() )
1056 			_RestoreCntntIdx( aBkmkArr, *pTxtNd, pTxtNd->GetTxt().Len(),
1057 								pTxtNd->GetTxt().Len()+1 );
1058 
1059 		pSttNd = new SwStartNode( aCntPos.nNode, ND_STARTNODE, SwTableBoxStartNode );
1060 		const SwNodeIndex aTmpIdx( aCntPos.nNode, 1 );
1061 		new SwEndNode( aTmpIdx, *pSttNd  );
1062 		pTxtNd->pStartOfSection = pSttNd;
1063 
1064 		pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
1065 		pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
1066 		if( nMaxBoxes < nBoxes )
1067 			nMaxBoxes = nBoxes;
1068 	}
1069 
1070 	// die Tabelle ausgleichen, leere Sections einfuegen
1071 	sal_uInt16 n;
1072 
1073 	for( n = 0; n < pTable->GetTabLines().Count(); ++n )
1074 	{
1075 		SwTableLine* pCurrLine = pTable->GetTabLines()[ n ];
1076 		if( nMaxBoxes != ( nBoxes = pCurrLine->GetTabBoxes().Count() ))
1077 		{
1078 			InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0,
1079 						nBoxes, nMaxBoxes - nBoxes );
1080 
1081 			if( pUndo )
1082 				for( sal_uInt16 i = nBoxes; i < nMaxBoxes; ++i )
1083 					pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[ i ] );
1084 
1085 			// fehlen der 1. Line Boxen, dann kann man das Breiten Array
1086 			// vergessen!
1087 			if( !n )
1088 				aPosArr.Remove( 0, aPosArr.Count() );
1089 		}
1090 	}
1091 
1092 	if( aPosArr.Count() )
1093 	{
1094 		SwTableLines& rLns = pTable->GetTabLines();
1095 		sal_uInt16 nLastPos = 0;
1096 		for( n = 0; n < aPosArr.Count(); ++n )
1097 		{
1098 			SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt();
1099             pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
1100 												aPosArr[ n ] - nLastPos ));
1101 			for( sal_uInt16 nTmpLine = 0; nTmpLine < rLns.Count(); ++nTmpLine )
1102 				//JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
1103 				//				von der rufenden Methode noch gebraucht wird!
1104 				pNewFmt->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] );
1105 
1106 			nLastPos = aPosArr[ n ];
1107 		}
1108 
1109 		// damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
1110 		// Groesse nach "oben" transportieren.
1111 		ASSERT( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" );
1112         pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos ));
1113 	}
1114 	else
1115         pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes ));
1116 
1117 	// das wars doch wohl ??
1118 	return pTblNd;
1119 }
1120 /*-- 18.05.2006 10:30:29---------------------------------------------------
1121 
1122   -----------------------------------------------------------------------*/
1123 const SwTable* SwDoc::TextToTable( const std::vector< std::vector<SwNodeRange> >& rTableNodes )
1124 {
1125     /* #106283# Save first node in the selection if it is a content node. */
1126     SwCntntNode * pSttCntntNd = rTableNodes.begin()->begin()->aStart.GetNode().GetCntntNode();
1127 
1128     /**debug**/
1129 #if OSL_DEBUG_LEVEL > 1
1130     const SwNodeRange& rStartRange = *rTableNodes.begin()->begin();
1131     const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin();
1132     (void) rStartRange;
1133     (void) rEndRange;
1134 #endif
1135     /**debug**/
1136 
1137     //!!! not necessarily TextNodes !!!
1138     SwPaM aOriginal( rTableNodes.begin()->begin()->aStart, rTableNodes.rbegin()->rbegin()->aEnd );
1139     const SwPosition *pStt = aOriginal.GetMark();
1140     const SwPosition *pEnd = aOriginal.GetPoint();
1141 
1142 #ifdef DEL_TABLE_REDLINES
1143     lcl_DelRedlines aDelRedl( aOriginal );
1144 #endif
1145 
1146 //    SwUndoTxtToTbl* pUndo = 0;
1147     bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
1148     if (bUndo)
1149     {
1150         // das Splitten vom TextNode nicht in die Undohistory aufnehmen
1151         GetIDocumentUndoRedo().DoUndo(false);
1152     }
1153 
1154     ::PaMCorrAbs( aOriginal, *pEnd );
1155 
1156     // sorge dafuer, das der Bereich auf Node-Grenzen liegt
1157     SwNodeRange aRg( pStt->nNode, pEnd->nNode );
1158     if( pStt->nContent.GetIndex() )
1159         SplitNode( *pStt, false );
1160 
1161     sal_Bool bEndCntnt = 0 != pEnd->nContent.GetIndex();
1162     // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
1163     if( bEndCntnt )
1164     {
1165         if( pEnd->nNode.GetNode().GetCntntNode()->Len() != pEnd->nContent.GetIndex()
1166             || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
1167         {
1168             SplitNode( *pEnd, false );
1169             ((SwNodeIndex&)pEnd->nNode)--;
1170             ((SwIndex&)pEnd->nContent).Assign(
1171                                 pEnd->nNode.GetNode().GetCntntNode(), 0 );
1172             // ein Node und am Ende ??
1173             if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
1174                 aRg.aStart--;
1175         }
1176         else
1177             aRg.aEnd++;
1178     }
1179 
1180 
1181     if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
1182     {
1183         ASSERT( sal_False, "Kein Bereich" );
1184         aRg.aEnd++;
1185     }
1186 
1187     // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
1188     SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
1189 
1190     GetIDocumentUndoRedo().DoUndo(bUndo);
1191 
1192     // dann erstelle die Box/Line/Table-Struktur
1193     SwTableBoxFmt* pBoxFmt = MakeTableBoxFmt();
1194     SwTableLineFmt* pLineFmt = MakeTableLineFmt();
1195     SwTableFmt* pTableFmt = MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
1196 
1197     // alle Zeilen haben die Fill-Order von links nach rechts !
1198     pLineFmt->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ));
1199     // die Tabelle bekommt USHRT_MAX als default SSize
1200     pTableFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
1201 
1202     /* #106283# If the first node in the selection is a context node and if it
1203        has an item FRAMEDIR set (no default) propagate the item to the
1204        replacing table. */
1205     if (pSttCntntNd)
1206     {
1207         const SwAttrSet & aNdSet = pSttCntntNd->GetSwAttrSet();
1208         const SfxPoolItem *pItem = NULL;
1209 
1210         if (SFX_ITEM_SET == aNdSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem )
1211             && pItem != NULL)
1212         {
1213             pTableFmt->SetFmtAttr( *pItem );
1214         }
1215     }
1216 
1217     SwTableNode* pTblNd = GetNodes().TextToTable(
1218             rTableNodes, pTableFmt, pLineFmt, pBoxFmt,
1219             GetTxtCollFromPool( RES_POOLCOLL_STANDARD )/*, pUndo*/ );
1220 
1221     SwTable * pNdTbl = &pTblNd->GetTable();
1222     ASSERT( pNdTbl, "kein Tabellen-Node angelegt."  )
1223     pNdTbl->RegisterToFormat( *pTableFmt );
1224 
1225     sal_Bool bUseBoxFmt = sal_False;
1226     if( !pBoxFmt->GetDepends() )
1227     {
1228         // die Formate an den Boxen haben schon die richtige Size, es darf
1229         // also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
1230         bUseBoxFmt = sal_True;
1231         pTableFmt->SetFmtAttr( pBoxFmt->GetFrmSize() );
1232         delete pBoxFmt;
1233     }
1234 
1235     sal_uLong nIdx = pTblNd->GetIndex();
1236     aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
1237 
1238     SetModified();
1239     SetFieldsDirty( true, NULL, 0 );
1240     return pNdTbl;
1241 }
1242 
1243 SwNodeRange * SwNodes::ExpandRangeForTableBox(const SwNodeRange & rRange)
1244 {
1245     SwNodeRange * pResult = NULL;
1246     bool bChanged = false;
1247 
1248 	SwNodeIndex aNewStart = rRange.aStart;
1249 	SwNodeIndex aNewEnd = rRange.aEnd;
1250 
1251 	SwNodeIndex aEndIndex = rRange.aEnd;
1252 	SwNodeIndex aIndex = rRange.aStart;
1253 
1254 	while (aIndex < aEndIndex)
1255 	{
1256 		SwNode& rNode = aIndex.GetNode();
1257 
1258 		if (rNode.IsStartNode())
1259 		{
1260             // advance aIndex to the end node of this start node
1261             SwNode * pEndNode = rNode.EndOfSectionNode();
1262             aIndex = *pEndNode;
1263 
1264             if (aIndex > aNewEnd)
1265             {
1266                 aNewEnd = aIndex;
1267                 bChanged = true;
1268             }
1269 		}
1270 		else if (rNode.IsEndNode())
1271 		{
1272             SwNode * pStartNode = rNode.StartOfSectionNode();
1273 			SwNodeIndex aStartIndex = *pStartNode;
1274 
1275 			if (aStartIndex < aNewStart)
1276             {
1277 				aNewStart = aStartIndex;
1278                 bChanged = true;
1279             }
1280 		}
1281 
1282 		if (aIndex < aEndIndex)
1283 			++aIndex;
1284 	}
1285 
1286     SwNode * pNode = &aIndex.GetNode();
1287     while (pNode->IsEndNode())
1288     {
1289         SwNode * pStartNode = pNode->StartOfSectionNode();
1290         SwNodeIndex aStartIndex(*pStartNode);
1291         aNewStart = aStartIndex;
1292         aNewEnd = aIndex;
1293         bChanged = true;
1294 
1295         ++aIndex;
1296         pNode = &aIndex.GetNode();
1297     }
1298 
1299     if (bChanged)
1300         pResult = new SwNodeRange(aNewStart, aNewEnd);
1301 
1302     return pResult;
1303 }
1304 
1305 /*-- 18.05.2006 08:23:28---------------------------------------------------
1306 
1307   -----------------------------------------------------------------------*/
1308 SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes,
1309                                     SwTableFmt* pTblFmt,
1310                                     SwTableLineFmt* pLineFmt,
1311                                     SwTableBoxFmt* pBoxFmt,
1312                                     SwTxtFmtColl* /*pTxtColl*/  /*, SwUndo... pUndo*/  )
1313 {
1314     if( !rTableNodes.size() )
1315         return 0;
1316 
1317     SwTableNode * pTblNd = new SwTableNode( rTableNodes.begin()->begin()->aStart );
1318     //insert the end node after the last text node
1319    SwNodeIndex aInsertIndex( rTableNodes.rbegin()->rbegin()->aEnd );
1320    ++aInsertIndex;
1321 
1322    //!! owner ship will be transferred in c-tor to SwNodes array.
1323    //!! Thus no real problem here...
1324    new SwEndNode( aInsertIndex, *pTblNd );
1325 
1326 #if OSL_DEBUG_LEVEL > 1
1327     /**debug**/
1328     const SwNodeRange& rStartRange = *rTableNodes.begin()->begin();
1329     const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin();
1330     (void) rStartRange;
1331     (void) rEndRange;
1332     /**debug**/
1333 #endif
1334 
1335     SwDoc* pDoc = GetDoc();
1336     SvUShorts aPosArr( 0, 16 );
1337     SwTable * pTable = &pTblNd->GetTable();
1338     SwTableLine* pLine;
1339     SwTableBox* pBox;
1340     sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
1341 
1342 //    SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
1343 
1344 
1345     SwNodeIndex aNodeIndex = rTableNodes.begin()->begin()->aStart;
1346     // delete frames of all contained content nodes
1347     for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines )
1348     {
1349         SwNode& rNode = aNodeIndex.GetNode();
1350         if( rNode.IsCntntNode() )
1351         {
1352             static_cast<SwCntntNode&>(rNode).DelFrms();
1353             if(rNode.IsTxtNode())
1354             {
1355                 SwTxtNode& rTxtNode = static_cast<SwTxtNode&>(rNode);
1356                 // setze den bei allen TextNode in der Tabelle den TableNode
1357                 // als StartNode
1358 // FIXME: this is setting wrong node StartOfSections in nested tables.
1359 //                rTxtNode.pStartOfSection = pTblNd;
1360                 // remove PageBreaks/PageDesc/ColBreak
1361                 const SwAttrSet* pSet = rTxtNode.GetpSwAttrSet();
1362                 if( pSet )
1363                 {
1364         // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle
1365         // erfolgen, denn sonst stehen sie falsch in der History !!!
1366         //          SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory );
1367                     const SfxPoolItem* pItem;
1368                     if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) )
1369                     {
1370                         if( !nLines )
1371                             pTblFmt->SetFmtAttr( *pItem );
1372                         rTxtNode.ResetAttr( RES_BREAK );
1373                         pSet = rTxtNode.GetpSwAttrSet();
1374                     }
1375 
1376                     if( pSet && SFX_ITEM_SET == pSet->GetItemState(
1377                         RES_PAGEDESC, sal_False, &pItem ) &&
1378                         ((SwFmtPageDesc*)pItem)->GetPageDesc() )
1379                     {
1380                         if( !nLines )
1381                             pTblFmt->SetFmtAttr( *pItem );
1382                         rTxtNode.ResetAttr( RES_PAGEDESC );
1383                     }
1384                 }
1385             }
1386         }
1387     }
1388 
1389 //    SwNodeIndex aSttIdx( *pTblNd, 1 );
1390 //    SwNodeIndex aEndIdx( rlNodes.rbegin()->aEnd, -1 );
1391     std::vector<std::vector < SwNodeRange > >::const_iterator aRowIter = rTableNodes.begin();
1392     for( nLines = 0, nBoxes = 0;
1393         aRowIter != rTableNodes.end();
1394         ++aRowIter, /*aSttIdx += 2, */nLines++, nBoxes = 0 )
1395     {
1396 //        SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
1397 //        ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" );
1398 
1399         pLine = new SwTableLine( pLineFmt, 1, 0 );
1400         pTable->GetTabLines().C40_INSERT( SwTableLine, pLine, nLines );
1401 
1402 //        SwStartNode* pSttNd;
1403 //        SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd ));
1404 
1405         std::vector< SwNodeRange >::const_iterator aCellIter = aRowIter->begin();
1406 //        SvULongs aBkmkArr( 15, 15 );
1407 //        _SaveCntntIdx( pDoc, aCellIter->aStart.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr );
1408 //        const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
1409 
1410         for( ; aCellIter != aRowIter->end(); ++aCellIter )
1411         {
1412 //            aCellIter->aStart aCellIter->aEnd
1413 //                aCntPos.nContent = nChPos;
1414 //                SwCntntNode* pNewNd = pTxtNd->SplitNode( aCntPos );
1415 
1416 //        auch f?rs undo?
1417 //                if( aBkmkArr.Count() )
1418 //                    _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos,
1419 //                                        nChPos + 1 );
1420 
1421                 const SwNodeIndex aTmpIdx( aCellIter->aStart, 0 );
1422 
1423                SwNodeIndex aCellEndIdx(aCellIter->aEnd);
1424                ++aCellEndIdx;
1425                SwStartNode* pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
1426                                             SwTableBoxStartNode );
1427                 new SwEndNode( aCellEndIdx, *pSttNd );
1428                 //set the start node on all node of the current cell
1429                 SwNodeIndex aCellNodeIdx = aCellIter->aStart;
1430                 for(;aCellNodeIdx <= aCellIter->aEnd; ++aCellNodeIdx )
1431                 {
1432                     aCellNodeIdx.GetNode().pStartOfSection = pSttNd;
1433                     //skip start/end node pairs
1434                     if( aCellNodeIdx.GetNode().IsStartNode() )
1435                         aCellNodeIdx = SwNodeIndex( *aCellNodeIdx.GetNode().EndOfSectionNode() );
1436                 }
1437 
1438                 // Section der Box zuweisen
1439                 pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
1440                 pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, nBoxes++ );
1441         }
1442         if( nMaxBoxes < nBoxes )
1443             nMaxBoxes = nBoxes;
1444     }
1445 
1446     // die Tabelle ausgleichen, leere Sections einfuegen
1447     sal_uInt16 n;
1448 
1449     if( aPosArr.Count() )
1450     {
1451         SwTableLines& rLns = pTable->GetTabLines();
1452         sal_uInt16 nLastPos = 0;
1453         for( n = 0; n < aPosArr.Count(); ++n )
1454         {
1455             SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt();
1456             pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
1457                                                 aPosArr[ n ] - nLastPos ));
1458             for( sal_uInt16 nLines2 = 0; nLines2 < rLns.Count(); ++nLines2 )
1459                 //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
1460                 //              von der rufenden Methode noch gebraucht wird!
1461                 pNewFmt->Add( rLns[ nLines2 ]->GetTabBoxes()[ n ] );
1462 
1463             nLastPos = aPosArr[ n ];
1464         }
1465 
1466         // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
1467         // Groesse nach "oben" transportieren.
1468         ASSERT( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" );
1469         pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos ));
1470     }
1471     else
1472         pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes ));
1473 
1474     // das wars doch wohl ??
1475     return pTblNd;
1476 }
1477 
1478 
1479 //---------------- Tabelle -> Text -----------------------
1480 
1481 
1482 sal_Bool SwDoc::TableToText( const SwTableNode* pTblNd, sal_Unicode cCh )
1483 {
1484 	if( !pTblNd )
1485 		return sal_False;
1486 
1487     // --> FME 2004-09-28 #i34471#
1488     // If this is trigged by SwUndoTblToTxt::Repeat() nobody ever deleted
1489     // the table cursor.
1490     SwEditShell* pESh = GetEditShell();
1491     if( pESh && pESh->IsTableMode() )
1492         pESh->ClearMark();
1493     // <--
1494 
1495 #ifdef DEL_TABLE_REDLINES
1496     lcl_DelRedlines aDelRedl( *pTblNd, sal_False );
1497 #endif
1498 
1499 	SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode() );
1500 	SwUndoTblToTxt* pUndo = 0;
1501 	SwNodeRange* pUndoRg = 0;
1502     if (GetIDocumentUndoRedo().DoesUndo())
1503     {
1504         GetIDocumentUndoRedo().ClearRedo();
1505 		pUndoRg = new SwNodeRange( aRg.aStart, -1, aRg.aEnd, +1 );
1506 		pUndo = new SwUndoTblToTxt( pTblNd->GetTable(), cCh );
1507 	}
1508 
1509 	SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
1510 	aMsgHnt.eFlags = TBL_BOXNAME;
1511 	UpdateTblFlds( &aMsgHnt );
1512 
1513 	sal_Bool bRet = GetNodes().TableToText( aRg, cCh, pUndo );
1514 	if( pUndoRg )
1515 	{
1516 		pUndoRg->aStart++;
1517 		pUndoRg->aEnd--;
1518 		pUndo->SetRange( *pUndoRg );
1519         GetIDocumentUndoRedo().AppendUndo(pUndo);
1520 		delete pUndoRg;
1521 	}
1522 
1523 	if( bRet )
1524 		SetModified();
1525 
1526 	return bRet;
1527 }
1528 
1529 // -- benutze die ForEach Methode vom PtrArray um aus einer Tabelle wieder
1530 //		Text zuerzeugen. (Die Boxen koennen auch noch Lines enthalten !!)
1531 struct _DelTabPara
1532 {
1533 	SwTxtNode* pLastNd;
1534 	SwNodes& rNds;
1535 	SwUndoTblToTxt* pUndo;
1536 	sal_Unicode cCh;
1537 
1538 	_DelTabPara( SwNodes& rNodes, sal_Unicode cChar, SwUndoTblToTxt* pU ) :
1539 		pLastNd(0), rNds( rNodes ), pUndo( pU ), cCh( cChar ) {}
1540 	_DelTabPara( const _DelTabPara& rPara ) :
1541 		pLastNd(rPara.pLastNd), rNds( rPara.rNds ),
1542 		pUndo( rPara.pUndo ), cCh( rPara.cCh ) {}
1543 };
1544 
1545 // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
1546 // koennen.
1547 sal_Bool lcl_DelBox( const SwTableBox*&, void *pPara );
1548 
1549 sal_Bool lcl_DelLine( const SwTableLine*& rpLine, void* pPara )
1550 {
1551 	ASSERT( pPara, "die Parameter fehlen" );
1552 	_DelTabPara aPara( *(_DelTabPara*)pPara );
1553 	((SwTableLine*&)rpLine)->GetTabBoxes().ForEach( &lcl_DelBox, &aPara );
1554 	if( rpLine->GetUpper() )		// gibt es noch eine uebergeordnete Box ??
1555 		// dann gebe den letzten TextNode zurueck
1556 		((_DelTabPara*)pPara)->pLastNd = aPara.pLastNd;
1557 	return sal_True;
1558 }
1559 
1560 
1561 sal_Bool lcl_DelBox( const SwTableBox*& rpBox, void* pPara )
1562 {
1563 	ASSERT( pPara, "die Parameter fehlen" );
1564 
1565 	// loesche erstmal die Lines der Box
1566 	_DelTabPara* pDelPara = (_DelTabPara*)pPara;
1567 	if( rpBox->GetTabLines().Count() )
1568 		((SwTableBox*&)rpBox)->GetTabLines().ForEach( &lcl_DelLine, pDelPara );
1569 	else
1570 	{
1571 		SwDoc* pDoc = pDelPara->rNds.GetDoc();
1572 		SwNodeRange aDelRg( *rpBox->GetSttNd(), 0,
1573 							*rpBox->GetSttNd()->EndOfSectionNode() );
1574 		// loesche die Section
1575 		pDelPara->rNds.SectionUp( &aDelRg );
1576 		const SwTxtNode* pCurTxtNd;
1577 		if( T2T_PARA != pDelPara->cCh && pDelPara->pLastNd &&
1578 			0 != ( pCurTxtNd = aDelRg.aStart.GetNode().GetTxtNode() ))
1579 		{
1580 			// Join the current text node with the last from the previous box if possible
1581 			sal_uLong nNdIdx = aDelRg.aStart.GetIndex();
1582 			aDelRg.aStart--;
1583 			if( pDelPara->pLastNd == &aDelRg.aStart.GetNode() )
1584 			{
1585                 // Inserting the seperator
1586                 SwIndex aCntIdx( pDelPara->pLastNd, pDelPara->pLastNd->GetTxt().Len());
1587                 pDelPara->pLastNd->InsertText( pDelPara->cCh, aCntIdx,
1588                     IDocumentContentOperations::INS_EMPTYEXPAND );
1589 				if( pDelPara->pUndo )
1590 					pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex(),
1591 												aCntIdx.GetIndex() );
1592 
1593 				SvULongs aBkmkArr( 4, 4 );
1594 				xub_StrLen nOldTxtLen = aCntIdx.GetIndex();
1595 				_SaveCntntIdx( pDoc, nNdIdx, pCurTxtNd->GetTxt().Len(),
1596 								aBkmkArr );
1597 
1598 				pDelPara->pLastNd->JoinNext();
1599 
1600 				if( aBkmkArr.Count() )
1601 					_RestoreCntntIdx( pDoc, aBkmkArr,
1602 										pDelPara->pLastNd->GetIndex(),
1603 										nOldTxtLen );
1604 			}
1605 			else if( pDelPara->pUndo )
1606             {
1607                 aDelRg.aStart++;
1608 				pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex() );
1609             }
1610 		}
1611 		else if( pDelPara->pUndo )
1612 			pDelPara->pUndo->AddBoxPos( *pDoc, aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1613 		aDelRg.aEnd--;
1614 		pDelPara->pLastNd = aDelRg.aEnd.GetNode().GetTxtNode();
1615 
1616 		//JP 03.04.97: die Ausrichtung der ZahlenFormatierung auf
1617 		//				keinen Fall uebernehmen
1618         if( pDelPara->pLastNd && pDelPara->pLastNd->HasSwAttrSet() )
1619 			pDelPara->pLastNd->ResetAttr( RES_PARATR_ADJUST );
1620 	}
1621 	return sal_True;
1622 }
1623 
1624 
1625 sal_Bool SwNodes::TableToText( const SwNodeRange& rRange, sal_Unicode cCh,
1626 							SwUndoTblToTxt* pUndo )
1627 {
1628 	// ist eine Tabelle selektiert ?
1629 	SwTableNode* pTblNd;
1630 	if( rRange.aStart.GetIndex() >= rRange.aEnd.GetIndex() ||
1631         0 == ( pTblNd = rRange.aStart.GetNode().GetTableNode()) ||
1632 		&rRange.aEnd.GetNode() != pTblNd->EndOfSectionNode() )
1633 		return sal_False;
1634 
1635 	// stand die Tabelle ganz alleine in einer Section ?
1636 	// dann ueber den Upper der Tabelle die Frames anlegen
1637 	SwNode2Layout* pNode2Layout = 0;
1638 	SwNodeIndex aFrmIdx( rRange.aStart );
1639 	SwNode* pFrmNd = FindPrvNxtFrmNode( aFrmIdx, &rRange.aEnd.GetNode() );
1640 	if( !pFrmNd )
1641 		// dann sammel mal alle Uppers ein
1642 		pNode2Layout = new SwNode2Layout( *pTblNd );
1643 
1644 	// loesche schon mal die Frames
1645 	pTblNd->DelFrms();
1646 
1647 	// dann "loeschen" die Tabellen und fasse alle Lines/Boxen zusammen
1648 	_DelTabPara aDelPara( *this, cCh, pUndo );
1649 	pTblNd->pTable->GetTabLines().ForEach( &lcl_DelLine, &aDelPara );
1650 
1651 	// jetzt ist aus jeder TableLine ein TextNode mit dem entsprechenden
1652 	// Trenner erzeugt worden. Es braucht nur noch die Table-Section
1653 	// geloescht und fuer die neuen TextNode die Frames erzeugt werden.
1654 	SwNodeRange aDelRg( rRange.aStart, rRange.aEnd );
1655 
1656 	// JP 14.01.97: hat die Tabelle PageDesc-/Break-Attribute? Dann in den
1657 	//				ersten TextNode uebernehmen
1658 	{
1659 // was ist mit UNDO???
1660 		const SfxItemSet& rTblSet = pTblNd->pTable->GetFrmFmt()->GetAttrSet();
1661 		const SfxPoolItem *pBreak, *pDesc;
1662 		if( SFX_ITEM_SET != rTblSet.GetItemState( RES_PAGEDESC, sal_False, &pDesc ))
1663 			pDesc = 0;
1664 		if( SFX_ITEM_SET != rTblSet.GetItemState( RES_BREAK, sal_False, &pBreak ))
1665 			pBreak = 0;
1666 
1667 		if( pBreak || pDesc )
1668 		{
1669 			SwNodeIndex aIdx( *pTblNd  );
1670 			SwCntntNode* pCNd = GoNext( &aIdx );
1671 			if( pBreak )
1672 				pCNd->SetAttr( *pBreak );
1673 			if( pDesc )
1674 				pCNd->SetAttr( *pDesc );
1675 		}
1676 	}
1677 
1678 	SectionUp( &aDelRg );		// loesche die Section und damit die Tabelle
1679     // #i28006#
1680     sal_uLong nStt = aDelRg.aStart.GetIndex(), nEnd = aDelRg.aEnd.GetIndex();
1681 	if( !pFrmNd )
1682 	{
1683 		pNode2Layout->RestoreUpperFrms( *this,
1684 						aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1685 		delete pNode2Layout;
1686 	}
1687 	else
1688 	{
1689 		SwCntntNode *pCNd;
1690 		SwSectionNode *pSNd;
1691 		while( aDelRg.aStart.GetIndex() < nEnd )
1692 		{
1693 			if( 0 != ( pCNd = aDelRg.aStart.GetNode().GetCntntNode()))
1694 			{
1695 				if( pFrmNd->IsCntntNode() )
1696 					((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
1697 				else if( pFrmNd->IsTableNode() )
1698 					((SwTableNode*)pFrmNd)->MakeFrms( aDelRg.aStart );
1699 				else if( pFrmNd->IsSectionNode() )
1700 					((SwSectionNode*)pFrmNd)->MakeFrms( aDelRg.aStart );
1701 				pFrmNd = pCNd;
1702 			}
1703 			else if( 0 != ( pSNd = aDelRg.aStart.GetNode().GetSectionNode()))
1704 			{
1705 				if( !pSNd->GetSection().IsHidden() && !pSNd->IsCntntHidden() )
1706 				{
1707 					pSNd->MakeFrms( &aFrmIdx, &aDelRg.aEnd );
1708 					pFrmNd = pSNd;
1709 					break;
1710 				}
1711 				aDelRg.aStart = *pSNd->EndOfSectionNode();
1712 			}
1713 			aDelRg.aStart++;
1714 		}
1715     }
1716 
1717     // #i28006# Fly frames have to be restored even if the table was
1718     // #alone in the section
1719     const SwSpzFrmFmts& rFlyArr = *GetDoc()->GetSpzFrmFmts();
1720     for( sal_uInt16 n = 0; n < rFlyArr.Count(); ++n )
1721     {
1722         SwFrmFmt *const pFmt = (SwFrmFmt*)rFlyArr[n];
1723         const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
1724         SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1725         if (pAPos &&
1726             ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1727              (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
1728             nStt <= pAPos->nNode.GetIndex() &&
1729             pAPos->nNode.GetIndex() < nEnd )
1730         {
1731             pFmt->MakeFrms();
1732         }
1733 	}
1734 
1735 	return sal_True;
1736 }
1737 
1738 
1739 // ----- einfuegen von Spalten/Zeilen ------------------------
1740 
1741 sal_Bool SwDoc::InsertCol( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind )
1742 {
1743 	if( !::CheckSplitCells( rCursor, nCnt + 1, nsSwTblSearchType::TBLSEARCH_COL ) )
1744 		return sal_False;
1745 
1746 	// lasse ueber das Layout die Boxen suchen
1747 	SwSelBoxes aBoxes;
1748 	::GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
1749 
1750 	sal_Bool bRet = sal_False;
1751 	if( aBoxes.Count() )
1752 		bRet = InsertCol( aBoxes, nCnt, bBehind );
1753 	return bRet;
1754 }
1755 
1756 sal_Bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
1757 {
1758 	// uebers SwDoc fuer Undo !!
1759 	ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
1760 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1761 	if( !pTblNd )
1762 		return sal_False;
1763 
1764 	SwTable& rTbl = pTblNd->GetTable();
1765 	if( rTbl.ISA( SwDDETable ))
1766 		return sal_False;
1767 
1768 #ifdef DEL_TABLE_REDLINES
1769 	lcl_DelRedlines aDelRedl( *pTblNd, sal_True );
1770 #endif
1771 
1772 	SwTableSortBoxes aTmpLst( 0, 5 );
1773 	SwUndoTblNdsChg* pUndo = 0;
1774     if (GetIDocumentUndoRedo().DoesUndo())
1775     {
1776 		pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSCOL, rBoxes, *pTblNd,
1777                                      0, 0, nCnt, bBehind, sal_False );
1778 		aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
1779 	}
1780 
1781     bool bRet(false);
1782     {
1783         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1784 
1785         SwTableFmlUpdate aMsgHnt( &rTbl );
1786         aMsgHnt.eFlags = TBL_BOXPTR;
1787         UpdateTblFlds( &aMsgHnt );
1788 
1789         bRet = rTbl.InsertCol( this, rBoxes, nCnt, bBehind );
1790         if (bRet)
1791         {
1792             SetModified();
1793             ::ClearFEShellTabCols();
1794             SetFieldsDirty( true, NULL, 0 );
1795         }
1796     }
1797 
1798 	if( pUndo )
1799     {
1800 		if( bRet )
1801         {
1802 			pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
1803             GetIDocumentUndoRedo().AppendUndo( pUndo );
1804         }
1805         else
1806 			delete pUndo;
1807 	}
1808 	return bRet;
1809 }
1810 
1811 sal_Bool SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, sal_Bool bBehind )
1812 {
1813 	// lasse ueber das Layout die Boxen suchen
1814 	SwSelBoxes aBoxes;
1815 	GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
1816 
1817 	sal_Bool bRet = sal_False;
1818 	if( aBoxes.Count() )
1819 		bRet = InsertRow( aBoxes, nCnt, bBehind );
1820 	return bRet;
1821 }
1822 
1823 sal_Bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
1824 {
1825 	// uebers SwDoc fuer Undo !!
1826 	ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
1827 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
1828 	if( !pTblNd )
1829 		return sal_False;
1830 
1831 	SwTable& rTbl = pTblNd->GetTable();
1832 	if( rTbl.ISA( SwDDETable ))
1833 		return sal_False;
1834 
1835 #ifdef DEL_TABLE_REDLINES
1836 	lcl_DelRedlines aDelRedl( *pTblNd, sal_True );
1837 #endif
1838 
1839 	SwTableSortBoxes aTmpLst( 0, 5 );
1840 	SwUndoTblNdsChg* pUndo = 0;
1841     if (GetIDocumentUndoRedo().DoesUndo())
1842     {
1843 		pUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW,rBoxes, *pTblNd,
1844 									 0, 0, nCnt, bBehind, sal_False );
1845 		aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
1846 	}
1847 
1848     bool bRet(false);
1849     {
1850         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1851 
1852         SwTableFmlUpdate aMsgHnt( &rTbl );
1853         aMsgHnt.eFlags = TBL_BOXPTR;
1854         UpdateTblFlds( &aMsgHnt );
1855 
1856         bRet = rTbl.InsertRow( this, rBoxes, nCnt, bBehind );
1857         if (bRet)
1858         {
1859             SetModified();
1860             ::ClearFEShellTabCols();
1861             SetFieldsDirty( true, NULL, 0 );
1862         }
1863     }
1864 
1865 	if( pUndo )
1866     {
1867 		if( bRet )
1868         {
1869 			pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
1870             GetIDocumentUndoRedo().AppendUndo( pUndo );
1871         }
1872         else
1873 			delete pUndo;
1874 	}
1875 	return bRet;
1876 
1877 }
1878 
1879 // ----- loeschen von Spalten/Zeilen ------------------------
1880 
1881 sal_Bool SwDoc::DeleteRow( const SwCursor& rCursor )
1882 {
1883 	// lasse ueber das Layout die Boxen suchen
1884 	SwSelBoxes aBoxes;
1885 	GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_ROW );
1886 	if( ::HasProtectedCells( aBoxes ))
1887 		return sal_False;
1888 
1889 	// die Crsr aus dem Loeschbereich entfernen.
1890 	// Der Cursor steht danach:
1891 	//	- es folgt noch eine Zeile, in dieser
1892 	//	- vorher steht noch eine Zeile, in dieser
1893 	//	- sonst immer dahinter
1894 	{
1895 		SwTableNode* pTblNd = rCursor.GetNode()->FindTableNode();
1896 
1897 		if( pTblNd->GetTable().ISA( SwDDETable ))
1898 			return sal_False;
1899 
1900 		// suche alle Boxen / Lines
1901 		_FndBox aFndBox( 0, 0 );
1902 		{
1903 			_FndPara aPara( aBoxes, &aFndBox );
1904 			pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
1905 		}
1906 
1907 		if( !aFndBox.GetLines().Count() )
1908 			return sal_False;
1909 
1910 		SwEditShell* pESh = GetEditShell();
1911 		if( pESh )
1912 		{
1913 			pESh->KillPams();
1914 			// JP: eigentlich sollte man ueber alle Shells iterieren!!
1915 		}
1916 
1917 		_FndBox* pFndBox = &aFndBox;
1918 		while( 1 == pFndBox->GetLines().Count() &&
1919 				1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
1920 		{
1921 			_FndBox* pTmp = pFndBox->GetLines()[0]->GetBoxes()[0];
1922 			if( pTmp->GetBox()->GetSttNd() )
1923 				break;		// das ist sonst zu weit
1924 			pFndBox = pTmp;
1925 		}
1926 
1927 		SwTableLine* pDelLine = pFndBox->GetLines()[
1928 						pFndBox->GetLines().Count()-1 ]->GetLine();
1929 		SwTableBox* pDelBox = pDelLine->GetTabBoxes()[
1930 							pDelLine->GetTabBoxes().Count() - 1 ];
1931 		while( !pDelBox->GetSttNd() )
1932 		{
1933 			SwTableLine* pLn = pDelBox->GetTabLines()[
1934 						pDelBox->GetTabLines().Count()-1 ];
1935 			pDelBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ];
1936 		}
1937 		SwTableBox* pNextBox = pDelLine->FindNextBox( pTblNd->GetTable(),
1938 														pDelBox, sal_True );
1939 		while( pNextBox &&
1940 				pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
1941 			pNextBox = pNextBox->FindNextBox( pTblNd->GetTable(), pNextBox );
1942 
1943 		if( !pNextBox )			// keine nachfolgende? dann die vorhergehende
1944 		{
1945 			pDelLine = pFndBox->GetLines()[ 0 ]->GetLine();
1946 			pDelBox = pDelLine->GetTabBoxes()[ 0 ];
1947 			while( !pDelBox->GetSttNd() )
1948 				pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
1949 			pNextBox = pDelLine->FindPreviousBox( pTblNd->GetTable(),
1950 														pDelBox, sal_True );
1951 			while( pNextBox &&
1952 					pNextBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
1953 				pNextBox = pNextBox->FindPreviousBox( pTblNd->GetTable(), pNextBox );
1954 		}
1955 
1956 		sal_uLong nIdx;
1957 		if( pNextBox )		// dann den Cursor hier hinein
1958 			nIdx = pNextBox->GetSttIdx() + 1;
1959 		else				// ansonsten hinter die Tabelle
1960 			nIdx = pTblNd->EndOfSectionIndex() + 1;
1961 
1962 		SwNodeIndex aIdx( GetNodes(), nIdx );
1963 		SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
1964 		if( !pCNd )
1965 			pCNd = GetNodes().GoNext( &aIdx );
1966 
1967 		if( pCNd )
1968 		{
1969 			// die Cursor von der Shell oder den uebergebenen Cursor aendern?
1970 			SwPaM* pPam = (SwPaM*)&rCursor;
1971 			pPam->GetPoint()->nNode = aIdx;
1972 			pPam->GetPoint()->nContent.Assign( pCNd, 0 );
1973 			pPam->SetMark();			// beide wollen etwas davon haben
1974 			pPam->DeleteMark();
1975 		}
1976 	}
1977 
1978 	// dann loesche doch die Zeilen
1979 
1980     GetIDocumentUndoRedo().StartUndo(UNDO_ROW_DELETE, NULL);
1981     sal_Bool bResult = DeleteRowCol( aBoxes );
1982     GetIDocumentUndoRedo().EndUndo(UNDO_ROW_DELETE, NULL);
1983 
1984 	return bResult;
1985 }
1986 
1987 sal_Bool SwDoc::DeleteCol( const SwCursor& rCursor )
1988 {
1989 	// lasse ueber das Layout die Boxen suchen
1990 	SwSelBoxes aBoxes;
1991 	GetTblSel( rCursor, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
1992 	if( ::HasProtectedCells( aBoxes ))
1993 		return sal_False;
1994 
1995 	// die Crsr muessen noch aus dem Loesch Bereich entfernt
1996 	// werden. Setze sie immer hinter/auf die Tabelle; ueber die
1997 	// Dokument-Position werden sie dann immer an die alte Position gesetzt.
1998 	SwEditShell* pESh = GetEditShell();
1999 	if( pESh )
2000 	{
2001 		const SwNode* pNd = rCursor.GetNode()->FindTableBoxStartNode();
2002 		pESh->ParkCrsr( SwNodeIndex( *pNd ) );
2003 	}
2004 
2005 	// dann loesche doch die Spalten
2006     GetIDocumentUndoRedo().StartUndo(UNDO_COL_DELETE, NULL);
2007     sal_Bool bResult = DeleteRowCol( aBoxes, true );
2008     GetIDocumentUndoRedo().EndUndo(UNDO_COL_DELETE, NULL);
2009 
2010 	return bResult;
2011 }
2012 
2013 sal_Bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
2014 {
2015 	if( ::HasProtectedCells( rBoxes ))
2016 		return sal_False;
2017 
2018 	// uebers SwDoc fuer Undo !!
2019 	ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
2020 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2021 	if( !pTblNd )
2022 		return sal_False;
2023 
2024 	if( pTblNd->GetTable().ISA( SwDDETable ))
2025 		return sal_False;
2026 
2027 	::ClearFEShellTabCols();
2028     SwSelBoxes aSelBoxes;
2029     aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
2030     SwTable &rTable = pTblNd->GetTable();
2031     long nMin = 0;
2032     long nMax = 0;
2033     if( rTable.IsNewModel() )
2034 	{
2035 		if( bColumn )
2036 			rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax );
2037 		else
2038 			rTable.FindSuperfluousRows( aSelBoxes );
2039 	}
2040 
2041 #ifdef DEL_TABLE_REDLINES
2042 	lcl_DelRedlines aDelRedl( *pTblNd, sal_True );
2043 #endif
2044 
2045 	// soll die gesamte Tabelle geloescht werden ??
2046 	const sal_uLong nTmpIdx1 = pTblNd->GetIndex();
2047 	const sal_uLong nTmpIdx2 = aSelBoxes[ aSelBoxes.Count()-1 ]->GetSttNd()->
2048 								EndOfSectionIndex()+1;
2049 	if( pTblNd->GetTable().GetTabSortBoxes().Count() == aSelBoxes.Count() &&
2050 		aSelBoxes[0]->GetSttIdx()-1 == nTmpIdx1 &&
2051 		nTmpIdx2 == pTblNd->EndOfSectionIndex() )
2052 	{
2053 		sal_Bool bNewTxtNd = sal_False;
2054 		// steht diese auch noch alleine in einem FlyFrame ?
2055 		SwNodeIndex aIdx( *pTblNd, -1 );
2056 		const SwStartNode* pSttNd = aIdx.GetNode().GetStartNode();
2057 		if( pSttNd )
2058 		{
2059 			const sal_uLong nTblEnd = pTblNd->EndOfSectionIndex() + 1;
2060 			const sal_uLong nSectEnd = pSttNd->EndOfSectionIndex();
2061 			if( nTblEnd == nSectEnd )
2062 			{
2063 				if( SwFlyStartNode == pSttNd->GetStartNodeType() )
2064 				{
2065 					SwFrmFmt* pFmt = pSttNd->GetFlyFmt();
2066 					if( pFmt )
2067 					{
2068 						// Ok, das ist das gesuchte FlyFormat
2069 						DelLayoutFmt( pFmt );
2070 						return sal_True;
2071 					}
2072 				}
2073 				// kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2074 				// TextNode ueberig lassen.
2075 				// Undo koennen wir dann vergessen !!
2076 				bNewTxtNd = sal_True;
2077 			}
2078 		}
2079 
2080 		// kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2081 		// TextNode ueberig lassen.
2082 		aIdx++;
2083         if (GetIDocumentUndoRedo().DoesUndo())
2084         {
2085             GetIDocumentUndoRedo().ClearRedo();
2086 			SwPaM aPaM( *pTblNd->EndOfSectionNode(), aIdx.GetNode() );
2087 
2088 			if( bNewTxtNd )
2089 			{
2090 				const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
2091 				GetNodes().MakeTxtNode( aTmpIdx,
2092 							GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
2093 			}
2094 
2095             // save the cursors (UNO and otherwise)
2096             SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) );
2097             if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
2098             {
2099                 *aSavePaM.GetMark() = SwPosition( *pTblNd );
2100                 aSavePaM.Move( fnMoveBackward, fnGoNode );
2101             }
2102             {
2103                 SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode());
2104                 ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2105             }
2106 
2107 			// harte SeitenUmbrueche am nachfolgenden Node verschieben
2108 			sal_Bool bSavePageBreak = sal_False, bSavePageDesc = sal_False;
2109 			sal_uLong nNextNd = pTblNd->EndOfSectionIndex()+1;
2110 			SwCntntNode* pNextNd = GetNodes()[ nNextNd ]->GetCntntNode();
2111 			if( pNextNd )
2112 			{
2113 //JP 24.08.98: will man wirklich den PageDesc/Break vom
2114 //				nachfolgen Absatz ueberbuegeln?
2115 //				const SwAttrSet& rAttrSet = pNextNd->GetSwAttrSet();
2116 //				if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
2117 //					SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
2118 				{
2119 					SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
2120 					const SfxPoolItem *pItem;
2121 					if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
2122 						sal_False, &pItem ) )
2123 					{
2124 						pNextNd->SetAttr( *pItem );
2125 						bSavePageDesc = sal_True;
2126 					}
2127 
2128 					if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
2129 						sal_False, &pItem ) )
2130 					{
2131 						pNextNd->SetAttr( *pItem );
2132 						bSavePageBreak = sal_True;
2133 					}
2134 				}
2135 			}
2136 			SwUndoDelete* pUndo = new SwUndoDelete( aPaM );
2137 			if( bNewTxtNd )
2138 				pUndo->SetTblDelLastNd();
2139 			pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
2140             pUndo->SetTableName(pTblNd->GetTable().GetFrmFmt()->GetName());
2141             GetIDocumentUndoRedo().AppendUndo( pUndo );
2142         }
2143         else
2144         {
2145 			if( bNewTxtNd )
2146 			{
2147 				const SwNodeIndex aTmpIdx( *pTblNd->EndOfSectionNode(), 1 );
2148 				GetNodes().MakeTxtNode( aTmpIdx,
2149 							GetTxtCollFromPool( RES_POOLCOLL_STANDARD ) );
2150 			}
2151 
2152             // save the cursors (UNO and otherwise)
2153             SwPaM aSavePaM( SwNodeIndex( *pTblNd->EndOfSectionNode() ) );
2154             if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
2155             {
2156                 *aSavePaM.GetMark() = SwPosition( *pTblNd );
2157                 aSavePaM.Move( fnMoveBackward, fnGoNode );
2158             }
2159             {
2160                 SwPaM const tmpPaM(*pTblNd, *pTblNd->EndOfSectionNode());
2161                 ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2162             }
2163 
2164 			// harte SeitenUmbrueche am nachfolgenden Node verschieben
2165 			SwCntntNode* pNextNd = GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
2166 			if( pNextNd )
2167 			{
2168 				SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
2169 				const SfxPoolItem *pItem;
2170 				if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
2171 					sal_False, &pItem ) )
2172 					pNextNd->SetAttr( *pItem );
2173 
2174 				if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
2175 					sal_False, &pItem ) )
2176 					pNextNd->SetAttr( *pItem );
2177 			}
2178 
2179 			pTblNd->DelFrms();
2180 			DeleteSection( pTblNd );
2181 		}
2182 		SetModified();
2183 		SetFieldsDirty( true, NULL, 0 );
2184 		return sal_True;
2185 	}
2186 
2187 	SwUndoTblNdsChg* pUndo = 0;
2188     if (GetIDocumentUndoRedo().DoesUndo())
2189     {
2190 		pUndo = new SwUndoTblNdsChg( UNDO_TABLE_DELBOX, aSelBoxes, *pTblNd,
2191                                      nMin, nMax, 0, sal_False, sal_False );
2192 	}
2193 
2194     bool bRet(false);
2195     {
2196         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2197 
2198         SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
2199         aMsgHnt.eFlags = TBL_BOXPTR;
2200         UpdateTblFlds( &aMsgHnt );
2201 
2202         if (rTable.IsNewModel())
2203         {
2204             if (bColumn)
2205                 rTable.PrepareDeleteCol( nMin, nMax );
2206             rTable.FindSuperfluousRows( aSelBoxes );
2207             if (pUndo)
2208                 pUndo->ReNewBoxes( aSelBoxes );
2209         }
2210         bRet = rTable.DeleteSel( this, aSelBoxes, 0, pUndo, sal_True, sal_True );
2211         if (bRet)
2212         {
2213             SetModified();
2214             SetFieldsDirty( true, NULL, 0 );
2215         }
2216     }
2217 
2218 	if( pUndo )
2219     {
2220 		if( bRet )
2221         {
2222             GetIDocumentUndoRedo().AppendUndo( pUndo );
2223         }
2224         else
2225 			delete pUndo;
2226 	}
2227 
2228 	return bRet;
2229 }
2230 
2231 
2232 // ---------- teilen / zusammenfassen von Boxen in der Tabelle --------
2233 
2234 sal_Bool SwDoc::SplitTbl( const SwSelBoxes& rBoxes, sal_Bool bVert, sal_uInt16 nCnt,
2235                       sal_Bool bSameHeight )
2236 {
2237 	// uebers SwDoc fuer Undo !!
2238 	ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" );
2239 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2240 	if( !pTblNd )
2241 		return sal_False;
2242 
2243 	SwTable& rTbl = pTblNd->GetTable();
2244 	if( rTbl.ISA( SwDDETable ))
2245 		return sal_False;
2246 
2247 #ifdef DEL_TABLE_REDLINES
2248 	lcl_DelRedlines aDelRedl( *pTblNd, sal_True );
2249 #endif
2250 
2251 	SvULongs aNdsCnts;
2252 	SwTableSortBoxes aTmpLst( 0, 5 );
2253 	SwUndoTblNdsChg* pUndo = 0;
2254     if (GetIDocumentUndoRedo().DoesUndo())
2255     {
2256         pUndo = new SwUndoTblNdsChg( UNDO_TABLE_SPLIT, rBoxes, *pTblNd, 0, 0,
2257                                      nCnt, bVert, bSameHeight );
2258 
2259 		aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
2260 		if( !bVert )
2261 		{
2262 			for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2263 			{
2264 				const SwStartNode* pSttNd = rBoxes[ n ]->GetSttNd();
2265 				aNdsCnts.Insert( pSttNd->EndOfSectionIndex() -
2266 								 pSttNd->GetIndex(), n );
2267 			}
2268 		}
2269 	}
2270 
2271     bool bRet(false);
2272     {
2273         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2274 
2275         SwTableFmlUpdate aMsgHnt( &rTbl );
2276         aMsgHnt.eFlags = TBL_BOXPTR;
2277         UpdateTblFlds( &aMsgHnt );
2278 
2279         if (bVert)
2280             bRet = rTbl.SplitCol( this, rBoxes, nCnt );
2281         else
2282             bRet = rTbl.SplitRow( this, rBoxes, nCnt, bSameHeight );
2283 
2284         if (bRet)
2285         {
2286             SetModified();
2287             SetFieldsDirty( true, NULL, 0 );
2288         }
2289     }
2290 
2291 	if( pUndo )
2292 	{
2293 		if( bRet )
2294 		{
2295 			if( bVert )
2296 				pUndo->SaveNewBoxes( *pTblNd, aTmpLst );
2297 			else
2298 				pUndo->SaveNewBoxes( *pTblNd, aTmpLst, rBoxes, aNdsCnts );
2299             GetIDocumentUndoRedo().AppendUndo( pUndo );
2300         }
2301         else
2302 			delete pUndo;
2303 	}
2304 
2305 	return bRet;
2306 }
2307 
2308 
2309 sal_uInt16 SwDoc::MergeTbl( SwPaM& rPam )
2310 {
2311 	// pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
2312 	SwTableNode* pTblNd = rPam.GetNode()->FindTableNode();
2313 	if( !pTblNd )
2314 		return TBLMERGE_NOSELECTION;
2315     SwTable& rTable = pTblNd->GetTable();
2316     if( rTable.ISA(SwDDETable) )
2317 		return TBLMERGE_NOSELECTION;
2318 	sal_uInt16 nRet = TBLMERGE_NOSELECTION;
2319     if( !rTable.IsNewModel() )
2320     {
2321         nRet =::CheckMergeSel( rPam );
2322         if( TBLMERGE_OK != nRet )
2323             return nRet;
2324         nRet = TBLMERGE_NOSELECTION;
2325     }
2326 
2327     // --> FME 2004-10-08 #i33394#
2328     GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_MERGE, NULL );
2329     // <--
2330 
2331 #ifdef DEL_TABLE_REDLINES
2332 	if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
2333 		DeleteRedline( *pTblNd, true, USHRT_MAX );
2334 #endif
2335 	RedlineMode_t eOld = GetRedlineMode();
2336 	SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
2337 
2338     SwUndoTblMerge *const pUndo( (GetIDocumentUndoRedo().DoesUndo())
2339         ?   new SwUndoTblMerge( rPam )
2340         :   0 );
2341 
2342 	// lasse ueber das Layout die Boxen suchen
2343 	SwSelBoxes aBoxes;
2344     SwSelBoxes aMerged;
2345 	SwTableBox* pMergeBox;
2346 
2347 	if( !rTable.PrepareMerge( rPam, aBoxes, aMerged, &pMergeBox, pUndo ) )
2348 	{   // no cells found to merge
2349 		SetRedlineMode_intern( eOld );
2350 		if( pUndo )
2351 		{
2352 			delete pUndo;
2353             SwUndoId nLastUndoId(UNDO_EMPTY);
2354             if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
2355                 && (UNDO_REDLINE == nLastUndoId))
2356             {
2357                 // FIXME: why is this horrible cleanup necessary?
2358                 SwUndoRedline *const pU = dynamic_cast<SwUndoRedline*>(
2359                         GetUndoManager().RemoveLastUndo());
2360 				if( pU->GetRedlSaveCount() )
2361                 {
2362                     SwEditShell *const pEditShell(GetEditShell(0));
2363                     OSL_ASSERT(pEditShell);
2364                     ::sw::UndoRedoContext context(*this, *pEditShell);
2365                     static_cast<SfxUndoAction *>(pU)->UndoWithContext(context);
2366                 }
2367 				delete pU;
2368 			}
2369 		}
2370 	}
2371 	else
2372 	{
2373 		// die PaMs muessen noch aus dem Loesch Bereich entfernt
2374 		// werden. Setze sie immer hinter/auf die Tabelle; ueber die
2375 		// Dokument-Position werden sie dann immer an die alte Position gesetzt.
2376 		// Erstmal einen Index auf die Parkposition merken, denn nach GetMergeSel
2377 		// komme ich nicht mehr dran.
2378 		{
2379 			rPam.DeleteMark();
2380 			rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2381 			rPam.GetPoint()->nContent.Assign( 0, 0 );
2382 			rPam.SetMark();
2383 			rPam.DeleteMark();
2384 
2385 			SwPaM* pTmp = &rPam;
2386 			while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ))
2387 				for( int i = 0; i < 2; ++i )
2388 					pTmp->GetBound( (sal_Bool)i ) = *rPam.GetPoint();
2389 		}
2390 
2391 		// dann fuege sie zusammen
2392 		SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
2393 		aMsgHnt.eFlags = TBL_BOXPTR;
2394 		UpdateTblFlds( &aMsgHnt );
2395 
2396 		if( pTblNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo ))
2397 		{
2398 			nRet = TBLMERGE_OK;
2399 			SetModified();
2400 			SetFieldsDirty( true, NULL, 0 );
2401 			if( pUndo )
2402             {
2403                 GetIDocumentUndoRedo().AppendUndo( pUndo );
2404             }
2405         }
2406 		else if( pUndo )
2407 			delete pUndo;
2408 
2409 		rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2410 		rPam.Move();
2411 
2412 		::ClearFEShellTabCols();
2413 		SetRedlineMode_intern( eOld );
2414 	}
2415     GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_MERGE, NULL );
2416 	return nRet;
2417 }
2418 
2419 
2420 
2421 // -------------------------------------------------------
2422 
2423 //---------
2424 // SwTableNode
2425 //---------
2426 
2427 SwTableNode::SwTableNode( const SwNodeIndex& rIdx )
2428 	: SwStartNode( rIdx, ND_TABLENODE )
2429 {
2430 	pTable = new SwTable( 0 );
2431 }
2432 
2433 SwTableNode::~SwTableNode()
2434 {
2435 	//don't forget to notify uno wrappers
2436 	SwFrmFmt* pTblFmt = GetTable().GetFrmFmt();
2437 	SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
2438 								pTblFmt );
2439 	pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint );
2440 	DelFrms();
2441 	delete pTable;
2442 }
2443 
2444 SwTabFrm *SwTableNode::MakeFrm( SwFrm* pSib )
2445 {
2446 	return new SwTabFrm( *pTable, pSib );
2447 }
2448 
2449 //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
2450 //Dokument. Die erzeugten Contentframes werden in das entsprechende
2451 //Layout gehaengt.
2452 void SwTableNode::MakeFrms(const SwNodeIndex & rIdx )
2453 {
2454 	if( !GetTable().GetFrmFmt()->GetDepends())//gibt es ueberhaupt Frames ??
2455 		return;
2456 
2457 	SwFrm *pFrm, *pNew;
2458 	SwCntntNode * pNode = rIdx.GetNode().GetCntntNode();
2459 
2460 	ASSERT( pNode, "Kein Contentnode oder Copy-Node und neuer Node identisch.");
2461 
2462 	sal_Bool bBefore = rIdx < GetIndex();
2463 
2464 	SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
2465 
2466 	while( 0 != (pFrm = aNode2Layout.NextFrm()) )
2467 	{
2468 		pNew = pNode->MakeFrm( pFrm );
2469 		// wird ein Node vorher oder nachher mit Frames versehen
2470 		if ( bBefore )
2471 			// der neue liegt vor mir
2472 			pNew->Paste( pFrm->GetUpper(), pFrm );
2473 		else
2474 			// der neue liegt hinter mir
2475 			pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
2476 	}
2477 }
2478 
2479 //Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden
2480 //CntntFrm pasten.
2481 
2482 void SwTableNode::MakeFrms( SwNodeIndex* pIdxBehind )
2483 {
2484 	ASSERT( pIdxBehind, "kein Index" );
2485 	*pIdxBehind = *this;
2486 	SwNode *pNd = GetNodes().FindPrvNxtFrmNode( *pIdxBehind, EndOfSectionNode() );
2487 	if( !pNd )
2488 		return ;
2489 
2490     SwFrm *pFrm( 0L );
2491 	SwLayoutFrm *pUpper( 0L );
2492 	SwNode2Layout aNode2Layout( *pNd, GetIndex() );
2493 	while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, *this )) )
2494 	{
2495         SwTabFrm* pNew = MakeFrm( pUpper );
2496 		pNew->Paste( pUpper, pFrm );
2497         // --> OD 2005-12-01 #i27138#
2498         // notify accessibility paragraphs objects about changed
2499         // CONTENT_FLOWS_FROM/_TO relation.
2500         // Relation CONTENT_FLOWS_FROM for next paragraph will change
2501         // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2502         {
2503             ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
2504             if ( pViewShell && pViewShell->GetLayout() &&
2505                  pViewShell->GetLayout()->IsAnyShellAccessible() )
2506             {
2507                 pViewShell->InvalidateAccessibleParaFlowRelation(
2508                             dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
2509                             dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
2510             }
2511         }
2512         // <--
2513         ((SwTabFrm*)pNew)->RegistFlys();
2514 	}
2515 }
2516 
2517 void SwTableNode::DelFrms()
2518 {
2519 	//Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows
2520 	//nehmen sie mit in's Grab.
2521 	//Die TabFrms haengen am FrmFmt des SwTable.
2522 	//Sie muessen etwas umstaendlich zerstort werden, damit die Master
2523 	//die Follows mit in's Grab nehmen.
2524 
2525 	SwIterator<SwTabFrm,SwFmt> aIter( *(pTable->GetFrmFmt()) );
2526 	SwTabFrm *pFrm = aIter.First();
2527 	while ( pFrm )
2528 	{
2529 		sal_Bool bAgain = sal_False;
2530 		{
2531 			if ( !pFrm->IsFollow() )
2532 			{
2533 				while ( pFrm->HasFollow() )
2534 					pFrm->JoinAndDelFollows();
2535                 // --> OD 2005-12-01 #i27138#
2536                 // notify accessibility paragraphs objects about changed
2537                 // CONTENT_FLOWS_FROM/_TO relation.
2538                 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2539                 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2540                 {
2541                     ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
2542                     if ( pViewShell && pViewShell->GetLayout() &&
2543                          pViewShell->GetLayout()->IsAnyShellAccessible() )
2544                     {
2545                         pViewShell->InvalidateAccessibleParaFlowRelation(
2546                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
2547                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
2548                     }
2549                 }
2550                 // <--
2551                 pFrm->Cut();
2552 				delete pFrm;
2553 				bAgain = sal_True;
2554 			}
2555 		}
2556 		pFrm = bAgain ? aIter.First() : aIter.Next();
2557 	}
2558 }
2559 
2560 
2561 void SwTableNode::SetNewTable( SwTable* pNewTable, sal_Bool bNewFrames )
2562 {
2563 	DelFrms();
2564 	delete pTable;
2565 	pTable = pNewTable;
2566 	if( bNewFrames )
2567 	{
2568 		SwNodeIndex aIdx( *EndOfSectionNode());
2569 		GetNodes().GoNext( &aIdx );
2570 		MakeFrms( &aIdx );
2571 	}
2572 }
2573 
2574 void SwDoc::GetTabCols( SwTabCols &rFill, const SwCursor* pCrsr,
2575 						const SwCellFrm* pBoxFrm ) const
2576 {
2577 	const SwTableBox* pBox = 0;
2578 	SwTabFrm *pTab = 0;
2579 
2580 	if( pBoxFrm )
2581 	{
2582 		pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
2583 		pBox = pBoxFrm->GetTabBox();
2584 	}
2585 	else if( pCrsr )
2586 	{
2587 		const SwCntntNode* pCNd = pCrsr->GetCntntNode();
2588 		if( !pCNd )
2589 			return ;
2590 
2591 		Point aPt;
2592         const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
2593 		if( pShCrsr )
2594 			aPt = pShCrsr->GetPtPos();
2595 
2596 		const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
2597 		do {
2598 			pTmpFrm = pTmpFrm->GetUpper();
2599 		} while ( !pTmpFrm->IsCellFrm() );
2600 
2601 		pBoxFrm = (SwCellFrm*)pTmpFrm;
2602 		pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
2603 		pBox = pBoxFrm->GetTabBox();
2604 	}
2605 	else if( !pCrsr && !pBoxFrm )
2606 	{
2607 		ASSERT( !this, "einer von beiden muss angegeben werden!" );
2608 		return ;
2609 	}
2610 
2611 	//Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2612     SWRECTFN( pTab )
2613     const SwPageFrm* pPage = pTab->FindPageFrm();
2614     const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
2615                            (pPage->Frm().*fnRect->fnGetLeft)();
2616     const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
2617                             (pPage->Frm().*fnRect->fnGetLeft)();
2618 
2619     rFill.SetLeftMin ( nLeftMin );
2620     rFill.SetLeft    ( (pTab->Prt().*fnRect->fnGetLeft)() );
2621     rFill.SetRight   ( (pTab->Prt().*fnRect->fnGetRight)());
2622     rFill.SetRightMax( nRightMax - nLeftMin );
2623 
2624 	pTab->GetTable()->GetTabCols( rFill, pBox );
2625 }
2626 
2627 //
2628 // Here are some little helpers used in SwDoc::GetTabRows
2629 //
2630 
2631 #define ROWFUZZY 25
2632 
2633 struct FuzzyCompare
2634 {
2635     bool operator() ( long s1, long s2 ) const;
2636 };
2637 
2638 bool FuzzyCompare::operator() ( long s1, long s2 ) const
2639 {
2640     return ( s1 < s2 && abs( s1 - s2 ) > ROWFUZZY );
2641 }
2642 
2643 bool lcl_IsFrmInColumn( const SwCellFrm& rFrm, SwSelBoxes& rBoxes )
2644 {
2645     for( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
2646     {
2647         if ( rFrm.GetTabBox() == rBoxes[ i ] )
2648             return true;
2649     }
2650 
2651     return false;
2652 }
2653 
2654 //
2655 // SwDoc::GetTabRows()
2656 //
2657 
2658 void SwDoc::GetTabRows( SwTabCols &rFill, const SwCursor* ,
2659 						const SwCellFrm* pBoxFrm ) const
2660 {
2661     ASSERT( pBoxFrm, "GetTabRows called without pBoxFrm" )
2662 
2663     // --> FME 2005-09-12 #121591# Make code robust:
2664     if ( !pBoxFrm )
2665         return;
2666     // <--
2667 
2668     // --> FME 2005-01-06 #i39552# Collection of the boxes of the current
2669     // column has to be done at the beginning of this function, because
2670     // the table may be formatted in ::GetTblSel.
2671     SwDeletionChecker aDelCheck( pBoxFrm );
2672 
2673     SwSelBoxes aBoxes;
2674     const SwCntntFrm* pCntnt = ::GetCellCntnt( *pBoxFrm );
2675     if ( pCntnt && pCntnt->IsTxtFrm() )
2676     {
2677         const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() );
2678         const SwCursor aTmpCrsr( aPos, 0, false );
2679         ::GetTblSel( aTmpCrsr, aBoxes, nsSwTblSearchType::TBLSEARCH_COL );
2680     }
2681     // <--
2682 
2683     // --> FME 2005-09-12 #121591# Make code robust:
2684     if ( aDelCheck.HasBeenDeleted() )
2685     {
2686         ASSERT( false, "Current box has been deleted during GetTabRows()" )
2687         return;
2688     }
2689     // <--
2690 
2691     // --> FME 2005-09-12 #121591# Make code robust:
2692     const SwTabFrm* pTab = pBoxFrm->FindTabFrm();
2693     ASSERT( pTab, "GetTabRows called without a table" )
2694     if ( !pTab )
2695         return;
2696     // <--
2697 
2698     const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
2699 
2700 	//Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2701     SWRECTFN( pTab )
2702     const SwPageFrm* pPage = pTab->FindPageFrm();
2703     const long nLeftMin  = ( bVert ?
2704                              pTab->GetPrtLeft() - pPage->Frm().Left() :
2705                              pTab->GetPrtTop() - pPage->Frm().Top() );
2706     const long nLeft     = bVert ? LONG_MAX : 0;
2707     const long nRight    = (pTab->Prt().*fnRect->fnGetHeight)();
2708     const long nRightMax = bVert ? nRight : LONG_MAX;
2709 
2710     rFill.SetLeftMin( nLeftMin );
2711     rFill.SetLeft( nLeft );
2712     rFill.SetRight( nRight );
2713     rFill.SetRightMax( nRightMax );
2714 
2715     typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap;
2716     BoundaryMap aBoundaries;
2717     BoundaryMap::iterator aIter;
2718     std::pair< long, long > aPair;
2719 
2720     typedef std::map< long, bool > HiddenMap;
2721     HiddenMap aHidden;
2722     HiddenMap::iterator aHiddenIter;
2723 
2724     while ( pFrm && pTab->IsAnLower( pFrm ) )
2725     {
2726         if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
2727         {
2728             // upper and lower borders of current cell frame:
2729             long nUpperBorder = (pFrm->Frm().*fnRect->fnGetTop)();
2730             long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
2731 
2732             // get boundaries for nUpperBorder:
2733             aIter = aBoundaries.find( nUpperBorder );
2734             if ( aIter == aBoundaries.end() )
2735             {
2736                 aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2737                 aBoundaries[ nUpperBorder ] = aPair;
2738             }
2739 
2740             // get boundaries for nLowerBorder:
2741             aIter = aBoundaries.find( nLowerBorder );
2742             if ( aIter == aBoundaries.end() )
2743             {
2744                 aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2745             }
2746             else
2747             {
2748                 nLowerBorder = (*aIter).first;
2749                 long nNewLowerBorderUpperBoundary = Max( (*aIter).second.first, nUpperBorder );
2750                 aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX;
2751             }
2752             aBoundaries[ nLowerBorder ] = aPair;
2753 
2754             // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2755             long nTmpVal = nUpperBorder;
2756             for ( sal_uInt8 i = 0; i < 2; ++i )
2757             {
2758                 aHiddenIter = aHidden.find( nTmpVal );
2759                 if ( aHiddenIter == aHidden.end() )
2760                     aHidden[ nTmpVal ] = !lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes );
2761                 else
2762                 {
2763                     if ( aHidden[ nTmpVal ] &&
2764                          lcl_IsFrmInColumn( *((SwCellFrm*)pFrm), aBoxes ) )
2765                         aHidden[ nTmpVal ] = false;
2766                 }
2767                 nTmpVal = nLowerBorder;
2768             }
2769         }
2770 
2771         pFrm = pFrm->GetNextLayoutLeaf();
2772     }
2773 
2774     // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2775     sal_uInt16 nIdx = 0;
2776     for ( aIter = aBoundaries.begin(); aIter != aBoundaries.end(); ++aIter )
2777     {
2778         const long nTabTop = (pTab->*fnRect->fnGetPrtTop)();
2779         const long nKey = (*fnRect->fnYDiff)( (*aIter).first, nTabTop );
2780         const std::pair< long, long > aTmpPair = (*aIter).second;
2781         const long nFirst = (*fnRect->fnYDiff)( aTmpPair.first, nTabTop );
2782         const long nSecond = aTmpPair.second;
2783 
2784         aHiddenIter = aHidden.find( (*aIter).first );
2785         const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second;
2786         rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ );
2787     }
2788 
2789     // delete first and last entry
2790     ASSERT( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" )
2791     // --> FME 2006-01-19 #i60818# There may be only one entry in rFill. Make
2792     // code robust by checking count of rFill.
2793     if ( rFill.Count() ) rFill.Remove( 0, 1 );
2794     if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 , 1 );
2795     // <--
2796     rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() );
2797 }
2798 
2799 void SwDoc::SetTabCols( const SwTabCols &rNew, sal_Bool bCurRowOnly,
2800 						const SwCursor* pCrsr, const SwCellFrm* pBoxFrm )
2801 {
2802 	const SwTableBox* pBox = 0;
2803 	SwTabFrm *pTab = 0;
2804 
2805 	if( pBoxFrm )
2806 	{
2807 		pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
2808 		pBox = pBoxFrm->GetTabBox();
2809 	}
2810 	else if( pCrsr )
2811 	{
2812 		const SwCntntNode* pCNd = pCrsr->GetCntntNode();
2813 		if( !pCNd )
2814 			return ;
2815 
2816 		Point aPt;
2817         const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
2818 		if( pShCrsr )
2819 			aPt = pShCrsr->GetPtPos();
2820 
2821 		const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
2822 		do {
2823 			pTmpFrm = pTmpFrm->GetUpper();
2824 		} while ( !pTmpFrm->IsCellFrm() );
2825 
2826 		pBoxFrm = (SwCellFrm*)pTmpFrm;
2827 		pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
2828 		pBox = pBoxFrm->GetTabBox();
2829 	}
2830 	else if( !pCrsr && !pBoxFrm )
2831 	{
2832 		ASSERT( !this, "einer von beiden muss angegeben werden!" );
2833 		return ;
2834 	}
2835 
2836 	// sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2837 	// dann muss es jetzt auf absolute umgerechnet werden.
2838 	SwTable& rTab = *pTab->GetTable();
2839 	const SwFmtFrmSize& rTblFrmSz = rTab.GetFrmFmt()->GetFrmSize();
2840     SWRECTFN( pTab )
2841     // OD 06.08.2003 #i17174# - With fix for #i9040# the shadow size is taken
2842     // from the table width. Thus, add its left and right size to current table
2843     // printing area width in order to get the correct table size attribute.
2844     SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
2845     {
2846         SvxShadowItem aShadow( rTab.GetFrmFmt()->GetShadow() );
2847         nPrtWidth += aShadow.CalcShadowSpace( SHADOW_LEFT ) +
2848                      aShadow.CalcShadowSpace( SHADOW_RIGHT );
2849     }
2850     if( nPrtWidth != rTblFrmSz.GetWidth() )
2851 	{
2852 		SwFmtFrmSize aSz( rTblFrmSz );
2853         aSz.SetWidth( nPrtWidth );
2854         rTab.GetFrmFmt()->SetFmtAttr( aSz );
2855 	}
2856 
2857     SwTabCols aOld( rNew.Count() );
2858 
2859     const SwPageFrm* pPage = pTab->FindPageFrm();
2860     const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
2861                            (pPage->Frm().*fnRect->fnGetLeft)();
2862     const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
2863                             (pPage->Frm().*fnRect->fnGetLeft)();
2864 
2865     //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2866     aOld.SetLeftMin ( nLeftMin );
2867     aOld.SetLeft    ( (pTab->Prt().*fnRect->fnGetLeft)() );
2868     aOld.SetRight   ( (pTab->Prt().*fnRect->fnGetRight)());
2869     aOld.SetRightMax( nRightMax - nLeftMin );
2870 
2871     rTab.GetTabCols( aOld, pBox );
2872     SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly );
2873 }
2874 
2875 void SwDoc::SetTabRows( const SwTabCols &rNew, sal_Bool bCurColOnly, const SwCursor*,
2876                         const SwCellFrm* pBoxFrm )
2877 {
2878 	const SwTableBox* pBox;
2879 	SwTabFrm *pTab;
2880 
2881     ASSERT( pBoxFrm, "SetTabRows called without pBoxFrm" )
2882 
2883 	pTab = ((SwFrm*)pBoxFrm)->ImplFindTabFrm();
2884 	pBox = pBoxFrm->GetTabBox();
2885 
2886 	// sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2887 	// dann muss es jetzt auf absolute umgerechnet werden.
2888     SWRECTFN( pTab )
2889 	SwTabCols aOld( rNew.Count() );
2890 
2891     //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2892     const SwPageFrm* pPage = pTab->FindPageFrm();
2893 
2894     aOld.SetRight( (pTab->Prt().*fnRect->fnGetHeight)() );
2895     long nLeftMin;
2896     if ( bVert )
2897     {
2898         nLeftMin = pTab->GetPrtLeft() - pPage->Frm().Left();
2899         aOld.SetLeft    ( LONG_MAX );
2900         aOld.SetRightMax( aOld.GetRight() );
2901 
2902     }
2903     else
2904     {
2905         nLeftMin = pTab->GetPrtTop() - pPage->Frm().Top();
2906         aOld.SetLeft    ( 0 );
2907         aOld.SetRightMax( LONG_MAX );
2908     }
2909     aOld.SetLeftMin ( nLeftMin );
2910 
2911     GetTabRows( aOld, 0, pBoxFrm );
2912 
2913     GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_ATTR, NULL );
2914 
2915     // check for differences between aOld and rNew:
2916     const sal_uInt16 nCount = rNew.Count();
2917     const SwTable* pTable = pTab->GetTable();
2918     ASSERT( pTable, "My colleague told me, this couldn't happen" );
2919 
2920     for ( sal_uInt16 i = 0; i <= nCount; ++i )
2921     {
2922         const sal_uInt16 nIdxStt = bVert ? nCount - i : i - 1;
2923         const sal_uInt16 nIdxEnd = bVert ? nCount - i - 1 : i;
2924 
2925         const long nOldRowStart = i == 0  ? 0 : aOld[ nIdxStt ];
2926         const long nOldRowEnd =   i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ];
2927         const long nOldRowHeight = nOldRowEnd - nOldRowStart;
2928 
2929         const long nNewRowStart = i == 0  ? 0 : rNew[ nIdxStt ];
2930         const long nNewRowEnd =   i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ];
2931         const long nNewRowHeight = nNewRowEnd - nNewRowStart;
2932 
2933         const long nDiff = nNewRowHeight - nOldRowHeight;
2934         if ( abs( nDiff ) >= ROWFUZZY )
2935         {
2936             // For the old table model pTxtFrm and pLine will be set for every box.
2937             // For the new table model pTxtFrm will be set if the box is not covered,
2938             // but the pLine will be set if the box is not an overlapping box
2939             // In the new table model the row height can be adjusted,
2940             // when both variables are set.
2941             SwTxtFrm* pTxtFrm = 0;
2942             const SwTableLine* pLine = 0;
2943 
2944             // Iterate over all SwCellFrms with Bottom = nOldPos
2945             const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
2946             while ( pFrm && pTab->IsAnLower( pFrm ) )
2947             {
2948                 if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
2949                 {
2950                     const long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
2951                     const sal_uLong nTabTop = (pTab->*fnRect->fnGetPrtTop)();
2952                     if ( abs( (*fnRect->fnYInc)( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY )
2953                     {
2954                         if ( !bCurColOnly || pFrm == pBoxFrm )
2955                         {
2956                             const SwFrm* pCntnt = ::GetCellCntnt( static_cast<const SwCellFrm&>(*pFrm) );
2957 
2958                             if ( pCntnt && pCntnt->IsTxtFrm() )
2959                             {
2960                                 pBox = ((SwCellFrm*)pFrm)->GetTabBox();
2961                                 const long nRowSpan = pBox->getRowSpan();
2962                                 if( nRowSpan > 0 ) // Not overlapped
2963                                     pTxtFrm = (SwTxtFrm*)pCntnt;
2964                                 if( nRowSpan < 2 ) // Not overlapping for row height
2965                                     pLine = pBox->GetUpper();
2966                                 if( pLine && pTxtFrm ) // always for old table model
2967                                 {
2968                                     // The new row height must not to be calculated from a overlapping box
2969                                     SwFmtFrmSize aNew( pLine->GetFrmFmt()->GetFrmSize() );
2970                                     const long nNewSize = (pFrm->Frm().*fnRect->fnGetHeight)() + nDiff;
2971                                     if( nNewSize != aNew.GetHeight() )
2972                                     {
2973                                         aNew.SetHeight( nNewSize );
2974                                         if ( ATT_VAR_SIZE == aNew.GetHeightSizeType() )
2975                                             aNew.SetHeightSizeType( ATT_MIN_SIZE );
2976                                         // This position must not be in an overlapped box
2977                                         const SwPosition aPos( *((SwTxtFrm*)pCntnt)->GetTxtNode() );
2978                                         const SwCursor aTmpCrsr( aPos, 0, false );
2979                                         SetRowHeight( aTmpCrsr, aNew );
2980                                         // For the new table model we're done, for the old one
2981                                         // there might be another (sub)row to adjust...
2982                                         if( pTable->IsNewModel() )
2983                                             break;
2984                                     }
2985                                     pLine = 0;
2986                                 }
2987                             }
2988                         }
2989                     }
2990                 }
2991                 pFrm = pFrm->GetNextLayoutLeaf();
2992             }
2993         }
2994     }
2995 
2996     GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_ATTR, NULL );
2997 
2998 	::ClearFEShellTabCols();
2999 }
3000 
3001 /* -----------------18.07.98 11:45-------------------
3002  *  Direktzugriff fuer UNO
3003  * --------------------------------------------------*/
3004 void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld,
3005 								const SwTableBox *pStart, sal_Bool bCurRowOnly )
3006 {
3007     if (GetIDocumentUndoRedo().DoesUndo())
3008     {
3009         GetIDocumentUndoRedo().AppendUndo(
3010             new SwUndoAttrTbl( *rTab.GetTableNode(), sal_True ));
3011 	}
3012 	rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
3013   	::ClearFEShellTabCols();
3014 	SetModified();
3015 }
3016 
3017 void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet )
3018 {
3019     if( nSet == rTable.GetRowsToRepeat() )
3020         return;
3021 
3022     if (GetIDocumentUndoRedo().DoesUndo())
3023     {
3024         GetIDocumentUndoRedo().AppendUndo(
3025             new SwUndoTblHeadline(rTable, rTable.GetRowsToRepeat(), nSet) );
3026     }
3027 
3028     SwMsgPoolItem aChg( RES_TBLHEADLINECHG );
3029     rTable.SetRowsToRepeat( nSet );
3030     rTable.GetFrmFmt()->ModifyNotification( &aChg, &aChg );
3031     SetModified();
3032 }
3033 
3034 
3035 
3036 
3037 // Splittet eine Tabelle in der Grund-Zeile, in der der Index steht.
3038 // Alle GrundZeilen dahinter wandern in eine neue Tabelle/-Node.
3039 // Ist das Flag bCalcNewSize auf sal_True, wird fuer beide neuen Tabellen
3040 // die neue Size aus dem Max der Boxen errechnet; vorrausgesetzt,
3041 // die Size ist "absolut" gesetzt (USHRT_MAX)
3042 
3043 void SwCollectTblLineBoxes::AddToUndoHistory( const SwCntntNode& rNd )
3044 {
3045 	if( pHst )
3046 		pHst->Add( rNd.GetFmtColl(), rNd.GetIndex(), ND_TEXTNODE );
3047 }
3048 
3049 void SwCollectTblLineBoxes::AddBox( const SwTableBox& rBox )
3050 {
3051 	aPosArr.Insert( nWidth, aPosArr.Count() );
3052 	SwTableBox* p = (SwTableBox*)&rBox;
3053 	aBoxes.Insert( p, aBoxes.Count() );
3054 	nWidth = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
3055 }
3056 
3057 const SwTableBox* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox& rBox )
3058 {
3059 	const SwTableBox* pRet = 0;
3060 	sal_uInt16 n;
3061 
3062 	if( aPosArr.Count() )
3063 	{
3064 		for( n = 0; n < aPosArr.Count(); ++n )
3065 			if( aPosArr[ n ] == nWidth )
3066 				break;
3067 			else if( aPosArr[ n ] > nWidth )
3068 			{
3069 				if( n )
3070 					--n;
3071 				break;
3072 			}
3073 
3074 		if( n >= aPosArr.Count() )
3075 			--n;
3076 
3077 		nWidth = nWidth + (sal_uInt16)rBox.GetFrmFmt()->GetFrmSize().GetWidth();
3078 		pRet = aBoxes[ n ];
3079 	}
3080 	return pRet;
3081 }
3082 
3083 sal_Bool SwCollectTblLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth )
3084 {
3085 	sal_uInt16 n;
3086 
3087 	if( aPosArr.Count() )
3088 	{
3089 		for( n = 0; n < aPosArr.Count(); ++n )
3090 			if( aPosArr[ n ] == nOffset )
3091 				break;
3092 			else if( aPosArr[ n ] > nOffset )
3093 			{
3094 				if( n )
3095 					--n;
3096 				break;
3097 			}
3098 
3099 		aPosArr.Remove( 0, n );
3100 		aBoxes.Remove( 0, n );
3101 
3102 		// dann die Positionen der neuen Size anpassen
3103 		for( n = 0; n < aPosArr.Count(); ++n )
3104 		{
3105 			sal_uLong nSize = nWidth;
3106 			nSize *= ( aPosArr[ n ] - nOffset );
3107 			nSize /= nOldWidth;
3108 			aPosArr[ n ] = sal_uInt16( nSize );
3109 		}
3110 	}
3111 	return 0 != aPosArr.Count();
3112 }
3113 
3114 sal_Bool lcl_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
3115 {
3116 	SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
3117 	if( pSplPara->IsGetValues() )
3118 		((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_Box_CollectBox, pPara );
3119 	else
3120 		((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, pPara );
3121 	return sal_True;
3122 }
3123 
3124 sal_Bool lcl_Box_CollectBox( const SwTableBox*& rpBox, void* pPara )
3125 {
3126 	SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
3127 	sal_uInt16 nLen = rpBox->GetTabLines().Count();
3128 	if( nLen )
3129 	{
3130 		// dann mit der richtigen Line weitermachen
3131 		if( pSplPara->IsGetFromTop() )
3132 			nLen = 0;
3133 		else
3134 			--nLen;
3135 
3136 		const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
3137 		lcl_Line_CollectBox( pLn, pPara );
3138 	}
3139 	else
3140 		pSplPara->AddBox( *rpBox );
3141 	return sal_True;
3142 }
3143 
3144 sal_Bool lcl_BoxSetSplitBoxFmts( const SwTableBox*& rpBox, void* pPara )
3145 {
3146 	SwCollectTblLineBoxes* pSplPara = (SwCollectTblLineBoxes*)pPara;
3147 	sal_uInt16 nLen = rpBox->GetTabLines().Count();
3148 	if( nLen )
3149 	{
3150 		// dann mit der richtigen Line weitermachen
3151 		if( pSplPara->IsGetFromTop() )
3152 			nLen = 0;
3153 		else
3154 			--nLen;
3155 
3156 		const SwTableLine* pLn = rpBox->GetTabLines()[ nLen ];
3157 		lcl_Line_CollectBox( pLn, pPara );
3158 	}
3159 	else
3160 	{
3161 		const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *rpBox );
3162 		SwFrmFmt* pFmt = pSrcBox->GetFrmFmt();
3163 		SwTableBox* pBox = (SwTableBox*)rpBox;
3164 
3165 		if( HEADLINE_BORDERCOPY == pSplPara->GetMode() )
3166 		{
3167 			const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
3168 			if( !rBoxItem.GetTop() )
3169 			{
3170 				SvxBoxItem aNew( rBoxItem );
3171 				aNew.SetLine( pFmt->GetBox().GetBottom(), BOX_LINE_TOP );
3172 				if( aNew != rBoxItem )
3173                     pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
3174 			}
3175 		}
3176 		else
3177 		{
3178 sal_uInt16 __FAR_DATA aTableSplitBoxSetRange[] = {
3179 	RES_LR_SPACE, 		RES_UL_SPACE,
3180 	RES_BACKGROUND, 	RES_SHADOW,
3181 	RES_PROTECT, 		RES_PROTECT,
3182 	RES_VERT_ORIENT,	RES_VERT_ORIENT,
3183 	0 };
3184 			SfxItemSet aTmpSet( pFmt->GetDoc()->GetAttrPool(),
3185 								aTableSplitBoxSetRange );
3186 			aTmpSet.Put( pFmt->GetAttrSet() );
3187 			if( aTmpSet.Count() )
3188                 pBox->ClaimFrmFmt()->SetFmtAttr( aTmpSet );
3189 
3190 			if( HEADLINE_BOXATRCOLLCOPY == pSplPara->GetMode() )
3191 			{
3192 				SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
3193 				SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
3194 				if( !pCNd )
3195 					pCNd = aIdx.GetNodes().GoNext( &aIdx );
3196 				aIdx = *pBox->GetSttNd();
3197 				SwCntntNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );
3198 
3199 				// nur wenn der Node alleine in der Section steht
3200 				if( 2 == pDNd->EndOfSectionIndex() -
3201 						pDNd->StartOfSectionIndex() )
3202 				{
3203 					pSplPara->AddToUndoHistory( *pDNd );
3204 					pDNd->ChgFmtColl( pCNd->GetFmtColl() );
3205 				}
3206 			}
3207 
3208 			// bedingte Vorlage beachten
3209 			pBox->GetSttNd()->CheckSectionCondColl();
3210 		}
3211 	}
3212 	return sal_True;
3213 }
3214 
3215 
3216 sal_Bool SwDoc::SplitTable( const SwPosition& rPos, sal_uInt16 eHdlnMode,
3217 						sal_Bool bCalcNewSize )
3218 {
3219 	SwNode* pNd = &rPos.nNode.GetNode();
3220 	SwTableNode* pTNd = pNd->FindTableNode();
3221 	if( !pTNd || pNd->IsTableNode() )
3222 		return 0;
3223 
3224 	if( pTNd->GetTable().ISA( SwDDETable ))
3225 		return sal_False;
3226 
3227 	SwTable& rTbl = pTNd->GetTable();
3228 	rTbl.SetHTMLTableLayout( 0 ); 	// MIB 9.7.97: HTML-Layout loeschen
3229 
3230 	SwTableFmlUpdate aMsgHnt( &rTbl );
3231 
3232 	SwHistory aHistory;
3233     if (GetIDocumentUndoRedo().DoesUndo())
3234     {
3235 		aMsgHnt.pHistory = &aHistory;
3236     }
3237 
3238 	{
3239 		sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3240 
3241 		// Suche die Grund-Line dieser Box:
3242 		SwTableBox* pBox = rTbl.GetTblBox( nSttIdx );
3243 		if( pBox )
3244 		{
3245 			SwTableLine* pLine = pBox->GetUpper();
3246 			while( pLine->GetUpper() )
3247 				pLine = pLine->GetUpper()->GetUpper();
3248 
3249 			// in pLine steht jetzt die GrundLine.
3250 			aMsgHnt.nSplitLine = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
3251 		}
3252 
3253 		String sNewTblNm( GetUniqueTblName() );
3254 		aMsgHnt.DATA.pNewTblNm = &sNewTblNm;
3255 		aMsgHnt.eFlags = TBL_SPLITTBL;
3256 		UpdateTblFlds( &aMsgHnt );
3257 	}
3258 
3259 	//Lines fuer das Layout-Update heraussuchen.
3260 	_FndBox aFndBox( 0, 0 );
3261     aFndBox.SetTableLines( rTbl );
3262     aFndBox.DelFrms( rTbl );
3263 
3264     // TL_CHART2: need to inform chart of probably changed cell names
3265     //pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3266 
3267 	SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, sal_False, bCalcNewSize );
3268 
3269 	if( pNew )
3270 	{
3271         SwSaveRowSpan* pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTbl.GetTabLines().Count() );
3272 		SwUndoSplitTbl* pUndo = 0;
3273         if (GetIDocumentUndoRedo().DoesUndo())
3274         {
3275             pUndo = new SwUndoSplitTbl(
3276                         *pNew, pSaveRowSp, eHdlnMode, bCalcNewSize);
3277             GetIDocumentUndoRedo().AppendUndo(pUndo);
3278 			if( aHistory.Count() )
3279 				pUndo->SaveFormula( aHistory );
3280 		}
3281 
3282 		switch( eHdlnMode )
3283 		{
3284 			// setze die untere Border der vorherige Line,
3285 			// an der aktuellen als obere
3286 		case HEADLINE_BORDERCOPY:
3287 			{
3288 				SwCollectTblLineBoxes aPara( sal_False, eHdlnMode );
3289 				SwTableLine* pLn = rTbl.GetTabLines()[
3290 							rTbl.GetTabLines().Count() - 1 ];
3291 				pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara );
3292 
3293 				aPara.SetValues( sal_True );
3294 				pLn = pNew->GetTable().GetTabLines()[ 0 ];
3295 				pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara );
3296 
3297 				// Kopfzeile wiederholen abschalten
3298                 pNew->GetTable().SetRowsToRepeat( 0 );
3299 			}
3300 			break;
3301 
3302 			// setze die Attributierung der ersten Line an der neuen ersten
3303 		case HEADLINE_BOXATTRCOPY:
3304 		case HEADLINE_BOXATRCOLLCOPY:
3305 			{
3306 				SwHistory* pHst = 0;
3307 				if( HEADLINE_BOXATRCOLLCOPY == eHdlnMode && pUndo )
3308 					pHst = pUndo->GetHistory();
3309 
3310 				SwCollectTblLineBoxes aPara( sal_True, eHdlnMode, pHst );
3311 				SwTableLine* pLn = rTbl.GetTabLines()[ 0 ];
3312 				pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aPara );
3313 
3314 				aPara.SetValues( sal_True );
3315 				pLn = pNew->GetTable().GetTabLines()[ 0 ];
3316 				pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aPara );
3317 			}
3318 			break;
3319 
3320 		case HEADLINE_CNTNTCOPY:
3321 			rTbl.CopyHeadlineIntoTable( *pNew );
3322 			if( pUndo )
3323 				pUndo->SetTblNodeOffset( pNew->GetIndex() );
3324 			break;
3325 
3326 		case HEADLINE_NONE:
3327 			// Kopfzeile wiederholen abschalten
3328             pNew->GetTable().SetRowsToRepeat( 0 );
3329 			break;
3330 		}
3331 
3332 		// und Frms einfuegen.
3333 		SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() );
3334 		GetNodes().GoNext( &aNdIdx );      // zum naechsten ContentNode
3335 		pNew->MakeFrms( &aNdIdx );
3336 
3337 		//Zwischen die Tabellen wird ein Absatz geschoben
3338 		GetNodes().MakeTxtNode( SwNodeIndex( *pNew ),
3339 								GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
3340 	}
3341 
3342 	//Layout updaten
3343     aFndBox.MakeFrms( rTbl );
3344 
3345     // TL_CHART2: need to inform chart of probably changed cell names
3346     UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3347 
3348     SetFieldsDirty( true, NULL, 0 );
3349 
3350 	return 0 != pNew;
3351 }
3352 
3353 sal_Bool lcl_ChgTblSize( SwTable& rTbl )
3354 {
3355 	// das Attribut darf nicht ueber das Modify an der
3356 	// Tabelle gesetzt werden, denn sonst werden alle
3357 	// Boxen wieder auf 0 zurueck gesetzt. Also locke das Format
3358 	SwFrmFmt* pFmt = rTbl.GetFrmFmt();
3359 	SwFmtFrmSize aTblMaxSz( pFmt->GetFrmSize() );
3360 
3361 	if( USHRT_MAX == aTblMaxSz.GetWidth() )
3362 		return sal_False;
3363 
3364 	sal_Bool bLocked = pFmt->IsModifyLocked();
3365 	pFmt->LockModify();
3366 
3367 	aTblMaxSz.SetWidth( 0 );
3368 
3369 	SwTableLines& rLns = rTbl.GetTabLines();
3370 	for( sal_uInt16 nLns = 0; nLns < rLns.Count(); ++nLns )
3371 	{
3372 		SwTwips nMaxLnWidth = 0;
3373 		SwTableBoxes& rBoxes = rLns[ nLns ]->GetTabBoxes();
3374 		for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
3375 			nMaxLnWidth += rBoxes[nBox]->GetFrmFmt()->GetFrmSize().GetWidth();
3376 
3377 		if( nMaxLnWidth > aTblMaxSz.GetWidth() )
3378 			aTblMaxSz.SetWidth( nMaxLnWidth );
3379 	}
3380     pFmt->SetFmtAttr( aTblMaxSz );
3381 	if( !bLocked )			// und gegebenenfalls Lock wieder freigeben
3382 		pFmt->UnlockModify();
3383 
3384 	return sal_True;
3385 }
3386 
3387 class _SplitTable_Para
3388 {
3389 	SvPtrarr aSrc, aDest;
3390 	SwTableNode* pNewTblNd;
3391 	SwTable& rOldTbl;
3392 
3393 public:
3394 	_SplitTable_Para( SwTableNode* pNew, SwTable& rOld )
3395 		: aSrc( 16, 16 ), aDest( 16, 16 ), pNewTblNd( pNew ), rOldTbl( rOld )
3396 	{}
3397 	sal_uInt16 SrcFmt_GetPos( void* pFmt ) const
3398 			{ return aSrc.GetPos( pFmt ); }
3399 
3400 	void DestFmt_Insert( void* pFmt )
3401 			{ aDest.Insert( pFmt, aDest.Count() ); }
3402 
3403 	void SrcFmt_Insert( void* pFmt )
3404 			{ aSrc.Insert( pFmt, aSrc.Count() ); }
3405 
3406 	SwFrmFmt* DestFmt_Get( sal_uInt16 nPos ) const
3407 			{ return (SwFrmFmt*)aDest[ nPos ]; }
3408 
3409 	void ChgBox( SwTableBox* pBox )
3410 	{
3411 		rOldTbl.GetTabSortBoxes().Remove( pBox );
3412 		pNewTblNd->GetTable().GetTabSortBoxes().Insert( pBox );
3413 	}
3414 };
3415 
3416 
3417 sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara );
3418 
3419 sal_Bool lcl_SplitTable_CpyLine( const SwTableLine*& rpLine, void* pPara )
3420 {
3421 	SwTableLine* pLn = (SwTableLine*)rpLine;
3422 	_SplitTable_Para& rPara = *(_SplitTable_Para*)pPara;
3423 
3424 	SwFrmFmt *pSrcFmt = pLn->GetFrmFmt();
3425 	sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt );
3426 	if( USHRT_MAX == nPos )
3427 	{
3428 		rPara.DestFmt_Insert( pLn->ClaimFrmFmt() );
3429 		rPara.SrcFmt_Insert( pSrcFmt );
3430 	}
3431 	else
3432 		pLn->ChgFrmFmt( (SwTableLineFmt*)rPara.DestFmt_Get( nPos ) );
3433 
3434 	pLn->GetTabBoxes().ForEach( &lcl_SplitTable_CpyBox, pPara );
3435 	return sal_True;
3436 }
3437 
3438 sal_Bool lcl_SplitTable_CpyBox( const SwTableBox*& rpBox, void* pPara )
3439 {
3440 	SwTableBox* pBox = (SwTableBox*)rpBox;
3441 	_SplitTable_Para& rPara = *(_SplitTable_Para*)pPara;
3442 
3443 	SwFrmFmt *pSrcFmt = pBox->GetFrmFmt();
3444 	sal_uInt16 nPos = rPara.SrcFmt_GetPos( pSrcFmt );
3445 	if( USHRT_MAX == nPos )
3446 	{
3447 		rPara.DestFmt_Insert( pBox->ClaimFrmFmt() );
3448 		rPara.SrcFmt_Insert( pSrcFmt );
3449 	}
3450 	else
3451 		pBox->ChgFrmFmt( (SwTableBoxFmt*)rPara.DestFmt_Get( nPos ) );
3452 
3453 	if( pBox->GetSttNd() )
3454 		rPara.ChgBox( pBox );
3455 	else
3456 		pBox->GetTabLines().ForEach( &lcl_SplitTable_CpyLine, pPara );
3457 	return sal_True;
3458 }
3459 
3460 SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, sal_Bool bAfter,
3461 									sal_Bool bCalcNewSize )
3462 {
3463 	SwNode* pNd = &rPos.GetNode();
3464 	SwTableNode* pTNd = pNd->FindTableNode();
3465 	if( !pTNd || pNd->IsTableNode() )
3466 		return 0;
3467 
3468 	sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3469 
3470 	// Suche die Grund-Line dieser Box:
3471 	SwTable& rTbl = pTNd->GetTable();
3472 	SwTableBox* pBox = rTbl.GetTblBox( nSttIdx );
3473 	if( !pBox )
3474 		return 0;
3475 
3476 	SwTableLine* pLine = pBox->GetUpper();
3477 	while( pLine->GetUpper() )
3478 		pLine = pLine->GetUpper()->GetUpper();
3479 
3480 	// in pLine steht jetzt die GrundLine.
3481 	sal_uInt16 nLinePos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
3482 	if( USHRT_MAX == nLinePos ||
3483 		( bAfter ? ++nLinePos >= rTbl.GetTabLines().Count() : !nLinePos ))
3484 		return 0;		// nicht gefunden oder letze Line !!
3485 
3486 	// Suche jetzt die 1. Box der nachfolgenden Line
3487 	SwTableLine* pNextLine = rTbl.GetTabLines()[ nLinePos ];
3488 	pBox = pNextLine->GetTabBoxes()[0];
3489 	while( !pBox->GetSttNd() )
3490 		pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
3491 
3492 	// dann fuege mal einen End- und TabelleNode ins Nodes-Array ein.
3493 	SwTableNode * pNewTblNd;
3494 	{
3495 		SwEndNode* pOldTblEndNd = (SwEndNode*)pTNd->EndOfSectionNode()->GetEndNode();
3496 		ASSERT( pOldTblEndNd, "wo ist der EndNode?" )
3497 
3498 		SwNodeIndex aIdx( *pBox->GetSttNd() );
3499 		new SwEndNode( aIdx, *pTNd );
3500 		pNewTblNd = new SwTableNode( aIdx );
3501         pNewTblNd->GetTable().SetTableModel( rTbl.IsNewModel() );
3502 
3503 		pOldTblEndNd->pStartOfSection = pNewTblNd;
3504 		pNewTblNd->pEndOfSection = pOldTblEndNd;
3505 
3506 		SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3507 		do {
3508 			ASSERT( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" );
3509 			pBoxNd->pStartOfSection = pNewTblNd;
3510 			pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3511 		} while( pBoxNd != pOldTblEndNd );
3512 	}
3513 
3514 	{
3515         // die Lines ruebermoven...
3516 		SwTable& rNewTbl = pNewTblNd->GetTable();
3517 		rNewTbl.GetTabLines().Insert( &rTbl.GetTabLines(), 0, nLinePos );
3518         //
3519         // von hinten (unten-rechts) nach vorn (oben-links) alle Boxen
3520         // beim chart data provider austragen (das modified event wird dann
3521         // in der aufrufenden Funktion getriggert.
3522         // TL_CHART2:
3523         SwChartDataProvider *pPCD = rTbl.GetFrmFmt()->getIDocumentChartDataProviderAccess()->GetChartDataProvider();
3524         if( pPCD )
3525         {
3526             for (sal_uInt16 k = nLinePos;  k < rTbl.GetTabLines().Count();  ++k)
3527             {
3528                 sal_uInt16 nLineIdx = (rTbl.GetTabLines().Count() - 1) - k + nLinePos;
3529                 sal_uInt16 nBoxCnt = rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes().Count();
3530                 for (sal_uInt16 j = 0;  j < nBoxCnt;  ++j)
3531                 {
3532                     sal_uInt16 nIdx = nBoxCnt - 1 - j;
3533                     pPCD->DeleteBox( &rTbl, *rTbl.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] );
3534                 }
3535             }
3536         }
3537         //
3538         // ...und loeschen
3539         sal_uInt16 nDeleted = rTbl.GetTabLines().Count() - nLinePos;
3540 		rTbl.GetTabLines().Remove( nLinePos, nDeleted );
3541 
3542 		// und die betr. Boxen verschieben. Dabei die Formate eindeutig
3543 		// machen und die StartNodes korrigieren
3544 		_SplitTable_Para aPara( pNewTblNd, rTbl );
3545 		rNewTbl.GetTabLines().ForEach( &lcl_SplitTable_CpyLine, &aPara );
3546         rTbl.CleanUpBottomRowSpan( nDeleted );
3547 	}
3548 
3549 	{
3550 		// Das Tabellen-FrmFormat kopieren
3551 		SwFrmFmt* pOldTblFmt = rTbl.GetFrmFmt();
3552 		SwFrmFmt* pNewTblFmt = pOldTblFmt->GetDoc()->MakeTblFrmFmt(
3553 								pOldTblFmt->GetDoc()->GetUniqueTblName(),
3554 								pOldTblFmt->GetDoc()->GetDfltFrmFmt() );
3555 
3556 		*pNewTblFmt = *pOldTblFmt;
3557         pNewTblNd->GetTable().RegisterToFormat( *pNewTblFmt );
3558 
3559 		// neue Size errechnen ? (lcl_ChgTblSize nur das 2. aufrufen, wenn es
3560 		// beim 1. schon geklappt hat; also absolute Groesse hat)
3561 		if( bCalcNewSize && lcl_ChgTblSize( rTbl ) )
3562 			lcl_ChgTblSize( pNewTblNd->GetTable() );
3563 	}
3564 
3565     // TL_CHART2: need to inform chart of probably changed cell names
3566     rTbl.UpdateCharts();
3567 
3568 	return pNewTblNd;		// das wars
3569 }
3570 
3571 // und die Umkehrung davon. rPos muss in der Tabelle stehen, die bestehen
3572 // bleibt. Das Flag besagt ob die aktuelle mit der davor oder dahinter
3573 // stehenden vereint wird.
3574 sal_Bool SwDoc::MergeTable( const SwPosition& rPos, sal_Bool bWithPrev, sal_uInt16 nMode )
3575 {
3576 	SwTableNode* pTblNd = rPos.nNode.GetNode().FindTableNode(), *pDelTblNd;
3577 	if( !pTblNd )
3578 		return sal_False;
3579 
3580 	SwNodes& rNds = GetNodes();
3581 	if( bWithPrev )
3582 		pDelTblNd = rNds[ pTblNd->GetIndex() - 1 ]->FindTableNode();
3583 	else
3584 		pDelTblNd = rNds[ pTblNd->EndOfSectionIndex() + 1 ]->GetTableNode();
3585 	if( !pDelTblNd )
3586 		return sal_False;
3587 
3588 	if( pTblNd->GetTable().ISA( SwDDETable ) ||
3589 		pDelTblNd->GetTable().ISA( SwDDETable ))
3590 		return sal_False;
3591 
3592 	// MIB 9.7.97: HTML-Layout loeschen
3593 	pTblNd->GetTable().SetHTMLTableLayout( 0 );
3594 	pDelTblNd->GetTable().SetHTMLTableLayout( 0 );
3595 
3596 	// beide Tabellen vorhanden, also kanns losgehen
3597 	SwUndoMergeTbl* pUndo = 0;
3598 	SwHistory* pHistory = 0;
3599     if (GetIDocumentUndoRedo().DoesUndo())
3600     {
3601         pUndo = new SwUndoMergeTbl( *pTblNd, *pDelTblNd, bWithPrev, nMode );
3602         GetIDocumentUndoRedo().AppendUndo(pUndo);
3603 		pHistory = new SwHistory;
3604 	}
3605 
3606 	// alle "Tabellenformeln" anpassen
3607 	SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
3608 	aMsgHnt.DATA.pDelTbl = &pDelTblNd->GetTable();
3609 	aMsgHnt.eFlags = TBL_MERGETBL;
3610 	aMsgHnt.pHistory = pHistory;
3611 	UpdateTblFlds( &aMsgHnt );
3612 
3613 	// das eigentliche Mergen
3614 	SwNodeIndex aIdx( bWithPrev ? *pTblNd : *pDelTblNd );
3615 	sal_Bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode, pHistory );
3616 
3617 	if( pHistory )
3618 	{
3619 		if( pHistory->Count() )
3620 			pUndo->SaveFormula( *pHistory );
3621 		delete pHistory;
3622 	}
3623 	if( bRet )
3624 	{
3625 		SetModified();
3626 		SetFieldsDirty( true, NULL, 0 );
3627 	}
3628 	return bRet;
3629 }
3630 
3631 sal_Bool SwNodes::MergeTable( const SwNodeIndex& rPos, sal_Bool bWithPrev,
3632 							sal_uInt16 nMode, SwHistory* )
3633 {
3634 	SwTableNode* pDelTblNd = rPos.GetNode().GetTableNode();
3635 	ASSERT( pDelTblNd, "wo ist der TableNode geblieben?" );
3636 
3637 	SwTableNode* pTblNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode();
3638 	ASSERT( pTblNd, "wo ist der TableNode geblieben?" );
3639 
3640 	if( !pDelTblNd || !pTblNd )
3641 		return sal_False;
3642 
3643 	pDelTblNd->DelFrms();
3644 
3645 	SwTable& rDelTbl = pDelTblNd->GetTable();
3646 	SwTable& rTbl = pTblNd->GetTable();
3647 
3648 	//Lines fuer das Layout-Update herausuchen.
3649 	_FndBox aFndBox( 0, 0 );
3650     aFndBox.SetTableLines( rTbl );
3651     aFndBox.DelFrms( rTbl );
3652 
3653     // TL_CHART2: since chart currently does not want to get informed about
3654     // additional rows/cols there is no need for a modified event in the
3655     // remaining first table. Also, if it is required it  should be done
3656     // after the merging and not here...
3657     // pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3658 
3659 
3660     // TL_CHART2:
3661     // tell the charts about the table to be deleted and have them use their own data
3662     GetDoc()->CreateChartInternalDataProviders( &rDelTbl );
3663 
3664 	// die Breite der TabellenFormate abgleichen:
3665 	{
3666 		const SwFmtFrmSize& rTblSz = rTbl.GetFrmFmt()->GetFrmSize();
3667 		const SwFmtFrmSize& rDelTblSz = rDelTbl.GetFrmFmt()->GetFrmSize();
3668 		if( rTblSz != rDelTblSz )
3669 		{
3670 			// dann sollten die mal schleunigst korrigiert werden
3671 			if( bWithPrev )
3672                 rDelTbl.GetFrmFmt()->SetFmtAttr( rTblSz );
3673 			else
3674                 rTbl.GetFrmFmt()->SetFmtAttr( rDelTblSz );
3675 		}
3676 	}
3677 
3678 	if( !bWithPrev )
3679 	{
3680 		// dann mussen alle Attruibute der hinteren Tabelle auf die
3681 		// vordere uebertragen werden, weil die hintere ueber das loeschen
3682 		// des Node geloescht wird.
3683         rTbl.SetRowsToRepeat( rDelTbl.GetRowsToRepeat() );
3684 		rTbl.SetTblChgMode( rDelTbl.GetTblChgMode() );
3685 
3686 		rTbl.GetFrmFmt()->LockModify();
3687 		*rTbl.GetFrmFmt() = *rDelTbl.GetFrmFmt();
3688 		// auch den Namen umsetzen!
3689 		rTbl.GetFrmFmt()->SetName( rDelTbl.GetFrmFmt()->GetName() );
3690 		rTbl.GetFrmFmt()->UnlockModify();
3691 	}
3692 
3693 	// die Lines und Boxen ruebermoven
3694 	sal_uInt16 nOldSize = rTbl.GetTabLines().Count();
3695 	rTbl.GetTabLines().Insert( &rDelTbl.GetTabLines(), nOldSize );
3696 	rDelTbl.GetTabLines().Remove( 0, rDelTbl.GetTabLines().Count() );
3697 
3698 	rTbl.GetTabSortBoxes().Insert( &rDelTbl.GetTabSortBoxes() );
3699 	rDelTbl.GetTabSortBoxes().Remove( (sal_uInt16)0, rDelTbl.GetTabSortBoxes().Count() );
3700 
3701 	// die vordere Tabelle bleibt immer stehen, die hintere wird geloescht
3702 	SwEndNode* pTblEndNd = pDelTblNd->EndOfSectionNode();
3703 	pTblNd->pEndOfSection = pTblEndNd;
3704 
3705 	SwNodeIndex aIdx( *pDelTblNd, 1 );
3706 
3707 	SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3708 	do {
3709 		ASSERT( pBoxNd->IsStartNode(), "das muss ein StartNode sein!" );
3710 		pBoxNd->pStartOfSection = pTblNd;
3711 		pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3712 	} while( pBoxNd != pTblEndNd );
3713 	pBoxNd->pStartOfSection = pTblNd;
3714 
3715 	aIdx -= 2;
3716 	DelNodes( aIdx, 2 );
3717 
3718 	// jetzt an der 1. eingefuegten Line die bedingten Vorlagen umschubsen
3719 	const SwTableLine* pFirstLn = rTbl.GetTabLines()[ nOldSize ];
3720 	if( 1 == nMode )		//
3721 	{
3722 		// Header-Vorlagen in der Zeile setzen
3723 		// und ggfs. in der History speichern fuers Undo!!!
3724 	}
3725 	lcl_LineSetHeadCondColl( pFirstLn, 0 );
3726 
3727 	// und die Borders "aufrauemen"
3728 	if( nOldSize )
3729 	{
3730 		_SwGCLineBorder aPara( rTbl );
3731 		aPara.nLinePos = --nOldSize;
3732 		pFirstLn = rTbl.GetTabLines()[ nOldSize ];
3733 		lcl_GC_Line_Border( pFirstLn, &aPara );
3734 	}
3735 
3736 	//Layout updaten
3737     aFndBox.MakeFrms( rTbl );
3738 
3739     return sal_True;
3740 }
3741 
3742 // -------------------------------------------------------------------
3743 
3744 
3745 // -- benutze die ForEach Methode vom PtrArray
3746 struct _SetAFmtTabPara
3747 {
3748 	SwTableAutoFmt& rTblFmt;
3749 	SwUndoTblAutoFmt* pUndo;
3750 	sal_uInt16 nEndBox, nCurBox;
3751 	sal_uInt8 nAFmtLine, nAFmtBox;
3752 
3753 	_SetAFmtTabPara( const SwTableAutoFmt& rNew )
3754 		: rTblFmt( (SwTableAutoFmt&)rNew ), pUndo( 0 ),
3755 		nEndBox( 0 ), nCurBox( 0 ), nAFmtLine( 0 ), nAFmtBox( 0 )
3756 	{}
3757 };
3758 
3759 // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
3760 // koennen.
3761 sal_Bool lcl_SetAFmtBox( const _FndBox*&, void *pPara );
3762 sal_Bool lcl_SetAFmtLine( const _FndLine*&, void *pPara );
3763 
3764 sal_Bool lcl_SetAFmtLine( const _FndLine*& rpLine, void *pPara )
3765 {
3766 	((_FndLine*&)rpLine)->GetBoxes().ForEach( &lcl_SetAFmtBox, pPara );
3767 	return sal_True;
3768 }
3769 
3770 sal_Bool lcl_SetAFmtBox( const _FndBox*& rpBox, void *pPara )
3771 {
3772 	_SetAFmtTabPara* pSetPara = (_SetAFmtTabPara*)pPara;
3773 
3774 	if( !rpBox->GetUpper()->GetUpper() )	// Box auf 1. Ebene ?
3775 	{
3776 		if( !pSetPara->nCurBox )
3777 			pSetPara->nAFmtBox = 0;
3778 		else if( pSetPara->nCurBox == pSetPara->nEndBox )
3779 			pSetPara->nAFmtBox = 3;
3780 		else
3781 			pSetPara->nAFmtBox = (sal_uInt8)(1 + ((pSetPara->nCurBox-1) & 1));
3782 	}
3783 
3784 	if( rpBox->GetBox()->GetSttNd() )
3785 	{
3786 		SwTableBox* pSetBox = (SwTableBox*)rpBox->GetBox();
3787 		SwDoc* pDoc = pSetBox->GetFrmFmt()->GetDoc();
3788         // --> OD 2008-02-25 #refactorlists#
3789 //        SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
3790         SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
3791         // <--
3792 		SfxItemSet aBoxSet( pDoc->GetAttrPool(), aTableBoxSetRange );
3793 		sal_uInt8 nPos = pSetPara->nAFmtLine * 4 + pSetPara->nAFmtBox;
3794 		pSetPara->rTblFmt.UpdateToSet( nPos, aCharSet,
3795 										SwTableAutoFmt::UPDATE_CHAR, 0 );
3796 		pSetPara->rTblFmt.UpdateToSet( nPos, aBoxSet,
3797 										SwTableAutoFmt::UPDATE_BOX,
3798 										pDoc->GetNumberFormatter( sal_True ) );
3799 		if( aCharSet.Count() )
3800 		{
3801 			sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
3802 			sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
3803 			for( ; nSttNd < nEndNd; ++nSttNd )
3804 			{
3805 				SwCntntNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetCntntNode();
3806 				if( pNd )
3807 					pNd->SetAttr( aCharSet );
3808 			}
3809 		}
3810 
3811 		if( aBoxSet.Count() )
3812 		{
3813 			if( pSetPara->pUndo &&
3814 				SFX_ITEM_SET == aBoxSet.GetItemState( RES_BOXATR_FORMAT ))
3815 				pSetPara->pUndo->SaveBoxCntnt( *pSetBox );
3816 
3817             pSetBox->ClaimFrmFmt()->SetFmtAttr( aBoxSet );
3818 		}
3819 	}
3820 	else
3821 		((_FndBox*&)rpBox)->GetLines().ForEach( &lcl_SetAFmtLine, pPara );
3822 
3823 	if( !rpBox->GetUpper()->GetUpper() )		// eine BaseLine
3824 		++pSetPara->nCurBox;
3825 	return sal_True;
3826 }
3827 
3828 
3829 		// AutoFormat fuer die Tabelle/TabellenSelection
3830 sal_Bool SwDoc::SetTableAutoFmt( const SwSelBoxes& rBoxes, const SwTableAutoFmt& rNew )
3831 {
3832 	ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
3833 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
3834 	if( !pTblNd )
3835 		return sal_False;
3836 
3837 	// suche alle Boxen / Lines
3838 	_FndBox aFndBox( 0, 0 );
3839 	{
3840 		_FndPara aPara( rBoxes, &aFndBox );
3841 		pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
3842 	}
3843 	if( !aFndBox.GetLines().Count() )
3844 		return sal_False;
3845 
3846 	pTblNd->GetTable().SetHTMLTableLayout( 0 );
3847 
3848 	_FndBox* pFndBox = &aFndBox;
3849 	while( 1 == pFndBox->GetLines().Count() &&
3850 			1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
3851 		pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
3852 
3853 	if( !pFndBox->GetLines().Count() )		// eine zu weit? (nur 1 sel.Box)
3854 		pFndBox = pFndBox->GetUpper()->GetUpper();
3855 
3856 
3857 	// Undo abschalten, Attribute werden sich vorher gemerkt
3858 	SwUndoTblAutoFmt* pUndo = 0;
3859     bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3860     if (bUndo)
3861     {
3862         pUndo = new SwUndoTblAutoFmt( *pTblNd, rNew );
3863         GetIDocumentUndoRedo().AppendUndo(pUndo);
3864         GetIDocumentUndoRedo().DoUndo(false);
3865     }
3866 
3867 	_SetAFmtTabPara aPara( rNew );
3868 	_FndLines& rFLns = pFndBox->GetLines();
3869 	_FndLine* pLine;
3870 
3871 	for( sal_uInt16 n = 0; n < rFLns.Count(); ++n )
3872 	{
3873 		pLine = rFLns[n];
3874 
3875 		// Upper auf 0 setzen (Base-Line simulieren!)
3876 		_FndBox* pSaveBox = pLine->GetUpper();
3877 		pLine->SetUpper( 0 );
3878 
3879 		if( !n )
3880 			aPara.nAFmtLine = 0;
3881 		else if( n+1 == rFLns.Count() )
3882 			aPara.nAFmtLine = 3;
3883 		else
3884 			aPara.nAFmtLine = (sal_uInt8)(1 + ((n-1) & 1 ));
3885 
3886 		aPara.nAFmtBox = 0;
3887 		aPara.nCurBox = 0;
3888 		aPara.nEndBox = pLine->GetBoxes().Count()-1;
3889 		aPara.pUndo = pUndo;
3890 		pLine->GetBoxes().ForEach( &lcl_SetAFmtBox, &aPara );
3891 
3892 		pLine->SetUpper( pSaveBox );
3893 	}
3894 
3895 	if( pUndo )
3896     {
3897         GetIDocumentUndoRedo().DoUndo(bUndo);
3898     }
3899 
3900 	SetModified();
3901 	SetFieldsDirty( true, NULL, 0 );
3902 
3903 	return sal_True;
3904 }
3905 
3906 
3907 		// Erfrage wie attributiert ist
3908 sal_Bool SwDoc::GetTableAutoFmt( const SwSelBoxes& rBoxes, SwTableAutoFmt& rGet )
3909 {
3910 	ASSERT( rBoxes.Count(), "keine gueltige Box-Liste" );
3911 	SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
3912 	if( !pTblNd )
3913 		return sal_False;
3914 
3915 	// suche alle Boxen / Lines
3916 	_FndBox aFndBox( 0, 0 );
3917 	{
3918 		_FndPara aPara( rBoxes, &aFndBox );
3919 		pTblNd->GetTable().GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
3920 	}
3921 	if( !aFndBox.GetLines().Count() )
3922 		return sal_False;
3923 
3924 	_FndBox* pFndBox = &aFndBox;
3925 	while( 1 == pFndBox->GetLines().Count() &&
3926 			1 == pFndBox->GetLines()[0]->GetBoxes().Count() )
3927 		pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0];
3928 
3929 	if( !pFndBox->GetLines().Count() )		// eine zu weit? (nur 1 sel.Box)
3930 		pFndBox = pFndBox->GetUpper()->GetUpper();
3931 
3932 	_FndLines& rFLns = pFndBox->GetLines();
3933 
3934 	sal_uInt16 aLnArr[4];
3935 	aLnArr[0] = 0;
3936 	aLnArr[1] = 1 < rFLns.Count() ? 1 : 0;
3937 	aLnArr[2] = 2 < rFLns.Count() ? 2 : aLnArr[1];
3938 	aLnArr[3] = rFLns.Count() - 1;
3939 
3940 	for( sal_uInt8 nLine = 0; nLine < 4; ++nLine )
3941 	{
3942 		_FndLine& rLine = *rFLns[ aLnArr[ nLine ] ];
3943 
3944 		sal_uInt16 aBoxArr[4];
3945 		aBoxArr[0] = 0;
3946 		aBoxArr[1] = 1 < rLine.GetBoxes().Count() ? 1 : 0;
3947 		aBoxArr[2] = 2 < rLine.GetBoxes().Count() ? 2 : aBoxArr[1];
3948 		aBoxArr[3] = rLine.GetBoxes().Count() - 1;
3949 
3950 		for( sal_uInt8 nBox = 0; nBox < 4; ++nBox )
3951 		{
3952 			SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ]->GetBox();
3953 			// immer auf die 1. runterfallen
3954 			while( !pFBox->GetSttNd() )
3955 				pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0];
3956 
3957 			sal_uInt8 nPos = nLine * 4 + nBox;
3958 			SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 );
3959 			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
3960 			if( !pCNd )
3961 				pCNd = GetNodes().GoNext( &aIdx );
3962 
3963 			if( pCNd )
3964 				rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(),
3965 									SwTableAutoFmt::UPDATE_CHAR, 0 );
3966 			rGet.UpdateFromSet( nPos, pFBox->GetFrmFmt()->GetAttrSet(),
3967 								SwTableAutoFmt::UPDATE_BOX,
3968 								GetNumberFormatter( sal_True ) );
3969 		}
3970 	}
3971 
3972 	return sal_True;
3973 }
3974 
3975 String SwDoc::GetUniqueTblName() const
3976 {
3977 	ResId aId( STR_TABLE_DEFNAME, *pSwResMgr );
3978 	String aName( aId );
3979 	xub_StrLen nNmLen = aName.Len();
3980 
3981 	sal_uInt16 nNum, nTmp, nFlagSize = ( pTblFrmFmtTbl->Count() / 8 ) +2;
3982 	sal_uInt16 n;
3983 
3984 	sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
3985 	memset( pSetFlags, 0, nFlagSize );
3986 
3987 	for( n = 0; n < pTblFrmFmtTbl->Count(); ++n )
3988 	{
3989 		const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
3990 		if( !pFmt->IsDefault() && IsUsed( *pFmt )  &&
3991 			pFmt->GetName().Match( aName ) == nNmLen )
3992 		{
3993 			// Nummer bestimmen und das Flag setzen
3994 			nNum = static_cast<sal_uInt16>(pFmt->GetName().Copy( nNmLen ).ToInt32());
3995 			if( nNum-- && nNum < pTblFrmFmtTbl->Count() )
3996 				pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
3997 		}
3998 	}
3999 
4000 	// alle Nummern entsprechend geflag, also bestimme die richtige Nummer
4001 	nNum = pTblFrmFmtTbl->Count();
4002 	for( n = 0; n < nFlagSize; ++n )
4003 		if( 0xff != ( nTmp = pSetFlags[ n ] ))
4004 		{
4005 			// also die Nummer bestimmen
4006 			nNum = n * 8;
4007 			while( nTmp & 1 )
4008 				++nNum, nTmp >>= 1;
4009 			break;
4010 		}
4011 
4012 	delete [] pSetFlags;
4013 	return aName += String::CreateFromInt32( ++nNum );
4014 }
4015 
4016 SwTableFmt* SwDoc::FindTblFmtByName( const String& rName, sal_Bool bAll ) const
4017 {
4018 	const SwFmt* pRet = 0;
4019 	if( bAll )
4020 		pRet = FindFmtByName( (SvPtrarr&)*pTblFrmFmtTbl, rName );
4021 	else
4022 	{
4023 		// dann nur die, die im Doc gesetzt sind
4024 		for( sal_uInt16 n = 0; n < pTblFrmFmtTbl->Count(); ++n )
4025 		{
4026 			const SwFrmFmt* pFmt = (*pTblFrmFmtTbl)[ n ];
4027 			if( !pFmt->IsDefault() && IsUsed( *pFmt ) &&
4028 				pFmt->GetName() == rName )
4029 			{
4030 				pRet = pFmt;
4031 				break;
4032 			}
4033 		}
4034 	}
4035 	return (SwTableFmt*)pRet;
4036 }
4037 
4038 sal_Bool SwDoc::SetColRowWidthHeight( SwTableBox& rAktBox, sal_uInt16 eType,
4039 									SwTwips nAbsDiff, SwTwips nRelDiff )
4040 {
4041 	SwTableNode* pTblNd = (SwTableNode*)rAktBox.GetSttNd()->FindTableNode();
4042 	SwUndo* pUndo = 0;
4043 
4044 	if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType && pTblNd->GetTable().ISA( SwDDETable ))
4045 		return sal_False;
4046 
4047 	SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
4048 	aMsgHnt.eFlags = TBL_BOXPTR;
4049 	UpdateTblFlds( &aMsgHnt );
4050 
4051     bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
4052 	sal_Bool bRet = sal_False;
4053 	switch( eType & 0xff )
4054 	{
4055 	case nsTblChgWidthHeightType::WH_COL_LEFT:
4056 	case nsTblChgWidthHeightType::WH_COL_RIGHT:
4057 	case nsTblChgWidthHeightType::WH_CELL_LEFT:
4058 	case nsTblChgWidthHeightType::WH_CELL_RIGHT:
4059 		{
4060 			 bRet = pTblNd->GetTable().SetColWidth( rAktBox,
4061 								eType, nAbsDiff, nRelDiff,
4062                                 (bUndo) ? &pUndo : 0 );
4063         }
4064 		break;
4065 	case nsTblChgWidthHeightType::WH_ROW_TOP:
4066 	case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
4067 	case nsTblChgWidthHeightType::WH_CELL_TOP:
4068 	case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
4069 		bRet = pTblNd->GetTable().SetRowHeight( rAktBox,
4070 							eType, nAbsDiff, nRelDiff,
4071                             (bUndo) ? &pUndo : 0 );
4072 		break;
4073 	}
4074 
4075     GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off
4076 	if( pUndo )
4077     {
4078         GetIDocumentUndoRedo().AppendUndo( pUndo );
4079     }
4080 
4081 	if( bRet )
4082 	{
4083 		SetModified();
4084 		if( nsTblChgWidthHeightType::WH_FLAG_INSDEL & eType )
4085 			SetFieldsDirty( true, NULL, 0 );
4086 	}
4087 	return bRet;
4088 }
4089 
4090 
4091 void SwDoc::ChkBoxNumFmt( SwTableBox& rBox, sal_Bool bCallUpdate )
4092 {
4093 	//JP 09.07.97: Optimierung: wenn die Box schon sagt, das es Text
4094 	//							sein soll, dann bleibt das auch Text!
4095 	const SfxPoolItem* pNumFmtItem = 0;
4096 	if( SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT,
4097 		sal_False, &pNumFmtItem ) && GetNumberFormatter()->IsTextFormat(
4098 			((SwTblBoxNumFormat*)pNumFmtItem)->GetValue() ))
4099 		return ;
4100 
4101 	SwUndoTblNumFmt* pUndo = 0;
4102 
4103 	sal_Bool bIsEmptyTxtNd, bChgd = sal_True;
4104 	sal_uInt32 nFmtIdx;
4105 	double fNumber;
4106 	if( rBox.HasNumCntnt( fNumber, nFmtIdx, bIsEmptyTxtNd ) )
4107 	{
4108 		if( !rBox.IsNumberChanged() )
4109 			bChgd = sal_False;
4110 		else
4111 		{
4112             if (GetIDocumentUndoRedo().DoesUndo())
4113             {
4114                 GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
4115 				pUndo = new SwUndoTblNumFmt( rBox );
4116 				pUndo->SetNumFmt( nFmtIdx, fNumber );
4117 			}
4118 
4119 			SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt();
4120 			SfxItemSet aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
4121 
4122 			sal_Bool bSetNumFmt = IsInsTblFormatNum(), bLockModify = sal_True;
4123 			if( bSetNumFmt )
4124 			{
4125 				if( !IsInsTblChangeNumFormat() )
4126 				{
4127 					if( !pNumFmtItem )
4128 						bSetNumFmt = sal_False;
4129 					else
4130 					{
4131 						sal_uLong nOldNumFmt = ((SwTblBoxNumFormat*)pNumFmtItem)->
4132 											GetValue();
4133 						SvNumberFormatter* pNumFmtr = GetNumberFormatter();
4134 
4135 						short nFmtType = pNumFmtr->GetType( nFmtIdx );
4136 						if( nFmtType == pNumFmtr->GetType( nOldNumFmt ) ||
4137 							NUMBERFORMAT_NUMBER == nFmtType )
4138 							// eingstelltes und vorgegebenes NumFormat
4139 							// stimmen ueberein -> altes Format beibehalten
4140 							nFmtIdx = nOldNumFmt;
4141 						else
4142 							// eingstelltes und vorgegebenes NumFormat
4143 							// stimmen nicht ueberein -> als Text einfuegen
4144 							bLockModify = bSetNumFmt = sal_False;
4145 					}
4146 				}
4147 
4148 				if( bSetNumFmt )
4149 				{
4150 					pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt();
4151 
4152 					aBoxSet.Put( SwTblBoxValue( fNumber ));
4153 					aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
4154 				}
4155 			}
4156 
4157 			// JP 28.04.98: Nur Formel zuruecksetzen reicht nicht.
4158 			//				Sorge dafuer, das der Text auch entsprechend
4159 			//				formatiert wird!
4160 
4161 			if( !bSetNumFmt && !bIsEmptyTxtNd && pNumFmtItem )
4162 			{
4163 				// JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4164 				//				Sorge dafuer, das der Text auch entsprechend
4165 				//				formatiert wird!
4166                 pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4167 			}
4168 
4169 			if( bLockModify ) pBoxFmt->LockModify();
4170             pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
4171 			if( bLockModify ) pBoxFmt->UnlockModify();
4172 
4173 			if( bSetNumFmt )
4174                 pBoxFmt->SetFmtAttr( aBoxSet );
4175 		}
4176 	}
4177 	else
4178 	{
4179 		// es ist keine Zahl
4180 		const SfxPoolItem* pValueItem = 0, *pFmtItem = 0;
4181 		SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rBox.GetFrmFmt();
4182 		if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMAT,
4183 				sal_False, &pFmtItem ) ||
4184 			SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_VALUE,
4185 				sal_False, &pValueItem ))
4186 		{
4187             if (GetIDocumentUndoRedo().DoesUndo())
4188             {
4189                 GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
4190 				pUndo = new SwUndoTblNumFmt( rBox );
4191 			}
4192 
4193 			pBoxFmt = (SwTableBoxFmt*)rBox.ClaimFrmFmt();
4194 
4195 			// alle Zahlenformate entfernen
4196 			sal_uInt16 nWhich1 = RES_BOXATR_FORMULA;
4197 			if( !bIsEmptyTxtNd )
4198 				//JP 15.01.99: dieser Teil wurde doch schon oben abgeprueft!
4199 				/* && pFmtItem && !GetNumberFormatter()->
4200 				IsTextFormat( ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ) )*/
4201 			{
4202 				nWhich1 = RES_BOXATR_FORMAT;
4203 
4204 				// JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4205 				//				Sorge dafuer, das der Text auch entsprechend
4206 				//				formatiert wird!
4207                 pBoxFmt->SetFmtAttr( *GetDfltAttr( nWhich1 ));
4208 			}
4209             pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE );
4210 		}
4211 		else
4212 			bChgd = sal_False;
4213 	}
4214 
4215 	if( bChgd )
4216 	{
4217 		if( pUndo )
4218 		{
4219 			pUndo->SetBox( rBox );
4220             GetIDocumentUndoRedo().AppendUndo(pUndo);
4221             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
4222         }
4223 
4224 		const SwTableNode* pTblNd = rBox.GetSttNd()->FindTableNode();
4225 		if( bCallUpdate )
4226 		{
4227 			SwTableFmlUpdate aTblUpdate( &pTblNd->GetTable() );
4228 			UpdateTblFlds( &aTblUpdate );
4229 
4230 			// TL_CHART2: update charts (when cursor leaves cell and
4231 			// automatic update is enabled)
4232 			if (AUTOUPD_FIELD_AND_CHARTS == getFieldUpdateFlags(true))
4233 				pTblNd->GetTable().UpdateCharts();
4234 		}
4235 		SetModified();
4236 	}
4237 }
4238 
4239 void SwDoc::SetTblBoxFormulaAttrs( SwTableBox& rBox, const SfxItemSet& rSet )
4240 {
4241     if (GetIDocumentUndoRedo().DoesUndo())
4242     {
4243         GetIDocumentUndoRedo().AppendUndo( new SwUndoTblNumFmt(rBox, &rSet) );
4244     }
4245 
4246 	SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
4247 	if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
4248 	{
4249 		pBoxFmt->LockModify();
4250         pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
4251 		pBoxFmt->UnlockModify();
4252 	}
4253 	else if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE ))
4254 	{
4255 		pBoxFmt->LockModify();
4256         pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
4257 		pBoxFmt->UnlockModify();
4258 	}
4259     pBoxFmt->SetFmtAttr( rSet );
4260 	SetModified();
4261 }
4262 
4263 void SwDoc::ClearBoxNumAttrs( const SwNodeIndex& rNode )
4264 {
4265 	SwStartNode* pSttNd;
4266     if( 0 != ( pSttNd = rNode.GetNode().
4267 								FindSttNodeByType( SwTableBoxStartNode )) &&
4268 		2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() )
4269 	{
4270 		SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
4271 							GetTblBox( pSttNd->GetIndex() );
4272 
4273 		const SfxPoolItem* pFmtItem = 0;
4274 		const SfxItemSet& rSet = pBox->GetFrmFmt()->GetAttrSet();
4275 		if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT, sal_False, &pFmtItem ) ||
4276 			SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMULA, sal_False ) ||
4277 			SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE, sal_False ))
4278 		{
4279             if (GetIDocumentUndoRedo().DoesUndo())
4280             {
4281                 GetIDocumentUndoRedo().AppendUndo(new SwUndoTblNumFmt(*pBox));
4282             }
4283 
4284 			SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
4285 
4286 			//JP 01.09.97: TextFormate bleiben erhalten!
4287 			sal_uInt16 nWhich1 = RES_BOXATR_FORMAT;
4288 			if( pFmtItem && GetNumberFormatter()->IsTextFormat(
4289 					((SwTblBoxNumFormat*)pFmtItem)->GetValue() ))
4290 				nWhich1 = RES_BOXATR_FORMULA;
4291 			else
4292 				// JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4293 				//				Sorge dafuer, das der Text auch entsprechend
4294 				//				formatiert wird!
4295                 pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4296 
4297             pBoxFmt->ResetFmtAttr( nWhich1, RES_BOXATR_VALUE );
4298 			SetModified();
4299 		}
4300 	}
4301 }
4302 
4303 // kopiert eine Tabelle aus dem selben oder einem anderen Doc in sich
4304 // selbst. Dabei wird eine neue Tabelle angelegt oder eine bestehende
4305 // mit dem Inhalt gefuellt; wobei entweder der Inhalt ab einer Box oder
4306 // in eine bestehende TblSelektion gefuellt wird.
4307 // Gerufen wird es von: edglss.cxx/fecopy.cxx
4308 
4309 sal_Bool SwDoc::InsCopyOfTbl( SwPosition& rInsPos, const SwSelBoxes& rBoxes,
4310 						const SwTable* pCpyTbl, sal_Bool bCpyName, sal_Bool bCorrPos )
4311 {
4312 	sal_Bool bRet;
4313 
4314 	const SwTableNode* pSrcTblNd = pCpyTbl
4315 			? pCpyTbl->GetTableNode()
4316 			: rBoxes[ 0 ]->GetSttNd()->FindTableNode();
4317 
4318     SwTableNode * pInsTblNd = rInsPos.nNode.GetNode().FindTableNode();
4319 
4320     bool const bUndo( GetIDocumentUndoRedo().DoesUndo() );
4321 	if( !pCpyTbl && !pInsTblNd )
4322 	{
4323 		SwUndoCpyTbl* pUndo = 0;
4324         if (bUndo)
4325         {
4326             GetIDocumentUndoRedo().ClearRedo();
4327 			pUndo = new SwUndoCpyTbl;
4328         }
4329 
4330         {
4331             ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
4332             bRet = pSrcTblNd->GetTable().MakeCopy( this, rInsPos, rBoxes,
4333 												sal_True, bCpyName );
4334         }
4335 
4336 		if( pUndo )
4337 		{
4338 			if( !bRet )
4339             {
4340 				delete pUndo;
4341                 pUndo = 0;
4342             }
4343 			else
4344 			{
4345 				pInsTblNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode();
4346 
4347 				pUndo->SetTableSttIdx( pInsTblNd->GetIndex() );
4348                 GetIDocumentUndoRedo().AppendUndo( pUndo );
4349             }
4350 		}
4351 	}
4352 	else
4353 	{
4354         RedlineMode_t eOld = GetRedlineMode();
4355         if( IsRedlineOn() )
4356 	  SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON |
4357 								  nsRedlineMode_t::REDLINE_SHOW_INSERT |
4358 								  nsRedlineMode_t::REDLINE_SHOW_DELETE));
4359 
4360 		SwUndoTblCpyTbl* pUndo = 0;
4361         if (bUndo)
4362         {
4363             GetIDocumentUndoRedo().ClearRedo();
4364 			pUndo = new SwUndoTblCpyTbl;
4365             GetIDocumentUndoRedo().DoUndo(false);
4366         }
4367 
4368 		SwDoc* pCpyDoc = (SwDoc*)pSrcTblNd->GetDoc();
4369 		sal_Bool bDelCpyDoc = pCpyDoc == this;
4370 
4371 		if( bDelCpyDoc )
4372 		{
4373 			// kopiere die Tabelle erstmal in ein temp. Doc
4374 			pCpyDoc = new SwDoc;
4375             pCpyDoc->acquire();
4376 
4377 			SwPosition aPos( SwNodeIndex( pCpyDoc->GetNodes().GetEndOfContent() ));
4378 			if( !pSrcTblNd->GetTable().MakeCopy( pCpyDoc, aPos, rBoxes, sal_True, sal_True ))
4379 			{
4380                 if( pCpyDoc->release() == 0 )
4381                     delete pCpyDoc;
4382 
4383 				if( pUndo )
4384                 {
4385                     GetIDocumentUndoRedo().DoUndo(bUndo);
4386 					delete pUndo;
4387                     pUndo = 0;
4388 				}
4389 				return sal_False;
4390 			}
4391 			aPos.nNode -= 1;		// auf den EndNode der Tabelle
4392 			pSrcTblNd = aPos.nNode.GetNode().FindTableNode();
4393 		}
4394 
4395 		const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
4396 
4397 		rInsPos.nContent.Assign( 0, 0 );
4398 
4399 		// no complex into complex, but copy into or from new model is welcome
4400 		if( ( !pSrcTblNd->GetTable().IsTblComplex() || pInsTblNd->GetTable().IsNewModel() )
4401             && ( bDelCpyDoc || rBoxes.Count() ) )
4402 		{
4403 			// dann die Tabelle "relativ" kopieren
4404 			const SwSelBoxes* pBoxes;
4405 			SwSelBoxes aBoxes;
4406 
4407 			if( bDelCpyDoc )
4408 			{
4409 				SwTableBox* pBox = pInsTblNd->GetTable().GetTblBox(
4410 										pSttNd->GetIndex() );
4411 				ASSERT( pBox, "Box steht nicht in dieser Tabelle" );
4412 				aBoxes.Insert( pBox );
4413 				pBoxes = &aBoxes;
4414 			}
4415 			else
4416 				pBoxes = &rBoxes;
4417 
4418 			// kopiere die Tabelle in die selktierten Zellen.
4419 			bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(),
4420 														*pBoxes, pUndo );
4421 		}
4422 		else
4423 		{
4424 			SwNodeIndex aNdIdx( *pSttNd, 1 );
4425 			bRet = pInsTblNd->GetTable().InsTable( pSrcTblNd->GetTable(),
4426 													aNdIdx, pUndo );
4427 		}
4428 
4429 		if( bDelCpyDoc )
4430         {
4431             if( pCpyDoc->release() == 0 )
4432                 delete pCpyDoc;
4433         }
4434 
4435 		if( pUndo )
4436 		{
4437 			// falls die Tabelle nicht kopiert werden konnte, das Undo-Object
4438 			// wieder loeschen
4439             GetIDocumentUndoRedo().DoUndo(bUndo);
4440 			if( !bRet && pUndo->IsEmpty() )
4441 				delete pUndo;
4442             else
4443             {
4444                 GetIDocumentUndoRedo().AppendUndo(pUndo);
4445             }
4446         }
4447 
4448 		if( bCorrPos )
4449 		{
4450 			rInsPos.nNode = *pSttNd;
4451 			rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 );
4452 		}
4453         SetRedlineMode( eOld );
4454 	}
4455 
4456 	if( bRet )
4457 	{
4458 		SetModified();
4459 		SetFieldsDirty( true, NULL, 0 );
4460 	}
4461 	return bRet;
4462 }
4463 
4464 
4465 
4466 sal_Bool SwDoc::_UnProtectTblCells( SwTable& rTbl )
4467 {
4468 	sal_Bool bChgd = sal_False;
4469     SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
4470         ?   new SwUndoAttrTbl( *rTbl.GetTableNode() )
4471         :   0;
4472 
4473 	SwTableSortBoxes& rSrtBox = rTbl.GetTabSortBoxes();
4474 	for( sal_uInt16 i = rSrtBox.Count(); i; )
4475 	{
4476 		SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt();
4477 		if( pBoxFmt->GetProtect().IsCntntProtected() )
4478 		{
4479             pBoxFmt->ResetFmtAttr( RES_PROTECT );
4480 			bChgd = sal_True;
4481 		}
4482 	}
4483 
4484 	if( pUndo )
4485 	{
4486 		if( bChgd )
4487         {
4488             GetIDocumentUndoRedo().AppendUndo( pUndo );
4489         }
4490         else
4491 			delete pUndo;
4492 	}
4493 	return bChgd;
4494 }
4495 
4496 
4497 sal_Bool SwDoc::UnProtectCells( const String& rName )
4498 {
4499 	sal_Bool bChgd = sal_False;
4500 	SwTableFmt* pFmt = FindTblFmtByName( rName );
4501 	if( pFmt )
4502 	{
4503 		bChgd = _UnProtectTblCells( *SwTable::FindTable( pFmt ) );
4504 		if( bChgd )
4505 			SetModified();
4506 	}
4507 
4508 	return bChgd;
4509 }
4510 
4511 sal_Bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes )
4512 {
4513 	sal_Bool bChgd = sal_False;
4514 	if( rBoxes.Count() )
4515     {
4516         SwUndoAttrTbl *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
4517 				? new SwUndoAttrTbl( *rBoxes[0]->GetSttNd()->FindTableNode() )
4518 				: 0;
4519 
4520 		SvPtrarr aFmts( 16 ), aNewFmts( 16 );
4521 		for( sal_uInt16 i = rBoxes.Count(); i; )
4522 		{
4523 			SwTableBox* pBox = rBoxes[ --i ];
4524 			SwFrmFmt* pBoxFmt = pBox->GetFrmFmt();
4525 			if( pBoxFmt->GetProtect().IsCntntProtected() )
4526 			{
4527 				sal_uInt16 nFnd = aFmts.GetPos( pBoxFmt );
4528 				if( USHRT_MAX != nFnd )
4529 					pBox->ChgFrmFmt( (SwTableBoxFmt*)aNewFmts[ nFnd ] );
4530 				else
4531 				{
4532 					aFmts.Insert( pBoxFmt, aFmts.Count() );
4533 					pBoxFmt = pBox->ClaimFrmFmt();
4534                     pBoxFmt->ResetFmtAttr( RES_PROTECT );
4535 					aNewFmts.Insert( pBoxFmt, aNewFmts.Count() );
4536 				}
4537 				bChgd = sal_True;
4538 			}
4539 		}
4540 
4541 		if( pUndo )
4542 		{
4543 			if( bChgd )
4544             {
4545                 GetIDocumentUndoRedo().AppendUndo( pUndo );
4546             }
4547             else
4548 				delete pUndo;
4549 		}
4550 	}
4551 	return bChgd;
4552 }
4553 
4554 sal_Bool SwDoc::UnProtectTbls( const SwPaM& rPam )
4555 {
4556     GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
4557 
4558 	sal_Bool bChgd = sal_False, bHasSel = rPam.HasMark() ||
4559 									rPam.GetNext() != (SwPaM*)&rPam;
4560 	SwFrmFmts& rFmts = *GetTblFrmFmts();
4561 	SwTable* pTbl;
4562 	const SwTableNode* pTblNd;
4563 	for( sal_uInt16 n = rFmts.Count(); n ; )
4564 		if( 0 != (pTbl = SwTable::FindTable( rFmts[ --n ] )) &&
4565 			0 != (pTblNd = pTbl->GetTableNode() ) &&
4566 			pTblNd->GetNodes().IsDocNodes() )
4567 		{
4568 			sal_uLong nTblIdx = pTblNd->GetIndex();
4569 
4570 			// dann ueberpruefe ob Tabelle in der Selection liegt
4571 			if( bHasSel )
4572 			{
4573 				int bFound = sal_False;
4574 				SwPaM* pTmp = (SwPaM*)&rPam;
4575 				do {
4576 					const SwPosition *pStt = pTmp->Start(),
4577 									*pEnd = pTmp->End();
4578 					bFound = pStt->nNode.GetIndex() < nTblIdx &&
4579 							nTblIdx < pEnd->nNode.GetIndex();
4580 
4581 				} while( !bFound && &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) );
4582 				if( !bFound )
4583 					continue;		// weitersuchen
4584 			}
4585 
4586 			// dann mal den Schutz aufheben
4587 			bChgd |= _UnProtectTblCells( *pTbl );
4588 		}
4589 
4590     GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
4591 	if( bChgd )
4592 		SetModified();
4593 
4594 	return bChgd;
4595 }
4596 
4597 sal_Bool SwDoc::HasTblAnyProtection( const SwPosition* pPos,
4598 								 const String* pTblName,
4599 								 sal_Bool* pFullTblProtection )
4600 {
4601 	sal_Bool bHasProtection = sal_False;
4602 	SwTable* pTbl = 0;
4603 	if( pTblName )
4604 		pTbl = SwTable::FindTable( FindTblFmtByName( *pTblName ) );
4605 	else if( pPos )
4606 	{
4607 		SwTableNode* pTblNd = pPos->nNode.GetNode().FindTableNode();
4608 		if( pTblNd )
4609 			pTbl = &pTblNd->GetTable();
4610 	}
4611 
4612 	if( pTbl )
4613 	{
4614 		SwTableSortBoxes& rSrtBox = pTbl->GetTabSortBoxes();
4615 		for( sal_uInt16 i = rSrtBox.Count(); i; )
4616 		{
4617 			SwFrmFmt *pBoxFmt = rSrtBox[ --i ]->GetFrmFmt();
4618 			if( pBoxFmt->GetProtect().IsCntntProtected() )
4619 			{
4620 				if( !bHasProtection )
4621 				{
4622 					bHasProtection = sal_True;
4623 					if( !pFullTblProtection )
4624 						break;
4625 					*pFullTblProtection = sal_True;
4626 				}
4627 			}
4628 			else if( bHasProtection && pFullTblProtection )
4629 			{
4630 				*pFullTblProtection = sal_False;
4631 				break;
4632 			}
4633 		}
4634 	}
4635 	return bHasProtection;
4636 }
4637 
4638 #ifdef DEL_TABLE_REDLINES
4639 lcl_DelRedlines::lcl_DelRedlines( const SwTableNode& rNd,
4640 									sal_Bool bCheckForOwnRedline )
4641 	: pDoc( (SwDoc*)rNd.GetNodes().GetDoc() )
4642 {
4643     pDoc->StartUndo(UNDO_EMPTY, NULL);
4644 	const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
4645 	if( !pDoc->IsIgnoreRedline() && rTbl.Count() )
4646 	{
4647 		sal_Bool bDelete = sal_True;
4648 		if( bCheckForOwnRedline )
4649 		{
4650 			sal_uInt16 nRedlPos = pDoc->GetRedlinePos( rNd, USHRT_MAX );
4651 			sal_uInt32 nSttNd = rNd.GetIndex(),
4652 					   nEndNd = rNd.EndOfSectionIndex();
4653 
4654 			for ( ; nRedlPos < rTbl.Count(); ++nRedlPos )
4655 			{
4656 				const SwRedline* pRedline = rTbl[ nRedlPos ];
4657 				const SwPosition* pStt = pRedline->Start(),
4658 						  		* pEnd = pStt == pRedline->GetPoint()
4659 						  							? pRedline->GetMark()
4660 													: pRedline->GetPoint();
4661 				if( pStt->nNode <= nSttNd )
4662 				{
4663 					if( pEnd->nNode >= nEndNd &&
4664 						pRedline->GetAuthor() == pDoc->GetRedlineAuthor() )
4665 					{
4666 						bDelete = sal_False;
4667 						break;
4668 					}
4669 				}
4670 				else
4671 					break;
4672 			}
4673 		}
4674 		if( bDelete )
4675 		{
4676 			SwPaM aPam(*rNd.EndOfSectionNode(), rNd);
4677 			pDoc->AcceptRedline( aPam, true );
4678 		}
4679 	}
4680 }
4681 #endif
4682 
4683 
4684