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 <ctype.h>
28 #include <float.h>
29 #include <hintids.hxx>
30 #include <hints.hxx> // fuer SwAttrSetChg
31 #include <editeng/lrspitem.hxx>
32 #include <editeng/shaditem.hxx>
33 #include <editeng/adjitem.hxx>
34 #include <editeng/colritem.hxx>
35 #include <sfx2/linkmgr.hxx>
36 #include <editeng/boxitem.hxx>
37 #include <fmtfsize.hxx>
38 #include <fmtornt.hxx>
39 #include <fmtpdsc.hxx>
40 #include <fldbas.hxx>
41 #include <fmtfld.hxx>
42 #include <frmatr.hxx>
43 #include <doc.hxx>
44 #include <docary.hxx> // fuer RedlineTbl()
45 #include <frame.hxx>
46 #include <swtable.hxx>
47 #include <ndtxt.hxx>
48 #include <tabcol.hxx>
49 #include <tabfrm.hxx>
50 #include <cellfrm.hxx>
51 #include <rowfrm.hxx>
52 #include <swserv.hxx>
53 #include <expfld.hxx>
54 #include <mdiexp.hxx>
55 #include <cellatr.hxx>
56 #include <txatbase.hxx>
57 #include <htmltbl.hxx>
58 #include <swtblfmt.hxx>
59 #include <ndindex.hxx>
60 #include <tblrwcl.hxx>
61 #include <shellres.hxx>
62 #include <viewsh.hxx>
63 #include <redline.hxx>
64 #include <list>
65 #include <switerator.hxx>
66
67 #ifndef DBG_UTIL
68 #define CHECK_TABLE(t)
69 #else
70 #ifdef DEBUG
71 #define CHECK_TABLE(t) (t).CheckConsistency();
72 #else
73 #define CHECK_TABLE(t)
74 #endif
75 #endif
76
77 using namespace com::sun::star;
78
79 TYPEINIT1( SwTable, SwClient );
80 TYPEINIT1( SwTableBox, SwClient );
81 TYPEINIT1( SwTableLine, SwClient );
82
83 //UUUU
84 TYPEINIT1( SwTableFmt, SwFrmFmt );
85
SwTableFmt(SwAttrPool & rPool,const sal_Char * pFmtNm,SwFrmFmt * pDrvdFrm)86 SwTableFmt::SwTableFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm)
87 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableSetRange)
88 {
89 }
90
SwTableFmt(SwAttrPool & rPool,const String & rFmtNm,SwFrmFmt * pDrvdFrm)91 SwTableFmt::SwTableFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm)
92 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableSetRange)
93 {
94 }
95
~SwTableFmt()96 SwTableFmt::~SwTableFmt()
97 {
98 }
99
100 //UUUU Do not support for table frames - may change later if support will be added
supportsFullDrawingLayerFillAttributeSet() const101 bool SwTableFmt::supportsFullDrawingLayerFillAttributeSet() const
102 {
103 return false;
104 }
105
106 //UUUU
107 TYPEINIT1( SwTableBoxFmt, SwFrmFmt );
108
SwTableBoxFmt(SwAttrPool & rPool,const sal_Char * pFmtNm,SwFrmFmt * pDrvdFrm)109 SwTableBoxFmt::SwTableBoxFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm)
110 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableBoxSetRange)
111 {
112 }
113
SwTableBoxFmt(SwAttrPool & rPool,const String & rFmtNm,SwFrmFmt * pDrvdFrm)114 SwTableBoxFmt::SwTableBoxFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm)
115 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableBoxSetRange)
116 {
117 }
118
~SwTableBoxFmt()119 SwTableBoxFmt::~SwTableBoxFmt()
120 {
121 }
122
123 //UUUU Do not support for table frames - may change later if support will be added
supportsFullDrawingLayerFillAttributeSet() const124 bool SwTableBoxFmt::supportsFullDrawingLayerFillAttributeSet() const
125 {
126 return false;
127 }
128
129 //UUUU
130 TYPEINIT1( SwTableLineFmt, SwFrmFmt );
131
SwTableLineFmt(SwAttrPool & rPool,const sal_Char * pFmtNm,SwFrmFmt * pDrvdFrm)132 SwTableLineFmt::SwTableLineFmt(SwAttrPool& rPool,const sal_Char* pFmtNm, SwFrmFmt *pDrvdFrm)
133 : SwFrmFmt(rPool,pFmtNm,pDrvdFrm,RES_FRMFMT,aTableLineSetRange)
134 {
135 }
136
SwTableLineFmt(SwAttrPool & rPool,const String & rFmtNm,SwFrmFmt * pDrvdFrm)137 SwTableLineFmt::SwTableLineFmt(SwAttrPool& rPool,const String &rFmtNm, SwFrmFmt *pDrvdFrm)
138 : SwFrmFmt(rPool,rFmtNm,pDrvdFrm,RES_FRMFMT,aTableLineSetRange)
139 {
140 }
141
~SwTableLineFmt()142 SwTableLineFmt::~SwTableLineFmt()
143 {
144 }
145
146 //UUUU Do not support for table frames - may change later if support will be added
supportsFullDrawingLayerFillAttributeSet() const147 bool SwTableLineFmt::supportsFullDrawingLayerFillAttributeSet() const
148 {
149 return false;
150 }
151
152 SV_IMPL_PTRARR(SwTableLines,SwTableLine*);
153 SV_IMPL_PTRARR(SwTableBoxes,SwTableBox*);
154 SV_IMPL_PTRARR_SORT(SwTableSortBoxes,SwTableBoxPtr);
155
156 SV_IMPL_REF( SwServerObject )
157
158 #define COLFUZZY 20
159
160 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
161 sal_Bool bChgAlign,sal_uLong nNdPos );
162 //----------------------------------
163
164 class SwTableBox_Impl
165 {
166 Color *mpUserColor, *mpNumFmtColor;
167 long mnRowSpan;
168 bool mbDummyFlag;
169
170 void SetNewCol( Color** ppCol, const Color* pNewCol );
171 public:
SwTableBox_Impl()172 SwTableBox_Impl() : mpUserColor(0), mpNumFmtColor(0), mnRowSpan(1),
173 mbDummyFlag( false ) {}
~SwTableBox_Impl()174 ~SwTableBox_Impl() { delete mpUserColor; delete mpNumFmtColor; }
175
GetSaveUserColor() const176 const Color* GetSaveUserColor() const { return mpUserColor; }
GetSaveNumFmtColor() const177 const Color* GetSaveNumFmtColor() const { return mpNumFmtColor; }
SetSaveUserColor(const Color * p)178 void SetSaveUserColor(const Color* p ) { SetNewCol( &mpUserColor, p ); }
SetSaveNumFmtColor(const Color * p)179 void SetSaveNumFmtColor( const Color* p ) { SetNewCol( &mpNumFmtColor, p ); }
getRowSpan() const180 long getRowSpan() const { return mnRowSpan; }
setRowSpan(long nNewRowSpan)181 void setRowSpan( long nNewRowSpan ) { mnRowSpan = nNewRowSpan; }
getDummyFlag() const182 bool getDummyFlag() const { return mbDummyFlag; }
setDummyFlag(bool bDummy)183 void setDummyFlag( bool bDummy ) { mbDummyFlag = bDummy; }
184 };
185
186 // ----------- Inlines -----------------------------
187
GetSaveUserColor() const188 inline const Color* SwTableBox::GetSaveUserColor() const
189 {
190 return pImpl ? pImpl->GetSaveUserColor() : 0;
191 }
192
GetSaveNumFmtColor() const193 inline const Color* SwTableBox::GetSaveNumFmtColor() const
194 {
195 return pImpl ? pImpl->GetSaveNumFmtColor() : 0;
196 }
197
SetSaveUserColor(const Color * p)198 inline void SwTableBox::SetSaveUserColor(const Color* p )
199 {
200 if( pImpl )
201 pImpl->SetSaveUserColor( p );
202 else if( p )
203 ( pImpl = new SwTableBox_Impl ) ->SetSaveUserColor( p );
204 }
205
SetSaveNumFmtColor(const Color * p)206 inline void SwTableBox::SetSaveNumFmtColor( const Color* p )
207 {
208 if( pImpl )
209 pImpl->SetSaveNumFmtColor( p );
210 else if( p )
211 ( pImpl = new SwTableBox_Impl )->SetSaveNumFmtColor( p );
212 }
213
getRowSpan() const214 long SwTableBox::getRowSpan() const
215 {
216 return pImpl ? pImpl->getRowSpan() : 1;
217 }
218
setRowSpan(long nNewRowSpan)219 void SwTableBox::setRowSpan( long nNewRowSpan )
220 {
221 if( !pImpl )
222 {
223 if( nNewRowSpan == 1 )
224 return;
225 pImpl = new SwTableBox_Impl();
226 }
227 pImpl->setRowSpan( nNewRowSpan );
228 }
229
getDummyFlag() const230 bool SwTableBox::getDummyFlag() const
231 {
232 return pImpl ? pImpl->getDummyFlag() : false;
233 }
234
setDummyFlag(bool bDummy)235 void SwTableBox::setDummyFlag( bool bDummy )
236 {
237 if( !pImpl )
238 {
239 if( !bDummy )
240 return;
241 pImpl = new SwTableBox_Impl();
242 }
243 pImpl->setDummyFlag( bDummy );
244 }
245
246 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten)
lcl_TabToBlankAtSttEnd(String & rTxt)247 String& lcl_TabToBlankAtSttEnd( String& rTxt )
248 {
249 sal_Unicode c;
250 xub_StrLen n;
251
252 for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
253 if( '\x9' == c )
254 rTxt.SetChar( n, ' ' );
255 for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
256 if( '\x9' == c )
257 rTxt.SetChar( n, ' ' );
258 return rTxt;
259 }
260
lcl_DelTabsAtSttEnd(String & rTxt)261 String& lcl_DelTabsAtSttEnd( String& rTxt )
262 {
263 sal_Unicode c;
264 xub_StrLen n;
265
266 for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
267 if( '\x9' == c )
268 rTxt.Erase( n--, 1 );
269 for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
270 if( '\x9' == c )
271 rTxt.Erase( n, 1 );
272 return rTxt;
273 }
274
_InsTblBox(SwDoc * pDoc,SwTableNode * pTblNd,SwTableLine * pLine,SwTableBoxFmt * pBoxFrmFmt,SwTableBox * pBox,sal_uInt16 nInsPos,sal_uInt16 nCnt)275 void _InsTblBox( SwDoc* pDoc, SwTableNode* pTblNd,
276 SwTableLine* pLine, SwTableBoxFmt* pBoxFrmFmt,
277 SwTableBox* pBox,
278 sal_uInt16 nInsPos, sal_uInt16 nCnt )
279 {
280 ASSERT( pBox->GetSttNd(), "Box ohne Start-Node" );
281 SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
282 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
283 if( !pCNd )
284 pCNd = pDoc->GetNodes().GoNext( &aIdx );
285 ASSERT( pCNd, "Box ohne ContentNode" );
286
287 if( pCNd->IsTxtNode() )
288 {
289 if( pBox->GetSaveNumFmtColor() && pCNd->GetpSwAttrSet() )
290 {
291 SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
292 if( pBox->GetSaveUserColor() )
293 aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
294 else
295 aAttrSet.ClearItem( RES_CHRATR_COLOR );
296 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
297 ((SwTxtNode*)pCNd)->GetTxtColl(),
298 &aAttrSet, nInsPos, nCnt );
299 }
300 else
301 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
302 ((SwTxtNode*)pCNd)->GetTxtColl(),
303 pCNd->GetpSwAttrSet(),
304 nInsPos, nCnt );
305 }
306 else
307 pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
308 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0,
309 nInsPos, nCnt );
310
311 long nRowSpan = pBox->getRowSpan();
312 if( nRowSpan != 1 )
313 {
314 SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
315 for( sal_uInt16 i = 0; i < nCnt; ++i )
316 {
317 pBox = rTblBoxes[ i + nInsPos ];
318 pBox->setRowSpan( nRowSpan );
319 }
320 }
321 }
322
323 /*************************************************************************
324 |*
325 |* SwTable::SwTable()
326 |*
327 |*************************************************************************/
SwTable(SwTableFmt * pFmt)328 SwTable::SwTable( SwTableFmt* pFmt )
329 : SwClient( pFmt ),
330 pHTMLLayout( 0 ),
331 pTableNode( 0 ),
332 nGrfsThatResize( 0 ),
333 nRowsToRepeat( 1 ),
334 bModifyLocked( sal_False ),
335 bNewModel( sal_True )
336 {
337 // default Wert aus den Optionen setzen
338 eTblChgMode = (TblChgMode)GetTblChgDefaultMode();
339 }
340
SwTable(const SwTable & rTable)341 SwTable::SwTable( const SwTable& rTable )
342 : SwClient( rTable.GetFrmFmt() ),
343 pHTMLLayout( 0 ),
344 pTableNode( 0 ),
345 eTblChgMode( rTable.eTblChgMode ),
346 nGrfsThatResize( 0 ),
347 nRowsToRepeat( rTable.GetRowsToRepeat() ),
348 bModifyLocked( sal_False ),
349 bNewModel( rTable.bNewModel )
350 {
351 }
352
DelBoxNode(SwTableSortBoxes & rSortCntBoxes)353 void DelBoxNode( SwTableSortBoxes& rSortCntBoxes )
354 {
355 for( sal_uInt16 n = 0; n < rSortCntBoxes.Count(); ++n )
356 rSortCntBoxes[ n ]->pSttNd = 0;
357 }
358
~SwTable()359 SwTable::~SwTable()
360 {
361 if( refObj.Is() )
362 {
363 SwDoc* pDoc = GetFrmFmt()->GetDoc();
364 if( !pDoc->IsInDtor() ) // dann aus der Liste entfernen
365 pDoc->GetLinkManager().RemoveServer( &refObj );
366
367 refObj->Closed();
368 }
369
370 // ist die Tabelle der letzte Client im FrameFormat, kann dieses
371 // geloescht werden
372 SwTableFmt* pFmt = (SwTableFmt*)GetFrmFmt();
373 pFmt->Remove( this ); // austragen,
374
375 if( !pFmt->GetDepends() )
376 pFmt->GetDoc()->DelTblFrmFmt( pFmt ); // und loeschen
377
378 // Loesche die Pointer aus dem SortArray der Boxen, die
379 // Objecte bleiben erhalten und werden vom DTOR der Lines/Boxes
380 // Arrays geloescht.
381 //JP: reicht leider nicht, es muessen die Pointer auf den StartNode
382 // der Section geloescht werden
383 DelBoxNode( aSortCntBoxes );
384 aSortCntBoxes.Remove( (sal_uInt16)0, aSortCntBoxes.Count() );
385 delete pHTMLLayout;
386 }
387
388 /*************************************************************************
389 |*
390 |* SwTable::Modify()
391 |*
392 |*************************************************************************/
FmtInArr(SvPtrarr & rFmtArr,SwFmt * pBoxFmt)393 inline void FmtInArr( SvPtrarr& rFmtArr, SwFmt* pBoxFmt )
394 {
395 sal_Bool bRet = USHRT_MAX != rFmtArr.GetPos( (VoidPtr)pBoxFmt );
396 if( !bRet )
397 rFmtArr.Insert( (VoidPtr)pBoxFmt, rFmtArr.Count() );
398 }
399
400 void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
401 const long nNew, SvPtrarr& rFmtArr );
402
lcl_ModifyLines(SwTableLines & rLines,const long nOld,const long nNew,SvPtrarr & rFmtArr,const bool bCheckSum)403 void lcl_ModifyLines( SwTableLines &rLines, const long nOld,
404 const long nNew, SvPtrarr& rFmtArr, const bool bCheckSum )
405 {
406 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
407 ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFmtArr );
408 if( bCheckSum )
409 {
410 for( sal_uInt16 i = 0; i < rFmtArr.Count(); ++i )
411 {
412 SwFmt* pFmt = (SwFmt*)rFmtArr[i];
413 sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
414 nBox *= nNew;
415 nBox /= nOld;
416 SwFmtFrmSize aNewBox( ATT_VAR_SIZE, SwTwips(nBox), 0 );
417 pFmt->LockModify();
418 pFmt->SetFmtAttr( aNewBox );
419 pFmt->UnlockModify();
420 }
421 }
422 }
423
lcl_ModifyBoxes(SwTableBoxes & rBoxes,const long nOld,const long nNew,SvPtrarr & rFmtArr)424 void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
425 const long nNew, SvPtrarr& rFmtArr )
426 {
427 sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
428 sal_uInt64 nOriginalSum = 0; // Sum of original widths
429 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
430 {
431 SwTableBox &rBox = *rBoxes[i];
432 if ( rBox.GetTabLines().Count() )
433 {
434 // For SubTables the rounding problem will not be solved :-(
435 ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFmtArr, false );
436 }
437 //Die Box anpassen
438 SwFrmFmt *pFmt = rBox.GetFrmFmt();
439 sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
440 nOriginalSum += nBox;
441 nBox *= nNew;
442 nBox /= nOld;
443 sal_uInt64 nWishedSum = nOriginalSum;
444 nWishedSum *= nNew;
445 nWishedSum /= nOld;
446 nWishedSum -= nSum;
447 if( nWishedSum > 0 )
448 {
449 if( nBox == nWishedSum )
450 FmtInArr( rFmtArr, pFmt );
451 else
452 {
453 nBox = nWishedSum;
454 pFmt = rBox.ClaimFrmFmt();
455 SwFmtFrmSize aNewBox( ATT_VAR_SIZE, static_cast< SwTwips >(nBox), 0 );
456 pFmt->LockModify();
457 pFmt->SetFmtAttr( aNewBox );
458 pFmt->UnlockModify();
459 }
460 }
461 else {
462 ASSERT( false, "Rounding error" );
463 }
464 nSum += nBox;
465 }
466 }
467
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)468 void SwTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
469 {
470 // fange SSize Aenderungen ab, um die Lines/Boxen anzupassen
471 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
472 const SwFmtFrmSize* pNewSize = 0, *pOldSize = 0;
473
474 if( RES_ATTRSET_CHG == nWhich )
475 {
476 if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
477 RES_FRM_SIZE, sal_False, (const SfxPoolItem**)&pNewSize ))
478 pOldSize = &((SwAttrSetChg*)pOld)->GetChgSet()->GetFrmSize();
479 }
480 else if( RES_FRM_SIZE == nWhich )
481 {
482 pOldSize = (const SwFmtFrmSize*)pOld;
483 pNewSize = (const SwFmtFrmSize*)pNew;
484 }
485 else
486 CheckRegistration( pOld, pNew );
487
488 if( pOldSize || pNewSize )
489 {
490 if ( !IsModifyLocked() )
491 {
492 ASSERT( pOldSize && pOldSize->Which() == RES_FRM_SIZE &&
493 pNewSize && pNewSize->Which() == RES_FRM_SIZE,
494 "Kein Old oder New fuer FmtFrmSize-Modify der SwTable." );
495 AdjustWidths( pOldSize->GetWidth(), pNewSize->GetWidth() );
496 }
497 }
498 }
499
AdjustWidths(const long nOld,const long nNew)500 void SwTable::AdjustWidths( const long nOld, const long nNew )
501 {
502 SvPtrarr aFmtArr( (sal_uInt8)aLines[0]->GetTabBoxes().Count(), 1 );
503 ::lcl_ModifyLines( aLines, nOld, nNew, aFmtArr, true );
504 }
505
506 /*************************************************************************
507 |*
508 |* SwTable::GetTabCols()
509 |*
510 |*************************************************************************/
lcl_RefreshHidden(SwTabCols & rToFill,sal_uInt16 nPos)511 void lcl_RefreshHidden( SwTabCols &rToFill, sal_uInt16 nPos )
512 {
513 for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
514 {
515 if ( Abs((long)(nPos - rToFill[i])) <= COLFUZZY )
516 {
517 rToFill.SetHidden( i, sal_False );
518 break;
519 }
520 }
521 }
522
lcl_SortedTabColInsert(SwTabCols & rToFill,const SwTableBox * pBox,const SwFrmFmt * pTabFmt,const sal_Bool bHidden,const FASTBOOL bRefreshHidden)523 void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
524 const SwFrmFmt *pTabFmt, const sal_Bool bHidden,
525 const FASTBOOL bRefreshHidden )
526 {
527 const long nWish = pTabFmt->GetFrmSize().GetWidth();
528 const long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why?
529
530 //Der Wert fuer die linke Kante der Box errechnet sich aus den
531 //Breiten der vorhergehenden Boxen.
532 sal_uInt16 nPos = 0;
533 sal_uInt16 nSum = 0;
534 sal_uInt16 nLeftMin = 0;
535 sal_uInt16 nRightMax = 0;
536 const SwTableBox *pCur = pBox;
537 const SwTableLine *pLine = pBox->GetUpper();
538 while ( pLine )
539 { const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
540 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
541 {
542 SwTwips nWidth = rBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
543 nSum = (sal_uInt16)(nSum + nWidth);
544 sal_uInt64 nTmp = nSum;
545 nTmp *= nAct;
546 nTmp /= nWish;
547 if (rBoxes[i] != pCur)
548 {
549 if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
550 nLeftMin = (sal_uInt16)(nTmp - nPos);
551 nPos = (sal_uInt16)nTmp;
552 }
553 else
554 {
555 nSum = (sal_uInt16)(nSum - nWidth);
556 if ( 0 == nRightMax )
557 nRightMax = (sal_uInt16)(nTmp - nPos);
558 break;
559 }
560 }
561 pCur = pLine->GetUpper();
562 pLine = pCur ? pCur->GetUpper() : 0;
563 }
564
565 sal_Bool bInsert = !bRefreshHidden;
566 for ( sal_uInt16 j = 0; bInsert && (j < rToFill.Count()); ++j )
567 {
568 long nCmp = rToFill[j];
569 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
570 (nPos <= (nCmp + COLFUZZY)) )
571 {
572 bInsert = sal_False; //Hat ihn schon.
573 }
574 else if ( nPos < nCmp )
575 {
576 bInsert = sal_False;
577 rToFill.Insert( nPos, bHidden, j );
578 }
579 }
580 if ( bInsert )
581 rToFill.Insert( nPos, bHidden, rToFill.Count() );
582 else if ( bRefreshHidden )
583 ::lcl_RefreshHidden( rToFill, nPos );
584
585 if ( bHidden && !bRefreshHidden )
586 {
587 // calculate minimum/maximum values for the existing entries:
588 nLeftMin = nPos - nLeftMin;
589 nRightMax = nPos + nRightMax;
590
591 // check if nPos is entry:
592 bool bFoundPos = false;
593 bool bFoundMax = false;
594 for ( sal_uInt16 j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
595 {
596 SwTabColsEntry& rEntry = rToFill.GetEntry( j );
597 long nCmp = rToFill[j];
598
599 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
600 (nPos <= (nCmp + COLFUZZY)) )
601 {
602 // check if nLeftMin is > old minimum for entry nPos:
603 const long nOldMin = rEntry.nMin;
604 if ( nLeftMin > nOldMin )
605 rEntry.nMin = nLeftMin;
606 // check if nRightMin is < old maximum for entry nPos:
607 const long nOldMax = rEntry.nMax;
608 if ( nRightMax < nOldMax )
609 rEntry.nMax = nRightMax;
610
611 bFoundPos = true;
612 }
613 else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
614 (nRightMax <= (nCmp + COLFUZZY)) )
615 {
616 // check if nPos is > old minimum for entry nRightMax:
617 const long nOldMin = rEntry.nMin;
618 if ( nPos > nOldMin )
619 rEntry.nMin = nPos;
620
621 bFoundMax = true;
622 }
623 }
624 }
625 }
626
lcl_ProcessBoxGet(const SwTableBox * pBox,SwTabCols & rToFill,const SwFrmFmt * pTabFmt,FASTBOOL bRefreshHidden)627 void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
628 const SwFrmFmt *pTabFmt, FASTBOOL bRefreshHidden )
629 {
630 if ( pBox->GetTabLines().Count() )
631 {
632 const SwTableLines &rLines = pBox->GetTabLines();
633 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
634 { const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
635 for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
636 ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFmt, bRefreshHidden);
637 }
638 }
639 else
640 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_False, bRefreshHidden );
641 }
642
lcl_ProcessLineGet(const SwTableLine * pLine,SwTabCols & rToFill,const SwFrmFmt * pTabFmt)643 void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
644 const SwFrmFmt *pTabFmt )
645 {
646 for ( sal_uInt16 i = 0; i < pLine->GetTabBoxes().Count(); ++i )
647 {
648 const SwTableBox *pBox = pLine->GetTabBoxes()[i];
649 if ( pBox->GetSttNd() )
650 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_True, sal_False );
651 else
652 for ( sal_uInt16 j = 0; j < pBox->GetTabLines().Count(); ++j )
653 ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFmt );
654 }
655 }
656
657 // MS: Sonst Absturz auf der DEC-Kiste
658 //
659 #if defined(ALPHA) && defined(WNT)
660 #pragma optimize("", off)
661 #endif
662
GetTabCols(SwTabCols & rToFill,const SwTableBox * pStart,sal_Bool bRefreshHidden,sal_Bool bCurRowOnly) const663 void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
664 sal_Bool bRefreshHidden, sal_Bool bCurRowOnly ) const
665 {
666 //MA 30. Nov. 95: Opt: wenn bHidden gesetzt ist, wird nur das Hidden
667 //Array aktualisiert.
668 if ( bRefreshHidden )
669 {
670 //Korrekturen entfernen
671 sal_uInt16 i;
672 for ( i = 0; i < rToFill.Count(); ++i )
673 {
674 SwTabColsEntry& rEntry = rToFill.GetEntry( i );
675 rEntry.nPos -= rToFill.GetLeft();
676 rEntry.nMin -= rToFill.GetLeft();
677 rEntry.nMax -= rToFill.GetLeft();
678 }
679
680 //Alle sind hidden, dann die sichtbaren eintragen.
681 for ( i = 0; i < rToFill.Count(); ++i )
682 rToFill.SetHidden( i, sal_True );
683 }
684 else
685 {
686 rToFill.Remove( 0, rToFill.Count() );
687 }
688
689 //Eingetragen werden:
690 //1. Alle Boxen unterhalb der dem Start uebergeordneten Line sowie
691 // deren untergeordnete Boxen falls vorhanden.
692 //2. Ausgehend von der Line die uebergeordnete Box sowie deren Nachbarn;
693 // nicht aber deren untergeordnete.
694 //3. Mit der der Boxenkette uebergeordneten Line wieder wie 2. bis einer
695 // Line keine Box (sondern die Table) uebergeordnet ist.
696 //Es werden nur diejenigen Boxen eingetragen, die keine weiteren Zeilen
697 //enhalten. Die eintragende Funktion sorgt dafuer, dass keine doppelten
698 //eingetragen werden. Um dies zu gewaehrleisten wird mit einer gewissen
699 //Unschaerfe gearbeitet (um Rundungsfehler auszuschalten).
700 //Es werden nur die linken Kanten der Boxen eingetragen.
701 //Am Schluss wird der Erste wieder ausgetragen denn er ist bereits vom
702 //Rand abgedeckt.
703
704 //4. Nochmalige abscannen der Tabelle und eintragen _aller_ Boxen,
705 // jetzt aber als Hidden.
706
707 const SwFrmFmt *pTabFmt = GetFrmFmt();
708
709 //1.
710 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
711
712 sal_uInt16 i;
713 for ( i = 0; i < rBoxes.Count(); ++i )
714 ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFmt, bRefreshHidden );
715
716 //2. und 3.
717 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
718 pStart->GetUpper()->GetUpper()->GetUpper() : 0;
719 while ( pLine )
720 {
721 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
722 for ( sal_uInt16 k = 0; k < rBoxes2.Count(); ++k )
723 ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
724 pTabFmt, sal_False, bRefreshHidden );
725 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
726 }
727
728 if ( !bRefreshHidden )
729 {
730 //4.
731 if ( !bCurRowOnly )
732 {
733 for ( i = 0; i < aLines.Count(); ++i )
734 ::lcl_ProcessLineGet( aLines[i], rToFill, pTabFmt );
735 }
736
737 rToFill.Remove( 0, 1 );
738 }
739
740 //Die Koordinaten sind jetzt relativ zum linken Rand der Tabelle - also
741 //relativ zum nLeft vom SwTabCols. Die Werte werden aber relativ zum
742 //linken Rand - also nLeftMin vom SwTabCols - erwartet.
743 //Alle Werte muessen also um nLeft erweitert werden.
744 for ( i = 0; i < rToFill.Count(); ++i )
745 {
746 SwTabColsEntry& rEntry = rToFill.GetEntry( i );
747 rEntry.nPos += rToFill.GetLeft();
748 rEntry.nMin += rToFill.GetLeft();
749 rEntry.nMax += rToFill.GetLeft();
750 }
751 }
752
753 #if defined(ALPHA) && defined(WNT)
754 #pragma optimize("", on)
755 #endif
756
757 /*************************************************************************
758 |*
759 |* SwTable::SetTabCols()
760 |*
761 |*************************************************************************/
762 //Struktur zur Parameteruebergabe
763 struct Parm
764 {
765 const SwTabCols &rNew;
766 const SwTabCols &rOld;
767 long nNewWish,
768 nOldWish;
769 SvPtrarr aBoxArr;
770 SwShareBoxFmts aShareFmts;
771
ParmParm772 Parm( const SwTabCols &rN, const SwTabCols &rO ) :
773 rNew( rN ), rOld( rO ), aBoxArr( 10, 1 ) {}
774 };
BoxInArr(SvPtrarr & rArr,SwTableBox * pBox)775 inline sal_Bool BoxInArr( SvPtrarr& rArr, SwTableBox* pBox )
776 {
777 sal_Bool bRet = USHRT_MAX != rArr.GetPos( (VoidPtr)pBox );
778 if( !bRet )
779 rArr.Insert( (VoidPtr)pBox, rArr.Count() );
780 return bRet;
781 }
782
783 void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
784
lcl_ProcessLine(SwTableLine * pLine,Parm & rParm)785 void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
786 {
787 SwTableBoxes &rBoxes = pLine->GetTabBoxes();
788 for ( int i = rBoxes.Count()-1; i >= 0; --i )
789 ::lcl_ProcessBoxSet( rBoxes[ static_cast< sal_uInt16 >(i) ], rParm );
790 }
791
lcl_ProcessBoxSet(SwTableBox * pBox,Parm & rParm)792 void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
793 {
794 if ( pBox->GetTabLines().Count() )
795 { SwTableLines &rLines = pBox->GetTabLines();
796 for ( int i = rLines.Count()-1; i >= 0; --i )
797 lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], rParm );
798 }
799 else
800 {
801 //Aktuelle Position (linke und rechte Kante berechnen) und im
802 //alten TabCols suchen. Im neuen TabCols die Werte vergleichen und
803 //wenn es Unterschiede gibt die Box entsprechend anpassen.
804 //Wenn an der veraenderten Kante kein Nachbar existiert werden auch
805 //alle uebergeordneten Boxen angepasst.
806
807 const long nOldAct = rParm.rOld.GetRight() -
808 rParm.rOld.GetLeft(); // +1 why?
809
810 //Der Wert fuer die linke Kante der Box errechnet sich aus den
811 //Breiten der vorhergehenden Boxen plus dem linken Rand
812 long nLeft = rParm.rOld.GetLeft();
813 const SwTableBox *pCur = pBox;
814 const SwTableLine *pLine = pBox->GetUpper();
815
816 while ( pLine )
817 { const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
818 for ( sal_uInt16 i = 0; (i < rBoxes.Count()) && (rBoxes[i] != pCur); ++i)
819 {
820 sal_uInt64 nWidth = rBoxes[i]->GetFrmFmt()->
821 GetFrmSize().GetWidth();
822 nWidth *= nOldAct;
823 nWidth /= rParm.nOldWish;
824 nLeft += (sal_uInt16)nWidth;
825 }
826 pCur = pLine->GetUpper();
827 pLine = pCur ? pCur->GetUpper() : 0;
828 }
829 long nLeftDiff;
830 long nRightDiff = 0;
831 if ( nLeft != rParm.rOld.GetLeft() ) //Es gibt noch Boxen davor.
832 {
833 //Rechte Kante ist linke Kante plus Breite.
834 sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
835 nWidth *= nOldAct;
836 nWidth /= rParm.nOldWish;
837 long nRight = nLeft + (long)nWidth;
838 sal_uInt16 nLeftPos = USHRT_MAX,
839 nRightPos = USHRT_MAX;
840 for ( sal_uInt16 i = 0; i < rParm.rOld.Count(); ++i )
841 {
842 if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
843 nLeft <= (rParm.rOld[i] + COLFUZZY) )
844 nLeftPos = i;
845 else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
846 nRight <= (rParm.rOld[i] + COLFUZZY) )
847 nRightPos = i;
848 }
849 nLeftDiff = nLeftPos != USHRT_MAX ?
850 (int)rParm.rOld[nLeftPos] - (int)rParm.rNew[nLeftPos] : 0;
851 nRightDiff= nRightPos!= USHRT_MAX ?
852 (int)rParm.rNew[nRightPos] - (int)rParm.rOld[nRightPos] : 0;
853 }
854 else //Die erste Box.
855 {
856 nLeftDiff = (long)rParm.rOld.GetLeft() - (long)rParm.rNew.GetLeft();
857 if ( rParm.rOld.Count() )
858 {
859 //Differnz zu der Kante berechnen, von der die erste Box
860 //beruehrt wird.
861 sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
862 nWidth *= nOldAct;
863 nWidth /= rParm.nOldWish;
864 long nTmp = (long)nWidth;
865 nTmp += rParm.rOld.GetLeft();
866 sal_uInt16 nLeftPos = USHRT_MAX;
867 for ( sal_uInt16 i = 0; i < rParm.rOld.Count() &&
868 nLeftPos == USHRT_MAX; ++i )
869 {
870 if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
871 nTmp <= (rParm.rOld[i] + COLFUZZY) )
872 nLeftPos = i;
873 }
874 if ( nLeftPos != USHRT_MAX )
875 nRightDiff = (long)rParm.rNew[nLeftPos] -
876 (long)rParm.rOld[nLeftPos];
877 }
878 //MA 11. Feb. 99: #61577# 0 sollte doch gerade richtig sein, weil die
879 //Kante doch schon in SetTabCols() korrigiert wurde.
880 // else
881 // nRightDiff = (long)rParm.rNew.GetRight() -
882 // (long)rParm.rOld.GetRight();
883 }
884
885 if( pBox->getRowSpan() == 1 )
886 {
887 SwTableBoxes& rTblBoxes = pBox->GetUpper()->GetTabBoxes();
888 sal_uInt16 nPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
889 if( nPos && rTblBoxes[ nPos - 1 ]->getRowSpan() != 1 )
890 nLeftDiff = 0;
891 if( nPos + 1 < rTblBoxes.Count() &&
892 rTblBoxes[ nPos + 1 ]->getRowSpan() != 1 )
893 nRightDiff = 0;
894 }
895 else
896 nLeftDiff = nRightDiff = 0;
897
898 if ( nLeftDiff || nRightDiff )
899 {
900 //Die Differenz ist der tatsaechliche Differenzbetrag; die
901 //Attribute der Boxen um diesen Betrag anzupassen macht keinen
902 //Sinn wenn die Tabelle gestrecht ist. Der Differenzbetrag muss
903 //entsprechend umgerechnet werden.
904 long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
905 nLeftDiff *= rParm.nNewWish;
906 nLeftDiff /= nTmp;
907 nRightDiff *= rParm.nNewWish;
908 nRightDiff /= nTmp;
909 long nDiff = nLeftDiff + nRightDiff;
910
911 //Box und alle uebergeordneten um den Differenzbetrag anpassen.
912 while ( pBox )
913 {
914 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
915 aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
916 if ( aFmtFrmSize.GetWidth() < 0 )
917 aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() );
918 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
919
920 // The outer cells of the last row are responsible to adjust a surrounding cell.
921 // Last line check:
922 if ( pBox->GetUpper()->GetUpper() &&
923 pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines()
924 [pBox->GetUpper()->GetUpper()->GetTabLines().Count()-1])
925 {
926 pBox = 0;
927 }
928 else
929 {
930 // Middle cell check:
931 if ( pBox != pBox->GetUpper()->GetTabBoxes()[0] )
932 nDiff = nRightDiff;
933
934 if ( pBox != pBox->GetUpper()->GetTabBoxes()
935 [pBox->GetUpper()->GetTabBoxes().Count()-1] )
936 nDiff -= nRightDiff;
937
938 pBox = nDiff ? pBox->GetUpper()->GetUpper() : 0;
939 }
940 }
941 }
942 }
943 }
944
lcl_ProcessBoxPtr(SwTableBox * pBox,SvPtrarr & rBoxArr,sal_Bool bBefore)945 void lcl_ProcessBoxPtr( SwTableBox *pBox, SvPtrarr &rBoxArr,
946 sal_Bool bBefore )
947 {
948 if ( pBox->GetTabLines().Count() )
949 {
950 const SwTableLines &rLines = pBox->GetTabLines();
951 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
952 {
953 const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
954 for ( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
955 ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
956 }
957 }
958 else if ( bBefore )
959 rBoxArr.Insert( (VoidPtr)pBox, 0 );
960 else
961 rBoxArr.Insert( (VoidPtr)pBox, rBoxArr.Count() );
962 }
963
964 void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm );
965
lcl_AdjustLines(SwTableLines & rLines,const long nDiff,Parm & rParm)966 void lcl_AdjustLines( SwTableLines &rLines, const long nDiff, Parm &rParm )
967 {
968 for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
969 {
970 SwTableBox *pBox = rLines[i]->GetTabBoxes()
971 [rLines[i]->GetTabBoxes().Count()-1];
972 lcl_AdjustBox( pBox, nDiff, rParm );
973 }
974 }
975
lcl_AdjustBox(SwTableBox * pBox,const long nDiff,Parm & rParm)976 void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm )
977 {
978 if ( pBox->GetTabLines().Count() )
979 ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
980
981 //Groesse der Box anpassen.
982 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
983 aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
984 //#30009# if ( aFmtFrmSize.GetWidth() < 0 )
985 // aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() );
986
987 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
988 }
989
SetTabCols(const SwTabCols & rNew,const SwTabCols & rOld,const SwTableBox * pStart,sal_Bool bCurRowOnly)990 void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
991 const SwTableBox *pStart, sal_Bool bCurRowOnly )
992 {
993 CHECK_TABLE( *this )
994
995 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
996
997 // FME: Made rOld const. The caller is responsible for passing correct
998 // values of rOld. Therefore we do not have to call GetTabCols anymore:
999 //GetTabCols( rOld, pStart );
1000
1001 Parm aParm( rNew, rOld );
1002
1003 ASSERT( rOld.Count() == rNew.Count(), "Columnanzahl veraendert.");
1004
1005 //Raender verarbeiten. Groesse der Tabelle und ein paar Boxen mussen
1006 //angepasst werden. Bei der Groesseneinstellung darf allerdings das
1007 //Modify nicht verarbeitet werden - dieses wuerde alle Boxen anpassen
1008 //und das koennen wir ueberhaupt nicht gebrauchen.
1009 SwFrmFmt *pFmt = GetFrmFmt();
1010 aParm.nOldWish = aParm.nNewWish = pFmt->GetFrmSize().GetWidth();
1011 if ( (rOld.GetLeft() != rNew.GetLeft()) ||
1012 (rOld.GetRight()!= rNew.GetRight()) )
1013 {
1014 LockModify();
1015 {
1016 SvxLRSpaceItem aLR( pFmt->GetLRSpace() );
1017 SvxShadowItem aSh( pFmt->GetShadow() );
1018
1019 SwTwips nShRight = aSh.CalcShadowSpace( SHADOW_RIGHT );
1020 SwTwips nShLeft = aSh.CalcShadowSpace( SHADOW_LEFT );
1021
1022 aLR.SetLeft ( rNew.GetLeft() - nShLeft );
1023 aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
1024 pFmt->SetFmtAttr( aLR );
1025
1026 //Die Ausrichtung der Tabelle muss entsprechend angepasst werden,
1027 //das geschieht so, dass die Tabelle genauso stehenbleibt wie der
1028 //Anwender sie gerade hingezuppelt hat.
1029 SwFmtHoriOrient aOri( pFmt->GetHoriOrient() );
1030 if(text::HoriOrientation::NONE != aOri.GetHoriOrient())
1031 {
1032 const sal_Bool bLeftDist = rNew.GetLeft() != nShLeft;
1033 const sal_Bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
1034 if(!bLeftDist && !bRightDist)
1035 aOri.SetHoriOrient( text::HoriOrientation::FULL );
1036 else if(!bRightDist && rNew.GetLeft() > nShLeft )
1037 aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
1038 else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
1039 aOri.SetHoriOrient( text::HoriOrientation::LEFT );
1040 else
1041 aOri.SetHoriOrient( text::HoriOrientation::NONE );
1042 }
1043 pFmt->SetFmtAttr( aOri );
1044 }
1045 const long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
1046 long nTabDiff = 0;
1047
1048 if ( rOld.GetLeft() != rNew.GetLeft() )
1049 {
1050 nTabDiff = rOld.GetLeft() - rNew.GetLeft();
1051 nTabDiff *= aParm.nOldWish;
1052 nTabDiff /= nAct;
1053 }
1054 if ( rOld.GetRight() != rNew.GetRight() )
1055 {
1056 long nDiff = rNew.GetRight() - rOld.GetRight();
1057 nDiff *= aParm.nOldWish;
1058 nDiff /= nAct;
1059 nTabDiff += nDiff;
1060 if( !IsNewModel() )
1061 ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
1062 }
1063
1064 //Groesse der Tabelle anpassen. Es muss beachtet werden, das die
1065 //Tabelle gestrecht sein kann.
1066 if ( nTabDiff )
1067 {
1068 aParm.nNewWish += nTabDiff;
1069 if ( aParm.nNewWish < 0 )
1070 aParm.nNewWish = USHRT_MAX; //Uuups! Eine Rolle rueckwaerts.
1071 SwFmtFrmSize aSz( pFmt->GetFrmSize() );
1072 if ( aSz.GetWidth() != aParm.nNewWish )
1073 {
1074 aSz.SetWidth( aParm.nNewWish );
1075 aSz.SetWidthPercent( 0 );
1076 pFmt->SetFmtAttr( aSz );
1077 }
1078 }
1079 UnlockModify();
1080 }
1081
1082 if( IsNewModel() )
1083 NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
1084 else
1085 {
1086 if ( bCurRowOnly )
1087 {
1088 //Um die aktuelle Zeile anzupassen muessen wir analog zu dem
1089 //Verfahren zum fuellen der TabCols (siehe GetTabCols()) die
1090 //Boxen der aktuellen Zeile abklappern.
1091 //Leider muessen wir auch hier dafuer sorgen, dass die Boxen von
1092 //hinten nach vorne bzw. von innen nach aussen veraendert werden.
1093 //Der beste Weg hierzu scheint mir darin zu liegen die
1094 //entsprechenden Boxen in einem PtrArray vorzumerken.
1095
1096 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
1097 for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
1098 ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, sal_False );
1099
1100 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
1101 pStart->GetUpper()->GetUpper()->GetUpper() : 0;
1102 const SwTableBox *pExcl = pStart->GetUpper()->GetUpper();
1103 while ( pLine )
1104 {
1105 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
1106 sal_Bool bBefore = sal_True;
1107 for ( sal_uInt16 i = 0; i < rBoxes2.Count(); ++i )
1108 {
1109 if ( rBoxes2[i] != pExcl )
1110 ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
1111 else
1112 bBefore = sal_False;
1113 }
1114 pExcl = pLine->GetUpper();
1115 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
1116 }
1117 //Nachdem wir haufenweise Boxen (hoffentlich alle und in der richtigen
1118 //Reihenfolge) eingetragen haben, brauchen diese nur noch rueckwaerts
1119 //verarbeitet zu werden.
1120 for ( int j = aParm.aBoxArr.Count()-1; j >= 0; --j )
1121 {
1122 SwTableBox *pBox = (SwTableBox*)aParm.aBoxArr[ static_cast< sal_uInt16 >(j)];
1123 ::lcl_ProcessBoxSet( pBox, aParm );
1124 }
1125 }
1126 else
1127 { //Die gesamte Tabelle anzupassen ist 'einfach'.
1128 //Es werden alle Boxen, die keine Lines mehr enthalten angepasst.
1129 //Diese Boxen passen alle uebergeordneten Boxen entsprechend mit an.
1130 //Um uns nicht selbst hereinzulegen muss natuerlich rueckwaerst
1131 //gearbeitet werden!
1132 SwTableLines &rLines = GetTabLines();
1133 for ( int i = rLines.Count()-1; i >= 0; --i )
1134 ::lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], aParm );
1135 }
1136 }
1137
1138 #ifdef DBG_UTIL
1139 {
1140 // steht im tblrwcl.cxx
1141 extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
1142 // checke doch mal ob die Tabellen korrekte Breiten haben
1143 SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth();
1144 for( sal_uInt16 n = 0; n < aLines.Count(); ++n )
1145 _CheckBoxWidth( *aLines[ n ], nSize );
1146 }
1147 #endif
1148 }
1149
1150 typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
1151 typedef std::list< ColChange > ChangeList;
1152
lcl_AdjustWidthsInLine(SwTableLine * pLine,ChangeList & rOldNew,Parm & rParm,sal_uInt16 nColFuzzy)1153 static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
1154 Parm& rParm, sal_uInt16 nColFuzzy )
1155 {
1156 ChangeList::iterator pCurr = rOldNew.begin();
1157 if( pCurr == rOldNew.end() )
1158 return;
1159 sal_uInt16 nCount = pLine->GetTabBoxes().Count();
1160 sal_uInt16 i = 0;
1161 SwTwips nBorder = 0;
1162 SwTwips nRest = 0;
1163 while( i < nCount )
1164 {
1165 SwTableBox* pBox = pLine->GetTabBoxes()[i++];
1166 SwTwips nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1167 SwTwips nNewWidth = nWidth - nRest;
1168 nRest = 0;
1169 nBorder += nWidth;
1170 if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
1171 {
1172 nBorder -= nColFuzzy;
1173 while( pCurr != rOldNew.end() && nBorder > pCurr->first )
1174 ++pCurr;
1175 if( pCurr != rOldNew.end() )
1176 {
1177 nBorder += nColFuzzy;
1178 if( nBorder + nColFuzzy >= pCurr->first )
1179 {
1180 if( pCurr->second == pCurr->first )
1181 nRest = 0;
1182 else
1183 nRest = pCurr->second - nBorder;
1184 nNewWidth += nRest;
1185 ++pCurr;
1186 }
1187 }
1188 }
1189 if( nNewWidth != nWidth )
1190 {
1191 if( nNewWidth < 0 )
1192 {
1193 nRest += 1 - nNewWidth;
1194 nNewWidth = 1;
1195 }
1196 SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
1197 aFmtFrmSize.SetWidth( nNewWidth );
1198 rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
1199 }
1200 }
1201 }
1202
lcl_CalcNewWidths(std::list<sal_uInt16> & rSpanPos,ChangeList & rChanges,SwTableLine * pLine,long nWish,long nWidth,bool bTop)1203 static void lcl_CalcNewWidths( std::list<sal_uInt16> &rSpanPos, ChangeList& rChanges,
1204 SwTableLine* pLine, long nWish, long nWidth, bool bTop )
1205 {
1206 if( !rChanges.size() )
1207 {
1208 rSpanPos.clear();
1209 return;
1210 }
1211 if( !rSpanPos.size() )
1212 {
1213 rChanges.clear();
1214 return;
1215 }
1216 std::list<sal_uInt16> aNewSpanPos;
1217 ChangeList aNewChanges;
1218 ChangeList::iterator pCurr = rChanges.begin();
1219 aNewChanges.push_back( *pCurr ); // Nullposition
1220 std::list<sal_uInt16>::iterator pSpan = rSpanPos.begin();
1221 sal_uInt16 nCurr = 0;
1222 sal_uInt16 nOrgSum = 0;
1223 bool bRowSpan = false;
1224 sal_uInt16 nRowSpanCount = 0;
1225 sal_uInt16 nCount = pLine->GetTabBoxes().Count();
1226 for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1227 {
1228 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1229 SwTwips nCurrWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1230 const long nRowSpan = pBox->getRowSpan();
1231 const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
1232 ( nRowSpan > 1 || nRowSpan < -1 );
1233 if( bRowSpan || bCurrRowSpan )
1234 aNewSpanPos.push_back( nRowSpanCount );
1235 bRowSpan = bCurrRowSpan;
1236 nOrgSum = (sal_uInt16)(nOrgSum + nCurrWidth);
1237 sal_uInt64 nSum = nOrgSum;
1238 nSum *= nWidth;
1239 nSum /= nWish;
1240 nSum *= nWish;
1241 nSum /= nWidth;
1242 sal_uInt16 nPos = (sal_uInt16)nSum;
1243 while( pCurr != rChanges.end() && pCurr->first < nPos )
1244 {
1245 #ifdef DBG_UTIL
1246 sal_uInt16 nTemp = pCurr->first;
1247 nTemp = pCurr->second;
1248 #endif
1249 ++nCurr;
1250 ++pCurr;
1251 }
1252 bool bNew = true;
1253 if( pCurr != rChanges.end() && pCurr->first <= nPos &&
1254 pCurr->first != pCurr->second )
1255 {
1256 while( pSpan != rSpanPos.end() && *pSpan < nCurr )
1257 ++pSpan;
1258 if( pSpan != rSpanPos.end() && *pSpan == nCurr )
1259 {
1260 aNewChanges.push_back( *pCurr );
1261 ++nRowSpanCount;
1262 bNew = false;
1263 }
1264 }
1265 if( bNew )
1266 {
1267 ColChange aTmp( nPos, nPos );
1268 aNewChanges.push_back( aTmp );
1269 ++nRowSpanCount;
1270 }
1271 }
1272
1273 pCurr = aNewChanges.begin();
1274 ChangeList::iterator pLast = pCurr;
1275 ChangeList::iterator pLeftMove = pCurr;
1276 while( pCurr != aNewChanges.end() )
1277 {
1278 if( pLeftMove == pCurr )
1279 {
1280 while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
1281 ;
1282 }
1283 if( pCurr->second == pCurr->first )
1284 {
1285 if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
1286 {
1287 if( pLeftMove->first == pLast->first )
1288 pCurr->second = pLeftMove->second;
1289 else
1290 {
1291 sal_uInt64 nTmp = pCurr->first - pLast->first;
1292 nTmp *= pLeftMove->second - pLast->second;
1293 nTmp /= pLeftMove->first - pLast->first;
1294 nTmp += pLast->second;
1295 pCurr->second = (sal_uInt16)nTmp;
1296 }
1297 }
1298 pLast = pCurr;
1299 ++pCurr;
1300 }
1301 else if( pCurr->second > pCurr->first )
1302 {
1303 pLast = pCurr;
1304 ++pCurr;
1305 ChangeList::iterator pNext = pCurr;
1306 while( pNext != pLeftMove && pNext->second == pNext->first &&
1307 pNext->second < pLast->second )
1308 ++pNext;
1309 while( pCurr != pNext )
1310 {
1311 if( pNext == aNewChanges.end() || pNext->first == pLast->first )
1312 pCurr->second = pLast->second;
1313 else
1314 {
1315 sal_uInt64 nTmp = pCurr->first - pLast->first;
1316 nTmp *= pNext->second - pLast->second;
1317 nTmp /= pNext->first - pLast->first;
1318 nTmp += pLast->second;
1319 pCurr->second = (sal_uInt16)nTmp;
1320 }
1321 ++pCurr;
1322 }
1323 pLast = pCurr;
1324 }
1325 else
1326 {
1327 pLast = pCurr;
1328 ++pCurr;
1329 }
1330 }
1331
1332 rChanges.clear();
1333 ChangeList::iterator pCopy = aNewChanges.begin();
1334 while( pCopy != aNewChanges.end() )
1335 rChanges.push_back( *pCopy++ );
1336 rSpanPos.clear();
1337 std::list<sal_uInt16>::iterator pSpCopy = aNewSpanPos.begin();
1338 while( pSpCopy != aNewSpanPos.end() )
1339 rSpanPos.push_back( *pSpCopy++ );
1340 }
1341
NewSetTabCols(Parm & rParm,const SwTabCols & rNew,const SwTabCols & rOld,const SwTableBox * pStart,sal_Bool bCurRowOnly)1342 void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
1343 const SwTabCols &rOld, const SwTableBox *pStart, sal_Bool bCurRowOnly )
1344 {
1345 #ifdef DBG_UTIL
1346 static int nCallCount = 0;
1347 ++nCallCount;
1348 #endif
1349 // First step: evaluate which lines have been moved/which widths changed
1350 ChangeList aOldNew;
1351 const long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1352 const long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1353 if( nNewWidth < 1 || nOldWidth < 1 )
1354 return;
1355 for( sal_uInt16 i = 0; i <= rOld.Count(); ++i )
1356 {
1357 sal_uInt64 nNewPos;
1358 sal_uInt64 nOldPos;
1359 if( i == rOld.Count() )
1360 {
1361 nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1362 nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1363 }
1364 else
1365 {
1366 nOldPos = rOld[i] - rParm.rOld.GetLeft();
1367 nNewPos = rNew[i] - rParm.rNew.GetLeft();
1368 }
1369 nNewPos *= rParm.nNewWish;
1370 nNewPos /= nNewWidth;
1371 nOldPos *= rParm.nOldWish;
1372 nOldPos /= nOldWidth;
1373 if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
1374 {
1375 ColChange aChg( (sal_uInt16)nOldPos, (sal_uInt16)nNewPos );
1376 aOldNew.push_back( aChg );
1377 }
1378 }
1379 // Finished first step
1380 int nCount = aOldNew.size();
1381 if( !nCount )
1382 return; // no change, nothing to do
1383 SwTableLines &rLines = GetTabLines();
1384 if( bCurRowOnly )
1385 {
1386 const SwTableLine* pCurrLine = pStart->GetUpper();
1387 sal_uInt16 nCurr = rLines.C40_GETPOS( SwTableLine, pCurrLine );
1388 if( nCurr >= USHRT_MAX )
1389 return;
1390
1391 ColChange aChg( 0, 0 );
1392 aOldNew.push_front( aChg );
1393 std::list<sal_uInt16> aRowSpanPos;
1394 if( nCurr )
1395 {
1396 ChangeList aCopy;
1397 ChangeList::iterator pCop = aOldNew.begin();
1398 sal_uInt16 nPos = 0;
1399 while( pCop != aOldNew.end() )
1400 {
1401 aCopy.push_back( *pCop );
1402 ++pCop;
1403 aRowSpanPos.push_back( nPos++ );
1404 }
1405 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1406 rParm.nOldWish, nOldWidth, true );
1407 bool bGoOn = aRowSpanPos.size() > 0;
1408 sal_uInt16 j = nCurr;
1409 while( bGoOn )
1410 {
1411 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
1412 rParm.nOldWish, nOldWidth, true );
1413 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1414 bGoOn = aRowSpanPos.size() > 0 && j > 0;
1415 };
1416 aRowSpanPos.clear();
1417 }
1418 if( nCurr+1 < rLines.Count() )
1419 {
1420 ChangeList aCopy;
1421 ChangeList::iterator pCop = aOldNew.begin();
1422 sal_uInt16 nPos = 0;
1423 while( pCop != aOldNew.end() )
1424 {
1425 aCopy.push_back( *pCop );
1426 ++pCop;
1427 aRowSpanPos.push_back( nPos++ );
1428 }
1429 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1430 rParm.nOldWish, nOldWidth, false );
1431 bool bGoOn = aRowSpanPos.size() > 0;
1432 sal_uInt16 j = nCurr;
1433 while( bGoOn )
1434 {
1435 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
1436 rParm.nOldWish, nOldWidth, false );
1437 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1438 bGoOn = aRowSpanPos.size() > 0 && j+1 < rLines.Count();
1439 };
1440 }
1441 ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, 1 );
1442 }
1443 else for( sal_uInt16 i = 0; i < rLines.Count(); ++i )
1444 ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
1445 CHECK_TABLE( *this )
1446 }
1447
1448
1449 /*************************************************************************
1450 |*
1451 |* const SwTableBox* SwTable::GetTblBox( const Strn?ng& rName ) const
1452 |* gebe den Pointer auf die benannte Box zurueck.
1453 |*
1454 |*************************************************************************/
1455
IsValidRowName(const String & rStr)1456 sal_Bool IsValidRowName( const String& rStr )
1457 {
1458 sal_Bool bIsValid = sal_True;
1459 xub_StrLen nLen = rStr.Len();
1460 for (xub_StrLen i = 0; i < nLen && bIsValid; ++i)
1461 {
1462 const sal_Unicode cChar = rStr.GetChar(i);
1463 if (cChar < '0' || cChar > '9')
1464 bIsValid = sal_False;
1465 }
1466 return bIsValid;
1467 }
1468
1469 // --> OD 2007-08-03 #i80314#
1470 // add 3rd parameter and its handling
_GetBoxNum(String & rStr,sal_Bool bFirstPart,const bool bPerformValidCheck)1471 sal_uInt16 SwTable::_GetBoxNum( String& rStr, sal_Bool bFirstPart,
1472 const bool bPerformValidCheck )
1473 {
1474 sal_uInt16 nRet = 0;
1475 xub_StrLen nPos = 0;
1476 if( bFirstPart ) // sal_True == column; sal_False == row
1477 {
1478 // die 1. ist mit Buchstaben addressiert!
1479 sal_Unicode cChar;
1480 sal_Bool bFirst = sal_True;
1481 while( 0 != ( cChar = rStr.GetChar( nPos )) &&
1482 ( (cChar >= 'A' && cChar <= 'Z') ||
1483 (cChar >= 'a' && cChar <= 'z') ) )
1484 {
1485 if( (cChar -= 'A') >= 26 )
1486 cChar -= 'a' - '[';
1487 if( bFirst )
1488 bFirst = sal_False;
1489 else
1490 ++nRet;
1491 nRet = nRet * 52 + cChar;
1492 ++nPos;
1493 }
1494 rStr.Erase( 0, nPos ); // Zeichen aus dem String loeschen
1495 }
1496 else if( STRING_NOTFOUND == ( nPos = rStr.Search( aDotStr ) ))
1497 {
1498 nRet = 0;
1499 if ( !bPerformValidCheck || IsValidRowName( rStr ) )
1500 {
1501 nRet = static_cast<sal_uInt16>(rStr.ToInt32());
1502 }
1503 rStr.Erase();
1504 }
1505 else
1506 {
1507 nRet = 0;
1508 String aTxt( rStr.Copy( 0, nPos ) );
1509 if ( !bPerformValidCheck || IsValidRowName( aTxt ) )
1510 {
1511 nRet = static_cast<sal_uInt16>(aTxt.ToInt32());
1512 }
1513 rStr.Erase( 0, nPos+1 );
1514 }
1515 return nRet;
1516 }
1517 // <--
1518
1519 // --> OD 2007-08-03 #i80314#
1520 // add 2nd parameter and its handling
GetTblBox(const String & rName,const bool bPerformValidCheck) const1521 const SwTableBox* SwTable::GetTblBox( const String& rName,
1522 const bool bPerformValidCheck ) const
1523 {
1524 const SwTableBox* pBox = 0;
1525 const SwTableLine* pLine;
1526 const SwTableLines* pLines;
1527 const SwTableBoxes* pBoxes;
1528
1529 sal_uInt16 nLine, nBox;
1530 String aNm( rName );
1531 while( aNm.Len() )
1532 {
1533 nBox = SwTable::_GetBoxNum( aNm, 0 == pBox, bPerformValidCheck );
1534 // erste Box ?
1535 if( !pBox )
1536 pLines = &GetTabLines();
1537 else
1538 {
1539 pLines = &pBox->GetTabLines();
1540 if( nBox )
1541 --nBox;
1542 }
1543
1544 nLine = SwTable::_GetBoxNum( aNm, sal_False, bPerformValidCheck );
1545
1546 // bestimme die Line
1547 if( !nLine || nLine > pLines->Count() )
1548 return 0;
1549 pLine = (*pLines)[ nLine-1 ];
1550
1551 // bestimme die Box
1552 pBoxes = &pLine->GetTabBoxes();
1553 if( nBox >= pBoxes->Count() )
1554 return 0;
1555 pBox = (*pBoxes)[ nBox ];
1556 }
1557
1558 // abpruefen, ob die gefundene Box auch wirklich eine Inhaltstragende
1559 // Box ist ??
1560 if( pBox && !pBox->GetSttNd() )
1561 {
1562 ASSERT( sal_False, "Box ohne Inhalt, suche die naechste !!" );
1563 // "herunterfallen lassen" bis zur ersten Box
1564 while( pBox->GetTabLines().Count() )
1565 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
1566 }
1567 return pBox;
1568 }
1569
GetTblBox(sal_uLong nSttIdx)1570 SwTableBox* SwTable::GetTblBox( sal_uLong nSttIdx )
1571 {
1572 //MA: Zur Optimierung nicht immer umstaendlich das ganze SortArray abhuenern.
1573 //OS: #102675# converting text to table tries und certain conditions
1574 // to ask for a table box of a table that is not yet having a format
1575 if(!GetFrmFmt())
1576 return 0;
1577 SwTableBox* pRet = 0;
1578 SwNodes& rNds = GetFrmFmt()->GetDoc()->GetNodes();
1579 sal_uLong nIndex = nSttIdx + 1;
1580 SwCntntNode* pCNd = 0;
1581 SwTableNode* pTblNd = 0;
1582
1583 while ( nIndex < rNds.Count() )
1584 {
1585 pTblNd = rNds[ nIndex ]->GetTableNode();
1586 if ( pTblNd )
1587 break;
1588
1589 pCNd = rNds[ nIndex ]->GetCntntNode();
1590 if ( pCNd )
1591 break;
1592
1593 ++nIndex;
1594 }
1595
1596 if ( pCNd || pTblNd )
1597 {
1598 SwModify* pModify = pCNd;
1599 // --> FME 2007-3-26 #144862# Better handling of table in table:
1600 if ( pTblNd && pTblNd->GetTable().GetFrmFmt() )
1601 pModify = pTblNd->GetTable().GetFrmFmt();
1602 // <--
1603
1604 SwFrm* pFrm = SwIterator<SwFrm,SwModify>::FirstElement( *pModify );
1605 while ( pFrm && !pFrm->IsCellFrm() )
1606 pFrm = pFrm->GetUpper();
1607 if ( pFrm )
1608 pRet = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1609 }
1610
1611 //Falls es das Layout noch nicht gibt oder sonstwie etwas schieft geht.
1612 if ( !pRet )
1613 {
1614 for( sal_uInt16 n = aSortCntBoxes.Count(); n; )
1615 if( aSortCntBoxes[ --n ]->GetSttIdx() == nSttIdx )
1616 return aSortCntBoxes[ n ];
1617 }
1618 return pRet;
1619 }
1620
IsTblComplex() const1621 sal_Bool SwTable::IsTblComplex() const
1622 {
1623 // returnt sal_True wenn sich in der Tabelle Verschachtelungen befinden
1624 // steht eine Box nicht in der obersten Line, da wurde gesplittet/
1625 // gemergt und die Struktur ist komplexer.
1626 for( sal_uInt16 n = 0; n < aSortCntBoxes.Count(); ++n )
1627 if( aSortCntBoxes[ n ]->GetUpper()->GetUpper() )
1628 return sal_True;
1629 return sal_False;
1630 }
1631
1632
1633
1634 /*************************************************************************
1635 |*
1636 |* SwTableLine::SwTableLine()
1637 |*
1638 |*************************************************************************/
SwTableLine(SwTableLineFmt * pFmt,sal_uInt16 nBoxes,SwTableBox * pUp)1639 SwTableLine::SwTableLine( SwTableLineFmt *pFmt, sal_uInt16 nBoxes,
1640 SwTableBox *pUp )
1641 : SwClient( pFmt ),
1642 aBoxes( (sal_uInt8)nBoxes, 1 ),
1643 pUpper( pUp )
1644 {
1645 }
1646
~SwTableLine()1647 SwTableLine::~SwTableLine()
1648 {
1649 // ist die TabelleLine der letzte Client im FrameFormat, kann dieses
1650 // geloescht werden
1651 SwModify* pMod = GetFrmFmt();
1652 pMod->Remove( this ); // austragen,
1653 if( !pMod->GetDepends() )
1654 delete pMod; // und loeschen
1655 }
1656
1657 /*************************************************************************
1658 |*
1659 |* SwTableLine::ClaimFrmFmt(), ChgFrmFmt()
1660 |*
1661 |*************************************************************************/
ClaimFrmFmt()1662 SwFrmFmt* SwTableLine::ClaimFrmFmt()
1663 {
1664 // This method makes sure that this object is an exclusive SwTableLine client
1665 // of an SwTableLineFmt object
1666 // If other SwTableLine objects currently listen to the same SwTableLineFmt as
1667 // this one, something needs to be done
1668 SwTableLineFmt *pRet = (SwTableLineFmt*)GetFrmFmt();
1669 SwIterator<SwTableLine,SwFmt> aIter( *pRet );
1670 for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1671 {
1672 if ( pLast != this )
1673 {
1674 // found another SwTableLine that is a client of the current Fmt
1675 // create a new Fmt as a copy and use it for this object
1676 SwTableLineFmt *pNewFmt = pRet->GetDoc()->MakeTableLineFmt();
1677 *pNewFmt = *pRet;
1678
1679 // register SwRowFrms that know me as clients at the new Fmt
1680 SwIterator<SwRowFrm,SwFmt> aFrmIter( *pRet );
1681 for( SwRowFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
1682 if( pFrm->GetTabLine() == this )
1683 pFrm->RegisterToFormat( *pNewFmt );
1684
1685 // register myself
1686 pNewFmt->Add( this );
1687 pRet = pNewFmt;
1688 break;
1689 }
1690 }
1691
1692 return pRet;
1693 }
1694
ChgFrmFmt(SwTableLineFmt * pNewFmt)1695 void SwTableLine::ChgFrmFmt( SwTableLineFmt *pNewFmt )
1696 {
1697 SwFrmFmt *pOld = GetFrmFmt();
1698 SwIterator<SwRowFrm,SwFmt> aIter( *pOld );
1699
1700 //Erstmal die Frms ummelden.
1701 for( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
1702 {
1703 if( pRow->GetTabLine() == this )
1704 {
1705 pRow->RegisterToFormat( *pNewFmt );
1706
1707 pRow->InvalidateSize();
1708 pRow->_InvalidatePrt();
1709 pRow->SetCompletePaint();
1710 pRow->ReinitializeFrmSizeAttrFlags();
1711
1712 // --> FME 2004-10-27 #i35063#
1713 // consider 'split row allowed' attribute
1714 SwTabFrm* pTab = pRow->FindTabFrm();
1715 bool bInFollowFlowRow = false;
1716 const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
1717 pRow == pTab->GetFirstNonHeadlineRow();
1718 if ( bInFirstNonHeadlineRow ||
1719 !pRow->GetNext() ||
1720 0 != ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) ||
1721 0 != pRow->IsInSplitTableRow() )
1722 {
1723 if ( bInFirstNonHeadlineRow || bInFollowFlowRow )
1724 pTab = pTab->FindMaster();
1725
1726 pTab->SetRemoveFollowFlowLinePending( sal_True );
1727 pTab->InvalidatePos();
1728 }
1729 // <--
1730 }
1731 }
1732
1733 //Jetzt noch mich selbst ummelden.
1734 pNewFmt->Add( this );
1735
1736 if ( !pOld->GetDepends() )
1737 delete pOld;
1738 }
1739
GetTableLineHeight(bool & bLayoutAvailable) const1740 SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
1741 {
1742 SwTwips nRet = 0;
1743 bLayoutAvailable = false;
1744 SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() );
1745 // A row could appear several times in headers/footers so only one chain of master/follow tables
1746 // will be accepted...
1747 const SwTabFrm* pChain = NULL; // My chain
1748 for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1749 {
1750 if( pLast->GetTabLine() == this )
1751 {
1752 const SwTabFrm* pTab = pLast->FindTabFrm();
1753 bLayoutAvailable = ( pTab && pTab->IsVertical() ) ?
1754 ( 0 < pTab->Frm().Height() ) :
1755 ( 0 < pTab->Frm().Width() );
1756
1757 // The first one defines the chain, if a chain is defined, only members of the chain
1758 // will be added.
1759 if( !pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow( pChain ) )
1760 {
1761 pChain = pTab; // defines my chain (even it is already)
1762 if( pTab->IsVertical() )
1763 nRet += pLast->Frm().Width();
1764 else
1765 nRet += pLast->Frm().Height();
1766 // Optimization, if there are no master/follows in my chain, nothing more to add
1767 if( !pTab->HasFollow() && !pTab->IsFollow() )
1768 break;
1769 // This is not an optimization, this is necessary to avoid double additions of
1770 // repeating rows
1771 if( pTab->IsInHeadline(*pLast) )
1772 break;
1773 }
1774 }
1775 }
1776 return nRet;
1777 }
1778
1779 /*************************************************************************
1780 |*
1781 |* SwTableBox::SwTableBox()
1782 |*
1783 |*************************************************************************/
SwTableBox(SwTableBoxFmt * pFmt,sal_uInt16 nLines,SwTableLine * pUp)1784 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, sal_uInt16 nLines, SwTableLine *pUp )
1785 : SwClient( 0 ),
1786 aLines( (sal_uInt8)nLines, 1 ),
1787 pSttNd( 0 ),
1788 pUpper( pUp ),
1789 pImpl( 0 )
1790 {
1791 CheckBoxFmt( pFmt )->Add( this );
1792 }
1793
SwTableBox(SwTableBoxFmt * pFmt,const SwNodeIndex & rIdx,SwTableLine * pUp)1794 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwNodeIndex &rIdx,
1795 SwTableLine *pUp )
1796 : SwClient( 0 ),
1797 aLines( 0, 0 ),
1798 pUpper( pUp ),
1799 pImpl( 0 )
1800 {
1801 CheckBoxFmt( pFmt )->Add( this );
1802
1803 pSttNd = rIdx.GetNode().GetStartNode();
1804
1805 // an der Table eintragen
1806 const SwTableNode* pTblNd = pSttNd->FindTableNode();
1807 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" );
1808 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1809 GetTabSortBoxes();
1810 SwTableBox* p = this; // error: &this
1811 rSrtArr.Insert( p ); // eintragen
1812 }
1813
SwTableBox(SwTableBoxFmt * pFmt,const SwStartNode & rSttNd,SwTableLine * pUp)1814 SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwStartNode& rSttNd, SwTableLine *pUp ) :
1815 SwClient( 0 ),
1816 aLines( 0, 0 ),
1817 pSttNd( &rSttNd ),
1818 pUpper( pUp ),
1819 pImpl( 0 )
1820 {
1821 CheckBoxFmt( pFmt )->Add( this );
1822
1823 // an der Table eintragen
1824 const SwTableNode* pTblNd = pSttNd->FindTableNode();
1825 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" );
1826 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1827 GetTabSortBoxes();
1828 SwTableBox* p = this; // error: &this
1829 rSrtArr.Insert( p ); // eintragen
1830 }
1831
~SwTableBox()1832 SwTableBox::~SwTableBox()
1833 {
1834 // Inhaltstragende Box ?
1835 if( !GetFrmFmt()->GetDoc()->IsInDtor() && pSttNd )
1836 {
1837 // an der Table austragen
1838 const SwTableNode* pTblNd = pSttNd->FindTableNode();
1839 ASSERT( pTblNd, "in welcher Tabelle steht denn die Box?" );
1840 SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1841 GetTabSortBoxes();
1842 SwTableBox *p = this; // error: &this
1843 rSrtArr.Remove( p ); // austragen
1844 }
1845
1846 // ist die TabelleBox der letzte Client im FrameFormat, kann dieses
1847 // geloescht werden
1848 SwModify* pMod = GetFrmFmt();
1849 pMod->Remove( this ); // austragen,
1850 if( !pMod->GetDepends() )
1851 delete pMod; // und loeschen
1852
1853 delete pImpl;
1854 }
1855
CheckBoxFmt(SwTableBoxFmt * pFmt)1856 SwTableBoxFmt* SwTableBox::CheckBoxFmt( SwTableBoxFmt* pFmt )
1857 {
1858 // sollte das Format eine Formel oder einen Value tragen, dann muss die
1859 // Box alleine am Format haengen. Ggfs. muss ein neues angelegt werden.
1860 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) ||
1861 SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ) )
1862 {
1863 SwTableBox* pOther = SwIterator<SwTableBox,SwFmt>::FirstElement( *pFmt );
1864 if( pOther )
1865 {
1866 SwTableBoxFmt* pNewFmt = pFmt->GetDoc()->MakeTableBoxFmt();
1867 pNewFmt->LockModify();
1868 *pNewFmt = *pFmt;
1869
1870 // Values und Formeln entfernen
1871 pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1872 pNewFmt->UnlockModify();
1873
1874 pFmt = pNewFmt;
1875 }
1876 }
1877 return pFmt;
1878 }
1879
1880 /*************************************************************************
1881 |*
1882 |* SwTableBox::ClaimFrmFmt(), ChgFrmFmt()
1883 |*
1884 |*************************************************************************/
ClaimFrmFmt()1885 SwFrmFmt* SwTableBox::ClaimFrmFmt()
1886 {
1887 // This method makes sure that this object is an exclusive SwTableBox client
1888 // of an SwTableBoxFmt object
1889 // If other SwTableBox objects currently listen to the same SwTableBoxFmt as
1890 // this one, something needs to be done
1891 SwTableBoxFmt *pRet = (SwTableBoxFmt*)GetFrmFmt();
1892 SwIterator<SwTableBox,SwFmt> aIter( *pRet );
1893 for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1894 {
1895 if ( pLast != this )
1896 {
1897 // Found another SwTableBox object
1898 // create a new Fmt as a copy and assign me to it
1899 // don't copy values and formulas
1900 SwTableBoxFmt* pNewFmt = pRet->GetDoc()->MakeTableBoxFmt();
1901 pNewFmt->LockModify();
1902 *pNewFmt = *pRet;
1903 pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1904 pNewFmt->UnlockModify();
1905
1906 // re-register SwCellFrm objects that know me
1907 SwIterator<SwCellFrm,SwFmt> aFrmIter( *pRet );
1908 for( SwCellFrm* pCell = aFrmIter.First(); pCell; pCell = aFrmIter.Next() )
1909 if( pCell->GetTabBox() == this )
1910 pCell->RegisterToFormat( *pNewFmt );
1911
1912 // re-register myself
1913 pNewFmt->Add( this );
1914 pRet = pNewFmt;
1915 break;
1916 }
1917 }
1918 return pRet;
1919 }
1920
ChgFrmFmt(SwTableBoxFmt * pNewFmt)1921 void SwTableBox::ChgFrmFmt( SwTableBoxFmt* pNewFmt )
1922 {
1923 SwFrmFmt *pOld = GetFrmFmt();
1924 SwIterator<SwCellFrm,SwFmt> aIter( *pOld );
1925
1926 //Erstmal die Frms ummelden.
1927 for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
1928 {
1929 if( pCell->GetTabBox() == this )
1930 {
1931 pCell->RegisterToFormat( *pNewFmt );
1932 pCell->InvalidateSize();
1933 pCell->_InvalidatePrt();
1934 pCell->SetCompletePaint();
1935 pCell->SetDerivedVert( sal_False );
1936 pCell->CheckDirChange();
1937
1938 // --> FME 2005-04-15 #i47489#
1939 // make sure that the row will be formatted, in order
1940 // to have the correct Get(Top|Bottom)MarginForLowers values
1941 // set at the row.
1942 const SwTabFrm* pTab = pCell->FindTabFrm();
1943 if ( pTab && pTab->IsCollapsingBorders() )
1944 {
1945 SwFrm* pRow = pCell->GetUpper();
1946 pRow->_InvalidateSize();
1947 pRow->_InvalidatePrt();
1948 }
1949 // <--
1950 }
1951 }
1952
1953 //Jetzt noch mich selbst ummelden.
1954 pNewFmt->Add( this );
1955
1956 if( !pOld->GetDepends() )
1957 delete pOld;
1958 }
1959
1960 /*************************************************************************
1961 |*
1962 |* String SwTableBox::GetName() const
1963 |* gebe den Namen dieser Box zurueck. Dieser wird dynamisch bestimmt
1964 |* und ergibt sich aus der Position in den Lines/Boxen/Tabelle
1965 |*
1966 |*************************************************************************/
lcl_GetTblBoxColStr(sal_uInt16 nCol,String & rNm)1967 void lcl_GetTblBoxColStr( sal_uInt16 nCol, String& rNm )
1968 {
1969 const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z'
1970 sal_uInt16 nCalc;
1971
1972 do {
1973 nCalc = nCol % coDiff;
1974 if( nCalc >= 26 )
1975 rNm.Insert( sal_Unicode('a' - 26 + nCalc ), 0 );
1976 else
1977 rNm.Insert( sal_Unicode('A' + nCalc ), 0 );
1978
1979 if( 0 == (nCol = nCol - nCalc) )
1980 break;
1981 nCol /= coDiff;
1982 --nCol;
1983 } while( 1 );
1984 }
1985
GetName() const1986 String SwTableBox::GetName() const
1987 {
1988 if( !pSttNd ) // keine Content Box ??
1989 {
1990 // die naechste erste Box suchen ??
1991 return aEmptyStr;
1992 }
1993
1994 const SwTable& rTbl = pSttNd->FindTableNode()->GetTable();
1995 sal_uInt16 nPos;
1996 String sNm, sTmp;
1997 const SwTableBox* pBox = this;
1998 do {
1999 const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes();
2000 const SwTableLine* pLine = pBox->GetUpper();
2001 // auf oberstere Ebene ?
2002 const SwTableLines* pLines = pLine->GetUpper()
2003 ? &pLine->GetUpper()->GetTabLines() : &rTbl.GetTabLines();
2004
2005 sTmp = String::CreateFromInt32( nPos = pLines->GetPos( pLine ) + 1 );
2006 if( sNm.Len() )
2007 sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
2008 else
2009 sNm = sTmp;
2010
2011 sTmp = String::CreateFromInt32(( nPos = pBoxes->GetPos( pBox )) + 1 );
2012 if( 0 != ( pBox = pLine->GetUpper()) )
2013 sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
2014 else
2015 ::lcl_GetTblBoxColStr( nPos, sNm );
2016
2017 } while( pBox );
2018 return sNm;
2019 }
2020
IsInHeadline(const SwTable * pTbl) const2021 sal_Bool SwTableBox::IsInHeadline( const SwTable* pTbl ) const
2022 {
2023 if( !GetUpper() ) // sollte nur beim Merge vorkommen.
2024 return sal_False;
2025
2026 if( !pTbl )
2027 pTbl = &pSttNd->FindTableNode()->GetTable();
2028
2029 const SwTableLine* pLine = GetUpper();
2030 while( pLine->GetUpper() )
2031 pLine = pLine->GetUpper()->GetUpper();
2032
2033 // Headerline?
2034 return pTbl->GetTabLines()[ 0 ] == pLine;
2035 }
2036
2037 #ifdef DBG_UTIL
2038
GetSttIdx() const2039 sal_uLong SwTableBox::GetSttIdx() const
2040 {
2041 return pSttNd ? pSttNd->GetIndex() : 0;
2042 }
2043 #endif
2044
2045 // erfrage vom Client Informationen
GetInfo(SfxPoolItem & rInfo) const2046 sal_Bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
2047 {
2048 switch( rInfo.Which() )
2049 {
2050 case RES_AUTOFMT_DOCNODE:
2051 {
2052 const SwTableNode* pTblNode = GetTableNode();
2053 if( pTblNode && &pTblNode->GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
2054 {
2055 if ( aSortCntBoxes.Count() )
2056 {
2057 SwNodeIndex aIdx( *aSortCntBoxes[ 0 ]->GetSttNd() );
2058 ((SwAutoFmtGetDocNode&)rInfo).pCntntNode =
2059 GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx );
2060 }
2061 return sal_False;
2062 }
2063 break;
2064 }
2065 case RES_FINDNEARESTNODE:
2066 if( GetFrmFmt() && ((SwFmtPageDesc&)GetFrmFmt()->GetFmtAttr(
2067 RES_PAGEDESC )).GetPageDesc() &&
2068 aSortCntBoxes.Count() &&
2069 aSortCntBoxes[ 0 ]->GetSttNd()->GetNodes().IsDocNodes() )
2070 ((SwFindNearestNode&)rInfo).CheckNode( *
2071 aSortCntBoxes[ 0 ]->GetSttNd()->FindTableNode() );
2072 break;
2073
2074 case RES_CONTENT_VISIBLE:
2075 {
2076 ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *GetFrmFmt() );
2077 }
2078 return sal_False;
2079 }
2080 return sal_True;
2081 }
2082
FindTable(SwFrmFmt const * const pFmt)2083 SwTable * SwTable::FindTable( SwFrmFmt const*const pFmt )
2084 {
2085 return (pFmt)
2086 ? SwIterator<SwTable,SwFmt>::FirstElement(*pFmt)
2087 : 0;
2088 }
2089
GetTableNode() const2090 SwTableNode* SwTable::GetTableNode() const
2091 {
2092 return GetTabSortBoxes().Count() ?
2093 (SwTableNode*)GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode() :
2094 pTableNode;
2095 }
2096
SetRefObject(SwServerObject * pObj)2097 void SwTable::SetRefObject( SwServerObject* pObj )
2098 {
2099 if( refObj.Is() )
2100 refObj->Closed();
2101
2102 refObj = pObj;
2103 }
2104
2105
SetHTMLTableLayout(SwHTMLTableLayout * p)2106 void SwTable::SetHTMLTableLayout( SwHTMLTableLayout *p )
2107 {
2108 delete pHTMLLayout;
2109 pHTMLLayout = p;
2110 }
2111
ChgTextToNum(SwTableBox & rBox,const String & rTxt,const Color * pCol,sal_Bool bChgAlign)2112 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
2113 sal_Bool bChgAlign )
2114 {
2115 sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_True );
2116 ChgTextToNum( rBox,rTxt,pCol,bChgAlign,nNdPos);
2117 }
ChgTextToNum(SwTableBox & rBox,const String & rTxt,const Color * pCol,sal_Bool bChgAlign,sal_uLong nNdPos)2118 void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
2119 sal_Bool bChgAlign,sal_uLong nNdPos )
2120 {
2121
2122 if( ULONG_MAX != nNdPos )
2123 {
2124 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2125 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
2126 const SfxPoolItem* pItem;
2127
2128 // Ausrichtung umsetzen
2129 if( bChgAlign )
2130 {
2131 pItem = &pTNd->SwCntntNode::GetAttr( RES_PARATR_ADJUST );
2132 SvxAdjust eAdjust = ((SvxAdjustItem*)pItem)->GetAdjust();
2133 if( SVX_ADJUST_LEFT == eAdjust || SVX_ADJUST_BLOCK == eAdjust )
2134 {
2135 SvxAdjustItem aAdjust( *(SvxAdjustItem*)pItem );
2136 aAdjust.SetAdjust( SVX_ADJUST_RIGHT );
2137 pTNd->SetAttr( aAdjust );
2138 }
2139 }
2140
2141 // Farbe umsetzen oder "Benutzer Farbe" sichern
2142 if( !pTNd->GetpSwAttrSet() || SFX_ITEM_SET != pTNd->GetpSwAttrSet()->
2143 GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
2144 pItem = 0;
2145
2146 const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
2147 const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
2148
2149 if( ( pNewUserColor && pOldNumFmtColor &&
2150 *pNewUserColor == *pOldNumFmtColor ) ||
2151 ( !pNewUserColor && !pOldNumFmtColor ))
2152 {
2153 // User Color nicht veraendern aktuellen Werte setzen
2154 // ggfs. die alte NumFmtColor loeschen
2155 if( pCol )
2156 // ggfs. die Farbe setzen
2157 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2158 else if( pItem )
2159 {
2160 pNewUserColor = rBox.GetSaveUserColor();
2161 if( pNewUserColor )
2162 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2163 else
2164 pTNd->ResetAttr( RES_CHRATR_COLOR );
2165 }
2166 }
2167 else
2168 {
2169 // User Color merken, ggfs. die NumFormat Color setzen, aber
2170 // nie die Farbe zurueck setzen
2171 rBox.SetSaveUserColor( pNewUserColor );
2172
2173 if( pCol )
2174 // ggfs. die Farbe setzen
2175 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2176
2177 }
2178 rBox.SetSaveNumFmtColor( pCol );
2179
2180 if( pTNd->GetTxt() != rTxt )
2181 {
2182 // Text austauschen
2183 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten!)
2184 const String& rOrig = pTNd->GetTxt();
2185 xub_StrLen n;
2186
2187 for( n = 0; n < rOrig.Len() && '\x9' == rOrig.GetChar( n ); ++n )
2188 ;
2189 for( ; n < rOrig.Len() && '\x01' == rOrig.GetChar( n ); ++n )
2190 ;
2191 SwIndex aIdx( pTNd, n );
2192 for( n = rOrig.Len(); n && '\x9' == rOrig.GetChar( --n ); )
2193 ;
2194 n -= aIdx.GetIndex() - 1;
2195
2196 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
2197 // zuruecksetzen, damit sie wieder aufgespannt werden
2198 {
2199 SwIndex aResetIdx( aIdx, n );
2200 pTNd->DontExpandFmt( aResetIdx, sal_False, sal_False );
2201 }
2202
2203 if( !pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() )
2204 {
2205 SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.Len());
2206 pDoc->DeleteRedline(aTemp, true, USHRT_MAX);
2207 }
2208
2209 pTNd->EraseText( aIdx, n,
2210 IDocumentContentOperations::INS_EMPTYEXPAND );
2211 pTNd->InsertText( rTxt, aIdx,
2212 IDocumentContentOperations::INS_EMPTYEXPAND );
2213
2214 if( pDoc->IsRedlineOn() )
2215 {
2216 SwPaM aTemp(*pTNd, 0, *pTNd, rTxt.Len());
2217 pDoc->AppendRedline(new SwRedline(nsRedlineType_t::REDLINE_INSERT, aTemp), true);
2218 }
2219 }
2220
2221 // vertikale Ausrichtung umsetzen
2222 if( bChgAlign &&
2223 ( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(
2224 RES_VERT_ORIENT, sal_True, &pItem ) ||
2225 text::VertOrientation::TOP == ((SwFmtVertOrient*)pItem)->GetVertOrient() ))
2226 {
2227 rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::BOTTOM ));
2228 }
2229 }
2230 }
2231
ChgNumToText(SwTableBox & rBox,sal_uLong nFmt)2232 void ChgNumToText( SwTableBox& rBox, sal_uLong nFmt )
2233 {
2234 sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_False );
2235 if( ULONG_MAX != nNdPos )
2236 {
2237 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2238 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
2239 sal_Bool bChgAlign = pDoc->IsInsTblAlignNum();
2240 const SfxPoolItem* pItem;
2241
2242 Color* pCol = 0;
2243 if( NUMBERFORMAT_TEXT != nFmt )
2244 {
2245 // speziellen Textformat:
2246 String sTmp, sTxt( pTNd->GetTxt() );
2247 pDoc->GetNumberFormatter()->GetOutputString( sTxt, nFmt, sTmp, &pCol );
2248 if( sTxt != sTmp )
2249 {
2250 // Text austauschen
2251 SwIndex aIdx( pTNd, sTxt.Len() );
2252 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
2253 // zuruecksetzen, damit sie wieder aufgespannt werden
2254 pTNd->DontExpandFmt( aIdx, sal_False, sal_False );
2255 aIdx = 0;
2256 pTNd->EraseText( aIdx, STRING_LEN,
2257 IDocumentContentOperations::INS_EMPTYEXPAND );
2258 pTNd->InsertText( sTmp, aIdx,
2259 IDocumentContentOperations::INS_EMPTYEXPAND );
2260 }
2261 }
2262
2263 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
2264
2265 // Ausrichtung umsetzen
2266 if( bChgAlign && pAttrSet && SFX_ITEM_SET == pAttrSet->GetItemState(
2267 RES_PARATR_ADJUST, sal_False, &pItem ) &&
2268 SVX_ADJUST_RIGHT == ((SvxAdjustItem*)pItem)->GetAdjust() )
2269 {
2270 pTNd->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
2271 }
2272
2273 // Farbe umsetzen oder "Benutzer Farbe" sichern
2274 if( !pAttrSet || SFX_ITEM_SET != pAttrSet->
2275 GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
2276 pItem = 0;
2277
2278 const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
2279 const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
2280
2281 if( ( pNewUserColor && pOldNumFmtColor &&
2282 *pNewUserColor == *pOldNumFmtColor ) ||
2283 ( !pNewUserColor && !pOldNumFmtColor ))
2284 {
2285 // User Color nicht veraendern aktuellen Werte setzen
2286 // ggfs. die alte NumFmtColor loeschen
2287 if( pCol )
2288 // ggfs. die Farbe setzen
2289 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2290 else if( pItem )
2291 {
2292 pNewUserColor = rBox.GetSaveUserColor();
2293 if( pNewUserColor )
2294 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2295 else
2296 pTNd->ResetAttr( RES_CHRATR_COLOR );
2297 }
2298 }
2299 else
2300 {
2301 // User Color merken, ggfs. die NumFormat Color setzen, aber
2302 // nie die Farbe zurueck setzen
2303 rBox.SetSaveUserColor( pNewUserColor );
2304
2305 if( pCol )
2306 // ggfs. die Farbe setzen
2307 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2308
2309 }
2310 rBox.SetSaveNumFmtColor( pCol );
2311
2312
2313 // vertikale Ausrichtung umsetzen
2314 if( bChgAlign &&
2315 SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState(
2316 RES_VERT_ORIENT, sal_False, &pItem ) &&
2317 text::VertOrientation::BOTTOM == ((SwFmtVertOrient*)pItem)->GetVertOrient() )
2318 {
2319 rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
2320 }
2321 }
2322 }
2323
2324 // zum Erkennen von Veraenderungen (haupts. TableBoxAttribute)
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2325 void SwTableBoxFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2326 {
2327 if( !IsModifyLocked() && !IsInDocDTOR() )
2328 {
2329 const SwTblBoxNumFormat *pNewFmt = 0;
2330 const SwTblBoxFormula *pNewFml = 0;
2331 const SwTblBoxValue *pNewVal = 0;
2332 double aOldValue = 0;
2333 sal_uLong nOldFmt = NUMBERFORMAT_TEXT;
2334
2335 switch( pNew ? pNew->Which() : 0 )
2336 {
2337 case RES_ATTRSET_CHG:
2338 {
2339 const SfxItemSet& rSet = *((SwAttrSetChg*)pNew)->GetChgSet();
2340 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT,
2341 sal_False, (const SfxPoolItem**)&pNewFmt ) )
2342 nOldFmt = ((SwTblBoxNumFormat&)((SwAttrSetChg*)pOld)->
2343 GetChgSet()->Get( RES_BOXATR_FORMAT )).GetValue();
2344 rSet.GetItemState( RES_BOXATR_FORMULA, sal_False,
2345 (const SfxPoolItem**)&pNewFml );
2346 if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_VALUE,
2347 sal_False, (const SfxPoolItem**)&pNewVal ) )
2348 aOldValue = ((SwTblBoxValue&)((SwAttrSetChg*)pOld)->
2349 GetChgSet()->Get( RES_BOXATR_VALUE )).GetValue();
2350 }
2351 break;
2352
2353 case RES_BOXATR_FORMAT:
2354 pNewFmt = (SwTblBoxNumFormat*)pNew;
2355 nOldFmt = ((SwTblBoxNumFormat*)pOld)->GetValue();
2356 break;
2357 case RES_BOXATR_FORMULA:
2358 pNewFml = (SwTblBoxFormula*)pNew;
2359 break;
2360 case RES_BOXATR_VALUE:
2361 pNewVal = (SwTblBoxValue*)pNew;
2362 aOldValue = ((SwTblBoxValue*)pOld)->GetValue();
2363 break;
2364 }
2365
2366 // es hat sich etwas getan und im Set ist noch irgendein BoxAttribut
2367 // vorhanden!
2368 if( pNewFmt || pNewFml || pNewVal )
2369 {
2370 GetDoc()->SetFieldsDirty(true, NULL, 0);
2371
2372 if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMAT, sal_False ) ||
2373 SFX_ITEM_SET == GetItemState( RES_BOXATR_VALUE, sal_False ) ||
2374 SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False ) )
2375 {
2376 // die Box holen
2377 SwIterator<SwTableBox,SwFmt> aIter( *this );
2378 SwTableBox* pBox = aIter.First();
2379 if( pBox )
2380 {
2381 ASSERT( !aIter.Next(), "keine Box oder mehrere am Format" );
2382
2383 sal_uLong nNewFmt;
2384 if( pNewFmt )
2385 {
2386 nNewFmt = pNewFmt->GetValue();
2387 // neu Formatieren
2388 // ist es neuer oder wurde der akt. entfernt?
2389 if( SFX_ITEM_SET != GetItemState( RES_BOXATR_VALUE, sal_False ))
2390 pNewFmt = 0;
2391 }
2392 else
2393 {
2394 // das akt. Item besorgen
2395 GetItemState( RES_BOXATR_FORMAT, sal_False,
2396 (const SfxPoolItem**)&pNewFmt );
2397 nOldFmt = GetTblBoxNumFmt().GetValue();
2398 nNewFmt = pNewFmt ? pNewFmt->GetValue() : nOldFmt;
2399 }
2400
2401 // ist es neuer oder wurde der akt. entfernt?
2402 if( pNewVal )
2403 {
2404 if( NUMBERFORMAT_TEXT != nNewFmt )
2405 {
2406 if( SFX_ITEM_SET == GetItemState(
2407 RES_BOXATR_VALUE, sal_False ))
2408 nOldFmt = NUMBERFORMAT_TEXT;
2409 else
2410 nNewFmt = NUMBERFORMAT_TEXT;
2411 }
2412 else if( NUMBERFORMAT_TEXT == nNewFmt )
2413 nOldFmt = 0;
2414 }
2415
2416 // Logik:
2417 // ValueAenderung: -> "simuliere" eine FormatAenderung!
2418 // FormatAenderung:
2419 // Text -> !Text oder FormatAenderung:
2420 // - Ausrichtung auf RECHTS, wenn LINKS oder Blocksatz
2421 // - vertikale Ausrichtung auf UNTEN wenn OBEN oder nicht
2422 // gesetzt ist.
2423 // - Text ersetzen (Farbe?? neg. Zahlen ROT??)
2424 // !Text -> Text:
2425 // - Ausrichtung auf LINKS, wenn RECHTS
2426 // - vertikale Ausrichtung auf OEBN, wenn UNTEN gesetzt ist
2427
2428 SvNumberFormatter* pNumFmtr = GetDoc()->GetNumberFormatter();
2429 sal_Bool bNewIsTxtFmt = pNumFmtr->IsTextFormat( nNewFmt ) ||
2430 NUMBERFORMAT_TEXT == nNewFmt;
2431
2432 if( (!bNewIsTxtFmt && nOldFmt != nNewFmt) || pNewFml )
2433 {
2434 sal_Bool bChgTxt = sal_True;
2435 double fVal = 0;
2436 if( !pNewVal && SFX_ITEM_SET != GetItemState(
2437 RES_BOXATR_VALUE, sal_False, (const SfxPoolItem**)&pNewVal ))
2438 {
2439 // es wurde noch nie ein Wert gesetzt, dann versuche
2440 // doch mal den Inhalt auszuwerten
2441 sal_uLong nNdPos = pBox->IsValidNumTxtNd( sal_True );
2442 if( ULONG_MAX != nNdPos )
2443 {
2444 sal_uInt32 nTmpFmtIdx = nNewFmt;
2445 String aTxt( GetDoc()->GetNodes()[ nNdPos ]
2446 ->GetTxtNode()->GetRedlineTxt());
2447 if( !aTxt.Len() )
2448 bChgTxt = sal_False;
2449 else
2450 {
2451 //JP 15.09.98: Bug 55741 - Tabs beibehalten
2452 lcl_TabToBlankAtSttEnd( aTxt );
2453
2454 // JP 22.04.98: Bug 49659 -
2455 // Sonderbehandlung fuer Prozent
2456 sal_Bool bIsNumFmt = sal_False;
2457 if( NUMBERFORMAT_PERCENT ==
2458 pNumFmtr->GetType( nNewFmt ))
2459 {
2460 sal_uInt32 nTmpFmt = 0;
2461 if( pNumFmtr->IsNumberFormat(
2462 aTxt, nTmpFmt, fVal ))
2463 {
2464 if( NUMBERFORMAT_NUMBER ==
2465 pNumFmtr->GetType( nTmpFmt ))
2466 aTxt += '%';
2467
2468 bIsNumFmt = pNumFmtr->IsNumberFormat(
2469 aTxt, nTmpFmtIdx, fVal );
2470 }
2471 }
2472 else
2473 bIsNumFmt = pNumFmtr->IsNumberFormat(
2474 aTxt, nTmpFmtIdx, fVal );
2475
2476 if( bIsNumFmt )
2477 {
2478 // dann setze den Value direkt in den Set -
2479 // ohne Modify
2480 int bIsLockMod = IsModifyLocked();
2481 LockModify();
2482 SetFmtAttr( SwTblBoxValue( fVal ));
2483 if( !bIsLockMod )
2484 UnlockModify();
2485 }
2486 }
2487 }
2488 }
2489 else
2490 fVal = pNewVal->GetValue();
2491
2492 // den Inhalt mit dem neuen Wert Formtieren und in den Absatz
2493 // schbreiben
2494 Color* pCol = 0;
2495 String sNewTxt;
2496 if( DBL_MAX == fVal )
2497 sNewTxt = ViewShell::GetShellRes()->aCalc_Error;
2498 else
2499 {
2500 pNumFmtr->GetOutputString( fVal, nNewFmt, sNewTxt, &pCol );
2501
2502 if( !bChgTxt )
2503 sNewTxt.Erase();
2504 }
2505
2506 // ueber alle Boxen
2507 ChgTextToNum( *pBox, sNewTxt, pCol,
2508 GetDoc()->IsInsTblAlignNum() );
2509
2510 }
2511 else if( bNewIsTxtFmt && nOldFmt != nNewFmt )
2512 {
2513 // auf jedenfall muessen jetzt die Formeln/Values
2514 // geloescht werden!
2515 // LockModify();
2516 // ResetAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
2517 // UnlockModify();
2518
2519
2520 ChgNumToText( *pBox, nNewFmt );
2521 }
2522 }
2523 }
2524 }
2525 }
2526 // Und die Basis-Klasse rufen
2527 SwFrmFmt::Modify( pOld, pNew );
2528 }
2529
HasNumCntnt(double & rNum,sal_uInt32 & rFmtIndex,sal_Bool & rIsEmptyTxtNd) const2530 sal_Bool SwTableBox::HasNumCntnt( double& rNum, sal_uInt32& rFmtIndex,
2531 sal_Bool& rIsEmptyTxtNd ) const
2532 {
2533 sal_Bool bRet = sal_False;
2534 sal_uLong nNdPos = IsValidNumTxtNd( sal_True );
2535 if( ULONG_MAX != nNdPos )
2536 {
2537 String aTxt( pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->
2538 GetRedlineTxt() );
2539 //JP 15.09.98: Bug 55741 - Tabs beibehalten
2540 lcl_TabToBlankAtSttEnd( aTxt );
2541 rIsEmptyTxtNd = 0 == aTxt.Len();
2542 SvNumberFormatter* pNumFmtr = GetFrmFmt()->GetDoc()->GetNumberFormatter();
2543
2544 const SfxPoolItem* pItem;
2545 if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT,
2546 sal_False, &pItem ))
2547 {
2548 rFmtIndex = ((SwTblBoxNumFormat*)pItem)->GetValue();
2549 // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent
2550 if( !rIsEmptyTxtNd &&
2551 NUMBERFORMAT_PERCENT == pNumFmtr->GetType( rFmtIndex ))
2552 {
2553 sal_uInt32 nTmpFmt = 0;
2554 if( pNumFmtr->IsNumberFormat( aTxt, nTmpFmt, rNum ) &&
2555 NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt ))
2556 aTxt += '%';
2557 }
2558 }
2559 else
2560 rFmtIndex = 0;
2561
2562 bRet = pNumFmtr->IsNumberFormat( aTxt, rFmtIndex, rNum );
2563 }
2564 else
2565 rIsEmptyTxtNd = sal_False;
2566 return bRet;
2567 }
2568
IsNumberChanged() const2569 sal_Bool SwTableBox::IsNumberChanged() const
2570 {
2571 sal_Bool bRet = sal_True;
2572
2573 if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA, sal_False ))
2574 {
2575 const SwTblBoxNumFormat *pNumFmt;
2576 const SwTblBoxValue *pValue;
2577
2578 if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_VALUE, sal_False,
2579 (const SfxPoolItem**)&pValue ))
2580 pValue = 0;
2581 if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, sal_False,
2582 (const SfxPoolItem**)&pNumFmt ))
2583 pNumFmt = 0;
2584
2585 sal_uLong nNdPos;
2586 if( pNumFmt && pValue &&
2587 ULONG_MAX != ( nNdPos = IsValidNumTxtNd( sal_True ) ) )
2588 {
2589 String sNewTxt, sOldTxt( pSttNd->GetNodes()[ nNdPos ]->
2590 GetTxtNode()->GetRedlineTxt() );
2591 lcl_DelTabsAtSttEnd( sOldTxt );
2592
2593 Color* pCol = 0;
2594 GetFrmFmt()->GetDoc()->GetNumberFormatter()->GetOutputString(
2595 pValue->GetValue(), pNumFmt->GetValue(), sNewTxt, &pCol );
2596
2597 bRet = sNewTxt != sOldTxt ||
2598 !( ( !pCol && !GetSaveNumFmtColor() ) ||
2599 ( pCol && GetSaveNumFmtColor() &&
2600 *pCol == *GetSaveNumFmtColor() ));
2601 }
2602 }
2603 return bRet;
2604 }
2605
IsValidNumTxtNd(sal_Bool bCheckAttr) const2606 sal_uLong SwTableBox::IsValidNumTxtNd( sal_Bool bCheckAttr ) const
2607 {
2608 sal_uLong nPos = ULONG_MAX;
2609 if( pSttNd )
2610 {
2611 SwNodeIndex aIdx( *pSttNd );
2612 sal_uLong nIndex = aIdx.GetIndex();
2613 const sal_uLong nIndexEnd = pSttNd->GetNodes()[ nIndex ]->EndOfSectionIndex();
2614 const SwTxtNode *pTextNode = 0;
2615 while( ++nIndex < nIndexEnd )
2616 {
2617 const SwNode* pNode = pSttNd->GetNodes()[nIndex];
2618 if( pNode->IsTableNode() )
2619 { /*return ULONG_MAX if the cell contains a table(in table)*/
2620 pTextNode = 0;
2621 break;
2622 }
2623 if( pNode->IsTxtNode() )
2624 {
2625 if( pTextNode )
2626 { /*return ULONG_MAX if the cell contains complex paragraphs*/
2627 pTextNode = 0;
2628 break;
2629 }
2630 else
2631 {
2632 pTextNode = pNode->GetTxtNode();
2633 nPos = nIndex;
2634 }
2635 }
2636 }
2637 if( pTextNode )
2638 {
2639 if( bCheckAttr )
2640 {
2641 const SwpHints* pHts = pTextNode->GetpSwpHints();
2642 const String& rTxt = pTextNode->GetTxt();
2643 // dann teste doch mal, ob das wirklich nur Text im Node steht!
2644 // Flys/Felder/..
2645 if( pHts )
2646 {
2647 xub_StrLen nNextSetField = 0;
2648 for( sal_uInt16 n = 0; n < pHts->Count(); ++n )
2649 {
2650 const SwTxtAttr* pAttr = (*pHts)[ n ];
2651 if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() ||
2652 *pAttr->GetStart() ||
2653 *pAttr->GetAnyEnd() < rTxt.Len() )
2654 {
2655 if ( (*pAttr->GetStart() == nNextSetField)
2656 && (pAttr->Which() == RES_TXTATR_FIELD))
2657 {
2658 // #i104949# hideous hack for report builder:
2659 // it inserts hidden variable-set fields at
2660 // the beginning of para in cell, but they
2661 // should not turn cell into text cell
2662 const SwField* pField = pAttr->GetFmtFld().GetField();
2663 if (pField &&
2664 (pField->GetTypeId() == TYP_SETFLD) &&
2665 (0 != (static_cast<SwSetExpField const*>
2666 (pField)->GetSubType() &
2667 nsSwExtendedSubType::SUB_INVISIBLE)))
2668 {
2669 nNextSetField = *pAttr->GetStart() + 1;
2670 continue;
2671 }
2672 }
2673 nPos = ULONG_MAX;
2674 break;
2675 }
2676 }
2677 }
2678 }
2679 }
2680 else
2681 nPos = ULONG_MAX;
2682 }
2683 return nPos;
2684 }
2685
2686 // ist das eine FormelBox oder eine Box mit numerischen Inhalt (AutoSum)
IsFormulaOrValueBox() const2687 sal_uInt16 SwTableBox::IsFormulaOrValueBox() const
2688 {
2689 sal_uInt16 nWhich = 0;
2690 const SwTxtNode* pTNd;
2691 SwFrmFmt* pFmt = GetFrmFmt();
2692 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ))
2693 nWhich = RES_BOXATR_FORMULA;
2694 else if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) &&
2695 !pFmt->GetDoc()->GetNumberFormatter()->IsTextFormat(
2696 pFmt->GetTblBoxNumFmt().GetValue() ))
2697 nWhich = RES_BOXATR_VALUE;
2698 else if( pSttNd && pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex()
2699 && 0 != ( pTNd = pSttNd->GetNodes()[ pSttNd->GetIndex() + 1 ]
2700 ->GetTxtNode() ) && !pTNd->GetTxt().Len() )
2701 nWhich = USHRT_MAX;
2702
2703 return nWhich;
2704 }
2705
ActualiseValueBox()2706 void SwTableBox::ActualiseValueBox()
2707 {
2708 const SfxPoolItem *pFmtItem, *pValItem;
2709 SwFrmFmt* pFmt = GetFrmFmt();
2710 if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT, sal_True, &pFmtItem )
2711 && SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_True, &pValItem ))
2712 {
2713 const sal_uLong nFmtId = ((SwTblBoxNumFormat*)pFmtItem)->GetValue();
2714 sal_uLong nNdPos = ULONG_MAX;
2715 SvNumberFormatter* pNumFmtr = pFmt->GetDoc()->GetNumberFormatter();
2716
2717 if( !pNumFmtr->IsTextFormat( nFmtId ) &&
2718 ULONG_MAX != (nNdPos = IsValidNumTxtNd( sal_True )) )
2719 {
2720 double fVal = ((SwTblBoxValue*)pValItem)->GetValue();
2721 Color* pCol = 0;
2722 String sNewTxt;
2723 pNumFmtr->GetOutputString( fVal, nFmtId, sNewTxt, &pCol );
2724
2725 const String& rTxt = pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->GetTxt();
2726 if( rTxt != sNewTxt )
2727 ChgTextToNum( *this, sNewTxt, pCol, sal_False ,nNdPos);
2728 }
2729 }
2730 }
2731
SetNewCol(Color ** ppCol,const Color * pNewCol)2732 void SwTableBox_Impl::SetNewCol( Color** ppCol, const Color* pNewCol )
2733 {
2734 if( *ppCol != pNewCol )
2735 {
2736 delete *ppCol;
2737 if( pNewCol )
2738 *ppCol = new Color( *pNewCol );
2739 else
2740 *ppCol = 0;
2741 }
2742 }
2743
2744 struct SwTableCellInfo::Impl
2745 {
2746 const SwTable * m_pTable;
2747 const SwCellFrm * m_pCellFrm;
2748 const SwTabFrm * m_pTabFrm;
2749 typedef ::std::set<const SwTableBox *> TableBoxes_t;
2750 TableBoxes_t m_HandledTableBoxes;
2751
2752 public:
ImplSwTableCellInfo::Impl2753 Impl()
2754 : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL)
2755 {
2756 }
2757
~ImplSwTableCellInfo::Impl2758 ~Impl() {}
2759
setTableSwTableCellInfo::Impl2760 void setTable(const SwTable * pTable) {
2761 m_pTable = pTable;
2762 SwFrmFmt * pFrmFmt = m_pTable->GetFrmFmt();
2763 m_pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement(*pFrmFmt);
2764 if (m_pTabFrm->IsFollow())
2765 m_pTabFrm = m_pTabFrm->FindMaster(true);
2766 }
getTableSwTableCellInfo::Impl2767 const SwTable * getTable() const { return m_pTable; }
2768
getCellFrmSwTableCellInfo::Impl2769 const SwCellFrm * getCellFrm() const { return m_pCellFrm; }
2770
2771 const SwFrm * getNextFrmInTable(const SwFrm * pFrm);
2772 const SwCellFrm * getNextCellFrm(const SwFrm * pFrm);
2773 const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm);
2774 bool getNext();
2775 };
2776
getNextFrmInTable(const SwFrm * pFrm)2777 const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm)
2778 {
2779 const SwFrm * pResult = NULL;
2780
2781 if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower())
2782 pResult = pFrm->GetLower();
2783 else if (pFrm->GetNext())
2784 pResult = pFrm->GetNext();
2785 else
2786 {
2787 while (pFrm->GetUpper() != NULL)
2788 {
2789 pFrm = pFrm->GetUpper();
2790
2791 if (pFrm->IsTabFrm())
2792 {
2793 m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow();
2794 pResult = m_pTabFrm;
2795 break;
2796 }
2797 else if (pFrm->GetNext())
2798 {
2799 pResult = pFrm->GetNext();
2800 break;
2801 }
2802 }
2803 }
2804
2805 return pResult;
2806 }
2807
getNextCellFrm(const SwFrm * pFrm)2808 const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm)
2809 {
2810 const SwCellFrm * pResult = NULL;
2811
2812 while ((pFrm = getNextFrmInTable(pFrm)) != NULL)
2813 {
2814 if (pFrm->IsCellFrm())
2815 {
2816 pResult = static_cast<const SwCellFrm *>(pFrm);
2817 break;
2818 }
2819 }
2820
2821 return pResult;
2822 }
2823
getNextTableBoxsCellFrm(const SwFrm * pFrm)2824 const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm)
2825 {
2826 const SwCellFrm * pResult = NULL;
2827
2828 while ((pFrm = getNextCellFrm(pFrm)) != NULL)
2829 {
2830 const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm);
2831 const SwTableBox * pTabBox = pCellFrm->GetTabBox();
2832 TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox);
2833
2834 if (aIt == m_HandledTableBoxes.end())
2835 {
2836 pResult = pCellFrm;
2837 m_HandledTableBoxes.insert(pTabBox);
2838 break;
2839 }
2840 }
2841
2842 return pResult;
2843 }
2844
getCellFrm() const2845 const SwCellFrm * SwTableCellInfo::getCellFrm() const
2846 {
2847 return m_pImpl->getCellFrm();
2848 }
2849
getNext()2850 bool SwTableCellInfo::Impl::getNext()
2851 {
2852 if (m_pCellFrm == NULL)
2853 {
2854 if (m_pTabFrm != NULL)
2855 m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm);
2856 }
2857 else
2858 m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm);
2859
2860 return m_pCellFrm != NULL;
2861 }
2862
SwTableCellInfo(const SwTable * pTable)2863 SwTableCellInfo::SwTableCellInfo(const SwTable * pTable)
2864 {
2865 m_pImpl.reset(new Impl());
2866 m_pImpl->setTable(pTable);
2867 }
2868
~SwTableCellInfo()2869 SwTableCellInfo::~SwTableCellInfo()
2870 {
2871 }
2872
getNext()2873 bool SwTableCellInfo::getNext()
2874 {
2875 return m_pImpl->getNext();
2876 }
2877
getRect() const2878 SwRect SwTableCellInfo::getRect() const
2879 {
2880 SwRect aRet;
2881
2882 if (getCellFrm() != NULL)
2883 aRet = getCellFrm()->Frm();
2884
2885 return aRet;
2886 }
2887
getTableBox() const2888 const SwTableBox * SwTableCellInfo::getTableBox() const
2889 {
2890 const SwTableBox * pRet = NULL;
2891
2892 if (getCellFrm() != NULL)
2893 pRet = getCellFrm()->GetTabBox();
2894
2895 return pRet;
2896 }
2897
RegisterToFormat(SwFmt & rFmt)2898 void SwTable::RegisterToFormat( SwFmt& rFmt )
2899 {
2900 rFmt.Add( this );
2901 }
2902
RegisterToFormat(SwFmt & rFmt)2903 void SwTableLine::RegisterToFormat( SwFmt& rFmt )
2904 {
2905 rFmt.Add( this );
2906 }
2907
RegisterToFormat(SwFmt & rFmt)2908 void SwTableBox::RegisterToFormat( SwFmt& rFmt )
2909 {
2910 rFmt.Add( this );
2911 }
2912
ForgetFrmFmt()2913 void SwTableBox::ForgetFrmFmt()
2914 {
2915 if ( GetRegisteredIn() )
2916 GetRegisteredInNonConst()->Remove(this);
2917 }
2918
2919
2920