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