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