Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <ctype.h>
22 : #include <float.h>
23 : #include <hintids.hxx>
24 : #include <hints.hxx> // for SwAttrSetChg
25 : #include <editeng/lrspitem.hxx>
26 : #include <editeng/shaditem.hxx>
27 : #include <editeng/adjitem.hxx>
28 : #include <editeng/colritem.hxx>
29 : #include <sfx2/linkmgr.hxx>
30 : #include <editeng/boxitem.hxx>
31 : #include <fmtfsize.hxx>
32 : #include <fmtornt.hxx>
33 : #include <fmtpdsc.hxx>
34 : #include <fldbas.hxx>
35 : #include <fmtfld.hxx>
36 : #include <frmatr.hxx>
37 : #include <doc.hxx>
38 : #include <docary.hxx> // for RedlineTbl()
39 : #include <frame.hxx>
40 : #include <swtable.hxx>
41 : #include <ndtxt.hxx>
42 : #include <tabcol.hxx>
43 : #include <tabfrm.hxx>
44 : #include <cellfrm.hxx>
45 : #include <rowfrm.hxx>
46 : #include <swserv.hxx>
47 : #include <expfld.hxx>
48 : #include <mdiexp.hxx>
49 : #include <cellatr.hxx>
50 : #include <txatbase.hxx>
51 : #include <htmltbl.hxx>
52 : #include <swtblfmt.hxx>
53 : #include <ndindex.hxx>
54 : #include <tblrwcl.hxx>
55 : #include <shellres.hxx>
56 : #include <viewsh.hxx>
57 : #include <redline.hxx>
58 : #include <list>
59 : #include <switerator.hxx>
60 :
61 : #ifdef DBG_UTIL
62 : #define CHECK_TABLE(t) (t).CheckConsistency();
63 : #else
64 : #define CHECK_TABLE(t)
65 : #endif
66 :
67 : using namespace com::sun::star;
68 :
69 72748 : TYPEINIT1( SwTable, SwClient );
70 167313 : TYPEINIT1( SwTableBox, SwClient );
71 12964 : TYPEINIT1( SwTableLine, SwClient );
72 264 : TYPEINIT1( SwTableFmt, SwFrmFmt );
73 3366 : TYPEINIT1( SwTableBoxFmt, SwFrmFmt );
74 930 : TYPEINIT1( SwTableLineFmt, SwFrmFmt );
75 :
76 0 : SV_IMPL_REF( SwServerObject )
77 :
78 : #define COLFUZZY 20
79 :
80 : void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
81 : sal_Bool bChgAlign,sal_uLong nNdPos );
82 : //----------------------------------
83 :
84 : class SwTableBox_Impl
85 : {
86 : Color *mpUserColor, *mpNumFmtColor;
87 : long mnRowSpan;
88 : bool mbDummyFlag;
89 :
90 : void SetNewCol( Color** ppCol, const Color* pNewCol );
91 : public:
92 0 : SwTableBox_Impl() : mpUserColor(0), mpNumFmtColor(0), mnRowSpan(1),
93 0 : mbDummyFlag( false ) {}
94 0 : ~SwTableBox_Impl() { delete mpUserColor; delete mpNumFmtColor; }
95 :
96 0 : const Color* GetSaveUserColor() const { return mpUserColor; }
97 0 : const Color* GetSaveNumFmtColor() const { return mpNumFmtColor; }
98 0 : void SetSaveUserColor(const Color* p ) { SetNewCol( &mpUserColor, p ); }
99 0 : void SetSaveNumFmtColor( const Color* p ) { SetNewCol( &mpNumFmtColor, p ); }
100 0 : long getRowSpan() const { return mnRowSpan; }
101 0 : void setRowSpan( long nNewRowSpan ) { mnRowSpan = nNewRowSpan; }
102 0 : bool getDummyFlag() const { return mbDummyFlag; }
103 0 : void setDummyFlag( bool bDummy ) { mbDummyFlag = bDummy; }
104 : };
105 :
106 : // ----------- Inlines -----------------------------
107 :
108 0 : inline const Color* SwTableBox::GetSaveUserColor() const
109 : {
110 0 : return pImpl ? pImpl->GetSaveUserColor() : 0;
111 : }
112 :
113 0 : inline const Color* SwTableBox::GetSaveNumFmtColor() const
114 : {
115 0 : return pImpl ? pImpl->GetSaveNumFmtColor() : 0;
116 : }
117 :
118 0 : inline void SwTableBox::SetSaveUserColor(const Color* p )
119 : {
120 0 : if( pImpl )
121 0 : pImpl->SetSaveUserColor( p );
122 0 : else if( p )
123 0 : ( pImpl = new SwTableBox_Impl ) ->SetSaveUserColor( p );
124 0 : }
125 :
126 0 : inline void SwTableBox::SetSaveNumFmtColor( const Color* p )
127 : {
128 0 : if( pImpl )
129 0 : pImpl->SetSaveNumFmtColor( p );
130 0 : else if( p )
131 0 : ( pImpl = new SwTableBox_Impl )->SetSaveNumFmtColor( p );
132 0 : }
133 :
134 29503 : long SwTableBox::getRowSpan() const
135 : {
136 29503 : return pImpl ? pImpl->getRowSpan() : 1;
137 : }
138 :
139 10 : void SwTableBox::setRowSpan( long nNewRowSpan )
140 : {
141 10 : if( !pImpl )
142 : {
143 10 : if( nNewRowSpan == 1 )
144 20 : return;
145 0 : pImpl = new SwTableBox_Impl();
146 : }
147 0 : pImpl->setRowSpan( nNewRowSpan );
148 : }
149 :
150 0 : bool SwTableBox::getDummyFlag() const
151 : {
152 0 : return pImpl ? pImpl->getDummyFlag() : false;
153 : }
154 :
155 0 : void SwTableBox::setDummyFlag( bool bDummy )
156 : {
157 0 : if( !pImpl )
158 : {
159 0 : if( !bDummy )
160 0 : return;
161 0 : pImpl = new SwTableBox_Impl();
162 : }
163 0 : pImpl->setDummyFlag( bDummy );
164 : }
165 :
166 : //JP 15.09.98: Bug 55741 - Keep tabs (front and rear)
167 0 : static String& lcl_TabToBlankAtSttEnd( String& rTxt )
168 : {
169 : sal_Unicode c;
170 : xub_StrLen n;
171 :
172 0 : for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
173 0 : if( '\x9' == c )
174 0 : rTxt.SetChar( n, ' ' );
175 0 : for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
176 0 : if( '\x9' == c )
177 0 : rTxt.SetChar( n, ' ' );
178 0 : return rTxt;
179 : }
180 :
181 0 : static String& lcl_DelTabsAtSttEnd( String& rTxt )
182 : {
183 : sal_Unicode c;
184 : xub_StrLen n;
185 :
186 0 : for( n = 0; n < rTxt.Len() && ' ' >= ( c = rTxt.GetChar( n )); ++n )
187 0 : if( '\x9' == c )
188 0 : rTxt.Erase( n--, 1 );
189 0 : for( n = rTxt.Len(); n && ' ' >= ( c = rTxt.GetChar( --n )); )
190 0 : if( '\x9' == c )
191 0 : rTxt.Erase( n, 1 );
192 0 : return rTxt;
193 : }
194 :
195 0 : void _InsTblBox( SwDoc* pDoc, SwTableNode* pTblNd,
196 : SwTableLine* pLine, SwTableBoxFmt* pBoxFrmFmt,
197 : SwTableBox* pBox,
198 : sal_uInt16 nInsPos, sal_uInt16 nCnt )
199 : {
200 : OSL_ENSURE( pBox->GetSttNd(), "Box with no start node" );
201 0 : SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
202 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
203 0 : if( !pCNd )
204 0 : pCNd = pDoc->GetNodes().GoNext( &aIdx );
205 : OSL_ENSURE( pCNd, "Box with no content node" );
206 :
207 0 : if( pCNd->IsTxtNode() )
208 : {
209 0 : if( pBox->GetSaveNumFmtColor() && pCNd->GetpSwAttrSet() )
210 : {
211 0 : SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
212 0 : if( pBox->GetSaveUserColor() )
213 0 : aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
214 : else
215 0 : aAttrSet.ClearItem( RES_CHRATR_COLOR );
216 0 : pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
217 : ((SwTxtNode*)pCNd)->GetTxtColl(),
218 0 : &aAttrSet, nInsPos, nCnt );
219 : }
220 : else
221 0 : pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
222 : ((SwTxtNode*)pCNd)->GetTxtColl(),
223 0 : pCNd->GetpSwAttrSet(),
224 0 : nInsPos, nCnt );
225 : }
226 : else
227 0 : pDoc->GetNodes().InsBoxen( pTblNd, pLine, pBoxFrmFmt,
228 0 : (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0,
229 0 : nInsPos, nCnt );
230 :
231 0 : long nRowSpan = pBox->getRowSpan();
232 0 : if( nRowSpan != 1 )
233 : {
234 0 : SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
235 0 : for( sal_uInt16 i = 0; i < nCnt; ++i )
236 : {
237 0 : pBox = rTblBoxes[ i + nInsPos ];
238 0 : pBox->setRowSpan( nRowSpan );
239 : }
240 0 : }
241 0 : }
242 :
243 : /*************************************************************************
244 : |*
245 : |* SwTable::SwTable()
246 : |*
247 : |*************************************************************************/
248 178 : SwTable::SwTable( SwTableFmt* pFmt )
249 : : SwClient( pFmt ),
250 : pHTMLLayout( 0 ),
251 : pTableNode( 0 ),
252 : nGrfsThatResize( 0 ),
253 : nRowsToRepeat( 1 ),
254 : bModifyLocked( false ),
255 178 : bNewModel( sal_True )
256 : {
257 : // default value set in the options
258 178 : eTblChgMode = (TblChgMode)GetTblChgDefaultMode();
259 178 : }
260 :
261 0 : SwTable::SwTable( const SwTable& rTable )
262 0 : : SwClient( rTable.GetFrmFmt() ),
263 : pHTMLLayout( 0 ),
264 : pTableNode( 0 ),
265 : eTblChgMode( rTable.eTblChgMode ),
266 : nGrfsThatResize( 0 ),
267 0 : nRowsToRepeat( rTable.GetRowsToRepeat() ),
268 : bModifyLocked( false ),
269 0 : bNewModel( rTable.bNewModel )
270 : {
271 0 : }
272 :
273 96 : void DelBoxNode( SwTableSortBoxes& rSortCntBoxes )
274 : {
275 1458 : for (size_t n = 0; n < rSortCntBoxes.size(); ++n)
276 : {
277 1362 : rSortCntBoxes[ n ]->pSttNd = 0;
278 : }
279 96 : }
280 :
281 288 : SwTable::~SwTable()
282 : {
283 96 : if( refObj.Is() )
284 : {
285 0 : SwDoc* pDoc = GetFrmFmt()->GetDoc();
286 0 : if( !pDoc->IsInDtor() ) // then remove from the list
287 0 : pDoc->GetLinkManager().RemoveServer( &refObj );
288 :
289 0 : refObj->Closed();
290 : }
291 :
292 : // the table can be deleted if it's the last client of the FrameFormat
293 96 : SwTableFmt* pFmt = (SwTableFmt*)GetFrmFmt();
294 96 : pFmt->Remove( this ); // remove
295 :
296 96 : if( !pFmt->GetDepends() )
297 96 : pFmt->GetDoc()->DelTblFrmFmt( pFmt ); // and delete
298 :
299 : // Delete the pointers from the SortArray of the boxes. The objects
300 : // are preserved and are deleted by the lines/boxes arrays dtor.
301 : // Note: unfortunately not enough, pointers to the StartNode of the
302 : // section need deletion.
303 96 : DelBoxNode(m_TabSortContentBoxes);
304 96 : m_TabSortContentBoxes.clear();
305 96 : delete pHTMLLayout;
306 192 : }
307 :
308 : /*************************************************************************
309 : |*
310 : |* SwTable::Modify()
311 : |*
312 : |*************************************************************************/
313 1014 : static void FmtInArr( std::vector<SwFmt*>& rFmtArr, SwFmt* pBoxFmt )
314 : {
315 1014 : std::vector<SwFmt*>::const_iterator it = std::find( rFmtArr.begin(), rFmtArr.end(), pBoxFmt );
316 1014 : if ( it == rFmtArr.end() )
317 294 : rFmtArr.push_back( pBoxFmt );
318 1014 : }
319 :
320 : static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
321 : const long nNew, std::vector<SwFmt*>& rFmtArr );
322 :
323 174 : static void lcl_ModifyLines( SwTableLines &rLines, const long nOld,
324 : const long nNew, std::vector<SwFmt*>& rFmtArr, const bool bCheckSum )
325 : {
326 650 : for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
327 476 : ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFmtArr );
328 174 : if( bCheckSum )
329 : {
330 468 : for( sal_uInt16 i = 0; i < rFmtArr.size(); ++i )
331 : {
332 294 : SwFmt* pFmt = rFmtArr[i];
333 294 : sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
334 294 : nBox *= nNew;
335 294 : nBox /= nOld;
336 294 : SwFmtFrmSize aNewBox( ATT_VAR_SIZE, SwTwips(nBox), 0 );
337 294 : pFmt->LockModify();
338 294 : pFmt->SetFmtAttr( aNewBox );
339 294 : pFmt->UnlockModify();
340 294 : }
341 : }
342 174 : }
343 :
344 476 : static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
345 : const long nNew, std::vector<SwFmt*>& rFmtArr )
346 : {
347 476 : sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
348 476 : sal_uInt64 nOriginalSum = 0; // Sum of original widths
349 1930 : for ( sal_uInt16 i = 0; i < rBoxes.size(); ++i )
350 : {
351 1454 : SwTableBox &rBox = *rBoxes[i];
352 1454 : if ( !rBox.GetTabLines().empty() )
353 : {
354 : // For SubTables the rounding problem will not be solved :-(
355 0 : ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFmtArr, false );
356 : }
357 : // Adjust the box
358 1454 : SwFrmFmt *pFmt = rBox.GetFrmFmt();
359 1454 : sal_uInt64 nBox = pFmt->GetFrmSize().GetWidth();
360 1454 : nOriginalSum += nBox;
361 1454 : nBox *= nNew;
362 1454 : nBox /= nOld;
363 1454 : sal_uInt64 nWishedSum = nOriginalSum;
364 1454 : nWishedSum *= nNew;
365 1454 : nWishedSum /= nOld;
366 1454 : nWishedSum -= nSum;
367 1454 : if( nWishedSum > 0 )
368 : {
369 1454 : if( nBox == nWishedSum )
370 1014 : FmtInArr( rFmtArr, pFmt );
371 : else
372 : {
373 440 : nBox = nWishedSum;
374 440 : pFmt = rBox.ClaimFrmFmt();
375 440 : SwFmtFrmSize aNewBox( ATT_VAR_SIZE, static_cast< SwTwips >(nBox), 0 );
376 440 : pFmt->LockModify();
377 440 : pFmt->SetFmtAttr( aNewBox );
378 440 : pFmt->UnlockModify();
379 : }
380 : }
381 : else {
382 : OSL_FAIL( "Rounding error" );
383 : }
384 1454 : nSum += nBox;
385 : }
386 476 : }
387 :
388 834 : void SwTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
389 : {
390 : // catch SSize changes, to adjust the lines/boxes
391 834 : sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
392 834 : const SwFmtFrmSize* pNewSize = 0, *pOldSize = 0;
393 :
394 834 : if( RES_ATTRSET_CHG == nWhich )
395 : {
396 1292 : if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
397 646 : RES_FRM_SIZE, sal_False, (const SfxPoolItem**)&pNewSize ))
398 174 : pOldSize = &((SwAttrSetChg*)pOld)->GetChgSet()->GetFrmSize();
399 : }
400 188 : else if( RES_FRM_SIZE == nWhich )
401 : {
402 0 : pOldSize = (const SwFmtFrmSize*)pOld;
403 0 : pNewSize = (const SwFmtFrmSize*)pNew;
404 : }
405 : else
406 188 : CheckRegistration( pOld, pNew );
407 :
408 834 : if( pOldSize || pNewSize )
409 : {
410 174 : if ( !IsModifyLocked() )
411 : {
412 : OSL_ENSURE( pOldSize && pOldSize->Which() == RES_FRM_SIZE &&
413 : pNewSize && pNewSize->Which() == RES_FRM_SIZE,
414 : "No Old or New for FmtFrmSize-Modify of the SwTable." );
415 174 : AdjustWidths( pOldSize->GetWidth(), pNewSize->GetWidth() );
416 : }
417 : }
418 834 : }
419 :
420 174 : void SwTable::AdjustWidths( const long nOld, const long nNew )
421 : {
422 174 : std::vector<SwFmt*> aFmtArr;
423 174 : aFmtArr.reserve( aLines[0]->GetTabBoxes().size() );
424 174 : ::lcl_ModifyLines( aLines, nOld, nNew, aFmtArr, true );
425 174 : }
426 :
427 : /*************************************************************************
428 : |*
429 : |* SwTable::GetTabCols()
430 : |*
431 : |*************************************************************************/
432 0 : static void lcl_RefreshHidden( SwTabCols &rToFill, sal_uInt16 nPos )
433 : {
434 0 : for ( sal_uInt16 i = 0; i < rToFill.Count(); ++i )
435 : {
436 0 : if ( Abs((long)(nPos - rToFill[i])) <= COLFUZZY )
437 : {
438 0 : rToFill.SetHidden( i, sal_False );
439 0 : break;
440 : }
441 : }
442 0 : }
443 :
444 656 : static void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
445 : const SwFrmFmt *pTabFmt, const sal_Bool bHidden,
446 : const bool bRefreshHidden )
447 : {
448 656 : const long nWish = pTabFmt->GetFrmSize().GetWidth();
449 : OSL_ENSURE(nWish, "weird <= 0 width frmfrm");
450 656 : const long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why?
451 :
452 : // The value for the left edge of the box is calculated from the
453 : // widths of the previous boxes.
454 656 : sal_uInt16 nPos = 0;
455 656 : sal_uInt16 nSum = 0;
456 656 : sal_uInt16 nLeftMin = 0;
457 656 : sal_uInt16 nRightMax = 0;
458 656 : const SwTableBox *pCur = pBox;
459 656 : const SwTableLine *pLine = pBox->GetUpper();
460 1968 : while ( pLine )
461 : {
462 656 : const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
463 2016 : for ( sal_uInt16 i = 0; i < rBoxes.size(); ++i )
464 : {
465 2016 : SwTwips nWidth = rBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
466 2016 : nSum = (sal_uInt16)(nSum + nWidth);
467 2016 : sal_uInt64 nTmp = nSum;
468 2016 : nTmp *= nAct;
469 :
470 2016 : if (nWish == 0) //fdo#33012 0 width frmfmt
471 0 : continue;
472 :
473 2016 : nTmp /= nWish;
474 2016 : if (rBoxes[i] != pCur)
475 : {
476 1360 : if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
477 1360 : nLeftMin = (sal_uInt16)(nTmp - nPos);
478 1360 : nPos = (sal_uInt16)nTmp;
479 : }
480 : else
481 : {
482 656 : nSum = (sal_uInt16)(nSum - nWidth);
483 656 : if ( 0 == nRightMax )
484 656 : nRightMax = (sal_uInt16)(nTmp - nPos);
485 656 : break;
486 : }
487 : }
488 656 : pCur = pLine->GetUpper();
489 656 : pLine = pCur ? pCur->GetUpper() : 0;
490 : }
491 :
492 656 : bool bInsert = !bRefreshHidden;
493 2044 : for ( sal_uInt16 j = 0; bInsert && (j < rToFill.Count()); ++j )
494 : {
495 1388 : long nCmp = rToFill[j];
496 1388 : if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
497 : (nPos <= (nCmp + COLFUZZY)) )
498 : {
499 52 : bInsert = false; // Already has it.
500 : }
501 1336 : else if ( nPos < nCmp )
502 : {
503 0 : bInsert = false;
504 0 : rToFill.Insert( nPos, bHidden, j );
505 : }
506 : }
507 656 : if ( bInsert )
508 604 : rToFill.Insert( nPos, bHidden, rToFill.Count() );
509 52 : else if ( bRefreshHidden )
510 0 : ::lcl_RefreshHidden( rToFill, nPos );
511 :
512 656 : if ( bHidden && !bRefreshHidden )
513 : {
514 : // calculate minimum/maximum values for the existing entries:
515 48 : nLeftMin = nPos - nLeftMin;
516 48 : nRightMax = nPos + nRightMax;
517 :
518 : // check if nPos is entry:
519 48 : bool bFoundPos = false;
520 48 : bool bFoundMax = false;
521 146 : for ( sal_uInt16 j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
522 : {
523 98 : SwTabColsEntry& rEntry = rToFill.GetEntry( j );
524 98 : long nCmp = rToFill[j];
525 :
526 98 : if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
527 : (nPos <= (nCmp + COLFUZZY)) )
528 : {
529 : // check if nLeftMin is > old minimum for entry nPos:
530 48 : const long nOldMin = rEntry.nMin;
531 48 : if ( nLeftMin > nOldMin )
532 0 : rEntry.nMin = nLeftMin;
533 : // check if nRightMin is < old maximum for entry nPos:
534 48 : const long nOldMax = rEntry.nMax;
535 48 : if ( nRightMax < nOldMax )
536 44 : rEntry.nMax = nRightMax;
537 :
538 48 : bFoundPos = true;
539 : }
540 50 : else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
541 : (nRightMax <= (nCmp + COLFUZZY)) )
542 : {
543 : // check if nPos is > old minimum for entry nRightMax:
544 23 : const long nOldMin = rEntry.nMin;
545 23 : if ( nPos > nOldMin )
546 4 : rEntry.nMin = nPos;
547 :
548 23 : bFoundMax = true;
549 : }
550 : }
551 : }
552 656 : }
553 :
554 608 : static void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
555 : const SwFrmFmt *pTabFmt, bool bRefreshHidden )
556 : {
557 608 : if ( !pBox->GetTabLines().empty() )
558 : {
559 0 : const SwTableLines &rLines = pBox->GetTabLines();
560 0 : for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
561 0 : { const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
562 0 : for ( sal_uInt16 j = 0; j < rBoxes.size(); ++j )
563 0 : ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFmt, bRefreshHidden);
564 : }
565 : }
566 : else
567 608 : ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_False, bRefreshHidden );
568 608 : }
569 :
570 25 : static void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
571 : const SwFrmFmt *pTabFmt )
572 : {
573 73 : for ( sal_uInt16 i = 0; i < pLine->GetTabBoxes().size(); ++i )
574 : {
575 48 : const SwTableBox *pBox = pLine->GetTabBoxes()[i];
576 48 : if ( pBox->GetSttNd() )
577 48 : ::lcl_SortedTabColInsert( rToFill, pBox, pTabFmt, sal_True, sal_False );
578 : else
579 0 : for ( sal_uInt16 j = 0; j < pBox->GetTabLines().size(); ++j )
580 0 : ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFmt );
581 : }
582 25 : }
583 :
584 165 : void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
585 : sal_Bool bRefreshHidden, sal_Bool bCurRowOnly ) const
586 : {
587 : // Optimization: if bHidden is set, we only update the Hidden Array.
588 165 : if ( bRefreshHidden )
589 : {
590 : // remove corrections
591 : sal_uInt16 i;
592 0 : for ( i = 0; i < rToFill.Count(); ++i )
593 : {
594 0 : SwTabColsEntry& rEntry = rToFill.GetEntry( i );
595 0 : rEntry.nPos -= rToFill.GetLeft();
596 0 : rEntry.nMin -= rToFill.GetLeft();
597 0 : rEntry.nMax -= rToFill.GetLeft();
598 : }
599 :
600 : // All are hidden, so add the visible ones.
601 0 : for ( i = 0; i < rToFill.Count(); ++i )
602 0 : rToFill.SetHidden( i, sal_True );
603 : }
604 : else
605 : {
606 165 : rToFill.Remove( 0, rToFill.Count() );
607 : }
608 :
609 : // Insertion cases:
610 : // 1. All boxes which are inferior to Line which is superior to the Start,
611 : // as well as their inferior boxes if present.
612 : // 2. Starting from the Line, the superior box plus its neighbours; but no inferiors.
613 : // 3. Apply 2. to the Line superior to the chain of boxes,
614 : // until the Line's superior is not a box but the table.
615 : // Only those boxes are inserted that don't contain further rows. The insertion
616 : // function takes care to avoid duplicates. In order to achieve this, we work
617 : // with some degree of fuzzyness (to avoid rounding errors).
618 : // Only the left edge of the boxes are inserted.
619 : // Finally, the first entry is removed again, because it's already
620 : // covered by the border.
621 : // 4. Scan the table again and insert _all_ boxes, this time as hidden.
622 :
623 165 : const SwFrmFmt *pTabFmt = GetFrmFmt();
624 :
625 : // 1.
626 165 : const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
627 :
628 : sal_uInt16 i;
629 773 : for ( i = 0; i < rBoxes.size(); ++i )
630 608 : ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFmt, bRefreshHidden );
631 :
632 : // 2. and 3.
633 165 : const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
634 165 : pStart->GetUpper()->GetUpper()->GetUpper() : 0;
635 330 : while ( pLine )
636 : {
637 0 : const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
638 0 : for ( sal_uInt16 k = 0; k < rBoxes2.size(); ++k )
639 0 : ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
640 0 : pTabFmt, sal_False, bRefreshHidden );
641 0 : pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
642 : }
643 :
644 165 : if ( !bRefreshHidden )
645 : {
646 : // 4.
647 165 : if ( !bCurRowOnly )
648 : {
649 46 : for ( i = 0; i < aLines.size(); ++i )
650 25 : ::lcl_ProcessLineGet( aLines[i], rToFill, pTabFmt );
651 : }
652 :
653 165 : rToFill.Remove( 0, 1 );
654 : }
655 :
656 : // Now the coordinates are relative to the left table border - i.e.
657 : // relative to SwTabCols.nLeft. However, they are expected
658 : // relative to the left document border, i.e. SwTabCols.nLeftMin.
659 : // So all values need to be extended by nLeft.
660 604 : for ( i = 0; i < rToFill.Count(); ++i )
661 : {
662 439 : SwTabColsEntry& rEntry = rToFill.GetEntry( i );
663 439 : rEntry.nPos += rToFill.GetLeft();
664 439 : rEntry.nMin += rToFill.GetLeft();
665 439 : rEntry.nMax += rToFill.GetLeft();
666 : }
667 165 : }
668 :
669 : /*************************************************************************
670 : |*
671 : |* SwTable::SetTabCols()
672 : |*
673 : |*************************************************************************/
674 : // Structure for parameter passing
675 118 : struct Parm
676 : {
677 : const SwTabCols &rNew;
678 : const SwTabCols &rOld;
679 : long nNewWish,
680 : nOldWish;
681 : std::deque<SwTableBox*> aBoxArr;
682 : SwShareBoxFmts aShareFmts;
683 :
684 118 : Parm( const SwTabCols &rN, const SwTabCols &rO )
685 118 : : rNew( rN ), rOld( rO ), nNewWish(0), nOldWish(0)
686 118 : {}
687 : };
688 :
689 : static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
690 :
691 0 : static void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
692 : {
693 0 : SwTableBoxes &rBoxes = pLine->GetTabBoxes();
694 0 : for ( int i = rBoxes.size()-1; i >= 0; --i )
695 0 : ::lcl_ProcessBoxSet( rBoxes[ static_cast< sal_uInt16 >(i) ], rParm );
696 0 : }
697 :
698 0 : static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
699 : {
700 0 : if ( !pBox->GetTabLines().empty() )
701 0 : { SwTableLines &rLines = pBox->GetTabLines();
702 0 : for ( int i = rLines.size()-1; i >= 0; --i )
703 0 : lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], rParm );
704 : }
705 : else
706 : {
707 : // Search the old TabCols for the current position (calculate from
708 : // left and right edge). Adjust the box if the values differ from
709 : // the new TabCols. If the adjusted edge has no neighbour we also
710 : // adjust all superior boxes.
711 :
712 0 : const long nOldAct = rParm.rOld.GetRight() -
713 0 : rParm.rOld.GetLeft(); // +1 why?
714 :
715 : // The value for the left edge of the box is calculated from the
716 : // widths of the previous boxes plus the left edge.
717 0 : long nLeft = rParm.rOld.GetLeft();
718 0 : const SwTableBox *pCur = pBox;
719 0 : const SwTableLine *pLine = pBox->GetUpper();
720 :
721 0 : while ( pLine )
722 0 : { const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
723 0 : for ( sal_uInt16 i = 0; (i < rBoxes.size()) && (rBoxes[i] != pCur); ++i)
724 : {
725 0 : sal_uInt64 nWidth = rBoxes[i]->GetFrmFmt()->
726 0 : GetFrmSize().GetWidth();
727 0 : nWidth *= nOldAct;
728 0 : nWidth /= rParm.nOldWish;
729 0 : nLeft += (sal_uInt16)nWidth;
730 : }
731 0 : pCur = pLine->GetUpper();
732 0 : pLine = pCur ? pCur->GetUpper() : 0;
733 : }
734 : long nLeftDiff;
735 0 : long nRightDiff = 0;
736 0 : if ( nLeft != rParm.rOld.GetLeft() ) // There are still boxes before this.
737 : {
738 : // Right edge is left edge plus width.
739 0 : sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
740 0 : nWidth *= nOldAct;
741 0 : nWidth /= rParm.nOldWish;
742 0 : long nRight = nLeft + (long)nWidth;
743 0 : sal_uInt16 nLeftPos = USHRT_MAX,
744 0 : nRightPos = USHRT_MAX;
745 0 : for ( sal_uInt16 i = 0; i < rParm.rOld.Count(); ++i )
746 : {
747 0 : if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
748 0 : nLeft <= (rParm.rOld[i] + COLFUZZY) )
749 0 : nLeftPos = i;
750 0 : else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
751 0 : nRight <= (rParm.rOld[i] + COLFUZZY) )
752 0 : nRightPos = i;
753 : }
754 : nLeftDiff = nLeftPos != USHRT_MAX ?
755 0 : (int)rParm.rOld[nLeftPos] - (int)rParm.rNew[nLeftPos] : 0;
756 : nRightDiff= nRightPos!= USHRT_MAX ?
757 0 : (int)rParm.rNew[nRightPos] - (int)rParm.rOld[nRightPos] : 0;
758 : }
759 : else // The first box.
760 : {
761 0 : nLeftDiff = (long)rParm.rOld.GetLeft() - (long)rParm.rNew.GetLeft();
762 0 : if ( rParm.rOld.Count() )
763 : {
764 : // Calculate the difference to the edge touching the first box.
765 0 : sal_uInt64 nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
766 0 : nWidth *= nOldAct;
767 0 : nWidth /= rParm.nOldWish;
768 0 : long nTmp = (long)nWidth;
769 0 : nTmp += rParm.rOld.GetLeft();
770 0 : sal_uInt16 nLeftPos = USHRT_MAX;
771 0 : for ( sal_uInt16 i = 0; i < rParm.rOld.Count() &&
772 : nLeftPos == USHRT_MAX; ++i )
773 : {
774 0 : if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
775 0 : nTmp <= (rParm.rOld[i] + COLFUZZY) )
776 0 : nLeftPos = i;
777 : }
778 0 : if ( nLeftPos != USHRT_MAX )
779 0 : nRightDiff = (long)rParm.rNew[nLeftPos] -
780 0 : (long)rParm.rOld[nLeftPos];
781 : }
782 : }
783 :
784 0 : if( pBox->getRowSpan() == 1 )
785 : {
786 0 : SwTableBoxes& rTblBoxes = pBox->GetUpper()->GetTabBoxes();
787 0 : sal_uInt16 nPos = rTblBoxes.GetPos( pBox );
788 0 : if( nPos && rTblBoxes[ nPos - 1 ]->getRowSpan() != 1 )
789 0 : nLeftDiff = 0;
790 0 : if( nPos + 1 < (sal_uInt16)rTblBoxes.size() &&
791 0 : rTblBoxes[ nPos + 1 ]->getRowSpan() != 1 )
792 0 : nRightDiff = 0;
793 : }
794 : else
795 0 : nLeftDiff = nRightDiff = 0;
796 :
797 0 : if ( nLeftDiff || nRightDiff )
798 : {
799 : // The difference is the actual difference amount. For stretched
800 : // tables, it does not make sense to adjust the attributes of the
801 : // boxes by this amount. The difference amount needs to be converted
802 : // accordingly.
803 0 : long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
804 0 : nLeftDiff *= rParm.nNewWish;
805 0 : nLeftDiff /= nTmp;
806 0 : nRightDiff *= rParm.nNewWish;
807 0 : nRightDiff /= nTmp;
808 0 : long nDiff = nLeftDiff + nRightDiff;
809 :
810 : // Adjust the box and all superiors by the difference amount.
811 0 : while ( pBox )
812 : {
813 0 : SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
814 0 : aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
815 0 : if ( aFmtFrmSize.GetWidth() < 0 )
816 0 : aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() );
817 0 : rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
818 :
819 : // The outer cells of the last row are responsible to adjust a surrounding cell.
820 : // Last line check:
821 0 : if ( pBox->GetUpper()->GetUpper() &&
822 0 : pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines().back())
823 : {
824 0 : pBox = 0;
825 : }
826 : else
827 : {
828 : // Middle cell check:
829 0 : if ( pBox != pBox->GetUpper()->GetTabBoxes().front() )
830 0 : nDiff = nRightDiff;
831 :
832 0 : if ( pBox != pBox->GetUpper()->GetTabBoxes().back() )
833 0 : nDiff -= nRightDiff;
834 :
835 0 : pBox = nDiff ? pBox->GetUpper()->GetUpper() : 0;
836 : }
837 0 : }
838 : }
839 : }
840 0 : }
841 :
842 0 : static void lcl_ProcessBoxPtr( SwTableBox *pBox, std::deque<SwTableBox*> &rBoxArr,
843 : bool bBefore )
844 : {
845 0 : if ( !pBox->GetTabLines().empty() )
846 : {
847 0 : const SwTableLines &rLines = pBox->GetTabLines();
848 0 : for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
849 : {
850 0 : const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
851 0 : for ( sal_uInt16 j = 0; j < rBoxes.size(); ++j )
852 0 : ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
853 : }
854 : }
855 0 : else if ( bBefore )
856 0 : rBoxArr.push_front( pBox );
857 : else
858 0 : rBoxArr.push_back( pBox );
859 0 : }
860 :
861 : static void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm );
862 :
863 0 : static void lcl_AdjustLines( SwTableLines &rLines, const long nDiff, Parm &rParm )
864 : {
865 0 : for ( sal_uInt16 i = 0; i < rLines.size(); ++i )
866 : {
867 0 : SwTableBox *pBox = rLines[i]->GetTabBoxes()
868 0 : [rLines[i]->GetTabBoxes().size()-1];
869 0 : lcl_AdjustBox( pBox, nDiff, rParm );
870 : }
871 0 : }
872 :
873 0 : static void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm )
874 : {
875 0 : if ( !pBox->GetTabLines().empty() )
876 0 : ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
877 :
878 : // Adjust the size of the box.
879 0 : SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
880 0 : aFmtFrmSize.SetWidth( aFmtFrmSize.GetWidth() + nDiff );
881 :
882 0 : rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
883 0 : }
884 :
885 118 : void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
886 : const SwTableBox *pStart, sal_Bool bCurRowOnly )
887 : {
888 : CHECK_TABLE( *this )
889 :
890 118 : SetHTMLTableLayout( 0 ); // delete HTML-Layout
891 :
892 : // FME: Made rOld const. The caller is responsible for passing correct
893 : // values of rOld. Therefore we do not have to call GetTabCols anymore:
894 : //GetTabCols( rOld, pStart );
895 :
896 118 : Parm aParm( rNew, rOld );
897 :
898 : OSL_ENSURE( rOld.Count() == rNew.Count(), "Columnanzahl veraendert.");
899 :
900 : // Convert the edges. We need to adjust the size of the table and some boxes.
901 : // For the size adjustment, we must not make use of the Modify, since that'd
902 : // adjust all boxes, which we really don't want.
903 118 : SwFrmFmt *pFmt = GetFrmFmt();
904 118 : aParm.nOldWish = aParm.nNewWish = pFmt->GetFrmSize().GetWidth();
905 236 : if ( (rOld.GetLeft() != rNew.GetLeft()) ||
906 118 : (rOld.GetRight()!= rNew.GetRight()) )
907 : {
908 0 : LockModify();
909 : {
910 0 : SvxLRSpaceItem aLR( pFmt->GetLRSpace() );
911 0 : SvxShadowItem aSh( pFmt->GetShadow() );
912 :
913 0 : SwTwips nShRight = aSh.CalcShadowSpace( SHADOW_RIGHT );
914 0 : SwTwips nShLeft = aSh.CalcShadowSpace( SHADOW_LEFT );
915 :
916 0 : aLR.SetLeft ( rNew.GetLeft() - nShLeft );
917 0 : aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
918 0 : pFmt->SetFmtAttr( aLR );
919 :
920 : // The alignment of the table needs to be adjusted accordingly.
921 : // This is done by preserving the exact positions that have been
922 : // set by the user.
923 0 : SwFmtHoriOrient aOri( pFmt->GetHoriOrient() );
924 0 : if(text::HoriOrientation::NONE != aOri.GetHoriOrient())
925 : {
926 0 : const sal_Bool bLeftDist = rNew.GetLeft() != nShLeft;
927 0 : const sal_Bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
928 0 : if(!bLeftDist && !bRightDist)
929 0 : aOri.SetHoriOrient( text::HoriOrientation::FULL );
930 0 : else if(!bRightDist && rNew.GetLeft() > nShLeft )
931 0 : aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
932 0 : else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
933 0 : aOri.SetHoriOrient( text::HoriOrientation::LEFT );
934 : else
935 0 : aOri.SetHoriOrient( text::HoriOrientation::LEFT_AND_WIDTH );
936 : }
937 0 : pFmt->SetFmtAttr( aOri );
938 : }
939 0 : const long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
940 0 : long nTabDiff = 0;
941 :
942 0 : if ( rOld.GetLeft() != rNew.GetLeft() )
943 : {
944 0 : nTabDiff = rOld.GetLeft() - rNew.GetLeft();
945 0 : nTabDiff *= aParm.nOldWish;
946 0 : nTabDiff /= nAct;
947 : }
948 0 : if ( rOld.GetRight() != rNew.GetRight() )
949 : {
950 0 : long nDiff = rNew.GetRight() - rOld.GetRight();
951 0 : nDiff *= aParm.nOldWish;
952 0 : nDiff /= nAct;
953 0 : nTabDiff += nDiff;
954 0 : if( !IsNewModel() )
955 0 : ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
956 : }
957 :
958 : // Adjust the size of the table, watch out for stretched tables.
959 0 : if ( nTabDiff )
960 : {
961 0 : aParm.nNewWish += nTabDiff;
962 0 : if ( aParm.nNewWish < 0 )
963 0 : aParm.nNewWish = USHRT_MAX; // Oops! Have to roll back.
964 0 : SwFmtFrmSize aSz( pFmt->GetFrmSize() );
965 0 : if ( aSz.GetWidth() != aParm.nNewWish )
966 : {
967 0 : aSz.SetWidth( aParm.nNewWish );
968 0 : aSz.SetWidthPercent( 0 );
969 0 : pFmt->SetFmtAttr( aSz );
970 0 : }
971 : }
972 0 : UnlockModify();
973 : }
974 :
975 118 : if( IsNewModel() )
976 118 : NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
977 : else
978 : {
979 0 : if ( bCurRowOnly )
980 : {
981 : // To adjust the current row, we need to process all its boxes,
982 : // similar to the filling of the TabCols (see GetTabCols()).
983 : // Unfortunately we again have to take care to adjust the boxes
984 : // from back to front, respectively from outer to inner.
985 : // The best way to achieve this is probably to track the boxes
986 : // in a PtrArray.
987 0 : const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
988 0 : for ( sal_uInt16 i = 0; i < rBoxes.size(); ++i )
989 0 : ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, false );
990 :
991 0 : const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
992 0 : pStart->GetUpper()->GetUpper()->GetUpper() : 0;
993 0 : const SwTableBox *pExcl = pStart->GetUpper()->GetUpper();
994 0 : while ( pLine )
995 : {
996 0 : const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
997 0 : bool bBefore = true;
998 0 : for ( sal_uInt16 i = 0; i < rBoxes2.size(); ++i )
999 : {
1000 0 : if ( rBoxes2[i] != pExcl )
1001 0 : ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
1002 : else
1003 0 : bBefore = false;
1004 : }
1005 0 : pExcl = pLine->GetUpper();
1006 0 : pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
1007 : }
1008 : // After we've inserted a bunch of boxes (hopefully all and in
1009 : // correct order), we just need to process them in reverse order.
1010 0 : for ( int j = aParm.aBoxArr.size()-1; j >= 0; --j )
1011 : {
1012 0 : SwTableBox *pBox = aParm.aBoxArr[j];
1013 0 : ::lcl_ProcessBoxSet( pBox, aParm );
1014 : }
1015 : }
1016 : else
1017 : {
1018 : // Adjusting the entire table is 'easy'. All boxes without lines are
1019 : // adjusted, as are their superiors. Of course we need to process
1020 : // in reverse order to prevent fooling ourselves!
1021 0 : SwTableLines &rLines = GetTabLines();
1022 0 : for ( int i = rLines.size()-1; i >= 0; --i )
1023 0 : ::lcl_ProcessLine( rLines[ static_cast< sal_uInt16 >(i) ], aParm );
1024 : }
1025 118 : }
1026 :
1027 : #ifdef DBG_UTIL
1028 : {
1029 : // to be found in tblrwcl.cxx
1030 : extern void _CheckBoxWidth( const SwTableLine&, SwTwips );
1031 : // do some checking for correct table widths
1032 : SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth();
1033 : for (size_t n = 0; n < aLines.size(); ++n)
1034 : {
1035 : _CheckBoxWidth( *aLines[ n ], nSize );
1036 : }
1037 : }
1038 : #endif
1039 118 : }
1040 :
1041 : typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
1042 : typedef std::list< ColChange > ChangeList;
1043 :
1044 118 : static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
1045 : Parm& rParm, sal_uInt16 nColFuzzy )
1046 : {
1047 118 : ChangeList::iterator pCurr = rOldNew.begin();
1048 118 : if( pCurr == rOldNew.end() )
1049 118 : return;
1050 118 : sal_uInt16 nCount = pLine->GetTabBoxes().size();
1051 118 : sal_uInt16 i = 0;
1052 118 : SwTwips nBorder = 0;
1053 118 : SwTwips nRest = 0;
1054 746 : while( i < nCount )
1055 : {
1056 510 : SwTableBox* pBox = pLine->GetTabBoxes()[i++];
1057 510 : SwTwips nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1058 510 : SwTwips nNewWidth = nWidth - nRest;
1059 510 : nRest = 0;
1060 510 : nBorder += nWidth;
1061 510 : if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
1062 : {
1063 374 : nBorder -= nColFuzzy;
1064 866 : while( pCurr != rOldNew.end() && nBorder > pCurr->first )
1065 118 : ++pCurr;
1066 374 : if( pCurr != rOldNew.end() )
1067 : {
1068 374 : nBorder += nColFuzzy;
1069 374 : if( nBorder + nColFuzzy >= pCurr->first )
1070 : {
1071 362 : if( pCurr->second == pCurr->first )
1072 0 : nRest = 0;
1073 : else
1074 362 : nRest = pCurr->second - nBorder;
1075 362 : nNewWidth += nRest;
1076 362 : ++pCurr;
1077 : }
1078 : }
1079 : }
1080 510 : if( nNewWidth != nWidth )
1081 : {
1082 336 : if( nNewWidth < 0 )
1083 : {
1084 0 : nRest += 1 - nNewWidth;
1085 0 : nNewWidth = 1;
1086 : }
1087 336 : SwFmtFrmSize aFmtFrmSize( pBox->GetFrmFmt()->GetFrmSize() );
1088 336 : aFmtFrmSize.SetWidth( nNewWidth );
1089 336 : rParm.aShareFmts.SetSize( *pBox, aFmtFrmSize );
1090 : }
1091 : }
1092 : }
1093 :
1094 80 : static void lcl_CalcNewWidths( std::list<sal_uInt16> &rSpanPos, ChangeList& rChanges,
1095 : SwTableLine* pLine, long nWish, long nWidth, bool bTop )
1096 : {
1097 80 : if( rChanges.empty() )
1098 : {
1099 0 : rSpanPos.clear();
1100 : return;
1101 : }
1102 80 : if( rSpanPos.empty() )
1103 : {
1104 0 : rChanges.clear();
1105 : return;
1106 : }
1107 80 : std::list<sal_uInt16> aNewSpanPos;
1108 80 : ChangeList aNewChanges;
1109 80 : ChangeList::iterator pCurr = rChanges.begin();
1110 80 : aNewChanges.push_back( *pCurr ); // Nullposition
1111 80 : std::list<sal_uInt16>::iterator pSpan = rSpanPos.begin();
1112 80 : sal_uInt16 nCurr = 0;
1113 80 : sal_uInt16 nOrgSum = 0;
1114 80 : bool bRowSpan = false;
1115 80 : sal_uInt16 nRowSpanCount = 0;
1116 80 : sal_uInt16 nCount = pLine->GetTabBoxes().size();
1117 334 : for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1118 : {
1119 254 : SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1120 254 : SwTwips nCurrWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1121 254 : const long nRowSpan = pBox->getRowSpan();
1122 : const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
1123 254 : ( nRowSpan > 1 || nRowSpan < -1 );
1124 254 : if( bRowSpan || bCurrRowSpan )
1125 0 : aNewSpanPos.push_back( nRowSpanCount );
1126 254 : bRowSpan = bCurrRowSpan;
1127 254 : nOrgSum = (sal_uInt16)(nOrgSum + nCurrWidth);
1128 254 : sal_uInt64 nSum = nOrgSum;
1129 254 : nSum *= nWidth;
1130 254 : nSum /= nWish;
1131 254 : nSum *= nWish;
1132 254 : nSum /= nWidth;
1133 254 : sal_uInt16 nPos = (sal_uInt16)nSum;
1134 746 : while( pCurr != rChanges.end() && pCurr->first < nPos )
1135 : {
1136 238 : ++nCurr;
1137 238 : ++pCurr;
1138 : }
1139 254 : bool bNew = true;
1140 570 : if( pCurr != rChanges.end() && pCurr->first <= nPos &&
1141 316 : pCurr->first != pCurr->second )
1142 : {
1143 474 : while( pSpan != rSpanPos.end() && *pSpan < nCurr )
1144 158 : ++pSpan;
1145 158 : if( pSpan != rSpanPos.end() && *pSpan == nCurr )
1146 : {
1147 158 : aNewChanges.push_back( *pCurr );
1148 158 : ++nRowSpanCount;
1149 158 : bNew = false;
1150 : }
1151 : }
1152 254 : if( bNew )
1153 : {
1154 96 : ColChange aTmp( nPos, nPos );
1155 96 : aNewChanges.push_back( aTmp );
1156 96 : ++nRowSpanCount;
1157 : }
1158 : }
1159 :
1160 80 : pCurr = aNewChanges.begin();
1161 80 : ChangeList::iterator pLast = pCurr;
1162 80 : ChangeList::iterator pLeftMove = pCurr;
1163 494 : while( pCurr != aNewChanges.end() )
1164 : {
1165 334 : if( pLeftMove == pCurr )
1166 : {
1167 102 : while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
1168 : ;
1169 : }
1170 334 : if( pCurr->second == pCurr->first )
1171 : {
1172 176 : if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
1173 : {
1174 0 : if( pLeftMove->first == pLast->first )
1175 0 : pCurr->second = pLeftMove->second;
1176 : else
1177 : {
1178 0 : sal_uInt64 nTmp = pCurr->first - pLast->first;
1179 0 : nTmp *= pLeftMove->second - pLast->second;
1180 0 : nTmp /= pLeftMove->first - pLast->first;
1181 0 : nTmp += pLast->second;
1182 0 : pCurr->second = (sal_uInt16)nTmp;
1183 : }
1184 : }
1185 176 : pLast = pCurr;
1186 176 : ++pCurr;
1187 : }
1188 158 : else if( pCurr->second > pCurr->first )
1189 : {
1190 136 : pLast = pCurr;
1191 136 : ++pCurr;
1192 136 : ChangeList::iterator pNext = pCurr;
1193 420 : while( pNext != pLeftMove && pNext->second == pNext->first &&
1194 148 : pNext->second < pLast->second )
1195 0 : ++pNext;
1196 272 : while( pCurr != pNext )
1197 : {
1198 0 : if( pNext == aNewChanges.end() || pNext->first == pLast->first )
1199 0 : pCurr->second = pLast->second;
1200 : else
1201 : {
1202 0 : sal_uInt64 nTmp = pCurr->first - pLast->first;
1203 0 : nTmp *= pNext->second - pLast->second;
1204 0 : nTmp /= pNext->first - pLast->first;
1205 0 : nTmp += pLast->second;
1206 0 : pCurr->second = (sal_uInt16)nTmp;
1207 : }
1208 0 : ++pCurr;
1209 : }
1210 136 : pLast = pCurr;
1211 : }
1212 : else
1213 : {
1214 22 : pLast = pCurr;
1215 22 : ++pCurr;
1216 : }
1217 : }
1218 :
1219 80 : rChanges.clear();
1220 80 : ChangeList::iterator pCopy = aNewChanges.begin();
1221 494 : while( pCopy != aNewChanges.end() )
1222 334 : rChanges.push_back( *pCopy++ );
1223 80 : rSpanPos.clear();
1224 80 : std::list<sal_uInt16>::iterator pSpCopy = aNewSpanPos.begin();
1225 160 : while( pSpCopy != aNewSpanPos.end() )
1226 80 : rSpanPos.push_back( *pSpCopy++ );
1227 : }
1228 :
1229 118 : void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
1230 : const SwTabCols &rOld, const SwTableBox *pStart, sal_Bool bCurRowOnly )
1231 : {
1232 : #if OSL_DEBUG_LEVEL > 1
1233 : static int nCallCount = 0;
1234 : ++nCallCount;
1235 : #endif
1236 : // First step: evaluate which lines have been moved/which widths changed
1237 118 : ChangeList aOldNew;
1238 118 : const long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1239 118 : const long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1240 118 : if( nNewWidth < 1 || nOldWidth < 1 )
1241 : return;
1242 628 : for( sal_uInt16 i = 0; i <= rOld.Count(); ++i )
1243 : {
1244 : sal_uInt64 nNewPos;
1245 : sal_uInt64 nOldPos;
1246 510 : if( i == rOld.Count() )
1247 : {
1248 118 : nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1249 118 : nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1250 : }
1251 : else
1252 : {
1253 392 : nOldPos = rOld[i] - rParm.rOld.GetLeft();
1254 392 : nNewPos = rNew[i] - rParm.rNew.GetLeft();
1255 : }
1256 510 : nNewPos *= rParm.nNewWish;
1257 510 : nNewPos /= nNewWidth;
1258 510 : nOldPos *= rParm.nOldWish;
1259 510 : nOldPos /= nOldWidth;
1260 510 : if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
1261 : {
1262 362 : ColChange aChg( (sal_uInt16)nOldPos, (sal_uInt16)nNewPos );
1263 362 : aOldNew.push_back( aChg );
1264 : }
1265 : }
1266 : // Finished first step
1267 118 : int nCount = aOldNew.size();
1268 118 : if( !nCount )
1269 : return; // no change, nothing to do
1270 118 : SwTableLines &rLines = GetTabLines();
1271 118 : if( bCurRowOnly )
1272 : {
1273 118 : const SwTableLine* pCurrLine = pStart->GetUpper();
1274 118 : sal_uInt16 nCurr = rLines.GetPos( pCurrLine );
1275 118 : if( nCurr >= USHRT_MAX )
1276 : return;
1277 :
1278 118 : ColChange aChg( 0, 0 );
1279 118 : aOldNew.push_front( aChg );
1280 118 : std::list<sal_uInt16> aRowSpanPos;
1281 118 : if( nCurr )
1282 : {
1283 40 : ChangeList aCopy;
1284 40 : ChangeList::iterator pCop = aOldNew.begin();
1285 40 : sal_uInt16 nPos = 0;
1286 196 : while( pCop != aOldNew.end() )
1287 : {
1288 116 : aCopy.push_back( *pCop );
1289 116 : ++pCop;
1290 116 : aRowSpanPos.push_back( nPos++ );
1291 : }
1292 40 : lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1293 80 : rParm.nOldWish, nOldWidth, true );
1294 40 : bool bGoOn = !aRowSpanPos.empty();
1295 40 : sal_uInt16 j = nCurr;
1296 80 : while( bGoOn )
1297 : {
1298 0 : lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
1299 0 : rParm.nOldWish, nOldWidth, true );
1300 0 : lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1301 0 : bGoOn = !aRowSpanPos.empty() && j > 0;
1302 : };
1303 40 : aRowSpanPos.clear();
1304 : }
1305 118 : if( nCurr+1 < (sal_uInt16)rLines.size() )
1306 : {
1307 40 : ChangeList aCopy;
1308 40 : ChangeList::iterator pCop = aOldNew.begin();
1309 40 : sal_uInt16 nPos = 0;
1310 202 : while( pCop != aOldNew.end() )
1311 : {
1312 122 : aCopy.push_back( *pCop );
1313 122 : ++pCop;
1314 122 : aRowSpanPos.push_back( nPos++ );
1315 : }
1316 40 : lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1317 80 : rParm.nOldWish, nOldWidth, false );
1318 40 : bool bGoOn = !aRowSpanPos.empty();
1319 40 : sal_uInt16 j = nCurr;
1320 80 : while( bGoOn )
1321 : {
1322 0 : lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
1323 0 : rParm.nOldWish, nOldWidth, false );
1324 0 : lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1325 0 : bGoOn = !aRowSpanPos.empty() && j+1 < (sal_uInt16)rLines.size();
1326 40 : };
1327 : }
1328 118 : ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, COLFUZZY );
1329 : }
1330 0 : else for( sal_uInt16 i = 0; i < rLines.size(); ++i )
1331 118 : ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
1332 : CHECK_TABLE( *this )
1333 : }
1334 :
1335 :
1336 : /*************************************************************************
1337 : |*
1338 : |* const SwTableBox* SwTable::GetTblBox( const Strn?ng& rName ) const
1339 : |* return the pointer of the box specified.
1340 : |*
1341 : |*************************************************************************/
1342 :
1343 0 : static bool lcl_IsValidRowName( const String& rStr )
1344 : {
1345 0 : bool bIsValid = true;
1346 0 : xub_StrLen nLen = rStr.Len();
1347 0 : for (xub_StrLen i = 0; i < nLen && bIsValid; ++i)
1348 : {
1349 0 : const sal_Unicode cChar = rStr.GetChar(i);
1350 0 : if (cChar < '0' || cChar > '9')
1351 0 : bIsValid = false;
1352 : }
1353 0 : return bIsValid;
1354 : }
1355 :
1356 : // #i80314#
1357 : // add 3rd parameter and its handling
1358 1968 : sal_uInt16 SwTable::_GetBoxNum( String& rStr, sal_Bool bFirstPart,
1359 : const bool bPerformValidCheck )
1360 : {
1361 1968 : sal_uInt16 nRet = 0;
1362 1968 : xub_StrLen nPos = 0;
1363 1968 : if( bFirstPart ) // sal_True == column; sal_False == row
1364 : {
1365 : // the first one uses letters for addressing!
1366 : sal_Unicode cChar;
1367 984 : bool bFirst = true;
1368 2952 : while( 0 != ( cChar = rStr.GetChar( nPos )) &&
1369 : ( (cChar >= 'A' && cChar <= 'Z') ||
1370 : (cChar >= 'a' && cChar <= 'z') ) )
1371 : {
1372 984 : if( (cChar -= 'A') >= 26 )
1373 0 : cChar -= 'a' - '[';
1374 984 : if( bFirst )
1375 984 : bFirst = false;
1376 : else
1377 0 : ++nRet;
1378 984 : nRet = nRet * 52 + cChar;
1379 984 : ++nPos;
1380 : }
1381 984 : rStr.Erase( 0, nPos ); // Remove char from String
1382 : }
1383 984 : else if( STRING_NOTFOUND == ( nPos = rStr.Search( aDotStr ) ))
1384 : {
1385 984 : nRet = 0;
1386 984 : if ( !bPerformValidCheck || lcl_IsValidRowName( rStr ) )
1387 : {
1388 984 : nRet = static_cast<sal_uInt16>(rStr.ToInt32());
1389 : }
1390 984 : rStr.Erase();
1391 : }
1392 : else
1393 : {
1394 0 : nRet = 0;
1395 0 : String aTxt( rStr.Copy( 0, nPos ) );
1396 0 : if ( !bPerformValidCheck || lcl_IsValidRowName( aTxt ) )
1397 : {
1398 0 : nRet = static_cast<sal_uInt16>(aTxt.ToInt32());
1399 : }
1400 0 : rStr.Erase( 0, nPos+1 );
1401 : }
1402 1968 : return nRet;
1403 : }
1404 :
1405 : // #i80314#
1406 : // add 2nd parameter and its handling
1407 984 : const SwTableBox* SwTable::GetTblBox( const String& rName,
1408 : const bool bPerformValidCheck ) const
1409 : {
1410 984 : const SwTableBox* pBox = 0;
1411 : const SwTableLine* pLine;
1412 : const SwTableLines* pLines;
1413 : const SwTableBoxes* pBoxes;
1414 :
1415 : sal_uInt16 nLine, nBox;
1416 984 : String aNm( rName );
1417 2952 : while( aNm.Len() )
1418 : {
1419 984 : nBox = SwTable::_GetBoxNum( aNm, 0 == pBox, bPerformValidCheck );
1420 : // first box ?
1421 984 : if( !pBox )
1422 984 : pLines = &GetTabLines();
1423 : else
1424 : {
1425 0 : pLines = &pBox->GetTabLines();
1426 0 : if( nBox )
1427 0 : --nBox;
1428 : }
1429 :
1430 984 : nLine = SwTable::_GetBoxNum( aNm, sal_False, bPerformValidCheck );
1431 :
1432 : // determine line
1433 984 : if( !nLine || nLine > pLines->size() )
1434 0 : return 0;
1435 984 : pLine = (*pLines)[ nLine-1 ];
1436 :
1437 : // determine box
1438 984 : pBoxes = &pLine->GetTabBoxes();
1439 984 : if( nBox >= pBoxes->size() )
1440 0 : return 0;
1441 984 : pBox = (*pBoxes)[ nBox ];
1442 : }
1443 :
1444 : // check if the box found has any contents
1445 984 : if( pBox && !pBox->GetSttNd() )
1446 : {
1447 : OSL_FAIL( "Box without content, looking for the next one!" );
1448 : // "drop this" until the first box
1449 0 : while( !pBox->GetTabLines().empty() )
1450 0 : pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
1451 : }
1452 984 : return pBox;
1453 : }
1454 :
1455 540 : SwTableBox* SwTable::GetTblBox( sal_uLong nSttIdx )
1456 : {
1457 : // For optimizations, don't always process the entire SortArray.
1458 : // Converting text to table, tries certain conditions
1459 : // to ask for a table box of a table that is not yet having a format
1460 540 : if(!GetFrmFmt())
1461 0 : return 0;
1462 540 : SwTableBox* pRet = 0;
1463 540 : SwNodes& rNds = GetFrmFmt()->GetDoc()->GetNodes();
1464 540 : sal_uLong nIndex = nSttIdx + 1;
1465 540 : SwCntntNode* pCNd = 0;
1466 540 : SwTableNode* pTblNd = 0;
1467 :
1468 1080 : while ( nIndex < rNds.Count() )
1469 : {
1470 540 : pTblNd = rNds[ nIndex ]->GetTableNode();
1471 540 : if ( pTblNd )
1472 0 : break;
1473 :
1474 540 : pCNd = rNds[ nIndex ]->GetCntntNode();
1475 540 : if ( pCNd )
1476 540 : break;
1477 :
1478 0 : ++nIndex;
1479 : }
1480 :
1481 540 : if ( pCNd || pTblNd )
1482 : {
1483 540 : SwModify* pModify = pCNd;
1484 : // #144862# Better handling of table in table
1485 540 : if ( pTblNd && pTblNd->GetTable().GetFrmFmt() )
1486 0 : pModify = pTblNd->GetTable().GetFrmFmt();
1487 :
1488 540 : SwFrm* pFrm = SwIterator<SwFrm,SwModify>::FirstElement( *pModify );
1489 1130 : while ( pFrm && !pFrm->IsCellFrm() )
1490 50 : pFrm = pFrm->GetUpper();
1491 540 : if ( pFrm )
1492 50 : pRet = (SwTableBox*)((SwCellFrm*)pFrm)->GetTabBox();
1493 : }
1494 :
1495 : // In case the layout doesn't exist yet or anything else goes wrong.
1496 540 : if ( !pRet )
1497 : {
1498 1064 : for (size_t n = m_TabSortContentBoxes.size(); n; )
1499 : {
1500 574 : if (m_TabSortContentBoxes[ --n ]->GetSttIdx() == nSttIdx)
1501 : {
1502 490 : return m_TabSortContentBoxes[ n ];
1503 : }
1504 : }
1505 : }
1506 50 : return pRet;
1507 : }
1508 :
1509 10 : bool SwTable::IsTblComplex() const
1510 : {
1511 : // Returns true for complex tables, i.e. tables that contain nestings,
1512 : // like containing boxes not part of the first line, e.g. results of
1513 : // splits/merges which lead to more complex structures.
1514 86 : for (size_t n = 0; n < m_TabSortContentBoxes.size(); ++n)
1515 : {
1516 76 : if (m_TabSortContentBoxes[ n ]->GetUpper()->GetUpper())
1517 : {
1518 0 : return true;
1519 : }
1520 : }
1521 10 : return false;
1522 : }
1523 :
1524 :
1525 :
1526 : /*************************************************************************
1527 : |*
1528 : |* SwTableLine::SwTableLine()
1529 : |*
1530 : |*************************************************************************/
1531 524 : SwTableLine::SwTableLine( SwTableLineFmt *pFmt, sal_uInt16 nBoxes,
1532 : SwTableBox *pUp )
1533 : : SwClient( pFmt ),
1534 : aBoxes(),
1535 524 : pUpper( pUp )
1536 : {
1537 524 : aBoxes.reserve( (sal_uInt8)nBoxes );
1538 524 : }
1539 :
1540 1242 : SwTableLine::~SwTableLine()
1541 : {
1542 1776 : for (size_t i = 0; i < aBoxes.size(); ++i)
1543 : {
1544 1362 : delete aBoxes[i];
1545 : }
1546 : // the TabelleLine can be deleted if it's the last client of the FrameFormat
1547 414 : SwModify* pMod = GetFrmFmt();
1548 414 : pMod->Remove( this ); // remove,
1549 414 : if( !pMod->GetDepends() )
1550 306 : delete pMod; // and delete
1551 828 : }
1552 :
1553 : /*************************************************************************
1554 : |*
1555 : |* SwTableLine::ClaimFrmFmt(), ChgFrmFmt()
1556 : |*
1557 : |*************************************************************************/
1558 390 : SwFrmFmt* SwTableLine::ClaimFrmFmt()
1559 : {
1560 : // This method makes sure that this object is an exclusive SwTableLine client
1561 : // of an SwTableLineFmt object
1562 : // If other SwTableLine objects currently listen to the same SwTableLineFmt as
1563 : // this one, something needs to be done
1564 390 : SwTableLineFmt *pRet = (SwTableLineFmt*)GetFrmFmt();
1565 390 : SwIterator<SwTableLine,SwFmt> aIter( *pRet );
1566 588 : for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1567 : {
1568 436 : if ( pLast != this )
1569 : {
1570 : // found another SwTableLine that is a client of the current Fmt
1571 : // create a new Fmt as a copy and use it for this object
1572 238 : SwTableLineFmt *pNewFmt = pRet->GetDoc()->MakeTableLineFmt();
1573 238 : *pNewFmt = *pRet;
1574 :
1575 : // register SwRowFrms that know me as clients at the new Fmt
1576 238 : SwIterator<SwRowFrm,SwFmt> aFrmIter( *pRet );
1577 238 : for( SwRowFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
1578 0 : if( pFrm->GetTabLine() == this )
1579 0 : pFrm->RegisterToFormat( *pNewFmt );
1580 :
1581 : // register myself
1582 238 : pNewFmt->Add( this );
1583 238 : pRet = pNewFmt;
1584 238 : break;
1585 : }
1586 : }
1587 :
1588 390 : return pRet;
1589 : }
1590 :
1591 0 : void SwTableLine::ChgFrmFmt( SwTableLineFmt *pNewFmt )
1592 : {
1593 0 : SwFrmFmt *pOld = GetFrmFmt();
1594 0 : SwIterator<SwRowFrm,SwFmt> aIter( *pOld );
1595 :
1596 : // First, re-register the Frms.
1597 0 : for( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
1598 : {
1599 0 : if( pRow->GetTabLine() == this )
1600 : {
1601 0 : pRow->RegisterToFormat( *pNewFmt );
1602 :
1603 0 : pRow->InvalidateSize();
1604 0 : pRow->_InvalidatePrt();
1605 0 : pRow->SetCompletePaint();
1606 0 : pRow->ReinitializeFrmSizeAttrFlags();
1607 :
1608 : // #i35063#
1609 : // consider 'split row allowed' attribute
1610 0 : SwTabFrm* pTab = pRow->FindTabFrm();
1611 0 : bool bInFollowFlowRow = false;
1612 0 : const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
1613 0 : pRow == pTab->GetFirstNonHeadlineRow();
1614 0 : if ( bInFirstNonHeadlineRow ||
1615 0 : !pRow->GetNext() ||
1616 0 : 0 != ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) ||
1617 0 : 0 != pRow->IsInSplitTableRow() )
1618 : {
1619 0 : if ( bInFirstNonHeadlineRow || bInFollowFlowRow )
1620 0 : pTab = pTab->FindMaster();
1621 :
1622 0 : pTab->SetRemoveFollowFlowLinePending( sal_True );
1623 0 : pTab->InvalidatePos();
1624 : }
1625 : }
1626 : }
1627 :
1628 : // Now, re-register self.
1629 0 : pNewFmt->Add( this );
1630 :
1631 0 : if ( !pOld->GetDepends() )
1632 0 : delete pOld;
1633 0 : }
1634 :
1635 48 : SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
1636 : {
1637 48 : SwTwips nRet = 0;
1638 48 : bLayoutAvailable = false;
1639 48 : SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() );
1640 : // A row could appear several times in headers/footers so only one chain of master/follow tables
1641 : // will be accepted...
1642 48 : const SwTabFrm* pChain = NULL; // My chain
1643 48 : for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1644 : {
1645 48 : if( pLast->GetTabLine() == this )
1646 : {
1647 48 : const SwTabFrm* pTab = pLast->FindTabFrm();
1648 48 : bLayoutAvailable = ( pTab && pTab->IsVertical() ) ?
1649 0 : ( 0 < pTab->Frm().Height() ) :
1650 96 : ( 0 < pTab->Frm().Width() );
1651 :
1652 : // The first one defines the chain, if a chain is defined, only members of the chain
1653 : // will be added.
1654 48 : if( !pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow( pChain ) )
1655 : {
1656 48 : pChain = pTab; // defines my chain (even it is already)
1657 48 : if( pTab->IsVertical() )
1658 0 : nRet += pLast->Frm().Width();
1659 : else
1660 48 : nRet += pLast->Frm().Height();
1661 : // Optimization, if there are no master/follows in my chain, nothing more to add
1662 48 : if( !pTab->HasFollow() && !pTab->IsFollow() )
1663 48 : break;
1664 : // This is not an optimization, this is necessary to avoid double additions of
1665 : // repeating rows
1666 0 : if( pTab->IsInHeadline(*pLast) )
1667 0 : break;
1668 : }
1669 : }
1670 : }
1671 48 : return nRet;
1672 : }
1673 :
1674 : /*************************************************************************
1675 : |*
1676 : |* SwTableBox::SwTableBox()
1677 : |*
1678 : |*************************************************************************/
1679 0 : SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, sal_uInt16 nLines, SwTableLine *pUp )
1680 : : SwClient( 0 ),
1681 : aLines(),
1682 : pSttNd( 0 ),
1683 : pUpper( pUp ),
1684 0 : pImpl( 0 )
1685 : {
1686 0 : aLines.reserve( (sal_uInt8)nLines );
1687 0 : CheckBoxFmt( pFmt )->Add( this );
1688 0 : }
1689 :
1690 934 : SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwNodeIndex &rIdx,
1691 : SwTableLine *pUp )
1692 : : SwClient( 0 ),
1693 : aLines(),
1694 : pUpper( pUp ),
1695 934 : pImpl( 0 )
1696 : {
1697 934 : CheckBoxFmt( pFmt )->Add( this );
1698 :
1699 934 : pSttNd = rIdx.GetNode().GetStartNode();
1700 :
1701 : // insert into the table
1702 934 : const SwTableNode* pTblNd = pSttNd->FindTableNode();
1703 : OSL_ENSURE( pTblNd, "In which table is that box?" );
1704 934 : SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1705 934 : GetTabSortBoxes();
1706 934 : SwTableBox* p = this; // error: &this
1707 934 : rSrtArr.insert( p ); // insert
1708 934 : }
1709 :
1710 874 : SwTableBox::SwTableBox( SwTableBoxFmt* pFmt, const SwStartNode& rSttNd, SwTableLine *pUp ) :
1711 : SwClient( 0 ),
1712 : aLines(),
1713 : pSttNd( &rSttNd ),
1714 : pUpper( pUp ),
1715 874 : pImpl( 0 )
1716 : {
1717 874 : CheckBoxFmt( pFmt )->Add( this );
1718 :
1719 : // insert into the table
1720 874 : const SwTableNode* pTblNd = pSttNd->FindTableNode();
1721 : OSL_ENSURE( pTblNd, "In which table is the box?" );
1722 874 : SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1723 874 : GetTabSortBoxes();
1724 874 : SwTableBox* p = this; // error: &this
1725 874 : rSrtArr.insert( p ); // insert
1726 874 : }
1727 :
1728 8 : void SwTableBox::RemoveFromTable()
1729 : {
1730 8 : if (pSttNd) // box containing contents?
1731 : {
1732 : // remove from table
1733 0 : const SwTableNode* pTblNd = pSttNd->FindTableNode();
1734 : OSL_ENSURE( pTblNd, "In which table is that box?" );
1735 0 : SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTblNd->GetTable().
1736 0 : GetTabSortBoxes();
1737 0 : SwTableBox *p = this; // error: &this
1738 0 : rSrtArr.erase( p ); // remove
1739 0 : pSttNd = 0; // clear it so this is only run once
1740 : }
1741 8 : }
1742 :
1743 4086 : SwTableBox::~SwTableBox()
1744 : {
1745 1362 : if (!GetFrmFmt()->GetDoc()->IsInDtor())
1746 : {
1747 8 : RemoveFromTable();
1748 : }
1749 :
1750 : // the TabelleBox can be deleted if it's the last client of the FrameFormat
1751 1362 : SwModify* pMod = GetFrmFmt();
1752 1362 : pMod->Remove( this ); // remove,
1753 1362 : if( !pMod->GetDepends() )
1754 1168 : delete pMod; // and delete
1755 :
1756 1362 : delete pImpl;
1757 2724 : }
1758 :
1759 1808 : SwTableBoxFmt* SwTableBox::CheckBoxFmt( SwTableBoxFmt* pFmt )
1760 : {
1761 : // We might need to create a new format here, because the box must be
1762 : // added to the format solely if pFmt has a value or formular.
1763 3616 : if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) ||
1764 1808 : SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ) )
1765 : {
1766 0 : SwTableBox* pOther = SwIterator<SwTableBox,SwFmt>::FirstElement( *pFmt );
1767 0 : if( pOther )
1768 : {
1769 0 : SwTableBoxFmt* pNewFmt = pFmt->GetDoc()->MakeTableBoxFmt();
1770 0 : pNewFmt->LockModify();
1771 0 : *pNewFmt = *pFmt;
1772 :
1773 : // Remove values and formulars
1774 0 : pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1775 0 : pNewFmt->UnlockModify();
1776 :
1777 0 : pFmt = pNewFmt;
1778 : }
1779 : }
1780 1808 : return pFmt;
1781 : }
1782 :
1783 : /*************************************************************************
1784 : |*
1785 : |* SwTableBox::ClaimFrmFmt(), ChgFrmFmt()
1786 : |*
1787 : |*************************************************************************/
1788 6122 : SwFrmFmt* SwTableBox::ClaimFrmFmt()
1789 : {
1790 : // This method makes sure that this object is an exclusive SwTableBox client
1791 : // of an SwTableBoxFmt object
1792 : // If other SwTableBox objects currently listen to the same SwTableBoxFmt as
1793 : // this one, something needs to be done
1794 6122 : SwTableBoxFmt *pRet = (SwTableBoxFmt*)GetFrmFmt();
1795 6122 : SwIterator<SwTableBox,SwFmt> aIter( *pRet );
1796 10960 : for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1797 : {
1798 6274 : if ( pLast != this )
1799 : {
1800 : // Found another SwTableBox object
1801 : // create a new Fmt as a copy and assign me to it
1802 : // don't copy values and formulas
1803 1436 : SwTableBoxFmt* pNewFmt = pRet->GetDoc()->MakeTableBoxFmt();
1804 1436 : pNewFmt->LockModify();
1805 1436 : *pNewFmt = *pRet;
1806 1436 : pNewFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1807 1436 : pNewFmt->UnlockModify();
1808 :
1809 : // re-register SwCellFrm objects that know me
1810 1436 : SwIterator<SwCellFrm,SwFmt> aFrmIter( *pRet );
1811 1436 : for( SwCellFrm* pCell = aFrmIter.First(); pCell; pCell = aFrmIter.Next() )
1812 0 : if( pCell->GetTabBox() == this )
1813 0 : pCell->RegisterToFormat( *pNewFmt );
1814 :
1815 : // re-register myself
1816 1436 : pNewFmt->Add( this );
1817 1436 : pRet = pNewFmt;
1818 1436 : break;
1819 : }
1820 : }
1821 6122 : return pRet;
1822 : }
1823 :
1824 224 : void SwTableBox::ChgFrmFmt( SwTableBoxFmt* pNewFmt )
1825 : {
1826 224 : SwFrmFmt *pOld = GetFrmFmt();
1827 224 : SwIterator<SwCellFrm,SwFmt> aIter( *pOld );
1828 :
1829 : // First, re-register the Frms.
1830 224 : for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
1831 : {
1832 0 : if( pCell->GetTabBox() == this )
1833 : {
1834 0 : pCell->RegisterToFormat( *pNewFmt );
1835 0 : pCell->InvalidateSize();
1836 0 : pCell->_InvalidatePrt();
1837 0 : pCell->SetCompletePaint();
1838 0 : pCell->SetDerivedVert( sal_False );
1839 0 : pCell->CheckDirChange();
1840 :
1841 : // #i47489#
1842 : // make sure that the row will be formatted, in order
1843 : // to have the correct Get(Top|Bottom)MarginForLowers values
1844 : // set at the row.
1845 0 : const SwTabFrm* pTab = pCell->FindTabFrm();
1846 0 : if ( pTab && pTab->IsCollapsingBorders() )
1847 : {
1848 0 : SwFrm* pRow = pCell->GetUpper();
1849 0 : pRow->_InvalidateSize();
1850 0 : pRow->_InvalidatePrt();
1851 : }
1852 : }
1853 : }
1854 :
1855 : // Now, re-register self.
1856 224 : pNewFmt->Add( this );
1857 :
1858 224 : if( !pOld->GetDepends() )
1859 0 : delete pOld;
1860 224 : }
1861 :
1862 : /*************************************************************************
1863 : |*
1864 : |* String SwTableBox::GetName() const
1865 : |* Return the name of this box. This is determined dynamically
1866 : |* resulting from the position in the lines/boxes/tables.
1867 : |*
1868 : |*************************************************************************/
1869 1794 : void sw_GetTblBoxColStr( sal_uInt16 nCol, String& rNm )
1870 : {
1871 1794 : const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z'
1872 : sal_uInt16 nCalc;
1873 :
1874 0 : do {
1875 1794 : nCalc = nCol % coDiff;
1876 1794 : if( nCalc >= 26 )
1877 0 : rNm.Insert( sal_Unicode('a' - 26 + nCalc ), 0 );
1878 : else
1879 1794 : rNm.Insert( sal_Unicode('A' + nCalc ), 0 );
1880 :
1881 1794 : if( 0 == (nCol = nCol - nCalc) )
1882 1794 : break;
1883 0 : nCol /= coDiff;
1884 0 : --nCol;
1885 : } while( 1 );
1886 1794 : }
1887 :
1888 1264 : String SwTableBox::GetName() const
1889 : {
1890 1264 : if( !pSttNd ) // box without content?
1891 : {
1892 : // search for the next first box?
1893 0 : return aEmptyStr;
1894 : }
1895 :
1896 1264 : const SwTable& rTbl = pSttNd->FindTableNode()->GetTable();
1897 : sal_uInt16 nPos;
1898 1264 : String sNm, sTmp;
1899 1264 : const SwTableBox* pBox = this;
1900 1264 : do {
1901 1264 : const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes();
1902 1264 : const SwTableLine* pLine = pBox->GetUpper();
1903 : // at the first level?
1904 1264 : const SwTableLines* pLines = pLine->GetUpper()
1905 1264 : ? &pLine->GetUpper()->GetTabLines() : &rTbl.GetTabLines();
1906 :
1907 1264 : sTmp = String::CreateFromInt32( nPos = pLines->GetPos( pLine ) + 1 );
1908 1264 : if( sNm.Len() )
1909 0 : sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
1910 : else
1911 1264 : sNm = sTmp;
1912 :
1913 1264 : sTmp = String::CreateFromInt32(( nPos = pBoxes->GetPos( pBox )) + 1 );
1914 1264 : if( 0 != ( pBox = pLine->GetUpper()) )
1915 0 : sNm.Insert( aDotStr, 0 ).Insert( sTmp, 0 );
1916 : else
1917 1264 : sw_GetTblBoxColStr( nPos, sNm );
1918 :
1919 : } while( pBox );
1920 1264 : return sNm;
1921 : }
1922 :
1923 8 : sal_Bool SwTableBox::IsInHeadline( const SwTable* pTbl ) const
1924 : {
1925 8 : if( !GetUpper() ) // should only happen upon merge.
1926 0 : return sal_False;
1927 :
1928 8 : if( !pTbl )
1929 0 : pTbl = &pSttNd->FindTableNode()->GetTable();
1930 :
1931 8 : const SwTableLine* pLine = GetUpper();
1932 16 : while( pLine->GetUpper() )
1933 0 : pLine = pLine->GetUpper()->GetUpper();
1934 :
1935 : // Headerline?
1936 8 : return pTbl->GetTabLines()[ 0 ] == pLine;
1937 : }
1938 :
1939 4928 : sal_uLong SwTableBox::GetSttIdx() const
1940 : {
1941 4928 : return pSttNd ? pSttNd->GetIndex() : 0;
1942 : }
1943 :
1944 : // retrieve informations from the client
1945 570 : bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
1946 : {
1947 570 : switch( rInfo.Which() )
1948 : {
1949 : case RES_AUTOFMT_DOCNODE:
1950 : {
1951 570 : const SwTableNode* pTblNode = GetTableNode();
1952 570 : if( pTblNode && &pTblNode->GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes )
1953 : {
1954 570 : if (!m_TabSortContentBoxes.empty())
1955 : {
1956 570 : SwNodeIndex aIdx( *m_TabSortContentBoxes[0]->GetSttNd() );
1957 : ((SwAutoFmtGetDocNode&)rInfo).pCntntNode =
1958 570 : GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx );
1959 : }
1960 570 : return false;
1961 : }
1962 0 : break;
1963 : }
1964 : case RES_FINDNEARESTNODE:
1965 0 : if( GetFrmFmt() && ((SwFmtPageDesc&)GetFrmFmt()->GetFmtAttr(
1966 0 : RES_PAGEDESC )).GetPageDesc() &&
1967 0 : !m_TabSortContentBoxes.empty() &&
1968 0 : m_TabSortContentBoxes[0]->GetSttNd()->GetNodes().IsDocNodes() )
1969 : static_cast<SwFindNearestNode&>(rInfo).CheckNode( *
1970 0 : m_TabSortContentBoxes[0]->GetSttNd()->FindTableNode() );
1971 0 : break;
1972 :
1973 : case RES_CONTENT_VISIBLE:
1974 : {
1975 0 : ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *GetFrmFmt() );
1976 : }
1977 0 : return false;
1978 : }
1979 0 : return true;
1980 : }
1981 :
1982 8112 : SwTable * SwTable::FindTable( SwFrmFmt const*const pFmt )
1983 : {
1984 : return (pFmt)
1985 8112 : ? SwIterator<SwTable,SwFmt>::FirstElement(*pFmt)
1986 16224 : : 0;
1987 : }
1988 :
1989 846 : SwTableNode* SwTable::GetTableNode() const
1990 : {
1991 846 : return !GetTabSortBoxes().empty() ?
1992 846 : (SwTableNode*)GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode() :
1993 1692 : pTableNode;
1994 : }
1995 :
1996 0 : void SwTable::SetRefObject( SwServerObject* pObj )
1997 : {
1998 0 : if( refObj.Is() )
1999 0 : refObj->Closed();
2000 :
2001 0 : refObj = pObj;
2002 0 : }
2003 :
2004 :
2005 118 : void SwTable::SetHTMLTableLayout( SwHTMLTableLayout *p )
2006 : {
2007 118 : delete pHTMLLayout;
2008 118 : pHTMLLayout = p;
2009 118 : }
2010 :
2011 0 : void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
2012 : sal_Bool bChgAlign )
2013 : {
2014 0 : sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_True );
2015 0 : ChgTextToNum( rBox,rTxt,pCol,bChgAlign,nNdPos);
2016 0 : }
2017 0 : void ChgTextToNum( SwTableBox& rBox, const String& rTxt, const Color* pCol,
2018 : sal_Bool bChgAlign,sal_uLong nNdPos )
2019 : {
2020 :
2021 0 : if( ULONG_MAX != nNdPos )
2022 : {
2023 0 : SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2024 0 : SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
2025 : const SfxPoolItem* pItem;
2026 :
2027 : // assign adjustment
2028 0 : if( bChgAlign )
2029 : {
2030 0 : pItem = &pTNd->SwCntntNode::GetAttr( RES_PARATR_ADJUST );
2031 0 : SvxAdjust eAdjust = ((SvxAdjustItem*)pItem)->GetAdjust();
2032 0 : if( SVX_ADJUST_LEFT == eAdjust || SVX_ADJUST_BLOCK == eAdjust )
2033 : {
2034 0 : SvxAdjustItem aAdjust( *(SvxAdjustItem*)pItem );
2035 0 : aAdjust.SetAdjust( SVX_ADJUST_RIGHT );
2036 0 : pTNd->SetAttr( aAdjust );
2037 : }
2038 : }
2039 :
2040 : // assign color or save "user color"
2041 0 : if( !pTNd->GetpSwAttrSet() || SFX_ITEM_SET != pTNd->GetpSwAttrSet()->
2042 0 : GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
2043 0 : pItem = 0;
2044 :
2045 0 : const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
2046 0 : const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
2047 :
2048 0 : if( ( pNewUserColor && pOldNumFmtColor &&
2049 0 : *pNewUserColor == *pOldNumFmtColor ) ||
2050 : ( !pNewUserColor && !pOldNumFmtColor ))
2051 : {
2052 : // Keep the user color, set updated values, delete old NumFmtColor if needed
2053 0 : if( pCol )
2054 : // if needed, set the color
2055 0 : pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2056 0 : else if( pItem )
2057 : {
2058 0 : pNewUserColor = rBox.GetSaveUserColor();
2059 0 : if( pNewUserColor )
2060 0 : pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2061 : else
2062 0 : pTNd->ResetAttr( RES_CHRATR_COLOR );
2063 : }
2064 : }
2065 : else
2066 : {
2067 : // Save user color, set NumFormat color if needed, but never reset the color
2068 0 : rBox.SetSaveUserColor( pNewUserColor );
2069 :
2070 0 : if( pCol )
2071 : // if needed, set the color
2072 0 : pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2073 :
2074 : }
2075 0 : rBox.SetSaveNumFmtColor( pCol );
2076 :
2077 0 : if( pTNd->GetTxt() != rTxt )
2078 : {
2079 : // Exchange text. Bugfix to keep Tabs (front and back!)
2080 0 : const String& rOrig = pTNd->GetTxt();
2081 : xub_StrLen n;
2082 :
2083 0 : for( n = 0; n < rOrig.Len() && '\x9' == rOrig.GetChar( n ); ++n )
2084 : ;
2085 0 : for( ; n < rOrig.Len() && '\x01' == rOrig.GetChar( n ); ++n )
2086 : ;
2087 0 : SwIndex aIdx( pTNd, n );
2088 0 : for( n = rOrig.Len(); n && '\x9' == rOrig.GetChar( --n ); )
2089 : ;
2090 0 : n -= aIdx.GetIndex() - 1;
2091 :
2092 : // Reset DontExpand-Flags before exchange, to retrigger expansion
2093 : {
2094 0 : SwIndex aResetIdx( aIdx, n );
2095 0 : pTNd->DontExpandFmt( aResetIdx, false, false );
2096 : }
2097 :
2098 0 : if( !pDoc->IsIgnoreRedline() && !pDoc->GetRedlineTbl().empty() )
2099 : {
2100 0 : SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.Len());
2101 0 : pDoc->DeleteRedline(aTemp, true, USHRT_MAX);
2102 : }
2103 :
2104 : pTNd->EraseText( aIdx, n,
2105 0 : IDocumentContentOperations::INS_EMPTYEXPAND );
2106 : pTNd->InsertText( rTxt, aIdx,
2107 0 : IDocumentContentOperations::INS_EMPTYEXPAND );
2108 :
2109 0 : if( pDoc->IsRedlineOn() )
2110 : {
2111 0 : SwPaM aTemp(*pTNd, 0, *pTNd, rTxt.Len());
2112 0 : pDoc->AppendRedline(new SwRedline(nsRedlineType_t::REDLINE_INSERT, aTemp), true);
2113 0 : }
2114 : }
2115 :
2116 : // assign vertical orientation
2117 0 : if( bChgAlign &&
2118 0 : ( SFX_ITEM_SET != rBox.GetFrmFmt()->GetItemState(
2119 0 : RES_VERT_ORIENT, sal_True, &pItem ) ||
2120 0 : text::VertOrientation::TOP == ((SwFmtVertOrient*)pItem)->GetVertOrient() ))
2121 : {
2122 0 : rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::BOTTOM ));
2123 : }
2124 : }
2125 0 : }
2126 :
2127 0 : void ChgNumToText( SwTableBox& rBox, sal_uLong nFmt )
2128 : {
2129 0 : sal_uLong nNdPos = rBox.IsValidNumTxtNd( sal_False );
2130 0 : if( ULONG_MAX != nNdPos )
2131 : {
2132 0 : SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2133 0 : SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
2134 0 : sal_Bool bChgAlign = pDoc->IsInsTblAlignNum();
2135 : const SfxPoolItem* pItem;
2136 :
2137 0 : Color* pCol = 0;
2138 0 : if( NUMBERFORMAT_TEXT != nFmt )
2139 : {
2140 : // special text format:
2141 0 : String sTmp, sTxt( pTNd->GetTxt() );
2142 0 : OUString sTempIn(sTxt);
2143 0 : OUString sTempOut;
2144 0 : pDoc->GetNumberFormatter()->GetOutputString( sTempIn, nFmt, sTempOut, &pCol );
2145 0 : sTxt = sTempIn;
2146 0 : sTmp = sTempOut;
2147 0 : if( sTxt != sTmp )
2148 : {
2149 : // exchange text
2150 0 : SwIndex aIdx( pTNd, sTxt.Len() );
2151 : // Reset DontExpand-Flags before exchange, to retrigger expansion
2152 0 : pTNd->DontExpandFmt( aIdx, false, false );
2153 0 : aIdx = 0;
2154 : pTNd->EraseText( aIdx, STRING_LEN,
2155 0 : IDocumentContentOperations::INS_EMPTYEXPAND );
2156 : pTNd->InsertText( sTmp, aIdx,
2157 0 : IDocumentContentOperations::INS_EMPTYEXPAND );
2158 0 : }
2159 : }
2160 :
2161 0 : const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
2162 :
2163 : // assign adjustment
2164 0 : if( bChgAlign && pAttrSet && SFX_ITEM_SET == pAttrSet->GetItemState(
2165 0 : RES_PARATR_ADJUST, sal_False, &pItem ) &&
2166 0 : SVX_ADJUST_RIGHT == ((SvxAdjustItem*)pItem)->GetAdjust() )
2167 : {
2168 0 : pTNd->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
2169 : }
2170 :
2171 : // assign color or save "user color"
2172 0 : if( !pAttrSet || SFX_ITEM_SET != pAttrSet->
2173 0 : GetItemState( RES_CHRATR_COLOR, sal_False, &pItem ))
2174 0 : pItem = 0;
2175 :
2176 0 : const Color* pOldNumFmtColor = rBox.GetSaveNumFmtColor();
2177 0 : const Color* pNewUserColor = pItem ? &((SvxColorItem*)pItem)->GetValue() : 0;
2178 :
2179 0 : if( ( pNewUserColor && pOldNumFmtColor &&
2180 0 : *pNewUserColor == *pOldNumFmtColor ) ||
2181 : ( !pNewUserColor && !pOldNumFmtColor ))
2182 : {
2183 : // Keep the user color, set updated values, delete old NumFmtColor if needed
2184 0 : if( pCol )
2185 : // if needed, set the color
2186 0 : pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2187 0 : else if( pItem )
2188 : {
2189 0 : pNewUserColor = rBox.GetSaveUserColor();
2190 0 : if( pNewUserColor )
2191 0 : pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2192 : else
2193 0 : pTNd->ResetAttr( RES_CHRATR_COLOR );
2194 : }
2195 : }
2196 : else
2197 : {
2198 : // Save user color, set NumFormat color if needed, but never reset the color
2199 0 : rBox.SetSaveUserColor( pNewUserColor );
2200 :
2201 0 : if( pCol )
2202 : // if needed, set the color
2203 0 : pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2204 :
2205 : }
2206 0 : rBox.SetSaveNumFmtColor( pCol );
2207 :
2208 :
2209 : // assign vertical orientation
2210 0 : if( bChgAlign &&
2211 0 : SFX_ITEM_SET == rBox.GetFrmFmt()->GetItemState(
2212 0 : RES_VERT_ORIENT, sal_False, &pItem ) &&
2213 0 : text::VertOrientation::BOTTOM == ((SwFmtVertOrient*)pItem)->GetVertOrient() )
2214 : {
2215 0 : rBox.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
2216 : }
2217 : }
2218 0 : }
2219 :
2220 : // for detection of modifications (mainly TableBoxAttribute)
2221 9534 : void SwTableBoxFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2222 : {
2223 9534 : if( !IsModifyLocked() && !IsInDocDTOR() )
2224 : {
2225 8098 : const SwTblBoxNumFormat *pNewFmt = 0;
2226 8098 : const SwTblBoxFormula *pNewFml = 0;
2227 8098 : const SwTblBoxValue *pNewVal = 0;
2228 8098 : sal_uLong nOldFmt = NUMBERFORMAT_TEXT;
2229 :
2230 8098 : switch( pNew ? pNew->Which() : 0 )
2231 : {
2232 : case RES_ATTRSET_CHG:
2233 : {
2234 8098 : const SfxItemSet& rSet = *((SwAttrSetChg*)pNew)->GetChgSet();
2235 8098 : if( SFX_ITEM_SET == rSet.GetItemState( RES_BOXATR_FORMAT,
2236 8098 : sal_False, (const SfxPoolItem**)&pNewFmt ) )
2237 : nOldFmt = ((SwTblBoxNumFormat&)((SwAttrSetChg*)pOld)->
2238 0 : GetChgSet()->Get( RES_BOXATR_FORMAT )).GetValue();
2239 : rSet.GetItemState( RES_BOXATR_FORMULA, sal_False,
2240 8098 : (const SfxPoolItem**)&pNewFml );
2241 : rSet.GetItemState( RES_BOXATR_VALUE, sal_False,
2242 8098 : (const SfxPoolItem**)&pNewVal );
2243 : }
2244 8098 : break;
2245 :
2246 : case RES_BOXATR_FORMAT:
2247 0 : pNewFmt = (SwTblBoxNumFormat*)pNew;
2248 0 : nOldFmt = ((SwTblBoxNumFormat*)pOld)->GetValue();
2249 0 : break;
2250 : case RES_BOXATR_FORMULA:
2251 0 : pNewFml = (SwTblBoxFormula*)pNew;
2252 0 : break;
2253 : case RES_BOXATR_VALUE:
2254 0 : pNewVal = (SwTblBoxValue*)pNew;
2255 0 : break;
2256 : }
2257 :
2258 : // something changed and some BoxAttribut remained in the set!
2259 8098 : if( pNewFmt || pNewFml || pNewVal )
2260 : {
2261 0 : GetDoc()->SetFieldsDirty(true, NULL, 0);
2262 :
2263 0 : if( SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMAT, sal_False ) ||
2264 0 : SFX_ITEM_SET == GetItemState( RES_BOXATR_VALUE, sal_False ) ||
2265 0 : SFX_ITEM_SET == GetItemState( RES_BOXATR_FORMULA, sal_False ) )
2266 : {
2267 : // fetch the box
2268 0 : SwIterator<SwTableBox,SwFmt> aIter( *this );
2269 0 : SwTableBox* pBox = aIter.First();
2270 0 : if( pBox )
2271 : {
2272 : OSL_ENSURE( !aIter.Next(), "zeor or more than one box at format" );
2273 :
2274 : sal_uLong nNewFmt;
2275 0 : if( pNewFmt )
2276 : {
2277 0 : nNewFmt = pNewFmt->GetValue();
2278 : // new formatting
2279 : // is it newer or has the current been removed?
2280 0 : if( SFX_ITEM_SET != GetItemState( RES_BOXATR_VALUE, sal_False ))
2281 0 : pNewFmt = 0;
2282 : }
2283 : else
2284 : {
2285 : // fetch the current Item
2286 : GetItemState( RES_BOXATR_FORMAT, sal_False,
2287 0 : (const SfxPoolItem**)&pNewFmt );
2288 0 : nOldFmt = GetTblBoxNumFmt().GetValue();
2289 0 : nNewFmt = pNewFmt ? pNewFmt->GetValue() : nOldFmt;
2290 : }
2291 :
2292 : // is it newer or has the current been removed?
2293 0 : if( pNewVal )
2294 : {
2295 0 : if( NUMBERFORMAT_TEXT != nNewFmt )
2296 : {
2297 0 : if( SFX_ITEM_SET == GetItemState(
2298 0 : RES_BOXATR_VALUE, sal_False ))
2299 0 : nOldFmt = NUMBERFORMAT_TEXT;
2300 : else
2301 0 : nNewFmt = NUMBERFORMAT_TEXT;
2302 : }
2303 0 : else if( NUMBERFORMAT_TEXT == nNewFmt )
2304 0 : nOldFmt = 0;
2305 : }
2306 :
2307 : // Logic:
2308 : // Value change: -> "simulate" a format change!
2309 : // Format change:
2310 : // Text -> !Text or format change:
2311 : // - align right for horizontal alignment, if LEFT or JUSTIFIED
2312 : // - align bottom for vertical alignment, if TOP is set, or default
2313 : // - replace text (color? negative numbers RED?)
2314 : // !Text -> Text:
2315 : // - align left for horizontal alignment, if RIGHT
2316 : // - align top for vertical alignment, if BOTTOM is set
2317 0 : SvNumberFormatter* pNumFmtr = GetDoc()->GetNumberFormatter();
2318 0 : bool bNewIsTxtFmt = pNumFmtr->IsTextFormat( nNewFmt ) ||
2319 0 : NUMBERFORMAT_TEXT == nNewFmt;
2320 :
2321 0 : if( (!bNewIsTxtFmt && nOldFmt != nNewFmt) || pNewFml )
2322 : {
2323 0 : bool bChgTxt = true;
2324 0 : double fVal = 0;
2325 0 : if( !pNewVal && SFX_ITEM_SET != GetItemState(
2326 0 : RES_BOXATR_VALUE, sal_False, (const SfxPoolItem**)&pNewVal ))
2327 : {
2328 : // so far, no value has been set, so try to evaluate the content
2329 0 : sal_uLong nNdPos = pBox->IsValidNumTxtNd( sal_True );
2330 0 : if( ULONG_MAX != nNdPos )
2331 : {
2332 0 : sal_uInt32 nTmpFmtIdx = nNewFmt;
2333 0 : String aTxt( GetDoc()->GetNodes()[ nNdPos ]
2334 0 : ->GetTxtNode()->GetRedlineTxt());
2335 0 : if( !aTxt.Len() )
2336 0 : bChgTxt = false;
2337 : else
2338 : {
2339 : // Keep Tabs
2340 0 : lcl_TabToBlankAtSttEnd( aTxt );
2341 :
2342 : // JP 22.04.98: Bug 49659 -
2343 : // Special casing for percent
2344 0 : sal_Bool bIsNumFmt = sal_False;
2345 0 : if( NUMBERFORMAT_PERCENT ==
2346 0 : pNumFmtr->GetType( nNewFmt ))
2347 : {
2348 0 : sal_uInt32 nTmpFmt = 0;
2349 0 : if( pNumFmtr->IsNumberFormat(
2350 0 : aTxt, nTmpFmt, fVal ))
2351 : {
2352 0 : if( NUMBERFORMAT_NUMBER ==
2353 0 : pNumFmtr->GetType( nTmpFmt ))
2354 0 : aTxt += '%';
2355 :
2356 : bIsNumFmt = pNumFmtr->IsNumberFormat(
2357 0 : aTxt, nTmpFmtIdx, fVal );
2358 : }
2359 : }
2360 : else
2361 : bIsNumFmt = pNumFmtr->IsNumberFormat(
2362 0 : aTxt, nTmpFmtIdx, fVal );
2363 :
2364 0 : if( bIsNumFmt )
2365 : {
2366 : // directly assign value - without Modify
2367 0 : bool bIsLockMod = IsModifyLocked();
2368 0 : LockModify();
2369 0 : SetFmtAttr( SwTblBoxValue( fVal ));
2370 0 : if( !bIsLockMod )
2371 0 : UnlockModify();
2372 : }
2373 0 : }
2374 : }
2375 : }
2376 : else
2377 0 : fVal = pNewVal->GetValue();
2378 :
2379 : // format contents with the new value assigned and write to paragraph
2380 0 : Color* pCol = 0;
2381 0 : String sNewTxt;
2382 0 : if( DBL_MAX == fVal )
2383 0 : sNewTxt = ViewShell::GetShellRes()->aCalc_Error;
2384 : else
2385 : {
2386 0 : pNumFmtr->GetOutputString( fVal, nNewFmt, sNewTxt, &pCol );
2387 :
2388 0 : if( !bChgTxt )
2389 0 : sNewTxt.Erase();
2390 : }
2391 :
2392 : // across all boxes
2393 : ChgTextToNum( *pBox, sNewTxt, pCol,
2394 0 : GetDoc()->IsInsTblAlignNum() );
2395 :
2396 : }
2397 0 : else if( bNewIsTxtFmt && nOldFmt != nNewFmt )
2398 : {
2399 0 : ChgNumToText( *pBox, nNewFmt );
2400 : }
2401 0 : }
2402 : }
2403 : }
2404 : }
2405 : // call base class
2406 9534 : SwFrmFmt::Modify( pOld, pNew );
2407 9534 : }
2408 :
2409 0 : sal_Bool SwTableBox::HasNumCntnt( double& rNum, sal_uInt32& rFmtIndex,
2410 : sal_Bool& rIsEmptyTxtNd ) const
2411 : {
2412 0 : sal_Bool bRet = sal_False;
2413 0 : sal_uLong nNdPos = IsValidNumTxtNd( sal_True );
2414 0 : if( ULONG_MAX != nNdPos )
2415 : {
2416 0 : String aTxt( pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->
2417 0 : GetRedlineTxt() );
2418 : // Keep Tabs
2419 0 : lcl_TabToBlankAtSttEnd( aTxt );
2420 0 : rIsEmptyTxtNd = 0 == aTxt.Len();
2421 0 : SvNumberFormatter* pNumFmtr = GetFrmFmt()->GetDoc()->GetNumberFormatter();
2422 :
2423 : const SfxPoolItem* pItem;
2424 0 : if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT,
2425 0 : sal_False, &pItem ))
2426 : {
2427 0 : rFmtIndex = ((SwTblBoxNumFormat*)pItem)->GetValue();
2428 : // Special casing for percent
2429 0 : if( !rIsEmptyTxtNd &&
2430 0 : NUMBERFORMAT_PERCENT == pNumFmtr->GetType( rFmtIndex ))
2431 : {
2432 0 : sal_uInt32 nTmpFmt = 0;
2433 0 : if( pNumFmtr->IsNumberFormat( aTxt, nTmpFmt, rNum ) &&
2434 0 : NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt ))
2435 0 : aTxt += '%';
2436 : }
2437 : }
2438 : else
2439 0 : rFmtIndex = 0;
2440 :
2441 0 : bRet = pNumFmtr->IsNumberFormat( aTxt, rFmtIndex, rNum );
2442 : }
2443 : else
2444 0 : rIsEmptyTxtNd = sal_False;
2445 0 : return bRet;
2446 : }
2447 :
2448 0 : sal_Bool SwTableBox::IsNumberChanged() const
2449 : {
2450 0 : sal_Bool bRet = sal_True;
2451 :
2452 0 : if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA, sal_False ))
2453 : {
2454 : const SwTblBoxNumFormat *pNumFmt;
2455 : const SwTblBoxValue *pValue;
2456 :
2457 0 : if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_VALUE, sal_False,
2458 0 : (const SfxPoolItem**)&pValue ))
2459 0 : pValue = 0;
2460 0 : if( SFX_ITEM_SET != GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT, sal_False,
2461 0 : (const SfxPoolItem**)&pNumFmt ))
2462 0 : pNumFmt = 0;
2463 :
2464 : sal_uLong nNdPos;
2465 0 : if( pNumFmt && pValue &&
2466 : ULONG_MAX != ( nNdPos = IsValidNumTxtNd( sal_True ) ) )
2467 : {
2468 0 : String sNewTxt, sOldTxt( pSttNd->GetNodes()[ nNdPos ]->
2469 0 : GetTxtNode()->GetRedlineTxt() );
2470 0 : lcl_DelTabsAtSttEnd( sOldTxt );
2471 :
2472 0 : Color* pCol = 0;
2473 0 : GetFrmFmt()->GetDoc()->GetNumberFormatter()->GetOutputString(
2474 0 : pValue->GetValue(), pNumFmt->GetValue(), sNewTxt, &pCol );
2475 :
2476 0 : bRet = sNewTxt != sOldTxt ||
2477 0 : !( ( !pCol && !GetSaveNumFmtColor() ) ||
2478 0 : ( pCol && GetSaveNumFmtColor() &&
2479 0 : *pCol == *GetSaveNumFmtColor() ));
2480 : }
2481 : }
2482 0 : return bRet;
2483 : }
2484 :
2485 0 : sal_uLong SwTableBox::IsValidNumTxtNd( sal_Bool bCheckAttr ) const
2486 : {
2487 0 : sal_uLong nPos = ULONG_MAX;
2488 0 : if( pSttNd )
2489 : {
2490 0 : SwNodeIndex aIdx( *pSttNd );
2491 0 : sal_uLong nIndex = aIdx.GetIndex();
2492 0 : const sal_uLong nIndexEnd = pSttNd->GetNodes()[ nIndex ]->EndOfSectionIndex();
2493 0 : const SwTxtNode *pTextNode = 0;
2494 0 : while( ++nIndex < nIndexEnd )
2495 : {
2496 0 : const SwNode* pNode = pSttNd->GetNodes()[nIndex];
2497 0 : if( pNode->IsTableNode() )
2498 : {
2499 0 : pTextNode = 0;
2500 0 : break;
2501 : }
2502 0 : if( pNode->IsTxtNode() )
2503 : {
2504 0 : if( pTextNode )
2505 : {
2506 0 : pTextNode = 0;
2507 0 : break;
2508 : }
2509 : else
2510 : {
2511 0 : pTextNode = pNode->GetTxtNode();
2512 0 : nPos = nIndex;
2513 : }
2514 : }
2515 : }
2516 0 : if( pTextNode )
2517 : {
2518 0 : if( bCheckAttr )
2519 : {
2520 0 : const SwpHints* pHts = pTextNode->GetpSwpHints();
2521 0 : const String& rTxt = pTextNode->GetTxt();
2522 : // do some tests if there's only text in the node!
2523 : // Flys/fields/...
2524 0 : if( pHts )
2525 : {
2526 0 : xub_StrLen nNextSetField = 0;
2527 0 : for( sal_uInt16 n = 0; n < pHts->Count(); ++n )
2528 : {
2529 0 : const SwTxtAttr* pAttr = (*pHts)[ n ];
2530 0 : if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() ||
2531 0 : *pAttr->GetStart() ||
2532 0 : *pAttr->GetAnyEnd() < rTxt.Len() )
2533 : {
2534 0 : if ((*pAttr->GetStart() == nNextSetField) &&
2535 0 : (pAttr->Which() == RES_TXTATR_FIELD))
2536 : {
2537 : // #i104949# hideous hack for report builder:
2538 : // it inserts hidden variable-set fields at
2539 : // the beginning of para in cell, but they
2540 : // should not turn cell into text cell
2541 0 : const SwField* pField = pAttr->GetFld().GetFld();
2542 0 : if (pField &&
2543 0 : (pField->GetTypeId() == TYP_SETFLD) &&
2544 : (0 != (static_cast<SwSetExpField const*>
2545 0 : (pField)->GetSubType() &
2546 : nsSwExtendedSubType::SUB_INVISIBLE)))
2547 : {
2548 0 : nNextSetField = *pAttr->GetStart() + 1;
2549 0 : continue;
2550 : }
2551 : }
2552 0 : nPos = ULONG_MAX;
2553 0 : break;
2554 : }
2555 : }
2556 : }
2557 : }
2558 : }
2559 : else
2560 0 : nPos = ULONG_MAX;
2561 : }
2562 0 : return nPos;
2563 : }
2564 :
2565 : // is this a Formula box or one with numeric content (AutoSum)
2566 0 : sal_uInt16 SwTableBox::IsFormulaOrValueBox() const
2567 : {
2568 0 : sal_uInt16 nWhich = 0;
2569 : const SwTxtNode* pTNd;
2570 0 : SwFrmFmt* pFmt = GetFrmFmt();
2571 0 : if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMULA, sal_False ))
2572 0 : nWhich = RES_BOXATR_FORMULA;
2573 0 : else if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_False ) &&
2574 : !pFmt->GetDoc()->GetNumberFormatter()->IsTextFormat(
2575 0 : pFmt->GetTblBoxNumFmt().GetValue() ))
2576 0 : nWhich = RES_BOXATR_VALUE;
2577 0 : else if( pSttNd && pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex()
2578 0 : && 0 != ( pTNd = pSttNd->GetNodes()[ pSttNd->GetIndex() + 1 ]
2579 0 : ->GetTxtNode() ) && !pTNd->GetTxt().Len() )
2580 0 : nWhich = USHRT_MAX;
2581 :
2582 0 : return nWhich;
2583 : }
2584 :
2585 230 : void SwTableBox::ActualiseValueBox()
2586 : {
2587 : const SfxPoolItem *pFmtItem, *pValItem;
2588 230 : SwFrmFmt* pFmt = GetFrmFmt();
2589 230 : if( SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_FORMAT, sal_True, &pFmtItem )
2590 0 : && SFX_ITEM_SET == pFmt->GetItemState( RES_BOXATR_VALUE, sal_True, &pValItem ))
2591 : {
2592 0 : const sal_uLong nFmtId = ((SwTblBoxNumFormat*)pFmtItem)->GetValue();
2593 0 : sal_uLong nNdPos = ULONG_MAX;
2594 0 : SvNumberFormatter* pNumFmtr = pFmt->GetDoc()->GetNumberFormatter();
2595 :
2596 0 : if( !pNumFmtr->IsTextFormat( nFmtId ) &&
2597 : ULONG_MAX != (nNdPos = IsValidNumTxtNd( sal_True )) )
2598 : {
2599 0 : double fVal = ((SwTblBoxValue*)pValItem)->GetValue();
2600 0 : Color* pCol = 0;
2601 0 : String sNewTxt;
2602 0 : pNumFmtr->GetOutputString( fVal, nFmtId, sNewTxt, &pCol );
2603 :
2604 0 : const String& rTxt = pSttNd->GetNodes()[ nNdPos ]->GetTxtNode()->GetTxt();
2605 0 : if( rTxt != sNewTxt )
2606 0 : ChgTextToNum( *this, sNewTxt, pCol, sal_False ,nNdPos);
2607 : }
2608 : }
2609 230 : }
2610 :
2611 0 : void SwTableBox_Impl::SetNewCol( Color** ppCol, const Color* pNewCol )
2612 : {
2613 0 : if( *ppCol != pNewCol )
2614 : {
2615 0 : delete *ppCol;
2616 0 : if( pNewCol )
2617 0 : *ppCol = new Color( *pNewCol );
2618 : else
2619 0 : *ppCol = 0;
2620 : }
2621 0 : }
2622 :
2623 : struct SwTableCellInfo::Impl
2624 : {
2625 : const SwTable * m_pTable;
2626 : const SwCellFrm * m_pCellFrm;
2627 : const SwTabFrm * m_pTabFrm;
2628 : typedef ::std::set<const SwTableBox *> TableBoxes_t;
2629 : TableBoxes_t m_HandledTableBoxes;
2630 :
2631 : public:
2632 0 : Impl()
2633 0 : : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL)
2634 : {
2635 0 : }
2636 :
2637 0 : ~Impl() {}
2638 :
2639 0 : void setTable(const SwTable * pTable) {
2640 0 : m_pTable = pTable;
2641 0 : SwFrmFmt * pFrmFmt = m_pTable->GetFrmFmt();
2642 0 : m_pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement(*pFrmFmt);
2643 0 : if (m_pTabFrm->IsFollow())
2644 0 : m_pTabFrm = m_pTabFrm->FindMaster(true);
2645 0 : }
2646 : const SwTable * getTable() const { return m_pTable; }
2647 :
2648 0 : const SwCellFrm * getCellFrm() const { return m_pCellFrm; }
2649 :
2650 : const SwFrm * getNextFrmInTable(const SwFrm * pFrm);
2651 : const SwCellFrm * getNextCellFrm(const SwFrm * pFrm);
2652 : const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm);
2653 : bool getNext();
2654 : };
2655 :
2656 0 : const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm)
2657 : {
2658 0 : const SwFrm * pResult = NULL;
2659 :
2660 0 : if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower())
2661 0 : pResult = pFrm->GetLower();
2662 0 : else if (pFrm->GetNext())
2663 0 : pResult = pFrm->GetNext();
2664 : else
2665 : {
2666 0 : while (pFrm->GetUpper() != NULL)
2667 : {
2668 0 : pFrm = pFrm->GetUpper();
2669 :
2670 0 : if (pFrm->IsTabFrm())
2671 : {
2672 0 : m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow();
2673 0 : pResult = m_pTabFrm;
2674 0 : break;
2675 : }
2676 0 : else if (pFrm->GetNext())
2677 : {
2678 0 : pResult = pFrm->GetNext();
2679 0 : break;
2680 : }
2681 : }
2682 : }
2683 :
2684 0 : return pResult;
2685 : }
2686 :
2687 0 : const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm)
2688 : {
2689 0 : const SwCellFrm * pResult = NULL;
2690 :
2691 0 : while ((pFrm = getNextFrmInTable(pFrm)) != NULL)
2692 : {
2693 0 : if (pFrm->IsCellFrm())
2694 : {
2695 0 : pResult = static_cast<const SwCellFrm *>(pFrm);
2696 0 : break;
2697 : }
2698 : }
2699 :
2700 0 : return pResult;
2701 : }
2702 :
2703 0 : const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm)
2704 : {
2705 0 : const SwCellFrm * pResult = NULL;
2706 :
2707 0 : while ((pFrm = getNextCellFrm(pFrm)) != NULL)
2708 : {
2709 0 : const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm);
2710 0 : const SwTableBox * pTabBox = pCellFrm->GetTabBox();
2711 0 : TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox);
2712 :
2713 0 : if (aIt == m_HandledTableBoxes.end())
2714 : {
2715 0 : pResult = pCellFrm;
2716 0 : m_HandledTableBoxes.insert(pTabBox);
2717 : break;
2718 : }
2719 : }
2720 :
2721 0 : return pResult;
2722 : }
2723 :
2724 0 : const SwCellFrm * SwTableCellInfo::getCellFrm() const
2725 : {
2726 0 : return m_pImpl->getCellFrm();
2727 : }
2728 :
2729 0 : bool SwTableCellInfo::Impl::getNext()
2730 : {
2731 0 : if (m_pCellFrm == NULL)
2732 : {
2733 0 : if (m_pTabFrm != NULL)
2734 0 : m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm);
2735 : }
2736 : else
2737 0 : m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm);
2738 :
2739 0 : return m_pCellFrm != NULL;
2740 : }
2741 :
2742 0 : SwTableCellInfo::SwTableCellInfo(const SwTable * pTable)
2743 : {
2744 0 : m_pImpl.reset(new Impl());
2745 0 : m_pImpl->setTable(pTable);
2746 0 : }
2747 :
2748 0 : SwTableCellInfo::~SwTableCellInfo()
2749 : {
2750 0 : }
2751 :
2752 0 : bool SwTableCellInfo::getNext()
2753 : {
2754 0 : return m_pImpl->getNext();
2755 : }
2756 :
2757 0 : SwRect SwTableCellInfo::getRect() const
2758 : {
2759 0 : SwRect aRet;
2760 :
2761 0 : if (getCellFrm() != NULL)
2762 0 : aRet = getCellFrm()->Frm();
2763 :
2764 0 : return aRet;
2765 : }
2766 :
2767 0 : const SwTableBox * SwTableCellInfo::getTableBox() const
2768 : {
2769 0 : const SwTableBox * pRet = NULL;
2770 :
2771 0 : if (getCellFrm() != NULL)
2772 0 : pRet = getCellFrm()->GetTabBox();
2773 :
2774 0 : return pRet;
2775 : }
2776 :
2777 178 : void SwTable::RegisterToFormat( SwFmt& rFmt )
2778 : {
2779 178 : rFmt.Add( this );
2780 178 : }
2781 :
2782 0 : bool SwTable::HasLayout() const
2783 : {
2784 0 : const SwFrmFmt* pFrmFmt = GetFrmFmt();
2785 : //a table in a clipboard document doesn't have any layout information
2786 0 : return pFrmFmt && SwIterator<SwTabFrm,SwFmt>::FirstElement(*pFrmFmt);
2787 : }
2788 :
2789 0 : void SwTableLine::RegisterToFormat( SwFmt& rFmt )
2790 : {
2791 0 : rFmt.Add( this );
2792 0 : }
2793 :
2794 0 : void SwTableBox::RegisterToFormat( SwFmt& rFmt )
2795 : {
2796 0 : rFmt.Add( this );
2797 0 : }
2798 :
2799 : // free's any remaining child objects
2800 2916 : SwTableLines::~SwTableLines()
2801 : {
2802 1872 : for ( const_iterator it = begin(); it != end(); ++it )
2803 414 : delete *it;
2804 1458 : }
2805 :
2806 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|