xref: /AOO41X/main/sw/source/core/docnode/ndtbl1.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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