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