xref: /aoo41x/main/sw/source/core/docnode/ndtbl1.cxx (revision efeef26f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include "hintids.hxx"
28 #include <editeng/lrspitem.hxx>
29 #include <editeng/boxitem.hxx>
30 #include <editeng/brshitem.hxx>
31 #include <editeng/frmdiritem.hxx>
32 #include <fmtornt.hxx>
33 #include <fmtfsize.hxx>
34 #include <fmtlsplt.hxx>
35 #include <fmtrowsplt.hxx>
36 #include <tabcol.hxx>
37 #include <frmatr.hxx>
38 #include <cellfrm.hxx>
39 #include <tabfrm.hxx>
40 #include <cntfrm.hxx>
41 #include <txtfrm.hxx>
42 #include <svx/svxids.hrc>
43 #include <doc.hxx>
44 #include <IDocumentUndoRedo.hxx>
45 #include "pam.hxx"
46 #include "swcrsr.hxx"
47 #include "viscrs.hxx"
48 #include "swtable.hxx"
49 #include "htmltbl.hxx"
50 #include "tblsel.hxx"
51 #include "swtblfmt.hxx"
52 #include "docary.hxx"
53 #include "ndindex.hxx"
54 #include "undobj.hxx"
55 #include "switerator.hxx"
56 #include <UndoTable.hxx>
57 
58 using namespace ::com::sun::star;
59 
60 
61 extern void ClearFEShellTabCols();
62 
63 //siehe auch swtable.cxx
64 #define COLFUZZY 20L
65 
IsSame(long nA,long nB)66 inline sal_Bool IsSame( long nA, long nB ) { return  Abs(nA-nB) <= COLFUZZY; }
67 
68 class SwTblFmtCmp
69 {
70 public:
71 	SwFrmFmt *pOld,
72 			 *pNew;
73 	sal_Int16     nType;
74 
75 	SwTblFmtCmp( SwFrmFmt *pOld, SwFrmFmt *pNew, sal_Int16 nType );
76 
77 	static SwFrmFmt *FindNewFmt( SvPtrarr &rArr, SwFrmFmt*pOld, sal_Int16 nType );
78 	static void Delete( SvPtrarr &rArr );
79 };
80 
81 
SwTblFmtCmp(SwFrmFmt * pO,SwFrmFmt * pN,sal_Int16 nT)82 SwTblFmtCmp::SwTblFmtCmp( SwFrmFmt *pO, SwFrmFmt *pN, sal_Int16 nT )
83 	: pOld ( pO ), pNew ( pN ), nType( nT )
84 {
85 }
86 
FindNewFmt(SvPtrarr & rArr,SwFrmFmt * pOld,sal_Int16 nType)87 SwFrmFmt *SwTblFmtCmp::FindNewFmt( SvPtrarr &rArr, SwFrmFmt *pOld, sal_Int16 nType )
88 {
89 	for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
90 	{
91 		SwTblFmtCmp *pCmp = (SwTblFmtCmp*)rArr[i];
92 		if ( pCmp->pOld == pOld && pCmp->nType == nType )
93 			return pCmp->pNew;
94 	}
95 	return 0;
96 }
97 
Delete(SvPtrarr & rArr)98 void SwTblFmtCmp::Delete( SvPtrarr &rArr )
99 {
100 	for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
101 		delete (SwTblFmtCmp*)rArr[i];
102 }
103 
lcl_GetStartEndCell(const SwCursor & rCrsr,SwLayoutFrm * & prStart,SwLayoutFrm * & prEnd)104 void lcl_GetStartEndCell( const SwCursor& rCrsr,
105 						SwLayoutFrm *&prStart, SwLayoutFrm *&prEnd )
106 {
107 	ASSERT( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( sal_False ),
108 			"Tabselection nicht auf Cnt." );
109 
110 	Point aPtPos, aMkPos;
111     const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
112 	if( pShCrsr )
113 	{
114 		aPtPos = pShCrsr->GetPtPos();
115 		aMkPos = pShCrsr->GetMkPos();
116 	}
117 
118     // robust:
119     SwCntntNode* pPointNd = rCrsr.GetCntntNode();
120     SwCntntNode* pMarkNd  = rCrsr.GetCntntNode(sal_False);
121 
122     SwFrm* pPointFrm = pPointNd ? pPointNd->getLayoutFrm( pPointNd->GetDoc()->GetCurrentLayout(), &aPtPos ) : 0;
123     SwFrm* pMarkFrm  = pMarkNd  ? pMarkNd->getLayoutFrm( pMarkNd->GetDoc()->GetCurrentLayout(), &aMkPos )  : 0;
124 
125     prStart = pPointFrm ? pPointFrm->GetUpper() : 0;
126     prEnd   = pMarkFrm  ? pMarkFrm->GetUpper() : 0;
127 }
128 
lcl_GetBoxSel(const SwCursor & rCursor,SwSelBoxes & rBoxes,sal_Bool bAllCrsr=sal_False)129 sal_Bool lcl_GetBoxSel( const SwCursor& rCursor, SwSelBoxes& rBoxes,
130 					sal_Bool bAllCrsr = sal_False )
131 {
132     const SwTableCursor* pTblCrsr =
133         dynamic_cast<const SwTableCursor*>(&rCursor);
134 	if( pTblCrsr )
135 		::GetTblSelCrs( *pTblCrsr, rBoxes );
136 	else
137 	{
138 		const SwPaM *pCurPam = &rCursor, *pSttPam = pCurPam;
139 		do {
140 			const SwNode* pNd = pCurPam->GetNode()->FindTableBoxStartNode();
141 			if( pNd )
142 			{
143 				SwTableBox* pBox = (SwTableBox*)pNd->FindTableNode()->GetTable().
144 											GetTblBox( pNd->GetIndex() );
145 				rBoxes.Insert( pBox );
146 			}
147 		} while( bAllCrsr &&
148 				pSttPam != ( pCurPam = (SwPaM*)pCurPam->GetNext()) );
149 	}
150 	return 0 != rBoxes.Count();
151 }
152 
153 /***********************************************************************
154 #*	Class	   :  SwDoc
155 #*	Methoden   :  SetRowHeight(), GetRowHeight()
156 #*	Datum	   :  MA 17. May. 93
157 #*	Update	   :  JP 28.04.98
158 #***********************************************************************/
159 //Die Zeilenhoehe wird ausgehend von der Selektion ermittelt/gesetzt.
160 //Ausgehend von jeder Zelle innerhalb der Selektion werden nach oben alle
161 //Zeilen abgeklappert, die oberste Zeile erhaelt den gewuenschten Wert alle
162 //tieferliegenden Zeilen einen entsprechenden Wert der sich aus der
163 //Relation der alten und neuen Groesse der obersten Zeile und ihrer
164 //eigenen Groesse ergiebt.
165 //Alle veraenderten Zeilen erhalten ggf. ein eigenes FrmFmt.
166 //Natuerlich darf jede Zeile nur einmal angefasst werden.
167 
InsertLine(SvPtrarr & rLineArr,SwTableLine * pLine)168 inline void InsertLine( SvPtrarr& rLineArr, SwTableLine* pLine )
169 {
170 	if( USHRT_MAX == rLineArr.GetPos( pLine ) )
171 		rLineArr.Insert( pLine, rLineArr.Count() );
172 }
173 
174 //-----------------------------------------------------------------------------
175 
lcl_IsAnLower(const SwTableLine * pLine,const SwTableLine * pAssumed)176 sal_Bool lcl_IsAnLower( const SwTableLine *pLine, const SwTableLine *pAssumed )
177 {
178 	const SwTableLine *pTmp = pAssumed->GetUpper() ?
179 									pAssumed->GetUpper()->GetUpper() : 0;
180 	while ( pTmp )
181 	{
182 		if ( pTmp == pLine )
183 			return sal_True;
184 		pTmp = pTmp->GetUpper() ? pTmp->GetUpper()->GetUpper() : 0;
185 	}
186 	return sal_False;
187 }
188 //-----------------------------------------------------------------------------
189 
190 struct LinesAndTable
191 {
192 		  SvPtrarr &rLines;
193 	const SwTable  &rTable;
194 		  sal_Bool		bInsertLines;
195 
LinesAndTableLinesAndTable196 	LinesAndTable( SvPtrarr &rL, const SwTable &rTbl ) :
197 		  rLines( rL ), rTable( rTbl ), bInsertLines( sal_True ) {}
198 };
199 
200 
201 sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara );
202 
_FindBox(const _FndBox * & rpBox,void * pPara)203 sal_Bool _FindBox( const _FndBox*& rpBox, void* pPara )
204 {
205 	if ( rpBox->GetLines().Count() )
206 	{
207 		((LinesAndTable*)pPara)->bInsertLines = sal_True;
208 		((_FndBox*)rpBox)->GetLines().ForEach( _FindLine, pPara );
209 		if ( ((LinesAndTable*)pPara)->bInsertLines )
210 		{
211 			const SwTableLines &rLines = rpBox->GetBox()
212 									? rpBox->GetBox()->GetTabLines()
213 									: ((LinesAndTable*)pPara)->rTable.GetTabLines();
214 			if ( rpBox->GetLines().Count() == rLines.Count() )
215 			{
216 				for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
217 					::InsertLine( ((LinesAndTable*)pPara)->rLines,
218 								  (SwTableLine*)rLines[i] );
219 			}
220 			else
221 				((LinesAndTable*)pPara)->bInsertLines = sal_False;
222 		}
223 	}
224 	else if ( rpBox->GetBox() )
225 		::InsertLine( ((LinesAndTable*)pPara)->rLines,
226 					  (SwTableLine*)rpBox->GetBox()->GetUpper() );
227 	return sal_True;
228 }
229 
_FindLine(const _FndLine * & rpLine,void * pPara)230 sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara )
231 {
232 	((_FndLine*)rpLine)->GetBoxes().ForEach( _FindBox, pPara );
233 	return sal_True;
234 }
235 
lcl_CollectLines(SvPtrarr & rArr,const SwCursor & rCursor,bool bRemoveLines)236 void lcl_CollectLines( SvPtrarr &rArr, const SwCursor& rCursor, bool bRemoveLines )
237 {
238 	//Zuerst die selektierten Boxen einsammeln.
239 	SwSelBoxes aBoxes;
240 	if( !::lcl_GetBoxSel( rCursor, aBoxes ))
241 		return ;
242 
243 	//Die selektierte Struktur kopieren.
244 	const SwTable &rTable = aBoxes[0]->GetSttNd()->FindTableNode()->GetTable();
245 	LinesAndTable aPara( rArr, rTable );
246 	_FndBox aFndBox( 0, 0 );
247 	{
248 		_FndPara aTmpPara( aBoxes, &aFndBox );
249 		((SwTableLines&)rTable.GetTabLines()).ForEach( &_FndLineCopyCol, &aTmpPara );
250 	}
251 
252 	//Diejenigen Lines einsammeln, die nur selektierte Boxen enthalten.
253 	const _FndBox *pTmp = &aFndBox;
254 	::_FindBox( pTmp, &aPara );
255 
256     // Remove lines, that have a common superordinate row.
257     // (Not for row split)
258     if ( bRemoveLines )
259     {
260     	for ( sal_uInt16 i = 0; i < rArr.Count(); ++i )
261 	    {
262 		    SwTableLine *pUpLine = (SwTableLine*)rArr[i];
263 		    for ( sal_uInt16 k = 0; k < rArr.Count(); ++k )
264 		    {
265     			if ( k != i && ::lcl_IsAnLower( pUpLine, (SwTableLine*)rArr[k] ) )
266 			    {
267     				rArr.Remove( k );
268 				    if ( k <= i )
269     					--i;
270 				    --k;
271 			    }
272 		    }
273 	    }
274     }
275 }
276 
277 //-----------------------------------------------------------------------------
278 
lcl_ProcessRowAttr(SvPtrarr & rFmtCmp,SwTableLine * pLine,const SfxPoolItem & rNew)279 void lcl_ProcessRowAttr( SvPtrarr& rFmtCmp, SwTableLine* pLine, const SfxPoolItem& rNew )
280 {
281     SwFrmFmt *pNewFmt;
282     if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( rFmtCmp, pLine->GetFrmFmt(), 0 )))
283         pLine->ChgFrmFmt( (SwTableLineFmt*)pNewFmt );
284     else
285     {
286         SwFrmFmt *pOld = pLine->GetFrmFmt();
287         SwFrmFmt *pNew = pLine->ClaimFrmFmt();
288         pNew->SetFmtAttr( rNew );
289         rFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), rFmtCmp.Count());
290     }
291 }
292 
293 //-----------------------------------------------------------------------------
294 
295 void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew );
296 
lcl_ProcessRowSize(SvPtrarr & rFmtCmp,SwTableLine * pLine,const SwFmtFrmSize & rNew)297 void lcl_ProcessRowSize( SvPtrarr &rFmtCmp, SwTableLine *pLine, const SwFmtFrmSize &rNew )
298 {
299     lcl_ProcessRowAttr( rFmtCmp, pLine, rNew );
300     SwTableBoxes &rBoxes = pLine->GetTabBoxes();
301 	for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
302 		::lcl_ProcessBoxSize( rFmtCmp, rBoxes[i], rNew );
303 }
304 
305 //-----------------------------------------------------------------------------
306 
lcl_ProcessBoxSize(SvPtrarr & rFmtCmp,SwTableBox * pBox,const SwFmtFrmSize & rNew)307 void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew )
308 {
309 	SwTableLines &rLines = pBox->GetTabLines();
310 	if ( rLines.Count() )
311 	{
312 		SwFmtFrmSize aSz( rNew );
313 		aSz.SetHeight( rNew.GetHeight() ? rNew.GetHeight() / rLines.Count() : 0 );
314 		for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
315 			::lcl_ProcessRowSize( rFmtCmp, rLines[i], aSz );
316 	}
317 }
318 
319 //-----------------------------------------------------------------------------
320 
321 /******************************************************************************
322  *              void SwDoc::SetRowSplit()
323  ******************************************************************************/
SetRowSplit(const SwCursor & rCursor,const SwFmtRowSplit & rNew)324 void SwDoc::SetRowSplit( const SwCursor& rCursor, const SwFmtRowSplit &rNew )
325 {
326     SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
327     if( pTblNd )
328     {
329         SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines.
330         ::lcl_CollectLines( aRowArr, rCursor, false );
331 
332         if( aRowArr.Count() )
333         {
334             if (GetIDocumentUndoRedo().DoesUndo())
335             {
336                 GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
337             }
338 
339 			SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
340 
341 			for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
342 				::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
343 
344             SwTblFmtCmp::Delete( aFmtCmp );
345             SetModified();
346         }
347     }
348 }
349 
350 
351 /******************************************************************************
352  *               SwTwips SwDoc::GetRowSplit() const
353  ******************************************************************************/
GetRowSplit(const SwCursor & rCursor,SwFmtRowSplit * & rpSz) const354 void SwDoc::GetRowSplit( const SwCursor& rCursor, SwFmtRowSplit *& rpSz ) const
355 {
356     rpSz = 0;
357 
358     SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
359     if( pTblNd )
360     {
361         SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines.
362         ::lcl_CollectLines( aRowArr, rCursor, false );
363 
364         if( aRowArr.Count() )
365         {
366             rpSz = &(SwFmtRowSplit&)((SwTableLine*)aRowArr[0])->
367                                                 GetFrmFmt()->GetRowSplit();
368 
369             for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i )
370             {
371                 if ( (*rpSz).GetValue() != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetRowSplit().GetValue() )
372                     rpSz = 0;
373             }
374             if ( rpSz )
375                 rpSz = new SwFmtRowSplit( *rpSz );
376         }
377     }
378 }
379 
380 
381 /******************************************************************************
382  *				void SwDoc::SetRowHeight( SwTwips nNew )
383  ******************************************************************************/
SetRowHeight(const SwCursor & rCursor,const SwFmtFrmSize & rNew)384 void SwDoc::SetRowHeight( const SwCursor& rCursor, const SwFmtFrmSize &rNew )
385 {
386 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
387 	if( pTblNd )
388 	{
389 		SvPtrarr aRowArr( 25, 50 );	//Zum sammeln Lines.
390 		::lcl_CollectLines( aRowArr, rCursor, true );
391 
392 		if( aRowArr.Count() )
393         {
394             if (GetIDocumentUndoRedo().DoesUndo())
395             {
396                 GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
397             }
398 
399 			SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
400 			for ( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
401 				::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
402 			SwTblFmtCmp::Delete( aFmtCmp );
403 
404 			SetModified();
405 		}
406 	}
407 }
408 
409 
410 /******************************************************************************
411  *				 SwTwips SwDoc::GetRowHeight() const
412  ******************************************************************************/
GetRowHeight(const SwCursor & rCursor,SwFmtFrmSize * & rpSz) const413 void SwDoc::GetRowHeight( const SwCursor& rCursor, SwFmtFrmSize *& rpSz ) const
414 {
415 	rpSz = 0;
416 
417 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
418 	if( pTblNd )
419 	{
420 		SvPtrarr aRowArr( 25, 50 );	//Zum sammeln der Lines.
421 		::lcl_CollectLines( aRowArr, rCursor, true );
422 
423 		if( aRowArr.Count() )
424 		{
425 			rpSz = &(SwFmtFrmSize&)((SwTableLine*)aRowArr[0])->
426 												GetFrmFmt()->GetFrmSize();
427 
428 			for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i )
429 			{
430 				if ( *rpSz != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetFrmSize() )
431 					rpSz = 0;
432 			}
433 			if ( rpSz )
434 				rpSz = new SwFmtFrmSize( *rpSz );
435 		}
436 	}
437 }
438 
BalanceRowHeight(const SwCursor & rCursor,sal_Bool bTstOnly)439 sal_Bool SwDoc::BalanceRowHeight( const SwCursor& rCursor, sal_Bool bTstOnly )
440 {
441 	sal_Bool bRet = sal_False;
442 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
443 	if( pTblNd )
444 	{
445 		SvPtrarr aRowArr( 25, 50 );	//Zum sammeln der Lines.
446 		::lcl_CollectLines( aRowArr, rCursor, true );
447 
448 		if( 1 < aRowArr.Count() )
449 		{
450 			if( !bTstOnly )
451 			{
452 				long nHeight = 0;
453 				sal_uInt16 i;
454 
455 				for ( i = 0; i < aRowArr.Count(); ++i )
456 				{
457 					SwIterator<SwFrm,SwFmt> aIter( *((SwTableLine*)aRowArr[i])->GetFrmFmt() );
458 					SwFrm* pFrm = aIter.First();
459 					while ( pFrm )
460 					{
461 						nHeight = Max( nHeight, pFrm->Frm().Height() );
462 						pFrm = aIter.Next();
463 					}
464 				}
465 				SwFmtFrmSize aNew( ATT_MIN_SIZE, 0, nHeight );
466 
467                 if (GetIDocumentUndoRedo().DoesUndo())
468                 {
469                     GetIDocumentUndoRedo().AppendUndo(
470                             new SwUndoAttrTbl(*pTblNd));
471                 }
472 
473 				SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
474 				for( i = 0; i < aRowArr.Count(); ++i )
475 					::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], aNew );
476 				SwTblFmtCmp::Delete( aFmtCmp );
477 
478 				SetModified();
479 			}
480 			bRet = sal_True;
481 		}
482 	}
483 	return bRet;
484 }
485 
486 /******************************************************************************
487  *				void SwDoc::SetRowBackground()
488  ******************************************************************************/
SetRowBackground(const SwCursor & rCursor,const SvxBrushItem & rNew)489 void SwDoc::SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew )
490 {
491 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
492 	if( pTblNd )
493 	{
494 		SvPtrarr aRowArr( 25, 50 );	//Zum sammeln Lines.
495 		::lcl_CollectLines( aRowArr, rCursor, true );
496 
497 		if( aRowArr.Count() )
498         {
499             if (GetIDocumentUndoRedo().DoesUndo())
500             {
501                 GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
502             }
503 
504 			SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 );
505 
506 			for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i )
507                 ::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew );
508 
509 			SwTblFmtCmp::Delete( aFmtCmp );
510 			SetModified();
511 		}
512 	}
513 }
514 
515 /******************************************************************************
516  *				 SwTwips SwDoc::GetRowBackground() const
517  ******************************************************************************/
GetRowBackground(const SwCursor & rCursor,SvxBrushItem & rToFill) const518 sal_Bool SwDoc::GetRowBackground( const SwCursor& rCursor, SvxBrushItem &rToFill ) const
519 {
520 	sal_Bool bRet = sal_False;
521 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
522 	if( pTblNd )
523 	{
524 		SvPtrarr aRowArr( 25, 50 );	//Zum sammeln Lines.
525 		::lcl_CollectLines( aRowArr, rCursor, true );
526 
527 		if( aRowArr.Count() )
528 		{
529 			rToFill = ((SwTableLine*)aRowArr[0])->GetFrmFmt()->GetBackground();
530 
531 			bRet = sal_True;
532 			for ( sal_uInt16 i = 1; i < aRowArr.Count(); ++i )
533 				if ( rToFill != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetBackground() )
534 				{
535 					bRet = sal_False;
536 					break;
537 				}
538 		}
539 	}
540 	return bRet;
541 }
542 
543 /***********************************************************************
544 #*	Class	   :  SwDoc
545 #*	Methoden   :  SetTabBorders(), GetTabBorders()
546 #*	Datum	   :  MA 18. May. 93
547 #*	Update	   :  JP 29.04.98
548 #***********************************************************************/
InsertCell(SvPtrarr & rCellArr,SwCellFrm * pCellFrm)549 inline void InsertCell( SvPtrarr& rCellArr, SwCellFrm* pCellFrm )
550 {
551 	if( USHRT_MAX == rCellArr.GetPos( pCellFrm ) )
552 		rCellArr.Insert( pCellFrm, rCellArr.Count() );
553 }
554 
555 //-----------------------------------------------------------------------------
lcl_CollectCells(SvPtrarr & rArr,const SwRect & rUnion,SwTabFrm * pTab)556 void lcl_CollectCells( SvPtrarr &rArr, const SwRect &rUnion,
557 						  SwTabFrm *pTab )
558 {
559 	SwLayoutFrm *pCell = pTab->FirstCell();
560 	do
561 	{
562 		// Wenn in der Zelle ein spaltiger Bereich sitzt, muessen wir
563 		// uns erst wieder zur Zelle hochhangeln
564 		while ( !pCell->IsCellFrm() )
565 			pCell = pCell->GetUpper();
566 		ASSERT( pCell, "Frame ist keine Zelle." );
567 		if ( rUnion.IsOver( pCell->Frm() ) )
568 			::InsertCell( rArr, (SwCellFrm*)pCell );
569 		//Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche)
570 		SwLayoutFrm *pTmp = pCell;
571 		do
572 		{	pTmp = pTmp->GetNextLayoutLeaf();
573 		} while ( pCell->IsAnLower( pTmp ) );
574 		pCell = pTmp;
575 	} while( pCell && pTab->IsAnLower( pCell ) );
576 }
577 
SetTabBorders(const SwCursor & rCursor,const SfxItemSet & rSet)578 void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet )
579 {
580 	SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
581 	SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
582 	if( !pTblNd )
583 		return ;
584 
585 	SwLayoutFrm *pStart, *pEnd;
586 	::lcl_GetStartEndCell( rCursor, pStart, pEnd );
587 
588 	SwSelUnions aUnions;
589 	::MakeSelUnions( aUnions, pStart, pEnd );
590 
591 	if( aUnions.Count() )
592 	{
593 		SwTable& rTable = pTblNd->GetTable();
594         if (GetIDocumentUndoRedo().DoesUndo())
595         {
596             GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) );
597         }
598 
599 		SvPtrarr aFmtCmp( 255, 255 );
600 		const SvxBoxItem* pSetBox;
601 		const SvxBoxInfoItem *pSetBoxInfo;
602 
603 		const SvxBorderLine* pLeft = 0;
604 		const SvxBorderLine* pRight = 0;
605 		const SvxBorderLine* pTop = 0;
606 		const SvxBorderLine* pBottom = 0;
607 		const SvxBorderLine* pHori = 0;
608 		const SvxBorderLine* pVert = 0;
609 		sal_Bool bHoriValid = sal_True, bVertValid = sal_True,
610 			 bTopValid = sal_True, bBottomValid = sal_True,
611 			 bLeftValid = sal_True, bRightValid = sal_True;
612 
613 		// JP 21.07.95: die Flags im BoxInfo-Item entscheiden, wann eine
614 		//				BorderLine gueltig ist!!
615 		if( SFX_ITEM_SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, sal_False,
616 			(const SfxPoolItem**)&pSetBoxInfo) )
617 		{
618 			pHori = pSetBoxInfo->GetHori();
619 			pVert = pSetBoxInfo->GetVert();
620 
621 			bHoriValid = pSetBoxInfo->IsValid(VALID_HORI);
622 			bVertValid = pSetBoxInfo->IsValid(VALID_VERT);
623 
624 			// wollen wir die auswerten ??
625 			bTopValid = pSetBoxInfo->IsValid(VALID_TOP);
626 			bBottomValid = pSetBoxInfo->IsValid(VALID_BOTTOM);
627 			bLeftValid = pSetBoxInfo->IsValid(VALID_LEFT);
628 			bRightValid = pSetBoxInfo->IsValid(VALID_RIGHT);
629 		}
630 
631 		if( SFX_ITEM_SET == rSet.GetItemState( RES_BOX, sal_False,
632 			(const SfxPoolItem**)&pSetBox) )
633 		{
634 			pLeft = pSetBox->GetLeft();
635 			pRight = pSetBox->GetRight();
636 			pTop = pSetBox->GetTop();
637 			pBottom = pSetBox->GetBottom();
638 		}
639 		else
640 		{
641 			// nicht gesetzt, also keine gueltigen Werte
642 			bTopValid = bBottomValid = bLeftValid = bRightValid = sal_False;
643 			pSetBox = 0;
644 		}
645 
646 		sal_Bool bFirst = sal_True;
647 		for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
648 		{
649 			SwSelUnion *pUnion = aUnions[i];
650 			SwTabFrm *pTab = pUnion->GetTable();
651 			const SwRect &rUnion = pUnion->GetUnion();
652 			const sal_Bool bLast  = i == aUnions.Count() - 1 ? sal_True : sal_False;
653 
654 			SvPtrarr aCellArr( 255, 255 );
655 			::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
656 
657 			//Alle Zellenkanten, die mit dem UnionRect uebereinstimmen oder
658 			//darueber hinausragen sind Aussenkanten. Alle anderen sind
659 			//Innenkanten.
660 			//neu: Die Aussenkanten koennen abhaengig davon, ob es sich um eine
661 			//Start/Mittlere/Folge -Tabelle (bei Selektionen ueber FollowTabs)
662 			//handelt doch keine Aussenkanten sein.
663 			//Aussenkanten werden links, rechts, oben und unten gesetzt.
664 			//Innenkanten werden nur oben und links gesetzt.
665 			for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
666 			{
667 				SwCellFrm *pCell = (SwCellFrm*)aCellArr[j];
668                 const sal_Bool bVert = pTab->IsVertical();
669                 const sal_Bool bRTL = pTab->IsRightToLeft();
670                 sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver;
671                 if ( bVert )
672                 {
673                     bTopOver = pCell->Frm().Right() >= rUnion.Right();
674                     bLeftOver = pCell->Frm().Top() <= rUnion.Top();
675                     bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom();
676                     bBottomOver = pCell->Frm().Left() <= rUnion.Left();
677                 }
678                 else
679                 {
680                     bTopOver = pCell->Frm().Top() <= rUnion.Top();
681                     bLeftOver = pCell->Frm().Left() <= rUnion.Left();
682                     bRightOver = pCell->Frm().Right() >= rUnion.Right();
683                     bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom();
684                 }
685 
686                 if ( bRTL )
687                 {
688                     sal_Bool bTmp = bRightOver;
689                     bRightOver = bLeftOver;
690                     bLeftOver = bTmp;
691                 }
692 
693                 //Grundsaetzlich nichts setzen in HeadlineRepeats.
694                 if ( pTab->IsFollow() &&
695                      ( pTab->IsInHeadline( *pCell ) ||
696                        // --> FME 2006-02-07 #126092# Same holds for follow flow rows.
697                        pCell->IsInFollowFlowRow() ) )
698                        // <--
699                     continue;
700 
701 				SvxBoxItem aBox( pCell->GetFmt()->GetBox() );
702 
703 				sal_Int16 nType = 0;
704 
705 				//Obere Kante
706 				if( bTopValid )
707 				{
708                     if ( bFirst && bTopOver )
709 					{
710 						aBox.SetLine( pTop, BOX_LINE_TOP );
711 						nType |= 0x0001;
712 					}
713 					else if ( bHoriValid )
714 					{
715 						aBox.SetLine( 0, BOX_LINE_TOP );
716 						nType |= 0x0002;
717 					}
718 				}
719 
720 				//Linke Kante
721                 if ( bLeftOver )
722 				{
723 					if( bLeftValid )
724 					{
725 						aBox.SetLine( pLeft, BOX_LINE_LEFT );
726 						nType |= 0x0004;
727 					}
728 				}
729 				else if( bVertValid )
730 				{
731 					aBox.SetLine( pVert, BOX_LINE_LEFT );
732 					nType |= 0x0008;
733 				}
734 
735 				//Rechte Kante
736 				if( bRightValid )
737 				{
738                     if ( bRightOver )
739 					{
740 						aBox.SetLine( pRight, BOX_LINE_RIGHT );
741 						nType |= 0x0010;
742 					}
743 					else if ( bVertValid )
744 					{
745 						aBox.SetLine( 0, BOX_LINE_RIGHT );
746 						nType |= 0x0020;
747 					}
748 				}
749 
750 				//Untere Kante
751                 if ( bLast && bBottomOver )
752 				{
753 					if( bBottomValid )
754 					{
755 						aBox.SetLine( pBottom, BOX_LINE_BOTTOM );
756 						nType |= 0x0040;
757 					}
758 				}
759 				else if( bHoriValid )
760 				{
761 					aBox.SetLine( pHori, BOX_LINE_BOTTOM );
762 					nType |= 0x0080;
763 				}
764 
765 				if( pSetBox )
766 				{
767 					static sal_uInt16 __READONLY_DATA aBorders[] = {
768 						BOX_LINE_BOTTOM, BOX_LINE_TOP,
769 						BOX_LINE_RIGHT, BOX_LINE_LEFT };
770 					const sal_uInt16* pBrd = aBorders;
771 					for( int k = 0; k < 4; ++k, ++pBrd )
772 						aBox.SetDistance( pSetBox->GetDistance( *pBrd ), *pBrd );
773 				}
774 
775 				SwTableBox *pBox = (SwTableBox*)pCell->GetTabBox();
776 				SwFrmFmt *pNewFmt;
777 				if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), nType )))
778 					pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
779 				else
780 				{
781 					SwFrmFmt *pOld = pBox->GetFrmFmt();
782 					SwFrmFmt *pNew = pBox->ClaimFrmFmt();
783                     pNew->SetFmtAttr( aBox );
784 					aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, nType ), aFmtCmp.Count());
785 				}
786 			}
787 
788 			bFirst = sal_False;
789 		}
790 
791 		SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
792 		if( pTableLayout )
793 		{
794 			SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
795 			SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
796 
797 			pTableLayout->BordersChanged(
798 				pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
799 		}
800 		SwTblFmtCmp::Delete( aFmtCmp );
801 		::ClearFEShellTabCols();
802 		SetModified();
803 	}
804 }
805 
lcl_SetLineStyle(SvxBorderLine * pToSet,const Color * pColor,const SvxBorderLine * pBorderLine)806 void lcl_SetLineStyle( SvxBorderLine *pToSet,
807 						  const Color *pColor, const SvxBorderLine *pBorderLine)
808 {
809 	if ( pBorderLine )
810 	{
811 		if ( !pColor )
812 		{
813 			Color aTmp( pToSet->GetColor() );
814 			*pToSet = *pBorderLine;
815 			pToSet->SetColor( aTmp );
816 		}
817 		else
818 			*pToSet = *pBorderLine;
819 	}
820 	if ( pColor )
821 		pToSet->SetColor( *pColor );
822 }
823 
SetTabLineStyle(const SwCursor & rCursor,const Color * pColor,sal_Bool bSetLine,const SvxBorderLine * pBorderLine)824 void SwDoc::SetTabLineStyle( const SwCursor& rCursor,
825 							 const Color* pColor, sal_Bool bSetLine,
826 							 const SvxBorderLine* pBorderLine )
827 {
828 	SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
829 	SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
830 	if( !pTblNd )
831 		return ;
832 
833 	SwLayoutFrm *pStart, *pEnd;
834 	::lcl_GetStartEndCell( rCursor, pStart, pEnd );
835 
836 	SwSelUnions aUnions;
837 	::MakeSelUnions( aUnions, pStart, pEnd );
838 
839 	if( aUnions.Count() )
840 	{
841 		SwTable& rTable = pTblNd->GetTable();
842         if (GetIDocumentUndoRedo().DoesUndo())
843         {
844             GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd));
845         }
846 
847 		for( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
848 		{
849 			SwSelUnion *pUnion = aUnions[i];
850 			SwTabFrm *pTab = pUnion->GetTable();
851 			SvPtrarr aCellArr( 255, 255 );
852 			::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab );
853 
854 			for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
855 			{
856 				SwCellFrm *pCell = ( SwCellFrm* )aCellArr[j];
857 
858                 //Grundsaetzlich nichts setzen in HeadlineRepeats.
859                 if ( pTab->IsFollow() && pTab->IsInHeadline( *pCell ) )
860                     continue;
861 
862 				((SwTableBox*)pCell->GetTabBox())->ClaimFrmFmt();
863 				SwFrmFmt *pFmt = pCell->GetFmt();
864 				SvxBoxItem aBox( pFmt->GetBox() );
865 
866 				if ( !pBorderLine && bSetLine )
867 					aBox = *(SvxBoxItem*)::GetDfltAttr( RES_BOX );
868 				else
869 				{
870 					if ( aBox.GetTop() )
871 						::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetTop(),
872 										pColor, pBorderLine );
873 					if ( aBox.GetBottom() )
874 						::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetBottom(),
875 										pColor, pBorderLine );
876 					if ( aBox.GetLeft() )
877 						::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetLeft(),
878 										pColor, pBorderLine );
879 					if ( aBox.GetRight() )
880 						::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetRight(),
881 										pColor, pBorderLine );
882 				}
883                 pFmt->SetFmtAttr( aBox );
884 			}
885 		}
886 
887 		SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
888 		if( pTableLayout )
889 		{
890 			SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
891 			SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
892 
893 			pTableLayout->BordersChanged(
894 				pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
895 		}
896 		::ClearFEShellTabCols();
897 		SetModified();
898 	}
899 }
900 
GetTabBorders(const SwCursor & rCursor,SfxItemSet & rSet) const901 void SwDoc::GetTabBorders( const SwCursor& rCursor, SfxItemSet& rSet ) const
902 {
903 	SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
904 	SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
905 	if( !pTblNd )
906 		return ;
907 
908 	SwLayoutFrm *pStart, *pEnd;
909 	::lcl_GetStartEndCell( rCursor, pStart, pEnd );
910 
911 	SwSelUnions aUnions;
912 	::MakeSelUnions( aUnions, pStart, pEnd );
913 
914 	if( aUnions.Count() )
915 	{
916 		SvxBoxItem	   aSetBox	  ((const SvxBoxItem	&) rSet.Get(RES_BOX    ));
917 		SvxBoxInfoItem aSetBoxInfo((const SvxBoxInfoItem&) rSet.Get(SID_ATTR_BORDER_INNER));
918 
919 		sal_Bool bTopSet	  =	sal_False,
920 			 bBottomSet   =	sal_False,
921 			 bLeftSet	  =	sal_False,
922 			 bRightSet	  =	sal_False,
923 			 bHoriSet	  = sal_False,
924 			 bVertSet	  = sal_False,
925 			 bDistanceSet = sal_False;
926 
927 		aSetBoxInfo.ResetFlags();
928 
929 		for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
930 		{
931 			SwSelUnion *pUnion = aUnions[i];
932 			const SwTabFrm *pTab = pUnion->GetTable();
933 			const SwRect &rUnion = pUnion->GetUnion();
934 			const sal_Bool bFirst = i == 0 ? sal_True : sal_False;
935 			const sal_Bool bLast  = i == aUnions.Count() - 1 ? sal_True : sal_False;
936 
937 			SvPtrarr aCellArr( 255, 255 );
938 			::lcl_CollectCells( aCellArr, rUnion, (SwTabFrm*)pTab );
939 
940 			for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j )
941 			{
942 				const SwCellFrm *pCell = (const SwCellFrm*)aCellArr[j];
943                 const sal_Bool bVert = pTab->IsVertical();
944                 const sal_Bool bRTL = pTab->IsRightToLeft();
945                 sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver;
946                 if ( bVert )
947                 {
948                     bTopOver = pCell->Frm().Right() >= rUnion.Right();
949                     bLeftOver = pCell->Frm().Top() <= rUnion.Top();
950                     bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom();
951                     bBottomOver = pCell->Frm().Left() <= rUnion.Left();
952                 }
953                 else
954                 {
955                     bTopOver = pCell->Frm().Top() <= rUnion.Top();
956                     bLeftOver = pCell->Frm().Left() <= rUnion.Left();
957                     bRightOver = pCell->Frm().Right() >= rUnion.Right();
958                     bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom();
959                 }
960 
961                 if ( bRTL )
962                 {
963                     sal_Bool bTmp = bRightOver;
964                     bRightOver = bLeftOver;
965                     bLeftOver = bTmp;
966                 }
967 
968 				const SwFrmFmt	*pFmt  = pCell->GetFmt();
969 				const SvxBoxItem  &rBox  = pFmt->GetBox();
970 
971 				//Obere Kante
972                 if ( bFirst && bTopOver )
973 				{
974 					if (aSetBoxInfo.IsValid(VALID_TOP))
975 					{
976 						if ( !bTopSet )
977 						{	bTopSet = sal_True;
978 							aSetBox.SetLine( rBox.GetTop(), BOX_LINE_TOP );
979 						}
980 						else if ((aSetBox.GetTop() && rBox.GetTop() &&
981 								 !(*aSetBox.GetTop() == *rBox.GetTop())) ||
982 								 ((!aSetBox.GetTop()) ^ (!rBox.GetTop()))) // XOR-Ausdruck ist sal_True, wenn genau einer der beiden Pointer 0 ist
983 						{
984 							aSetBoxInfo.SetValid(VALID_TOP, sal_False );
985 							aSetBox.SetLine( 0, BOX_LINE_TOP );
986 						}
987 					}
988 				}
989 
990 				//Linke Kante
991                 if ( bLeftOver )
992                 {
993 					if (aSetBoxInfo.IsValid(VALID_LEFT))
994 					{
995 						if ( !bLeftSet )
996 						{	bLeftSet = sal_True;
997 							aSetBox.SetLine( rBox.GetLeft(), BOX_LINE_LEFT );
998 						}
999 						else if ((aSetBox.GetLeft() && rBox.GetLeft() &&
1000 								 !(*aSetBox.GetLeft() == *rBox.GetLeft())) ||
1001 								 ((!aSetBox.GetLeft()) ^ (!rBox.GetLeft())))
1002 						{
1003 							aSetBoxInfo.SetValid(VALID_LEFT, sal_False );
1004 							aSetBox.SetLine( 0, BOX_LINE_LEFT );
1005 						}
1006 					}
1007 				}
1008 				else
1009 				{
1010 					if (aSetBoxInfo.IsValid(VALID_VERT))
1011 					{
1012 						if ( !bVertSet )
1013 						{	bVertSet = sal_True;
1014 							aSetBoxInfo.SetLine( rBox.GetLeft(), BOXINFO_LINE_VERT );
1015 						}
1016 						else if ((aSetBoxInfo.GetVert() && rBox.GetLeft() &&
1017 								 !(*aSetBoxInfo.GetVert() == *rBox.GetLeft())) ||
1018 								 ((!aSetBoxInfo.GetVert()) ^ (!rBox.GetLeft())))
1019 						{	aSetBoxInfo.SetValid( VALID_VERT, sal_False );
1020 							aSetBoxInfo.SetLine( 0, BOXINFO_LINE_VERT );
1021 						}
1022 					}
1023 				}
1024 
1025 				//Rechte Kante
1026                 if ( aSetBoxInfo.IsValid(VALID_RIGHT) && bRightOver )
1027 				{
1028 					if ( !bRightSet )
1029 					{	bRightSet = sal_True;
1030 						aSetBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
1031 					}
1032 					else if ((aSetBox.GetRight() && rBox.GetRight() &&
1033 							 !(*aSetBox.GetRight() == *rBox.GetRight())) ||
1034 							 (!aSetBox.GetRight() ^ !rBox.GetRight()))
1035 					{	aSetBoxInfo.SetValid( VALID_RIGHT, sal_False );
1036 						aSetBox.SetLine( 0, BOX_LINE_RIGHT );
1037 					}
1038 				}
1039 
1040 				//Untere Kante
1041                 if ( bLast && bBottomOver )
1042 				{
1043 					if ( aSetBoxInfo.IsValid(VALID_BOTTOM) )
1044 					{
1045 						if ( !bBottomSet )
1046 						{	bBottomSet = sal_True;
1047 							aSetBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
1048 						}
1049 						else if ((aSetBox.GetBottom() && rBox.GetBottom() &&
1050 								 !(*aSetBox.GetBottom() == *rBox.GetBottom())) ||
1051 								 (!aSetBox.GetBottom() ^ !rBox.GetBottom()))
1052 						{	aSetBoxInfo.SetValid( VALID_BOTTOM, sal_False );
1053 							aSetBox.SetLine( 0, BOX_LINE_BOTTOM );
1054 						}
1055 					}
1056 				}
1057 				//in allen Zeilen ausser der letzten werden die
1058 				// horiz. Linien aus der Bottom-Linie entnommen
1059 				else
1060 				{
1061 					if (aSetBoxInfo.IsValid(VALID_HORI))
1062 					{
1063 						if ( !bHoriSet )
1064 						{	bHoriSet = sal_True;
1065 							aSetBoxInfo.SetLine( rBox.GetBottom(), BOXINFO_LINE_HORI );
1066 						}
1067 						else if ((aSetBoxInfo.GetHori() && rBox.GetBottom() &&
1068 								 !(*aSetBoxInfo.GetHori() == *rBox.GetBottom())) ||
1069 								 ((!aSetBoxInfo.GetHori()) ^ (!rBox.GetBottom())))
1070 						{
1071 							aSetBoxInfo.SetValid( VALID_HORI, sal_False );
1072 							aSetBoxInfo.SetLine( 0, BOXINFO_LINE_HORI );
1073 						}
1074 					}
1075 				}
1076 
1077 				// Abstand zum Text
1078 				if (aSetBoxInfo.IsValid(VALID_DISTANCE))
1079 				{
1080 					static sal_uInt16 __READONLY_DATA aBorders[] = {
1081 						BOX_LINE_BOTTOM, BOX_LINE_TOP,
1082 						BOX_LINE_RIGHT, BOX_LINE_LEFT };
1083 					const sal_uInt16* pBrd = aBorders;
1084 
1085 					if( !bDistanceSet )		// bei 1. Durchlauf erstmal setzen
1086 					{
1087 						bDistanceSet = sal_True;
1088 						for( int k = 0; k < 4; ++k, ++pBrd )
1089 							aSetBox.SetDistance( rBox.GetDistance( *pBrd ),
1090 												*pBrd );
1091 					}
1092 					else
1093 					{
1094 						for( int k = 0; k < 4; ++k, ++pBrd )
1095 							if( aSetBox.GetDistance( *pBrd ) !=
1096 								rBox.GetDistance( *pBrd ) )
1097 							{
1098 								aSetBoxInfo.SetValid( VALID_DISTANCE, sal_False );
1099 								aSetBox.SetDistance( (sal_uInt16) 0 );
1100 								break;
1101 							}
1102 					}
1103 				}
1104 			}
1105 		}
1106 		rSet.Put( aSetBox );
1107 		rSet.Put( aSetBoxInfo );
1108 	}
1109 }
1110 
1111 /***********************************************************************
1112 #*	Class	   :  SwDoc
1113 #*	Methoden   :  SetBoxAttr
1114 #*	Datum	   :  MA 18. Dec. 96
1115 #*	Update	   :  JP 29.04.98
1116 #***********************************************************************/
SetBoxAttr(const SwCursor & rCursor,const SfxPoolItem & rNew)1117 void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew )
1118 {
1119 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1120 	SwSelBoxes aBoxes;
1121 	if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes, sal_True ) )
1122 	{
1123 		SwTable& rTable = pTblNd->GetTable();
1124         if (GetIDocumentUndoRedo().DoesUndo())
1125         {
1126             GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) );
1127         }
1128 
1129 		SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aBoxes.Count()) ), 255 );
1130 		for ( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
1131 		{
1132 			SwTableBox *pBox = aBoxes[i];
1133 
1134 			SwFrmFmt *pNewFmt;
1135 			if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), 0 )))
1136 				pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
1137 			else
1138 			{
1139 				SwFrmFmt *pOld = pBox->GetFrmFmt();
1140 				SwFrmFmt *pNew = pBox->ClaimFrmFmt();
1141                 pNew->SetFmtAttr( rNew );
1142 				aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), aFmtCmp.Count());
1143 			}
1144 		}
1145 
1146 		SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
1147 		if( pTableLayout )
1148 		{
1149 			SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() );
1150 			SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm();
1151 
1152 			pTableLayout->Resize(
1153 				pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True );
1154 		}
1155 		SwTblFmtCmp::Delete( aFmtCmp );
1156 		SetModified();
1157 	}
1158 }
1159 
1160 /***********************************************************************
1161 #*	Class	   :  SwDoc
1162 #*  Methoden   :  GetBoxAttr()
1163 #*	Datum	   :  MA 01. Jun. 93
1164 #*	Update	   :  JP 29.04.98
1165 #***********************************************************************/
1166 
GetBoxAttr(const SwCursor & rCursor,SfxPoolItem & rToFill) const1167 sal_Bool SwDoc::GetBoxAttr( const SwCursor& rCursor, SfxPoolItem& rToFill ) const
1168 {
1169 	sal_Bool bRet = sal_False;
1170 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1171 	SwSelBoxes aBoxes;
1172 	if( pTblNd && lcl_GetBoxSel( rCursor, aBoxes ))
1173 	{
1174 		bRet = sal_True;
1175 		sal_Bool bOneFound = sal_False;
1176         const sal_uInt16 nWhich = rToFill.Which();
1177 		for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
1178 		{
1179             switch ( nWhich )
1180             {
1181                 case RES_BACKGROUND:
1182                 {
1183                     const SvxBrushItem &rBack =
1184                                     aBoxes[i]->GetFrmFmt()->GetBackground();
1185                     if( !bOneFound )
1186                     {
1187                         (SvxBrushItem&)rToFill = rBack;
1188                         bOneFound = sal_True;
1189                     }
1190                     else if( rToFill != rBack )
1191                         bRet = sal_False;
1192                 }
1193                 break;
1194 
1195                 case RES_FRAMEDIR:
1196                 {
1197                     const SvxFrameDirectionItem& rDir =
1198                                     aBoxes[i]->GetFrmFmt()->GetFrmDir();
1199                     if( !bOneFound )
1200                     {
1201                         (SvxFrameDirectionItem&)rToFill = rDir;
1202                         bOneFound = sal_True;
1203                     }
1204                     else if( rToFill != rDir )
1205                         bRet = sal_False;
1206                 }
1207             }
1208 
1209             if ( sal_False == bRet )
1210                 break;
1211 		}
1212 	}
1213 	return bRet;
1214 }
1215 
1216 /***********************************************************************
1217 #*	Class	   :  SwDoc
1218 #*	Methoden   :  SetBoxAlign, SetBoxAlign
1219 #*	Datum	   :  MA 18. Dec. 96
1220 #*	Update	   :  JP 29.04.98
1221 #***********************************************************************/
SetBoxAlign(const SwCursor & rCursor,sal_uInt16 nAlign)1222 void SwDoc::SetBoxAlign( const SwCursor& rCursor, sal_uInt16 nAlign )
1223 {
1224     ASSERT( nAlign == text::VertOrientation::NONE   ||
1225             nAlign == text::VertOrientation::CENTER ||
1226             nAlign == text::VertOrientation::BOTTOM, "wrong alignment" );
1227     SwFmtVertOrient aVertOri( 0, nAlign );
1228 	SetBoxAttr( rCursor, aVertOri );
1229 }
1230 
GetBoxAlign(const SwCursor & rCursor) const1231 sal_uInt16 SwDoc::GetBoxAlign( const SwCursor& rCursor ) const
1232 {
1233 	sal_uInt16 nAlign = USHRT_MAX;
1234 	SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode();
1235 	SwSelBoxes aBoxes;
1236 	if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes ))
1237 		for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i )
1238 		{
1239 			const SwFmtVertOrient &rOri =
1240 							aBoxes[i]->GetFrmFmt()->GetVertOrient();
1241 			if( USHRT_MAX == nAlign )
1242 				nAlign = static_cast<sal_uInt16>(rOri.GetVertOrient());
1243 			else if( rOri.GetVertOrient() != nAlign )
1244 			{
1245 				nAlign = USHRT_MAX;
1246 				break;
1247 			}
1248 		}
1249 	return nAlign;
1250 }
1251 
1252 
1253 /***********************************************************************
1254 #*	Class	   :  SwDoc
1255 #*	Methoden   :  AdjustCellWidth()
1256 #*	Datum	   :  MA 20. Feb. 95
1257 #*	Update	   :  JP 29.04.98
1258 #***********************************************************************/
lcl_CalcCellFit(const SwLayoutFrm * pCell)1259 sal_uInt16 lcl_CalcCellFit( const SwLayoutFrm *pCell )
1260 {
1261 	SwTwips nRet = 0;
1262 	const SwFrm *pFrm = pCell->Lower();	//Die ganze Zelle.
1263 	SWRECTFN( pCell )
1264 	while ( pFrm )
1265 	{
1266 		const SwTwips nAdd = (pFrm->Frm().*fnRect->fnGetWidth)() -
1267 							 (pFrm->Prt().*fnRect->fnGetWidth)();
1268 
1269         // --> FME 2005-12-02 #127801# pFrm does not necessarily have to be a SwTxtFrm!
1270         const SwTwips nCalcFitToContent = pFrm->IsTxtFrm() ?
1271                                           ((SwTxtFrm*)pFrm)->CalcFitToContent() :
1272                                           (pFrm->Prt().*fnRect->fnGetWidth)();
1273         // <--
1274 
1275         nRet = Max( nRet, nCalcFitToContent + nAdd );
1276         pFrm = pFrm->GetNext();
1277 	}
1278 	//Umrandung und linker/rechter Rand wollen mit kalkuliert werden.
1279 	nRet += (pCell->Frm().*fnRect->fnGetWidth)() -
1280 			(pCell->Prt().*fnRect->fnGetWidth)();
1281 
1282 	//Um Rechenungenauikeiten, die spaeter bei SwTable::SetTabCols enstehen,
1283 	//auszugleichen, addieren wir noch ein bischen.
1284 	nRet += COLFUZZY;
1285 	return (sal_uInt16)Max( long(MINLAY), nRet );
1286 }
1287 
1288 /*Die Zelle ist in der Selektion, wird aber nicht von den TabCols beschrieben.
1289  *Das bedeutet, dass die Zelle aufgrund der zweidimensionalen Darstellung von
1290  *anderen Zellen "geteilt" wurde. Wir muessen also den Wunsch- bzw. Minimalwert
1291  *der Zelle auf die Spalten, durch die sie geteilt wurde verteilen.
1292  *
1293  *Dazu sammeln wir zuerst die Spalten - nicht die Spaltentrenner! - ein, die
1294  *sich mit der Zelle ueberschneiden. Den Wunschwert der Zelle verteilen wir
1295  *dann anhand des Betrages der Ueberschneidung auf die Zellen.
1296  *Wenn eine Zelle bereits einen groesseren Wunschwert angemeldet hat, so bleibt
1297  *dieser erhalten, kleinere Wuensche werden ueberschrieben.
1298  */
1299 
lcl_CalcSubColValues(SvUShorts & rToFill,const SwTabCols & rCols,const SwLayoutFrm * pCell,const SwLayoutFrm * pTab,sal_Bool bWishValues)1300 void lcl_CalcSubColValues( SvUShorts &rToFill, const SwTabCols &rCols,
1301 							  const SwLayoutFrm *pCell, const SwLayoutFrm *pTab,
1302 							  sal_Bool bWishValues )
1303 {
1304 	const sal_uInt16 nWish = bWishValues ?
1305 					::lcl_CalcCellFit( pCell ) :
1306 					MINLAY + sal_uInt16(pCell->Frm().Width() - pCell->Prt().Width());
1307 
1308     SWRECTFN( pTab )
1309 
1310 	for ( sal_uInt16 i = 0 ; i <= rCols.Count(); ++i )
1311 	{
1312 		long nColLeft  = i == 0 			? rCols.GetLeft()  : rCols[i-1];
1313 		long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
1314 		nColLeft  += rCols.GetLeftMin();
1315 		nColRight += rCols.GetLeftMin();
1316 
1317 		//Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
1318         if ( rCols.GetLeftMin() !=  sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) )
1319 		{
1320             const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin();
1321 			nColLeft  += nDiff;
1322 			nColRight += nDiff;
1323 		}
1324         const long nCellLeft  = (pCell->Frm().*fnRect->fnGetLeft)();
1325         const long nCellRight = (pCell->Frm().*fnRect->fnGetRight)();
1326 
1327 		//Ueberschneidungsbetrag ermitteln.
1328 		long nWidth = 0;
1329 		if ( nColLeft <= nCellLeft && nColRight >= (nCellLeft+COLFUZZY) )
1330 			nWidth = nColRight - nCellLeft;
1331 		else if ( nColLeft <= (nCellRight-COLFUZZY) && nColRight >= nCellRight )
1332 			nWidth = nCellRight - nColLeft;
1333 		else if ( nColLeft >= nCellLeft && nColRight <= nCellRight )
1334 			nWidth = nColRight - nColLeft;
1335 		if ( nWidth && pCell->Frm().Width() )
1336 		{
1337 			long nTmp = nWidth * nWish / pCell->Frm().Width();
1338 			if ( sal_uInt16(nTmp) > rToFill[i] )
1339 				rToFill[i] = sal_uInt16(nTmp);
1340 		}
1341 	}
1342 }
1343 
1344 /*Besorgt neue Werte zu Einstellung der TabCols.
1345  *Es wird nicht ueber die Eintrage in den TabCols itereriert, sondern
1346  *quasi ueber die Zwischenraeume, die ja die Zellen beschreiben.
1347  *
1348  *bWishValues == sal_True:	Es werden zur aktuellen Selektion bzw. zur aktuellen
1349  *						Zelle die Wunschwerte aller betroffen Zellen ermittelt.
1350  * 						Sind mehrere Zellen in einer Spalte, so wird der
1351  *						groesste Wunschwert als Ergebnis geliefert.
1352  * 						Fuer die TabCol-Eintraege, zu denen keine Zellen
1353  * 						ermittelt wurden, werden 0-en eingetragen.
1354  *
1355  *bWishValues == sal_False: Die Selektion wird senkrecht ausgedehnt. Zu jeder
1356  * 						Spalte in den TabCols, die sich mit der Selektion
1357  *						schneidet wird der Minimalwert ermittelt.
1358  */
1359 
lcl_CalcColValues(SvUShorts & rToFill,const SwTabCols & rCols,const SwLayoutFrm * pStart,const SwLayoutFrm * pEnd,sal_Bool bWishValues)1360 void lcl_CalcColValues( SvUShorts &rToFill, const SwTabCols &rCols,
1361 						   const SwLayoutFrm *pStart, const SwLayoutFrm *pEnd,
1362 						   sal_Bool bWishValues )
1363 {
1364 	SwSelUnions aUnions;
1365 	::MakeSelUnions( aUnions, pStart, pEnd,
1366 					bWishValues ? nsSwTblSearchType::TBLSEARCH_NONE : nsSwTblSearchType::TBLSEARCH_COL );
1367 
1368 	for ( sal_uInt16 i2 = 0; i2 < aUnions.Count(); ++i2 )
1369 	{
1370 		SwSelUnion *pSelUnion = aUnions[i2];
1371 		const SwTabFrm *pTab = pSelUnion->GetTable();
1372 		const SwRect &rUnion = pSelUnion->GetUnion();
1373 
1374 		SWRECTFN( pTab )
1375         sal_Bool bRTL = pTab->IsRightToLeft();
1376 
1377 		const SwLayoutFrm *pCell = pTab->FirstCell();
1378 		do
1379 		{
1380             if ( pCell->IsCellFrm() && pCell->FindTabFrm() == pTab && ::IsFrmInTblSel( rUnion, pCell ) )
1381 			{
1382 				const long nCLeft  = (pCell->Frm().*fnRect->fnGetLeft)();
1383 				const long nCRight = (pCell->Frm().*fnRect->fnGetRight)();
1384 
1385 				sal_Bool bNotInCols = sal_True;
1386 
1387 				for ( sal_uInt16 i = 0; i <= rCols.Count(); ++i )
1388 				{
1389 					sal_uInt16 nFit = rToFill[i];
1390 					long nColLeft  = i == 0 			? rCols.GetLeft()  : rCols[i-1];
1391 					long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i];
1392 
1393                     if ( bRTL )
1394                     {
1395 						long nTmpRight = nColRight;
1396                         nColRight = rCols.GetRight() - nColLeft;
1397                         nColLeft = rCols.GetRight() - nTmpRight;
1398                     }
1399 
1400                     nColLeft  += rCols.GetLeftMin();
1401                     nColRight += rCols.GetLeftMin();
1402 
1403 					//Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
1404 					long nLeftA  = nColLeft;
1405 					long nRightA = nColRight;
1406 					if ( rCols.GetLeftMin() !=	sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) )
1407 					{
1408 						const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin();
1409 						nLeftA	+= nDiff;
1410 						nRightA += nDiff;
1411 					}
1412 
1413 					//Wir wollen nicht allzu genau hinsehen.
1414 					if ( ::IsSame(nCLeft, nLeftA) && ::IsSame(nCRight, nRightA))
1415 					{
1416 						bNotInCols = sal_False;
1417 						if ( bWishValues )
1418 						{
1419 							const sal_uInt16 nWish = ::lcl_CalcCellFit( pCell );
1420 							if ( nWish > nFit )
1421 								nFit = nWish;
1422 						}
1423 						else
1424 						{	const sal_uInt16 nMin = MINLAY + sal_uInt16(pCell->Frm().Width() -
1425 																pCell->Prt().Width());
1426 							if ( !nFit || nMin < nFit )
1427 								nFit = nMin;
1428 						}
1429 						if ( rToFill[i] < nFit )
1430 							rToFill[i] = nFit;
1431 					}
1432 				}
1433 				if ( bNotInCols )
1434 					::lcl_CalcSubColValues( rToFill, rCols, pCell, pTab, bWishValues );
1435 			}
1436             do {
1437                 pCell = pCell->GetNextLayoutLeaf();
1438             }while( pCell && pCell->Frm().Width() == 0 );
1439         } while ( pCell && pTab->IsAnLower( pCell ) );
1440 	}
1441 }
1442 
1443 
AdjustCellWidth(const SwCursor & rCursor,sal_Bool bBalance)1444 void SwDoc::AdjustCellWidth( const SwCursor& rCursor, sal_Bool bBalance )
1445 {
1446 	// pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
1447 	SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode();
1448 	SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0;
1449 	if( !pTblNd )
1450 		return ;
1451 
1452 	SwLayoutFrm *pStart, *pEnd;
1453 	::lcl_GetStartEndCell( rCursor, pStart, pEnd );
1454 
1455 	//TabCols besorgen, den ueber diese stellen wir die Tabelle neu ein.
1456 	SwFrm* pBoxFrm = pStart;
1457     while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1458 		pBoxFrm = pBoxFrm->GetUpper();
1459 
1460     if ( !pBoxFrm )
1461         return; // robust
1462 
1463 	SwTabCols aTabCols;
1464 	GetTabCols( aTabCols, 0, (SwCellFrm*)pBoxFrm );
1465 
1466     if ( ! aTabCols.Count() )
1467         return;
1468 
1469 	const sal_uInt8 nTmp = (sal_uInt8)Max( sal_uInt16(255), sal_uInt16(aTabCols.Count() + 1) );
1470 	SvUShorts aWish( nTmp, nTmp ),
1471 			  aMins( nTmp, nTmp );
1472 	sal_uInt16 i;
1473 
1474 	for ( i = 0; i <= aTabCols.Count(); ++i )
1475 	{
1476 		aWish.Insert( sal_uInt16(0), aWish.Count() );
1477 		aMins.Insert( sal_uInt16(0), aMins.Count() );
1478 	}
1479 	::lcl_CalcColValues( aWish, aTabCols, pStart, pEnd, sal_True  );
1480 
1481 	//Es ist Robuster wenn wir die Min-Werte fuer die ganze Tabelle berechnen.
1482 	const SwTabFrm *pTab = pStart->ImplFindTabFrm();
1483 	pStart = (SwLayoutFrm*)pTab->FirstCell();
1484 	pEnd   = (SwLayoutFrm*)pTab->FindLastCntnt()->GetUpper();
1485 	while( !pEnd->IsCellFrm() )
1486 		pEnd = pEnd->GetUpper();
1487 	::lcl_CalcColValues( aMins, aTabCols, pStart, pEnd, sal_False );
1488 
1489 	if( bBalance )
1490 	{
1491 		//Alle Spalten, die makiert sind haben jetzt einen Wunschwert
1492 		//eingtragen. Wir addieren die aktuellen Werte, teilen das Ergebnis
1493 		//durch die Anzahl und haben eine Wunschwert fuer den ausgleich.
1494 		sal_uInt16 nWish = 0, nCnt = 0;
1495 		for ( i = 0; i <= aTabCols.Count(); ++i )
1496 		{
1497 			int nDiff = aWish[i];
1498 			if ( nDiff )
1499 			{
1500 				if ( i == 0 )
1501 					nWish = static_cast<sal_uInt16>( nWish + aTabCols[i] - aTabCols.GetLeft() );
1502 				else if ( i == aTabCols.Count() )
1503 					nWish = static_cast<sal_uInt16>(nWish + aTabCols.GetRight() - aTabCols[i-1] );
1504 				else
1505 					nWish = static_cast<sal_uInt16>(nWish + aTabCols[i] - aTabCols[i-1] );
1506 				++nCnt;
1507 			}
1508 		}
1509 		nWish = nWish / nCnt;
1510 		for ( i = 0; i < aWish.Count(); ++i )
1511 			if ( aWish[i] )
1512 				aWish[i] = nWish;
1513 	}
1514 
1515 	const sal_uInt16 nOldRight = static_cast<sal_uInt16>(aTabCols.GetRight());
1516 
1517 	//Um die Impl. einfach zu gestalten, aber trotzdem in den meissten Faellen
1518 	//den Platz richtig auszunutzen laufen wir zweimal.
1519 	//Problem: Erste Spalte wird breiter, die anderen aber erst danach
1520 	//schmaler. Die Wunschbreite der ersten Spalte wuerde abgelehnt, weil
1521 	//mit ihr die max. Breite der Tabelle ueberschritten wuerde.
1522 	for ( sal_uInt16 k= 0; k < 2; ++k )
1523 	{
1524 		for ( i = 0; i <= aTabCols.Count(); ++i )
1525 		{
1526 			int nDiff = aWish[i];
1527 			if ( nDiff )
1528 			{
1529 				int nMin = aMins[i];
1530 				if ( nMin > nDiff )
1531 					nDiff = nMin;
1532 
1533 				if ( i == 0 )
1534 				{
1535 					if( aTabCols.Count() )
1536 						nDiff -= aTabCols[0] - aTabCols.GetLeft();
1537 					else
1538 						nDiff -= aTabCols.GetRight() - aTabCols.GetLeft();
1539 				}
1540 				else if ( i == aTabCols.Count() )
1541 					nDiff -= aTabCols.GetRight() - aTabCols[i-1];
1542 				else
1543 					nDiff -= aTabCols[i] - aTabCols[i-1];
1544 
1545                 long nTabRight = aTabCols.GetRight() + nDiff;
1546 
1547 				//Wenn die Tabelle zu breit wuerde begrenzen wir die Anpassung
1548 				//auf das erlaubte Maximum.
1549 				if ( !bBalance && nTabRight > aTabCols.GetRightMax() )
1550 				{
1551                     const long nTmpD = nTabRight - aTabCols.GetRightMax();
1552 					nDiff	  -= nTmpD;
1553 					nTabRight -= nTmpD;
1554 				}
1555 				for ( sal_uInt16 i2 = i; i2 < aTabCols.Count(); ++i2 )
1556 					aTabCols[i2] += nDiff;
1557 				aTabCols.SetRight( nTabRight );
1558 			}
1559 		}
1560 	}
1561 
1562 	const sal_uInt16 nNewRight = static_cast<sal_uInt16>(aTabCols.GetRight());
1563 
1564     SwFrmFmt *pFmt = pTblNd->GetTable().GetFrmFmt();
1565     const sal_Int16 nOriHori = pFmt->GetHoriOrient().GetHoriOrient();
1566 
1567 	//So, die richtige Arbeit koennen wir jetzt der SwTable ueberlassen.
1568 	SetTabCols( aTabCols, sal_False, 0, (SwCellFrm*)pBoxFrm );
1569 
1570     // i54248: lijian/fme
1571     // alignment might have been changed in SetTabCols, restore old value:
1572     const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
1573     SwFmtHoriOrient aHori( rHori );
1574     if ( aHori.GetHoriOrient() != nOriHori )
1575     {
1576         aHori.SetHoriOrient( nOriHori );
1577         pFmt->SetFmtAttr( aHori );
1578     }
1579 
1580     //Bei Automatischer Breite wird auf Linksbuendig umgeschaltet.
1581 	//Bei Randattributen wird der Rechte Rand angepasst.
1582 	if( !bBalance && nNewRight < nOldRight )
1583 	{
1584         if( aHori.GetHoriOrient() == text::HoriOrientation::FULL )
1585 		{
1586             aHori.SetHoriOrient( text::HoriOrientation::LEFT );
1587             pFmt->SetFmtAttr( aHori );
1588 		}
1589 	}
1590 
1591 	SetModified();
1592 }
1593 
1594