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