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 <com/sun/star/chart2/XChartDocument.hpp>
21 : #include <fesh.hxx>
22 : #include <hintids.hxx>
23 : #include <editeng/lrspitem.hxx>
24 : #include <editeng/formatbreakitem.hxx>
25 : #include <editeng/protitem.hxx>
26 : #include <editeng/boxitem.hxx>
27 : #include <svl/stritem.hxx>
28 : #include <editeng/shaditem.hxx>
29 : #include <fmtfsize.hxx>
30 : #include <fmtornt.hxx>
31 : #include <fmtfordr.hxx>
32 : #include <fmtpdsc.hxx>
33 : #include <fmtanchr.hxx>
34 : #include <fmtlsplt.hxx>
35 : #include <frmatr.hxx>
36 : #include <charatr.hxx>
37 : #include <cellfrm.hxx>
38 : #include <pagefrm.hxx>
39 : #include <tabcol.hxx>
40 : #include <doc.hxx>
41 : #include <IDocumentUndoRedo.hxx>
42 : #include <UndoManager.hxx>
43 : #include <DocumentSettingManager.hxx>
44 : #include <IDocumentChartDataProviderAccess.hxx>
45 : #include <IDocumentRedlineAccess.hxx>
46 : #include <IDocumentStylePoolAccess.hxx>
47 : #include <IDocumentFieldsAccess.hxx>
48 : #include <IDocumentLayoutAccess.hxx>
49 : #include <IDocumentState.hxx>
50 : #include <cntfrm.hxx>
51 : #include <pam.hxx>
52 : #include <swcrsr.hxx>
53 : #include <viscrs.hxx>
54 : #include <swtable.hxx>
55 : #include <swundo.hxx>
56 : #include <tblsel.hxx>
57 : #include <fldbas.hxx>
58 : #include <poolfmt.hxx>
59 : #include <tabfrm.hxx>
60 : #include <UndoCore.hxx>
61 : #include <UndoRedline.hxx>
62 : #include <UndoDelete.hxx>
63 : #include <UndoNumbering.hxx>
64 : #include <UndoTable.hxx>
65 : #include <hints.hxx>
66 : #include <tblafmt.hxx>
67 : #include <swcache.hxx>
68 : #include <ddefld.hxx>
69 : #include <frminf.hxx>
70 : #include <cellatr.hxx>
71 : #include <swtblfmt.hxx>
72 : #include <swddetbl.hxx>
73 : #include <mvsave.hxx>
74 : #include <docary.hxx>
75 : #include <redline.hxx>
76 : #include <rolbck.hxx>
77 : #include <tblrwcl.hxx>
78 : #include <editsh.hxx>
79 : #include <txtfrm.hxx>
80 : #include <ftnfrm.hxx>
81 : #include <section.hxx>
82 : #include <frmtool.hxx>
83 : #include <node2lay.hxx>
84 : #include <comcore.hrc>
85 : #include "docsh.hxx"
86 : #include <unochart.hxx>
87 : #include <node.hxx>
88 : #include <ndtxt.hxx>
89 : #include <cstdlib>
90 : #include <map>
91 : #include <algorithm>
92 : #include <rootfrm.hxx>
93 : #include <fldupde.hxx>
94 : #include <calbck.hxx>
95 : #include <o3tl/numeric.hxx>
96 : #include <tools/datetimeutils.hxx>
97 :
98 : #ifdef DBG_UTIL
99 : #define CHECK_TABLE(t) (t).CheckConsistency();
100 : #else
101 : #define CHECK_TABLE(t)
102 : #endif
103 :
104 : using ::editeng::SvxBorderLine;
105 : using namespace ::com::sun::star;
106 :
107 : const sal_Unicode T2T_PARA = 0x0a;
108 :
109 232 : static void lcl_SetDfltBoxAttr( SwFrameFormat& rFormat, sal_uInt8 nId )
110 : {
111 232 : bool bTop = false, bBottom = false, bLeft = false, bRight = false;
112 232 : switch ( nId )
113 : {
114 34 : case 0: bTop = bBottom = bLeft = true; break;
115 130 : case 1: bTop = bBottom = bLeft = bRight = true; break;
116 34 : case 2: bBottom = bLeft = true; break;
117 34 : case 3: bBottom = bLeft = bRight = true; break;
118 : }
119 :
120 232 : const bool bHTML = rFormat.getIDocumentSettingAccess()->get(DocumentSettingId::HTML_MODE);
121 232 : Color aCol( bHTML ? COL_GRAY : COL_BLACK );
122 232 : SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
123 232 : if ( bHTML )
124 : {
125 0 : aLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
126 0 : aLine.SetWidth( DEF_LINE_WIDTH_0 );
127 : }
128 232 : SvxBoxItem aBox(RES_BOX); aBox.SetDistance( 55 );
129 232 : if ( bTop )
130 164 : aBox.SetLine( &aLine, SvxBoxItemLine::TOP );
131 232 : if ( bBottom )
132 232 : aBox.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
133 232 : if ( bLeft )
134 232 : aBox.SetLine( &aLine, SvxBoxItemLine::LEFT );
135 232 : if ( bRight )
136 164 : aBox.SetLine( &aLine, SvxBoxItemLine::RIGHT );
137 232 : rFormat.SetFormatAttr( aBox );
138 232 : }
139 :
140 : typedef std::map<SwFrameFormat *, SwTableBoxFormat *> DfltBoxAttrMap_t;
141 : typedef std::vector<DfltBoxAttrMap_t *> DfltBoxAttrList_t;
142 :
143 : static void
144 0 : lcl_SetDfltBoxAttr(SwTableBox& rBox, DfltBoxAttrList_t & rBoxFormatArr,
145 : sal_uInt8 const nId, SwTableAutoFormat const*const pAutoFormat = 0)
146 : {
147 0 : DfltBoxAttrMap_t * pMap = rBoxFormatArr[ nId ];
148 0 : if (!pMap)
149 : {
150 0 : pMap = new DfltBoxAttrMap_t;
151 0 : rBoxFormatArr[ nId ] = pMap;
152 : }
153 :
154 0 : SwTableBoxFormat* pNewTableBoxFormat = 0;
155 0 : SwFrameFormat* pBoxFrameFormat = rBox.GetFrameFormat();
156 0 : DfltBoxAttrMap_t::iterator const iter(pMap->find(pBoxFrameFormat));
157 0 : if (pMap->end() != iter)
158 : {
159 0 : pNewTableBoxFormat = iter->second;
160 : }
161 : else
162 : {
163 0 : SwDoc* pDoc = pBoxFrameFormat->GetDoc();
164 : // format does not exist, so create it
165 0 : pNewTableBoxFormat = pDoc->MakeTableBoxFormat();
166 0 : pNewTableBoxFormat->SetFormatAttr( pBoxFrameFormat->GetAttrSet().Get( RES_FRM_SIZE ) );
167 :
168 0 : if( pAutoFormat )
169 0 : pAutoFormat->UpdateToSet( nId, (SfxItemSet&)pNewTableBoxFormat->GetAttrSet(),
170 : SwTableAutoFormat::UPDATE_BOX,
171 0 : pDoc->GetNumberFormatter( true ) );
172 : else
173 0 : ::lcl_SetDfltBoxAttr( *pNewTableBoxFormat, nId );
174 :
175 0 : (*pMap)[pBoxFrameFormat] = pNewTableBoxFormat;
176 : }
177 0 : rBox.ChgFrameFormat( pNewTableBoxFormat );
178 0 : }
179 :
180 495 : static SwTableBoxFormat *lcl_CreateDfltBoxFormat( SwDoc &rDoc, std::vector<SwTableBoxFormat*> &rBoxFormatArr,
181 : sal_uInt16 nCols, sal_uInt8 nId )
182 : {
183 495 : if ( !rBoxFormatArr[nId] )
184 : {
185 232 : SwTableBoxFormat* pBoxFormat = rDoc.MakeTableBoxFormat();
186 232 : if( USHRT_MAX != nCols )
187 : pBoxFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE,
188 232 : USHRT_MAX / nCols, 0 ));
189 232 : ::lcl_SetDfltBoxAttr( *pBoxFormat, nId );
190 232 : rBoxFormatArr[ nId ] = pBoxFormat;
191 : }
192 495 : return rBoxFormatArr[nId];
193 : }
194 :
195 0 : static SwTableBoxFormat *lcl_CreateAFormatBoxFormat( SwDoc &rDoc, std::vector<SwTableBoxFormat*> &rBoxFormatArr,
196 : const SwTableAutoFormat& rAutoFormat,
197 : sal_uInt16 nCols, sal_uInt8 nId )
198 : {
199 0 : if( !rBoxFormatArr[nId] )
200 : {
201 0 : SwTableBoxFormat* pBoxFormat = rDoc.MakeTableBoxFormat();
202 0 : rAutoFormat.UpdateToSet( nId, (SfxItemSet&)pBoxFormat->GetAttrSet(),
203 : SwTableAutoFormat::UPDATE_BOX,
204 0 : rDoc.GetNumberFormatter( true ) );
205 0 : if( USHRT_MAX != nCols )
206 : pBoxFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE,
207 0 : USHRT_MAX / nCols, 0 ));
208 0 : rBoxFormatArr[ nId ] = pBoxFormat;
209 : }
210 0 : return rBoxFormatArr[nId];
211 : }
212 :
213 185 : SwTableNode* SwDoc::IsIdxInTable(const SwNodeIndex& rIdx)
214 : {
215 185 : SwTableNode* pTableNd = 0;
216 185 : sal_uLong nIndex = rIdx.GetIndex();
217 338 : do {
218 376 : SwNode* pNd = static_cast<SwNode*>(GetNodes()[ nIndex ]->StartOfSectionNode());
219 376 : if( 0 != ( pTableNd = pNd->GetTableNode() ) )
220 38 : break;
221 :
222 338 : nIndex = pNd->GetIndex();
223 : } while ( nIndex );
224 185 : return pTableNd;
225 : }
226 :
227 : /**
228 : * Insert a new Box before the InsPos
229 : */
230 61 : bool SwNodes::InsBoxen( SwTableNode* pTableNd,
231 : SwTableLine* pLine,
232 : SwTableBoxFormat* pBoxFormat,
233 : SwTextFormatColl* pTextColl,
234 : const SfxItemSet* pAutoAttr,
235 : sal_uInt16 nInsPos,
236 : sal_uInt16 nCnt )
237 : {
238 61 : if( !nCnt )
239 0 : return false;
240 : OSL_ENSURE( pLine, "No valid Line" );
241 :
242 : // Move Index after the Line's last Box
243 61 : sal_uLong nIdxPos = 0;
244 61 : SwTableBox *pPrvBox = 0, *pNxtBox = 0;
245 61 : if( !pLine->GetTabBoxes().empty() )
246 : {
247 57 : if( nInsPos < pLine->GetTabBoxes().size() )
248 : {
249 0 : if( 0 == (pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable(),
250 0 : pLine->GetTabBoxes()[ nInsPos ] )))
251 0 : pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable() );
252 : }
253 : else
254 : {
255 57 : if( 0 == (pNxtBox = pLine->FindNextBox( pTableNd->GetTable(),
256 57 : pLine->GetTabBoxes().back() )))
257 19 : pNxtBox = pLine->FindNextBox( pTableNd->GetTable() );
258 : }
259 : }
260 4 : else if( 0 == ( pNxtBox = pLine->FindNextBox( pTableNd->GetTable() )))
261 2 : pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable() );
262 :
263 61 : if( !pPrvBox && !pNxtBox )
264 : {
265 19 : bool bSetIdxPos = true;
266 19 : if( pTableNd->GetTable().GetTabLines().size() && !nInsPos )
267 : {
268 0 : const SwTableLine* pTableLn = pLine;
269 0 : while( pTableLn->GetUpper() )
270 0 : pTableLn = pTableLn->GetUpper()->GetUpper();
271 :
272 0 : if( pTableNd->GetTable().GetTabLines()[ 0 ] == pTableLn )
273 : {
274 : // Before the Table's first Box
275 0 : while( ( pNxtBox = pLine->GetTabBoxes()[0])->GetTabLines().size() )
276 0 : pLine = pNxtBox->GetTabLines()[0];
277 0 : nIdxPos = pNxtBox->GetSttIdx();
278 0 : bSetIdxPos = false;
279 : }
280 : }
281 19 : if( bSetIdxPos )
282 : // Tables without content or at the end; move before the End
283 19 : nIdxPos = pTableNd->EndOfSectionIndex();
284 : }
285 42 : else if( pNxtBox ) // There is a successor
286 40 : nIdxPos = pNxtBox->GetSttIdx();
287 : else // There is a predecessor
288 2 : nIdxPos = pPrvBox->GetSttNd()->EndOfSectionIndex() + 1;
289 :
290 61 : SwNodeIndex aEndIdx( *this, nIdxPos );
291 333 : for( sal_uInt16 n = 0; n < nCnt; ++n )
292 : {
293 : SwStartNode* pSttNd = new SwStartNode( aEndIdx, ND_STARTNODE,
294 272 : SwTableBoxStartNode );
295 272 : pSttNd->pStartOfSection = pTableNd;
296 272 : new SwEndNode( aEndIdx, *pSttNd );
297 :
298 272 : pPrvBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
299 :
300 272 : SwTableBoxes & rTabBoxes = pLine->GetTabBoxes();
301 272 : sal_uInt16 nRealInsPos = nInsPos + n;
302 272 : if (nRealInsPos > rTabBoxes.size())
303 0 : nRealInsPos = rTabBoxes.size();
304 :
305 272 : rTabBoxes.insert( rTabBoxes.begin() + nRealInsPos, pPrvBox );
306 :
307 544 : if( ! pTextColl->IsAssignedToListLevelOfOutlineStyle()
308 : //FEATURE::CONDCOLL
309 272 : && RES_CONDTXTFMTCOLL != pTextColl->Which()
310 : //FEATURE::CONDCOLL
311 : )
312 272 : new SwTextNode( SwNodeIndex( *pSttNd->EndOfSectionNode() ),
313 272 : pTextColl, pAutoAttr );
314 : else
315 : {
316 : // Handle Outline numbering correctly!
317 : SwTextNode* pTNd = new SwTextNode(
318 0 : SwNodeIndex( *pSttNd->EndOfSectionNode() ),
319 0 : GetDoc()->GetDfltTextFormatColl(),
320 0 : pAutoAttr );
321 0 : pTNd->ChgFormatColl( pTextColl );
322 : }
323 : }
324 61 : return true;
325 : }
326 :
327 : /**
328 : * Insert a new Table
329 : */
330 211 : const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTableOpts,
331 : const SwPosition& rPos, sal_uInt16 nRows,
332 : sal_uInt16 nCols, sal_Int16 eAdjust,
333 : const SwTableAutoFormat* pTAFormat,
334 : const std::vector<sal_uInt16> *pColArr,
335 : bool bCalledFromShell,
336 : bool bNewModel )
337 : {
338 : OSL_ENSURE( nRows, "Table without line?" );
339 : OSL_ENSURE( nCols, "Table without rows?" );
340 :
341 : {
342 : // Do not copy into Footnotes!
343 211 : if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() &&
344 0 : rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
345 0 : return 0;
346 :
347 : // If the ColumnArray has a wrong count, ignore it!
348 211 : if( pColArr &&
349 0 : (size_t)(nCols + ( text::HoriOrientation::NONE == eAdjust ? 2 : 1 )) != pColArr->size() )
350 0 : pColArr = 0;
351 : }
352 :
353 211 : OUString aTableName = GetUniqueTableName();
354 :
355 211 : if( GetIDocumentUndoRedo().DoesUndo() )
356 : {
357 50 : GetIDocumentUndoRedo().AppendUndo(
358 : new SwUndoInsTable( rPos, nCols, nRows, static_cast<sal_uInt16>(eAdjust),
359 : rInsTableOpts, pTAFormat, pColArr,
360 50 : aTableName));
361 : }
362 :
363 : // Start with inserting the Nodes and get the AutoFormat for the Table
364 211 : SwTextFormatColl *pBodyColl = getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TABLE ),
365 211 : *pHeadColl = pBodyColl;
366 :
367 211 : bool bDfltBorders = 0 != ( rInsTableOpts.mnInsMode & tabopts::DEFAULT_BORDER );
368 :
369 211 : if( (rInsTableOpts.mnInsMode & tabopts::HEADLINE) && (1 != nRows || !bDfltBorders) )
370 114 : pHeadColl = getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TABLE_HDLN );
371 :
372 : const sal_uInt16 nRowsToRepeat =
373 211 : tabopts::HEADLINE == (rInsTableOpts.mnInsMode & tabopts::HEADLINE) ?
374 : rInsTableOpts.mnRowsToRepeat :
375 211 : 0;
376 :
377 : /* Save content node to extract FRAMEDIR from. */
378 211 : const SwContentNode * pContentNd = rPos.nNode.GetNode().GetContentNode();
379 :
380 : /* If we are called from a shell pass the attrset from
381 : pContentNd (aka the node the table is inserted at) thus causing
382 : SwNodes::InsertTable to propagate an adjust item if
383 : necessary. */
384 : SwTableNode *pTableNd = SwNodes::InsertTable(
385 : rPos.nNode,
386 : nCols,
387 : pBodyColl,
388 : nRows,
389 : nRowsToRepeat,
390 : pHeadColl,
391 211 : bCalledFromShell ? &pContentNd->GetSwAttrSet() : 0 );
392 :
393 : // Create the Box/Line/Table construct
394 211 : SwTableLineFormat* pLineFormat = MakeTableLineFormat();
395 211 : SwTableFormat* pTableFormat = MakeTableFrameFormat( aTableName, GetDfltFrameFormat() );
396 :
397 : /* If the node to insert the table at is a context node and has a
398 : non-default FRAMEDIR propagate it to the table. */
399 211 : if (pContentNd)
400 : {
401 211 : const SwAttrSet & aNdSet = pContentNd->GetSwAttrSet();
402 211 : const SfxPoolItem *pItem = NULL;
403 :
404 422 : if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
405 211 : && pItem != NULL)
406 : {
407 83 : pTableFormat->SetFormatAttr( *pItem );
408 : }
409 : }
410 :
411 : // Set Orientation at the Table's Format
412 211 : pTableFormat->SetFormatAttr( SwFormatHoriOrient( 0, eAdjust ) );
413 : // All lines use the left-to-right Fill-Order!
414 211 : pLineFormat->SetFormatAttr( SwFormatFillOrder( ATT_LEFT_TO_RIGHT ));
415 :
416 : // Set USHRT_MAX as the Table's default SSize
417 211 : SwTwips nWidth = USHRT_MAX;
418 211 : if( pColArr )
419 : {
420 0 : sal_uInt16 nSttPos = pColArr->front();
421 0 : sal_uInt16 nLastPos = pColArr->back();
422 0 : if( text::HoriOrientation::NONE == eAdjust )
423 : {
424 0 : sal_uInt16 nFrmWidth = nLastPos;
425 0 : nLastPos = (*pColArr)[ pColArr->size()-2 ];
426 0 : pTableFormat->SetFormatAttr( SvxLRSpaceItem( nSttPos, nFrmWidth - nLastPos, 0, 0, RES_LR_SPACE ) );
427 : }
428 0 : nWidth = nLastPos - nSttPos;
429 : }
430 211 : else if( nCols )
431 : {
432 211 : nWidth /= nCols;
433 211 : nWidth *= nCols; // to avoid rounding problems
434 : }
435 211 : pTableFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, nWidth ));
436 211 : if( !(rInsTableOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
437 1 : pTableFormat->SetFormatAttr( SwFormatLayoutSplit( false ));
438 :
439 : // Move the hard PageDesc/PageBreak Attributes if needed
440 422 : SwContentNode* pNextNd = GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]
441 422 : ->GetContentNode();
442 211 : if( pNextNd && pNextNd->HasSwAttrSet() )
443 : {
444 18 : const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet();
445 : const SfxPoolItem *pItem;
446 18 : if( SfxItemState::SET == pNdSet->GetItemState( RES_PAGEDESC, false,
447 18 : &pItem ) )
448 : {
449 4 : pTableFormat->SetFormatAttr( *pItem );
450 4 : pNextNd->ResetAttr( RES_PAGEDESC );
451 4 : pNdSet = pNextNd->GetpSwAttrSet();
452 : }
453 36 : if( pNdSet && SfxItemState::SET == pNdSet->GetItemState( RES_BREAK, false,
454 18 : &pItem ) )
455 : {
456 0 : pTableFormat->SetFormatAttr( *pItem );
457 0 : pNextNd->ResetAttr( RES_BREAK );
458 : }
459 : }
460 :
461 211 : SwTable& rNdTable = pTableNd->GetTable();
462 211 : rNdTable.RegisterToFormat( *pTableFormat );
463 :
464 211 : rNdTable.SetRowsToRepeat( nRowsToRepeat );
465 211 : rNdTable.SetTableModel( bNewModel );
466 :
467 422 : std::vector<SwTableBoxFormat*> aBoxFormatArr;
468 211 : SwTableBoxFormat* pBoxFormat = 0;
469 211 : if( !bDfltBorders && !pTAFormat )
470 : {
471 81 : pBoxFormat = MakeTableBoxFormat();
472 81 : pBoxFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, USHRT_MAX / nCols, 0 ));
473 : }
474 : else
475 : {
476 130 : const sal_uInt16 nBoxArrLen = pTAFormat ? 16 : 4;
477 130 : aBoxFormatArr.resize( nBoxArrLen, NULL );
478 : }
479 422 : SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
480 :
481 422 : SwNodeIndex aNdIdx( *pTableNd, 1 ); // Set to StartNode of first Box
482 211 : SwTableLines& rLines = rNdTable.GetTabLines();
483 741 : for( sal_uInt16 n = 0; n < nRows; ++n )
484 : {
485 530 : SwTableLine* pLine = new SwTableLine( pLineFormat, nCols, 0 );
486 530 : rLines.insert( rLines.begin() + n, pLine );
487 530 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
488 1759 : for( sal_uInt16 i = 0; i < nCols; ++i )
489 : {
490 : SwTableBoxFormat *pBoxF;
491 1229 : if( pTAFormat )
492 : {
493 0 : sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
494 0 : ? 12 : (4 * (1 + ((n-1) & 1 )))));
495 : nId = nId + static_cast<sal_uInt8>( !i ? 0 :
496 0 : ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
497 : pBoxF = ::lcl_CreateAFormatBoxFormat( *this, aBoxFormatArr, *pTAFormat,
498 0 : nCols, nId );
499 :
500 : // Set the Paragraph/Character Attributes if needed
501 0 : if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
502 : {
503 0 : aCharSet.ClearItem();
504 : pTAFormat->UpdateToSet( nId, aCharSet,
505 0 : SwTableAutoFormat::UPDATE_CHAR, 0 );
506 0 : if( aCharSet.Count() )
507 0 : GetNodes()[ aNdIdx.GetIndex()+1 ]->GetContentNode()->
508 0 : SetAttr( aCharSet );
509 : }
510 : }
511 1229 : else if( bDfltBorders )
512 : {
513 495 : sal_uInt8 nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
514 495 : pBoxF = ::lcl_CreateDfltBoxFormat( *this, aBoxFormatArr, nCols, nBoxId);
515 : }
516 : else
517 734 : pBoxF = pBoxFormat;
518 :
519 : // For AutoFormat on input: the columns are set when inserting the Table
520 : // The Array contains the columns positions and not their widths!
521 1229 : if( pColArr )
522 : {
523 0 : nWidth = (*pColArr)[ i + 1 ] - (*pColArr)[ i ];
524 0 : if( pBoxF->GetFrmSize().GetWidth() != nWidth )
525 : {
526 0 : if( pBoxF->HasWriterListeners() ) // Create new Format
527 : {
528 0 : SwTableBoxFormat *pNewFormat = MakeTableBoxFormat();
529 0 : *pNewFormat = *pBoxF;
530 0 : pBoxF = pNewFormat;
531 : }
532 0 : pBoxF->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, nWidth ));
533 : }
534 : }
535 :
536 1229 : SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine);
537 1229 : rBoxes.insert( rBoxes.begin() + i, pBox );
538 1229 : aNdIdx += 3; // StartNode, TextNode, EndNode == 3 Nodes
539 : }
540 : }
541 : // Insert Frms
542 211 : GetNodes().GoNext( &aNdIdx ); // Go to the next ContentNode
543 211 : pTableNd->MakeFrms( &aNdIdx );
544 :
545 : // To-Do - add 'SwExtraRedlineTable' also ?
546 211 : if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
547 : {
548 21 : SwPaM aPam( *pTableNd->EndOfSectionNode(), *pTableNd, 1 );
549 21 : if( getIDocumentRedlineAccess().IsRedlineOn() )
550 0 : getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
551 : else
552 21 : getIDocumentRedlineAccess().SplitRedline( aPam );
553 : }
554 :
555 211 : getIDocumentState().SetModified();
556 : CHECK_TABLE(rNdTable);
557 422 : return &rNdTable;
558 : }
559 :
560 211 : SwTableNode* SwNodes::InsertTable( const SwNodeIndex& rNdIdx,
561 : sal_uInt16 nBoxes,
562 : SwTextFormatColl* pContentTextColl,
563 : sal_uInt16 nLines,
564 : sal_uInt16 nRepeat,
565 : SwTextFormatColl* pHeadlineTextColl,
566 : const SwAttrSet * pAttrSet)
567 : {
568 211 : if( !nBoxes )
569 0 : return 0;
570 :
571 : // If Lines is given, create the Matrix from Lines and Boxes
572 211 : if( !pHeadlineTextColl || !nLines )
573 0 : pHeadlineTextColl = pContentTextColl;
574 :
575 211 : SwTableNode * pTableNd = new SwTableNode( rNdIdx );
576 211 : SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTableNd );
577 :
578 211 : if( !nLines ) // For the for loop
579 0 : ++nLines;
580 :
581 211 : SwNodeIndex aIdx( *pEndNd );
582 211 : SwTextFormatColl* pTextColl = pHeadlineTextColl;
583 741 : for( sal_uInt16 nL = 0; nL < nLines; ++nL )
584 : {
585 1759 : for( sal_uInt16 nB = 0; nB < nBoxes; ++nB )
586 : {
587 : SwStartNode* pSttNd = new SwStartNode( aIdx, ND_STARTNODE,
588 1229 : SwTableBoxStartNode );
589 1229 : pSttNd->pStartOfSection = pTableNd;
590 :
591 1229 : SwTextNode * pTmpNd = new SwTextNode( aIdx, pTextColl );
592 :
593 : // #i60422# Propagate some more attributes.
594 1229 : const SfxPoolItem* pItem = NULL;
595 1229 : if ( NULL != pAttrSet )
596 : {
597 : static const sal_uInt16 aPropagateItems[] = {
598 : RES_PARATR_ADJUST,
599 : RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
600 : RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
601 : RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, 0 };
602 :
603 9 : const sal_uInt16* pIdx = aPropagateItems;
604 81 : while ( *pIdx != 0 )
605 : {
606 126 : if ( SfxItemState::SET != pTmpNd->GetSwAttrSet().GetItemState( *pIdx ) &&
607 63 : SfxItemState::SET == pAttrSet->GetItemState( *pIdx, true, &pItem ) )
608 0 : static_cast<SwContentNode *>(pTmpNd)->SetAttr(*pItem);
609 63 : ++pIdx;
610 : }
611 : }
612 :
613 1229 : new SwEndNode( aIdx, *pSttNd );
614 : }
615 530 : if ( nL + 1 >= nRepeat )
616 530 : pTextColl = pContentTextColl;
617 : }
618 211 : return pTableNd;
619 : }
620 :
621 : /**
622 : * Text to Table
623 : */
624 0 : const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTableOpts,
625 : const SwPaM& rRange, sal_Unicode cCh,
626 : sal_Int16 eAdjust,
627 : const SwTableAutoFormat* pTAFormat )
628 : {
629 : // See if the selection contains a Table
630 0 : const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
631 : {
632 0 : sal_uLong nCnt = pStt->nNode.GetIndex();
633 0 : for( ; nCnt <= pEnd->nNode.GetIndex(); ++nCnt )
634 0 : if( !GetNodes()[ nCnt ]->IsTextNode() )
635 0 : return 0;
636 : }
637 :
638 : // Save first node in the selection if it is a context node
639 0 : SwContentNode * pSttContentNd = pStt->nNode.GetNode().GetContentNode();
640 :
641 0 : SwPaM aOriginal( *pStt, *pEnd );
642 0 : pStt = aOriginal.GetMark();
643 0 : pEnd = aOriginal.GetPoint();
644 :
645 0 : SwUndoTextToTable* pUndo = 0;
646 0 : if( GetIDocumentUndoRedo().DoesUndo() )
647 : {
648 0 : GetIDocumentUndoRedo().StartUndo( UNDO_TEXTTOTABLE, NULL );
649 : pUndo = new SwUndoTextToTable( aOriginal, rInsTableOpts, cCh,
650 0 : static_cast<sal_uInt16>(eAdjust), pTAFormat );
651 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
652 :
653 : // Do not add splitting the TextNode to the Undo history
654 0 : GetIDocumentUndoRedo().DoUndo( false );
655 : }
656 :
657 0 : ::PaMCorrAbs( aOriginal, *pEnd );
658 :
659 : // Make sure that the range is on Node Edges
660 0 : SwNodeRange aRg( pStt->nNode, pEnd->nNode );
661 0 : if( pStt->nContent.GetIndex() )
662 0 : getIDocumentContentOperations().SplitNode( *pStt, false );
663 :
664 0 : bool bEndContent = 0 != pEnd->nContent.GetIndex();
665 :
666 : // Do not split at the End of a Line (except at the End of the Doc)
667 0 : if( bEndContent )
668 : {
669 0 : if( pEnd->nNode.GetNode().GetContentNode()->Len() != pEnd->nContent.GetIndex()
670 0 : || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
671 : {
672 0 : getIDocumentContentOperations().SplitNode( *pEnd, false );
673 0 : --((SwNodeIndex&)pEnd->nNode);
674 : ((SwIndex&)pEnd->nContent).Assign(
675 0 : pEnd->nNode.GetNode().GetContentNode(), 0 );
676 : // A Node and at the End?
677 0 : if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
678 0 : --aRg.aStart;
679 : }
680 : else
681 0 : ++aRg.aEnd;
682 : }
683 :
684 0 : if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
685 : {
686 : OSL_FAIL( "empty range" );
687 0 : ++aRg.aEnd;
688 : }
689 :
690 : // We always use Upper to insert the Table
691 0 : SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
692 :
693 0 : GetIDocumentUndoRedo().DoUndo( 0 != pUndo );
694 :
695 : // Create the Box/Line/Table construct
696 0 : SwTableBoxFormat* pBoxFormat = MakeTableBoxFormat();
697 0 : SwTableLineFormat* pLineFormat = MakeTableLineFormat();
698 0 : SwTableFormat* pTableFormat = MakeTableFrameFormat( GetUniqueTableName(), GetDfltFrameFormat() );
699 :
700 : // All Lines have a left-to-right Fill Order
701 0 : pLineFormat->SetFormatAttr( SwFormatFillOrder( ATT_LEFT_TO_RIGHT ));
702 : // The Table's SSize is USHRT_MAX
703 0 : pTableFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
704 0 : if( !(rInsTableOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
705 0 : pTableFormat->SetFormatAttr( SwFormatLayoutSplit( false ));
706 :
707 : /* If the first node in the selection is a context node and if it
708 : has an item FRAMEDIR set (no default) propagate the item to the
709 : replacing table. */
710 0 : if (pSttContentNd)
711 : {
712 0 : const SwAttrSet & aNdSet = pSttContentNd->GetSwAttrSet();
713 0 : const SfxPoolItem *pItem = NULL;
714 :
715 0 : if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
716 0 : && pItem != NULL)
717 : {
718 0 : pTableFormat->SetFormatAttr( *pItem );
719 : }
720 : }
721 :
722 0 : SwTableNode* pTableNd = GetNodes().TextToTable(
723 : aRg, cCh, pTableFormat, pLineFormat, pBoxFormat,
724 0 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ), pUndo );
725 :
726 0 : SwTable& rNdTable = pTableNd->GetTable();
727 :
728 : const sal_uInt16 nRowsToRepeat =
729 0 : tabopts::HEADLINE == (rInsTableOpts.mnInsMode & tabopts::HEADLINE) ?
730 : rInsTableOpts.mnRowsToRepeat :
731 0 : 0;
732 0 : rNdTable.SetRowsToRepeat(nRowsToRepeat);
733 :
734 0 : bool bUseBoxFormat = false;
735 0 : if( !pBoxFormat->HasWriterListeners() )
736 : {
737 : // The Box's Formats already have the right size, we must only set
738 : // the right Border/AutoFormat.
739 0 : bUseBoxFormat = true;
740 0 : pTableFormat->SetFormatAttr( pBoxFormat->GetFrmSize() );
741 0 : delete pBoxFormat;
742 0 : eAdjust = text::HoriOrientation::NONE;
743 : }
744 :
745 : // Set Orientation in the Table's Format
746 0 : pTableFormat->SetFormatAttr( SwFormatHoriOrient( 0, eAdjust ) );
747 :
748 0 : if( pTAFormat || ( rInsTableOpts.mnInsMode & tabopts::DEFAULT_BORDER) )
749 : {
750 0 : sal_uInt8 nBoxArrLen = pTAFormat ? 16 : 4;
751 0 : std::unique_ptr< DfltBoxAttrList_t > aBoxFormatArr1;
752 0 : std::unique_ptr< std::vector<SwTableBoxFormat*> > aBoxFormatArr2;
753 0 : if( bUseBoxFormat )
754 : {
755 0 : aBoxFormatArr1.reset(new DfltBoxAttrList_t( nBoxArrLen, NULL ));
756 : }
757 : else
758 : {
759 0 : aBoxFormatArr2.reset(new std::vector<SwTableBoxFormat*>( nBoxArrLen, NULL ));
760 : }
761 :
762 0 : SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
763 :
764 0 : SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
765 :
766 0 : SwTableBoxFormat *pBoxF = 0;
767 0 : SwTableLines& rLines = rNdTable.GetTabLines();
768 0 : const SwTableLines::size_type nRows = rLines.size();
769 0 : for( SwTableLines::size_type n = 0; n < nRows; ++n )
770 : {
771 0 : SwTableBoxes& rBoxes = rLines[ n ]->GetTabBoxes();
772 0 : const SwTableBoxes::size_type nCols = rBoxes.size();
773 0 : for( SwTableBoxes::size_type i = 0; i < nCols; ++i )
774 : {
775 0 : SwTableBox* pBox = rBoxes[ i ];
776 0 : bool bChgSz = false;
777 :
778 0 : if( pTAFormat )
779 : {
780 0 : sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
781 0 : ? 12 : (4 * (1 + ((n-1) & 1 )))));
782 : nId = nId + static_cast<sal_uInt8>(!i ? 0 :
783 0 : ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
784 0 : if( bUseBoxFormat )
785 0 : ::lcl_SetDfltBoxAttr( *pBox, *aBoxFormatArr1, nId, pTAFormat );
786 : else
787 : {
788 0 : bChgSz = 0 == (*aBoxFormatArr2)[ nId ];
789 0 : pBoxF = ::lcl_CreateAFormatBoxFormat( *this, *aBoxFormatArr2,
790 0 : *pTAFormat, USHRT_MAX, nId );
791 : }
792 :
793 : // Set Paragraph/Character Attributes if needed
794 0 : if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
795 : {
796 0 : aCharSet.ClearItem();
797 : pTAFormat->UpdateToSet( nId, aCharSet,
798 0 : SwTableAutoFormat::UPDATE_CHAR, 0 );
799 0 : if( aCharSet.Count() )
800 : {
801 0 : sal_uLong nSttNd = pBox->GetSttIdx()+1;
802 0 : sal_uLong nEndNd = pBox->GetSttNd()->EndOfSectionIndex();
803 0 : for( ; nSttNd < nEndNd; ++nSttNd )
804 : {
805 0 : SwContentNode* pNd = GetNodes()[ nSttNd ]->GetContentNode();
806 0 : if( pNd )
807 : {
808 0 : if( pHistory )
809 : {
810 0 : SwRegHistory aReg( pNd, *pNd, pHistory );
811 0 : pNd->SetAttr( aCharSet );
812 : }
813 : else
814 0 : pNd->SetAttr( aCharSet );
815 : }
816 : }
817 : }
818 : }
819 : }
820 : else
821 : {
822 0 : sal_uInt8 nId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
823 0 : if( bUseBoxFormat )
824 0 : ::lcl_SetDfltBoxAttr( *pBox, *aBoxFormatArr1, nId );
825 : else
826 : {
827 0 : bChgSz = 0 == (*aBoxFormatArr2)[ nId ];
828 0 : pBoxF = ::lcl_CreateDfltBoxFormat( *this, *aBoxFormatArr2,
829 0 : USHRT_MAX, nId );
830 : }
831 : }
832 :
833 0 : if( !bUseBoxFormat )
834 : {
835 0 : if( bChgSz )
836 0 : pBoxF->SetFormatAttr( pBox->GetFrameFormat()->GetFrmSize() );
837 0 : pBox->ChgFrameFormat( pBoxF );
838 : }
839 : }
840 : }
841 :
842 0 : if( bUseBoxFormat )
843 : {
844 0 : for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
845 : {
846 0 : delete (*aBoxFormatArr1)[ i ];
847 : }
848 0 : }
849 : }
850 :
851 : // Check the boxes for numbers
852 0 : if( IsInsTableFormatNum() )
853 : {
854 0 : for (size_t nBoxes = rNdTable.GetTabSortBoxes().size(); nBoxes; )
855 : {
856 0 : ChkBoxNumFormat(*rNdTable.GetTabSortBoxes()[ --nBoxes ], false);
857 : }
858 : }
859 :
860 0 : sal_uLong nIdx = pTableNd->GetIndex();
861 0 : aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
862 :
863 : {
864 0 : SwPaM& rTmp = (SwPaM&)rRange; // Point always at the Start
865 0 : rTmp.DeleteMark();
866 0 : rTmp.GetPoint()->nNode = *pTableNd;
867 0 : SwContentNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode );
868 0 : rTmp.GetPoint()->nContent.Assign( pCNd, 0 );
869 : }
870 :
871 0 : if( pUndo )
872 : {
873 0 : GetIDocumentUndoRedo().EndUndo( UNDO_TEXTTOTABLE, NULL );
874 : }
875 :
876 0 : getIDocumentState().SetModified();
877 0 : getIDocumentFieldsAccess().SetFieldsDirty(true, NULL, 0);
878 0 : return &rNdTable;
879 : }
880 :
881 10384 : static void lcl_RemoveBreaks(SwContentNode & rNode, SwTableFormat *const pTableFormat)
882 : {
883 : // delete old layout frames, new ones need to be created...
884 10384 : rNode.DelFrms();
885 :
886 10384 : if (!rNode.IsTextNode())
887 : {
888 10384 : return;
889 : }
890 :
891 10384 : SwTextNode & rTextNode = *rNode.GetTextNode();
892 : // remove PageBreaks/PageDesc/ColBreak
893 10384 : SfxItemSet const* pSet = rTextNode.GetpSwAttrSet();
894 10384 : if (pSet)
895 : {
896 : const SfxPoolItem* pItem;
897 7540 : if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false, &pItem))
898 : {
899 0 : if (pTableFormat)
900 : {
901 0 : pTableFormat->SetFormatAttr(*pItem);
902 : }
903 0 : rTextNode.ResetAttr(RES_BREAK);
904 0 : pSet = rTextNode.GetpSwAttrSet();
905 : }
906 :
907 7540 : if (pSet
908 7540 : && (SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false, &pItem))
909 7540 : && static_cast<SwFormatPageDesc const*>(pItem)->GetPageDesc())
910 : {
911 0 : if (pTableFormat)
912 : {
913 0 : pTableFormat->SetFormatAttr(*pItem);
914 : }
915 0 : rTextNode.ResetAttr(RES_PAGEDESC);
916 : }
917 : }
918 : }
919 :
920 : /**
921 : * balance lines in table, insert empty boxes so all lines have the size
922 : */
923 : static void
924 0 : lcl_BalanceTable(SwTable & rTable, size_t const nMaxBoxes,
925 : SwTableNode & rTableNd, SwTableBoxFormat & rBoxFormat, SwTextFormatColl & rTextColl,
926 : SwUndoTextToTable *const pUndo, std::vector<sal_uInt16> *const pPositions)
927 : {
928 0 : for (size_t n = 0; n < rTable.GetTabLines().size(); ++n)
929 : {
930 0 : SwTableLine *const pCurrLine = rTable.GetTabLines()[ n ];
931 0 : size_t const nBoxes = pCurrLine->GetTabBoxes().size();
932 0 : if (nMaxBoxes != nBoxes)
933 : {
934 0 : rTableNd.GetNodes().InsBoxen(&rTableNd, pCurrLine, &rBoxFormat, &rTextColl,
935 0 : 0, nBoxes, nMaxBoxes - nBoxes);
936 :
937 0 : if (pUndo)
938 : {
939 0 : for (size_t i = nBoxes; i < nMaxBoxes; ++i)
940 : {
941 0 : pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[i] );
942 : }
943 : }
944 :
945 : // if the first line is missing boxes, the width array is useless!
946 0 : if (!n && pPositions)
947 : {
948 0 : pPositions->clear();
949 : }
950 : }
951 : }
952 0 : }
953 :
954 : static void
955 0 : lcl_SetTableBoxWidths(SwTable & rTable, size_t const nMaxBoxes,
956 : SwTableBoxFormat & rBoxFormat, SwDoc & rDoc,
957 : std::vector<sal_uInt16> *const pPositions)
958 : {
959 0 : if (pPositions && !pPositions->empty())
960 : {
961 0 : SwTableLines& rLns = rTable.GetTabLines();
962 0 : sal_uInt16 nLastPos = 0;
963 0 : for (size_t n = 0; n < pPositions->size(); ++n)
964 : {
965 0 : SwTableBoxFormat *pNewFormat = rDoc.MakeTableBoxFormat();
966 : pNewFormat->SetFormatAttr(
967 0 : SwFormatFrmSize(ATT_VAR_SIZE, (*pPositions)[n] - nLastPos));
968 0 : for (size_t nTmpLine = 0; nTmpLine < rLns.size(); ++nTmpLine)
969 : {
970 : // Have to do an Add here, because the BoxFormat
971 : // is still needed by the caller
972 0 : pNewFormat->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] );
973 : }
974 :
975 0 : nLastPos = (*pPositions)[ n ];
976 : }
977 :
978 : // propagate size upwards from format, so the table gets the right size
979 : SAL_WARN_IF(rBoxFormat.HasWriterListeners(), "sw.core",
980 : "who is still registered in the format?");
981 0 : rBoxFormat.SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, nLastPos ));
982 : }
983 : else
984 : {
985 0 : size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
986 0 : rBoxFormat.SetFormatAttr(SwFormatFrmSize(ATT_VAR_SIZE, nWidth));
987 : }
988 0 : }
989 :
990 0 : SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh,
991 : SwTableFormat* pTableFormat,
992 : SwTableLineFormat* pLineFormat,
993 : SwTableBoxFormat* pBoxFormat,
994 : SwTextFormatColl* pTextColl,
995 : SwUndoTextToTable* pUndo )
996 : {
997 0 : if( rRange.aStart >= rRange.aEnd )
998 0 : return 0;
999 :
1000 0 : SwTableNode * pTableNd = new SwTableNode( rRange.aStart );
1001 0 : new SwEndNode( rRange.aEnd, *pTableNd );
1002 :
1003 0 : SwDoc* pDoc = GetDoc();
1004 0 : std::vector<sal_uInt16> aPosArr;
1005 0 : SwTable& rTable = pTableNd->GetTable();
1006 : SwTableBox* pBox;
1007 0 : sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
1008 :
1009 0 : SwNodeIndex aSttIdx( *pTableNd, 1 );
1010 0 : SwNodeIndex aEndIdx( rRange.aEnd, -1 );
1011 0 : for( nLines = 0, nBoxes = 0;
1012 0 : aSttIdx.GetIndex() < aEndIdx.GetIndex();
1013 : aSttIdx += 2, nLines++, nBoxes = 0 )
1014 : {
1015 0 : SwTextNode* pTextNd = aSttIdx.GetNode().GetTextNode();
1016 : OSL_ENSURE( pTextNd, "Only add TextNodes to the Table" );
1017 :
1018 0 : if( !nLines && 0x0b == cCh )
1019 : {
1020 0 : cCh = 0x09;
1021 :
1022 : // Get the separator's position from the first Node, in order for the Boxes to be set accordingly
1023 0 : SwTextFrmInfo aFInfo( static_cast<SwTextFrm*>(pTextNd->getLayoutFrm( pTextNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() )) );
1024 0 : if( aFInfo.IsOneLine() ) // only makes sense in this case
1025 : {
1026 0 : OUString const& rText(pTextNd->GetText());
1027 0 : for (sal_Int32 nChPos = 0; nChPos < rText.getLength(); ++nChPos)
1028 : {
1029 0 : if (rText[nChPos] == cCh)
1030 : {
1031 : aPosArr.push_back( static_cast<sal_uInt16>(
1032 0 : aFInfo.GetCharPos( nChPos+1, false )) );
1033 : }
1034 : }
1035 :
1036 : aPosArr.push_back(
1037 0 : static_cast<sal_uInt16>(aFInfo.GetFrm()->IsVertical() ?
1038 0 : aFInfo.GetFrm()->Prt().Bottom() :
1039 0 : aFInfo.GetFrm()->Prt().Right()) );
1040 :
1041 : }
1042 : }
1043 :
1044 0 : lcl_RemoveBreaks(*pTextNd, (0 == nLines) ? pTableFormat : 0);
1045 :
1046 : // Set the TableNode as StartNode for all TextNodes in the Table
1047 0 : pTextNd->pStartOfSection = pTableNd;
1048 :
1049 0 : SwTableLine* pLine = new SwTableLine( pLineFormat, 1, 0 );
1050 0 : rTable.GetTabLines().insert(rTable.GetTabLines().begin() + nLines, pLine);
1051 :
1052 : SwStartNode* pSttNd;
1053 0 : SwPosition aCntPos( aSttIdx, SwIndex( pTextNd ));
1054 :
1055 0 : const std::shared_ptr< sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1056 0 : pContentStore->Save( pDoc, aSttIdx.GetIndex(), pTextNd->GetText().getLength() );
1057 :
1058 0 : if( T2T_PARA != cCh )
1059 : {
1060 0 : for (sal_Int32 nChPos = 0; nChPos < pTextNd->GetText().getLength();)
1061 : {
1062 0 : if (pTextNd->GetText()[nChPos] == cCh)
1063 : {
1064 0 : aCntPos.nContent = nChPos;
1065 0 : SwContentNode* pNewNd = pTextNd->SplitContentNode( aCntPos );
1066 :
1067 0 : if( !pContentStore->Empty() )
1068 0 : pContentStore->Restore( *pNewNd, nChPos, nChPos + 1 );
1069 :
1070 : // Delete separator and correct search string
1071 0 : pTextNd->EraseText( aCntPos.nContent, 1 );
1072 0 : nChPos = 0;
1073 :
1074 : // Set the TableNode as StartNode for all TextNodes in the Table
1075 0 : const SwNodeIndex aTmpIdx( aCntPos.nNode, -1 );
1076 : pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
1077 0 : SwTableBoxStartNode );
1078 0 : new SwEndNode( aCntPos.nNode, *pSttNd );
1079 0 : pNewNd->pStartOfSection = pSttNd;
1080 :
1081 : // Assign Section to the Box
1082 0 : pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1083 0 : pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1084 : }
1085 : else
1086 : {
1087 0 : ++nChPos;
1088 : }
1089 : }
1090 : }
1091 :
1092 : // Now for the last substring
1093 0 : if( !pContentStore->Empty())
1094 0 : pContentStore->Restore( *pTextNd, pTextNd->GetText().getLength(), pTextNd->GetText().getLength()+1 );
1095 :
1096 0 : pSttNd = new SwStartNode( aCntPos.nNode, ND_STARTNODE, SwTableBoxStartNode );
1097 0 : const SwNodeIndex aTmpIdx( aCntPos.nNode, 1 );
1098 0 : new SwEndNode( aTmpIdx, *pSttNd );
1099 0 : pTextNd->pStartOfSection = pSttNd;
1100 :
1101 0 : pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1102 0 : pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1103 0 : if( nMaxBoxes < nBoxes )
1104 0 : nMaxBoxes = nBoxes;
1105 0 : }
1106 :
1107 : lcl_BalanceTable(rTable, nMaxBoxes, *pTableNd, *pBoxFormat, *pTextColl,
1108 0 : pUndo, &aPosArr);
1109 0 : rTable.RegisterToFormat(*pTableFormat);
1110 0 : lcl_SetTableBoxWidths(rTable, nMaxBoxes, *pBoxFormat, *pDoc, &aPosArr);
1111 :
1112 0 : return pTableNd;
1113 : }
1114 :
1115 604 : const SwTable* SwDoc::TextToTable( const std::vector< std::vector<SwNodeRange> >& rTableNodes )
1116 : {
1117 604 : if (rTableNodes.empty())
1118 0 : return NULL;
1119 :
1120 604 : const std::vector<SwNodeRange>& rFirstRange = *rTableNodes.begin();
1121 :
1122 604 : if (rFirstRange.empty())
1123 1 : return NULL;
1124 :
1125 603 : const std::vector<SwNodeRange>& rLastRange = *rTableNodes.rbegin();
1126 :
1127 603 : if (rLastRange.empty())
1128 0 : return NULL;
1129 :
1130 : /* Save first node in the selection if it is a content node. */
1131 603 : SwContentNode * pSttContentNd = rFirstRange.begin()->aStart.GetNode().GetContentNode();
1132 :
1133 603 : const SwNodeRange& rStartRange = *rFirstRange.begin();
1134 603 : const SwNodeRange& rEndRange = *rLastRange.rbegin();
1135 :
1136 : //!!! not necessarily TextNodes !!!
1137 603 : SwPaM aOriginal( rStartRange.aStart, rEndRange.aEnd );
1138 603 : const SwPosition *pStt = aOriginal.GetMark();
1139 603 : const SwPosition *pEnd = aOriginal.GetPoint();
1140 :
1141 603 : bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
1142 603 : if (bUndo)
1143 : {
1144 : // Do not add splitting the TextNode to the Undo history
1145 0 : GetIDocumentUndoRedo().DoUndo(false);
1146 : }
1147 :
1148 603 : ::PaMCorrAbs( aOriginal, *pEnd );
1149 :
1150 : // make sure that the range is on Node Edges
1151 1206 : SwNodeRange aRg( pStt->nNode, pEnd->nNode );
1152 603 : if( pStt->nContent.GetIndex() )
1153 0 : getIDocumentContentOperations().SplitNode( *pStt, false );
1154 :
1155 603 : bool bEndContent = 0 != pEnd->nContent.GetIndex();
1156 :
1157 : // Do not split at the End of a Line (except at the End of the Doc)
1158 603 : if( bEndContent )
1159 : {
1160 0 : if( pEnd->nNode.GetNode().GetContentNode()->Len() != pEnd->nContent.GetIndex()
1161 0 : || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
1162 : {
1163 0 : getIDocumentContentOperations().SplitNode( *pEnd, false );
1164 0 : --((SwNodeIndex&)pEnd->nNode);
1165 : ((SwIndex&)pEnd->nContent).Assign(
1166 0 : pEnd->nNode.GetNode().GetContentNode(), 0 );
1167 : // A Node and at the End?
1168 0 : if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
1169 0 : --aRg.aStart;
1170 : }
1171 : else
1172 0 : ++aRg.aEnd;
1173 : }
1174 :
1175 : assert(aRg.aEnd == pEnd->nNode);
1176 : assert(aRg.aStart == pStt->nNode);
1177 603 : if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
1178 : {
1179 : OSL_FAIL( "empty range" );
1180 70 : ++aRg.aEnd;
1181 : }
1182 :
1183 :
1184 : {
1185 : // TODO: this is not Undo-able - only good enough for file import
1186 603 : IDocumentRedlineAccess & rIDRA(getIDocumentRedlineAccess());
1187 603 : SwNodeIndex const prev(rTableNodes.begin()->begin()->aStart, -1);
1188 603 : SwNodeIndex const* pPrev(&prev);
1189 : // pPrev could point to non-textnode now
1190 3533 : for (auto row = rTableNodes.begin(); row != rTableNodes.end(); ++row)
1191 : {
1192 11153 : for (auto cell = row->begin(); cell != row->end(); ++cell)
1193 : {
1194 : assert(SwNodeIndex(*pPrev, +1) == cell->aStart);
1195 8223 : SwPaM pam(cell->aStart, 0, *pPrev,
1196 8223 : (pPrev->GetNode().IsContentNode())
1197 16446 : ? pPrev->GetNode().GetContentNode()->Len() : 0);
1198 8223 : rIDRA.SplitRedline(pam);
1199 8223 : pPrev = &cell->aEnd;
1200 8223 : }
1201 : }
1202 : // another one to break between last cell and node after table
1203 : SwPaM pam(SwNodeIndex(*pPrev, +1), 0, *pPrev,
1204 603 : (pPrev->GetNode().IsContentNode())
1205 1206 : ? pPrev->GetNode().GetContentNode()->Len() : 0);
1206 1206 : rIDRA.SplitRedline(pam);
1207 : }
1208 :
1209 : // We always use Upper to insert the Table
1210 1206 : SwNode2Layout aNode2Layout( aRg.aStart.GetNode() );
1211 :
1212 603 : GetIDocumentUndoRedo().DoUndo(bUndo);
1213 :
1214 : // Create the Box/Line/Table construct
1215 603 : SwTableBoxFormat* pBoxFormat = MakeTableBoxFormat();
1216 603 : SwTableLineFormat* pLineFormat = MakeTableLineFormat();
1217 603 : SwTableFormat* pTableFormat = MakeTableFrameFormat( GetUniqueTableName(), GetDfltFrameFormat() );
1218 :
1219 : // All Lines have a left-to-right Fill Order
1220 603 : pLineFormat->SetFormatAttr( SwFormatFillOrder( ATT_LEFT_TO_RIGHT ));
1221 : // The Table's SSize is USHRT_MAX
1222 603 : pTableFormat->SetFormatAttr( SwFormatFrmSize( ATT_VAR_SIZE, USHRT_MAX ));
1223 :
1224 : /* If the first node in the selection is a context node and if it
1225 : has an item FRAMEDIR set (no default) propagate the item to the
1226 : replacing table. */
1227 603 : if (pSttContentNd)
1228 : {
1229 591 : const SwAttrSet & aNdSet = pSttContentNd->GetSwAttrSet();
1230 591 : const SfxPoolItem *pItem = NULL;
1231 :
1232 1182 : if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
1233 591 : && pItem != NULL)
1234 : {
1235 541 : pTableFormat->SetFormatAttr( *pItem );
1236 : }
1237 : }
1238 :
1239 603 : SwTableNode* pTableNd = GetNodes().TextToTable(
1240 : rTableNodes, pTableFormat, pLineFormat, pBoxFormat,
1241 1206 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD )/*, pUndo*/ );
1242 :
1243 603 : SwTable& rNdTable = pTableNd->GetTable();
1244 :
1245 603 : if( !pBoxFormat->HasWriterListeners() )
1246 : {
1247 : // The Box's Formats already have the right size, we must only set
1248 : // the right Border/AutoFormat.
1249 0 : pTableFormat->SetFormatAttr( pBoxFormat->GetFrmSize() );
1250 0 : delete pBoxFormat;
1251 : }
1252 :
1253 603 : sal_uLong nIdx = pTableNd->GetIndex();
1254 603 : aNode2Layout.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
1255 :
1256 603 : getIDocumentState().SetModified();
1257 603 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
1258 1206 : return &rNdTable;
1259 : }
1260 :
1261 8262 : SwNodeRange * SwNodes::ExpandRangeForTableBox(const SwNodeRange & rRange)
1262 : {
1263 8262 : SwNodeRange * pResult = NULL;
1264 8262 : bool bChanged = false;
1265 :
1266 8262 : SwNodeIndex aNewStart = rRange.aStart;
1267 16524 : SwNodeIndex aNewEnd = rRange.aEnd;
1268 :
1269 16524 : SwNodeIndex aEndIndex = rRange.aEnd;
1270 16524 : SwNodeIndex aIndex = rRange.aStart;
1271 :
1272 17862 : while (aIndex < aEndIndex)
1273 : {
1274 1338 : SwNode& rNode = aIndex.GetNode();
1275 :
1276 1338 : if (rNode.IsStartNode())
1277 : {
1278 : // advance aIndex to the end node of this start node
1279 129 : SwNode * pEndNode = rNode.EndOfSectionNode();
1280 129 : aIndex = *pEndNode;
1281 :
1282 129 : if (aIndex > aNewEnd)
1283 : {
1284 0 : aNewEnd = aIndex;
1285 0 : bChanged = true;
1286 : }
1287 : }
1288 1209 : else if (rNode.IsEndNode())
1289 : {
1290 70 : SwNode * pStartNode = rNode.StartOfSectionNode();
1291 70 : SwNodeIndex aStartIndex = *pStartNode;
1292 :
1293 70 : if (aStartIndex < aNewStart)
1294 : {
1295 70 : aNewStart = aStartIndex;
1296 70 : bChanged = true;
1297 70 : }
1298 : }
1299 :
1300 1338 : if (aIndex < aEndIndex)
1301 1338 : ++aIndex;
1302 : }
1303 :
1304 8262 : SwNode * pNode = &aIndex.GetNode();
1305 16524 : while (pNode->IsEndNode())
1306 : {
1307 0 : SwNode * pStartNode = pNode->StartOfSectionNode();
1308 0 : SwNodeIndex aStartIndex(*pStartNode);
1309 0 : aNewStart = aStartIndex;
1310 0 : aNewEnd = aIndex;
1311 0 : bChanged = true;
1312 :
1313 0 : ++aIndex;
1314 0 : pNode = &aIndex.GetNode();
1315 0 : }
1316 :
1317 8262 : if (bChanged)
1318 35 : pResult = new SwNodeRange(aNewStart, aNewEnd);
1319 :
1320 16524 : return pResult;
1321 : }
1322 :
1323 : static void
1324 603 : lcl_SetTableBoxWidths2(SwTable & rTable, size_t const nMaxBoxes,
1325 : SwTableBoxFormat & rBoxFormat, SwDoc & rDoc)
1326 : {
1327 : // rhbz#820283, fdo#55462: set default box widths so table width is covered
1328 603 : SwTableLines & rLines = rTable.GetTabLines();
1329 3533 : for (size_t nTmpLine = 0; nTmpLine < rLines.size(); ++nTmpLine)
1330 : {
1331 2930 : SwTableBoxes & rBoxes = rLines[nTmpLine]->GetTabBoxes();
1332 2930 : size_t const nMissing = nMaxBoxes - rBoxes.size();
1333 2930 : if (nMissing)
1334 : {
1335 : // default width for box at the end of an incomplete line
1336 199 : SwTableBoxFormat *const pNewFormat = rDoc.MakeTableBoxFormat();
1337 199 : size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
1338 : pNewFormat->SetFormatAttr( SwFormatFrmSize(ATT_VAR_SIZE,
1339 199 : nWidth * (nMissing + 1)) );
1340 199 : pNewFormat->Add(rBoxes.back());
1341 : }
1342 : }
1343 603 : size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
1344 : // default width for all boxes not at the end of an incomplete line
1345 603 : rBoxFormat.SetFormatAttr(SwFormatFrmSize(ATT_VAR_SIZE, nWidth));
1346 603 : }
1347 :
1348 603 : SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes,
1349 : SwTableFormat* pTableFormat,
1350 : SwTableLineFormat* pLineFormat,
1351 : SwTableBoxFormat* pBoxFormat,
1352 : SwTextFormatColl* /*pTextColl*/ /*, SwUndo... pUndo*/ )
1353 : {
1354 603 : if( !rTableNodes.size() )
1355 0 : return 0;
1356 :
1357 603 : SwTableNode * pTableNd = new SwTableNode( rTableNodes.begin()->begin()->aStart );
1358 : //insert the end node after the last text node
1359 603 : SwNodeIndex aInsertIndex( rTableNodes.rbegin()->rbegin()->aEnd );
1360 603 : ++aInsertIndex;
1361 :
1362 : //!! ownership will be transferred in c-tor to SwNodes array.
1363 : //!! Thus no real problem here...
1364 603 : new SwEndNode( aInsertIndex, *pTableNd );
1365 :
1366 : #if OSL_DEBUG_LEVEL > 1
1367 : const SwNodeRange& rStartRange = *rTableNodes.begin()->begin();
1368 : const SwNodeRange& rEndRange = *rTableNodes.rbegin()->rbegin();
1369 : (void) rStartRange;
1370 : (void) rEndRange;
1371 : #endif
1372 :
1373 603 : SwDoc* pDoc = GetDoc();
1374 603 : SwTable& rTable = pTableNd->GetTable();
1375 : SwTableBox* pBox;
1376 603 : sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
1377 :
1378 1206 : SwNodeIndex aNodeIndex = rTableNodes.begin()->begin()->aStart;
1379 : // delete frames of all contained content nodes
1380 13217 : for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines )
1381 : {
1382 12614 : SwNode& rNode = aNodeIndex.GetNode();
1383 12614 : if( rNode.IsContentNode() )
1384 : {
1385 : lcl_RemoveBreaks(static_cast<SwContentNode&>(rNode),
1386 10384 : (0 == nLines) ? pTableFormat : 0);
1387 : }
1388 : }
1389 :
1390 603 : std::vector<std::vector < SwNodeRange > >::const_iterator aRowIter = rTableNodes.begin();
1391 10599 : for( nLines = 0, nBoxes = 0;
1392 7066 : aRowIter != rTableNodes.end();
1393 : ++aRowIter, nLines++, nBoxes = 0 )
1394 : {
1395 2930 : SwTableLine* pLine = new SwTableLine( pLineFormat, 1, 0 );
1396 2930 : rTable.GetTabLines().insert(rTable.GetTabLines().begin() + nLines, pLine);
1397 :
1398 2930 : std::vector< SwNodeRange >::const_iterator aCellIter = aRowIter->begin();
1399 :
1400 11153 : for( ; aCellIter != aRowIter->end(); ++aCellIter )
1401 : {
1402 8223 : const SwNodeIndex aTmpIdx( aCellIter->aStart, 0 );
1403 :
1404 16446 : SwNodeIndex aCellEndIdx(aCellIter->aEnd);
1405 8223 : ++aCellEndIdx;
1406 : SwStartNode* pSttNd = new SwStartNode( aTmpIdx, ND_STARTNODE,
1407 8223 : SwTableBoxStartNode );
1408 :
1409 : // Quotation of http://nabble.documentfoundation.org/Some-strange-lines-by-taking-a-look-at-the-bt-of-fdo-51916-tp3994561p3994639.html
1410 : // SwNode's constructor adds itself to the same SwNodes array as the other node (pSttNd).
1411 : // So this statement is only executed for the side-effect.
1412 8223 : new SwEndNode( aCellEndIdx, *pSttNd );
1413 :
1414 : //set the start node on all node of the current cell
1415 16446 : SwNodeIndex aCellNodeIdx = aCellIter->aStart;
1416 17580 : for(;aCellNodeIdx <= aCellIter->aEnd; ++aCellNodeIdx )
1417 : {
1418 9357 : aCellNodeIdx.GetNode().pStartOfSection = pSttNd;
1419 : //skip start/end node pairs
1420 9357 : if( aCellNodeIdx.GetNode().IsStartNode() )
1421 54 : aCellNodeIdx = SwNodeIndex( *aCellNodeIdx.GetNode().EndOfSectionNode() );
1422 : }
1423 :
1424 : // assign Section to the Box
1425 8223 : pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1426 8223 : pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1427 8223 : }
1428 2930 : if( nMaxBoxes < nBoxes )
1429 660 : nMaxBoxes = nBoxes;
1430 : }
1431 :
1432 603 : rTable.RegisterToFormat(*pTableFormat);
1433 603 : lcl_SetTableBoxWidths2(rTable, nMaxBoxes, *pBoxFormat, *pDoc);
1434 :
1435 1206 : return pTableNd;
1436 : }
1437 :
1438 : /**
1439 : * Table to Text
1440 : */
1441 0 : bool SwDoc::TableToText( const SwTableNode* pTableNd, sal_Unicode cCh )
1442 : {
1443 0 : if( !pTableNd )
1444 0 : return false;
1445 :
1446 : // #i34471#
1447 : // If this is trigged by SwUndoTableToText::Repeat() nobody ever deleted
1448 : // the table cursor.
1449 0 : SwEditShell* pESh = GetEditShell();
1450 0 : if( pESh && pESh->IsTableMode() )
1451 0 : pESh->ClearMark();
1452 :
1453 0 : SwNodeRange aRg( *pTableNd, 0, *pTableNd->EndOfSectionNode() );
1454 0 : SwUndoTableToText* pUndo = 0;
1455 0 : SwNodeRange* pUndoRg = 0;
1456 0 : if (GetIDocumentUndoRedo().DoesUndo())
1457 : {
1458 0 : GetIDocumentUndoRedo().ClearRedo();
1459 0 : pUndoRg = new SwNodeRange( aRg.aStart, -1, aRg.aEnd, +1 );
1460 0 : pUndo = new SwUndoTableToText( pTableNd->GetTable(), cCh );
1461 : }
1462 :
1463 0 : SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
1464 0 : aMsgHint.eFlags = TBL_BOXNAME;
1465 0 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1466 :
1467 0 : bool bRet = GetNodes().TableToText( aRg, cCh, pUndo );
1468 0 : if( pUndoRg )
1469 : {
1470 0 : ++pUndoRg->aStart;
1471 0 : --pUndoRg->aEnd;
1472 0 : pUndo->SetRange( *pUndoRg );
1473 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
1474 0 : delete pUndoRg;
1475 : }
1476 :
1477 0 : if( bRet )
1478 0 : getIDocumentState().SetModified();
1479 :
1480 0 : return bRet;
1481 : }
1482 :
1483 : /**
1484 : * Use the ForEach method from PtrArray to recreate Text from a Table.
1485 : * The Boxes can also contain Lines!
1486 : */
1487 : struct _DelTabPara
1488 : {
1489 : SwTextNode* pLastNd;
1490 : SwNodes& rNds;
1491 : SwUndoTableToText* pUndo;
1492 : sal_Unicode cCh;
1493 :
1494 0 : _DelTabPara( SwNodes& rNodes, sal_Unicode cChar, SwUndoTableToText* pU ) :
1495 0 : pLastNd(0), rNds( rNodes ), pUndo( pU ), cCh( cChar ) {}
1496 0 : _DelTabPara( const _DelTabPara& rPara ) :
1497 : pLastNd(rPara.pLastNd), rNds( rPara.rNds ),
1498 0 : pUndo( rPara.pUndo ), cCh( rPara.cCh ) {}
1499 : };
1500 :
1501 : // Forward declare so that the Lines and Boxes can use recursion
1502 : static void lcl_DelBox( SwTableBox* pBox, _DelTabPara* pDelPara );
1503 :
1504 0 : static void lcl_DelLine( SwTableLine* pLine, _DelTabPara* pPara )
1505 : {
1506 : assert(pPara && "The parameters are missing!");
1507 0 : _DelTabPara aPara( *pPara );
1508 0 : for( SwTableBoxes::iterator it = pLine->GetTabBoxes().begin();
1509 0 : it != pLine->GetTabBoxes().end(); ++it)
1510 0 : lcl_DelBox(*it, &aPara );
1511 0 : if( pLine->GetUpper() ) // Is there a parent Box?
1512 : // Return the last TextNode
1513 0 : pPara->pLastNd = aPara.pLastNd;
1514 0 : }
1515 :
1516 0 : static void lcl_DelBox( SwTableBox* pBox, _DelTabPara* pDelPara )
1517 : {
1518 : assert(pDelPara && "The parameters are missing");
1519 :
1520 : // Delete the Box's Lines
1521 0 : if( !pBox->GetTabLines().empty() )
1522 : {
1523 0 : for( SwTableLine* pLine : pBox->GetTabLines() )
1524 0 : lcl_DelLine( pLine, pDelPara );
1525 : }
1526 : else
1527 : {
1528 0 : SwDoc* pDoc = pDelPara->rNds.GetDoc();
1529 0 : SwNodeRange aDelRg( *pBox->GetSttNd(), 0,
1530 0 : *pBox->GetSttNd()->EndOfSectionNode() );
1531 : // Delete the Section
1532 0 : pDelPara->rNds.SectionUp( &aDelRg );
1533 : const SwTextNode* pCurTextNd;
1534 0 : if( T2T_PARA != pDelPara->cCh && pDelPara->pLastNd &&
1535 0 : 0 != ( pCurTextNd = aDelRg.aStart.GetNode().GetTextNode() ))
1536 : {
1537 : // Join the current text node with the last from the previous box if possible
1538 0 : sal_uLong nNdIdx = aDelRg.aStart.GetIndex();
1539 0 : --aDelRg.aStart;
1540 0 : if( pDelPara->pLastNd == &aDelRg.aStart.GetNode() )
1541 : {
1542 : // Inserting the separator
1543 : SwIndex aCntIdx( pDelPara->pLastNd,
1544 0 : pDelPara->pLastNd->GetText().getLength());
1545 : pDelPara->pLastNd->InsertText( OUString(pDelPara->cCh), aCntIdx,
1546 0 : SwInsertFlags::EMPTYEXPAND );
1547 0 : if( pDelPara->pUndo )
1548 : pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex(),
1549 0 : aCntIdx.GetIndex() );
1550 :
1551 0 : const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1552 0 : const sal_Int32 nOldTextLen = aCntIdx.GetIndex();
1553 0 : pContentStore->Save( pDoc, nNdIdx, pCurTextNd->GetText().getLength() );
1554 :
1555 0 : pDelPara->pLastNd->JoinNext();
1556 :
1557 0 : if( !pContentStore->Empty() )
1558 0 : pContentStore->Restore( pDoc, pDelPara->pLastNd->GetIndex(), nOldTextLen );
1559 : }
1560 0 : else if( pDelPara->pUndo )
1561 : {
1562 0 : ++aDelRg.aStart;
1563 0 : pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex() );
1564 : }
1565 : }
1566 0 : else if( pDelPara->pUndo )
1567 0 : pDelPara->pUndo->AddBoxPos( *pDoc, aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1568 0 : --aDelRg.aEnd;
1569 0 : pDelPara->pLastNd = aDelRg.aEnd.GetNode().GetTextNode();
1570 :
1571 : // Do not take over the NumberFormatting's adjustment
1572 0 : if( pDelPara->pLastNd && pDelPara->pLastNd->HasSwAttrSet() )
1573 0 : pDelPara->pLastNd->ResetAttr( RES_PARATR_ADJUST );
1574 : }
1575 0 : }
1576 :
1577 0 : bool SwNodes::TableToText( const SwNodeRange& rRange, sal_Unicode cCh,
1578 : SwUndoTableToText* pUndo )
1579 : {
1580 : // Is a Table selected?
1581 : SwTableNode* pTableNd;
1582 0 : if( rRange.aStart.GetIndex() >= rRange.aEnd.GetIndex() ||
1583 0 : 0 == ( pTableNd = rRange.aStart.GetNode().GetTableNode()) ||
1584 0 : &rRange.aEnd.GetNode() != pTableNd->EndOfSectionNode() )
1585 0 : return false;
1586 :
1587 : // If the Table was alone in a Section, create the Frames via the Table's Upper
1588 0 : SwNode2Layout* pNode2Layout = 0;
1589 0 : SwNodeIndex aFrmIdx( rRange.aStart );
1590 0 : SwNode* pFrmNd = FindPrvNxtFrmNode( aFrmIdx, &rRange.aEnd.GetNode() );
1591 0 : if( !pFrmNd )
1592 : // Collect all Uppers
1593 0 : pNode2Layout = new SwNode2Layout( *pTableNd );
1594 :
1595 : // Delete the Frames
1596 0 : pTableNd->DelFrms();
1597 :
1598 : // "Delete" the Table and merge all Lines/Boxes
1599 0 : _DelTabPara aDelPara( *this, cCh, pUndo );
1600 0 : for( SwTableLine *pLine : pTableNd->pTable->GetTabLines() )
1601 0 : lcl_DelLine( pLine, &aDelPara );
1602 :
1603 : // We just created a TextNode with fitting separator for every TableLine.
1604 : // Now we only need to delete the TableSection and create the Frames for the
1605 : // new TextNode.
1606 0 : SwNodeRange aDelRg( rRange.aStart, rRange.aEnd );
1607 :
1608 : // If the Table has PageDesc/Break Attributes, carry them over to the
1609 : // first Text Node
1610 : {
1611 : // What about UNDO?
1612 0 : const SfxItemSet& rTableSet = pTableNd->pTable->GetFrameFormat()->GetAttrSet();
1613 : const SfxPoolItem *pBreak, *pDesc;
1614 0 : if( SfxItemState::SET != rTableSet.GetItemState( RES_PAGEDESC, false, &pDesc ))
1615 0 : pDesc = 0;
1616 0 : if( SfxItemState::SET != rTableSet.GetItemState( RES_BREAK, false, &pBreak ))
1617 0 : pBreak = 0;
1618 :
1619 0 : if( pBreak || pDesc )
1620 : {
1621 0 : SwNodeIndex aIdx( *pTableNd );
1622 0 : SwContentNode* pCNd = GoNext( &aIdx );
1623 0 : if( pBreak )
1624 0 : pCNd->SetAttr( *pBreak );
1625 0 : if( pDesc )
1626 0 : pCNd->SetAttr( *pDesc );
1627 : }
1628 : }
1629 :
1630 0 : SectionUp( &aDelRg ); // Delete this Section and by that the Table
1631 : // #i28006#
1632 0 : sal_uLong nStt = aDelRg.aStart.GetIndex(), nEnd = aDelRg.aEnd.GetIndex();
1633 0 : if( !pFrmNd )
1634 : {
1635 : pNode2Layout->RestoreUpperFrms( *this,
1636 0 : aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1637 0 : delete pNode2Layout;
1638 : }
1639 : else
1640 : {
1641 : SwContentNode *pCNd;
1642 : SwSectionNode *pSNd;
1643 0 : while( aDelRg.aStart.GetIndex() < nEnd )
1644 : {
1645 0 : if( 0 != ( pCNd = aDelRg.aStart.GetNode().GetContentNode()))
1646 : {
1647 0 : if( pFrmNd->IsContentNode() )
1648 0 : static_cast<SwContentNode*>(pFrmNd)->MakeFrms( *pCNd );
1649 0 : else if( pFrmNd->IsTableNode() )
1650 0 : static_cast<SwTableNode*>(pFrmNd)->MakeFrms( aDelRg.aStart );
1651 0 : else if( pFrmNd->IsSectionNode() )
1652 0 : static_cast<SwSectionNode*>(pFrmNd)->MakeFrms( aDelRg.aStart );
1653 0 : pFrmNd = pCNd;
1654 : }
1655 0 : else if( 0 != ( pSNd = aDelRg.aStart.GetNode().GetSectionNode()))
1656 : {
1657 0 : if( !pSNd->GetSection().IsHidden() && !pSNd->IsContentHidden() )
1658 : {
1659 0 : pSNd->MakeFrms( &aFrmIdx, &aDelRg.aEnd );
1660 0 : pFrmNd = pSNd;
1661 0 : break;
1662 : }
1663 0 : aDelRg.aStart = *pSNd->EndOfSectionNode();
1664 : }
1665 0 : ++aDelRg.aStart;
1666 : }
1667 : }
1668 :
1669 : // #i28006# Fly frames have to be restored even if the table was
1670 : // #alone in the section
1671 0 : const SwFrameFormats& rFlyArr = *GetDoc()->GetSpzFrameFormats();
1672 0 : for( auto pFly : rFlyArr )
1673 : {
1674 0 : SwFrameFormat *const pFormat = pFly;
1675 0 : const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1676 0 : SwPosition const*const pAPos = rAnchor.GetContentAnchor();
1677 0 : if (pAPos &&
1678 0 : ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1679 0 : (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
1680 0 : nStt <= pAPos->nNode.GetIndex() &&
1681 0 : pAPos->nNode.GetIndex() < nEnd )
1682 : {
1683 0 : pFormat->MakeFrms();
1684 : }
1685 : }
1686 :
1687 0 : return true;
1688 : }
1689 :
1690 : /**
1691 : * Inserting Columns/Rows
1692 : */
1693 0 : bool SwDoc::InsertCol( const SwCursor& rCursor, sal_uInt16 nCnt, bool bBehind )
1694 : {
1695 0 : if( !::CheckSplitCells( rCursor, nCnt + 1, nsSwTableSearchType::TBLSEARCH_COL ) )
1696 0 : return false;
1697 :
1698 : // Find the Boxes via the Layout
1699 0 : SwSelBoxes aBoxes;
1700 0 : ::GetTableSel( rCursor, aBoxes, nsSwTableSearchType::TBLSEARCH_COL );
1701 :
1702 0 : bool bRet = false;
1703 0 : if( !aBoxes.empty() )
1704 0 : bRet = InsertCol( aBoxes, nCnt, bBehind );
1705 0 : return bRet;
1706 : }
1707 :
1708 0 : bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
1709 : {
1710 : OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1711 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1712 0 : if( !pTableNd )
1713 0 : return false;
1714 :
1715 0 : SwTable& rTable = pTableNd->GetTable();
1716 0 : if( rTable.ISA( SwDDETable ))
1717 0 : return false;
1718 :
1719 0 : SwTableSortBoxes aTmpLst;
1720 0 : SwUndoTableNdsChg* pUndo = 0;
1721 0 : if (GetIDocumentUndoRedo().DoesUndo())
1722 : {
1723 : pUndo = new SwUndoTableNdsChg( UNDO_TABLE_INSCOL, rBoxes, *pTableNd,
1724 0 : 0, 0, nCnt, bBehind, false );
1725 0 : aTmpLst.insert( rTable.GetTabSortBoxes() );
1726 : }
1727 :
1728 0 : bool bRet(false);
1729 : {
1730 0 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1731 :
1732 0 : SwTableFormulaUpdate aMsgHint( &rTable );
1733 0 : aMsgHint.eFlags = TBL_BOXPTR;
1734 0 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1735 :
1736 0 : bRet = rTable.InsertCol( this, rBoxes, nCnt, bBehind );
1737 0 : if (bRet)
1738 : {
1739 0 : getIDocumentState().SetModified();
1740 0 : ::ClearFEShellTabCols();
1741 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
1742 0 : }
1743 : }
1744 :
1745 0 : if( pUndo )
1746 : {
1747 0 : if( bRet )
1748 : {
1749 0 : pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
1750 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
1751 : }
1752 : else
1753 0 : delete pUndo;
1754 : }
1755 0 : return bRet;
1756 : }
1757 :
1758 1 : bool SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, bool bBehind )
1759 : {
1760 : // Find the Boxes via the Layout
1761 1 : SwSelBoxes aBoxes;
1762 1 : GetTableSel( rCursor, aBoxes, nsSwTableSearchType::TBLSEARCH_ROW );
1763 :
1764 1 : bool bRet = false;
1765 1 : if( !aBoxes.empty() )
1766 1 : bRet = InsertRow( aBoxes, nCnt, bBehind );
1767 1 : return bRet;
1768 : }
1769 :
1770 3 : bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
1771 : {
1772 : OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1773 3 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1774 3 : if( !pTableNd )
1775 0 : return false;
1776 :
1777 3 : SwTable& rTable = pTableNd->GetTable();
1778 3 : if( rTable.ISA( SwDDETable ))
1779 0 : return false;
1780 :
1781 3 : SwTableSortBoxes aTmpLst;
1782 3 : SwUndoTableNdsChg* pUndo = 0;
1783 3 : if (GetIDocumentUndoRedo().DoesUndo())
1784 : {
1785 : pUndo = new SwUndoTableNdsChg( UNDO_TABLE_INSROW,rBoxes, *pTableNd,
1786 3 : 0, 0, nCnt, bBehind, false );
1787 3 : aTmpLst.insert( rTable.GetTabSortBoxes() );
1788 : }
1789 :
1790 3 : bool bRet(false);
1791 : {
1792 3 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1793 :
1794 6 : SwTableFormulaUpdate aMsgHint( &rTable );
1795 3 : aMsgHint.eFlags = TBL_BOXPTR;
1796 3 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1797 :
1798 3 : bRet = rTable.InsertRow( this, rBoxes, nCnt, bBehind );
1799 3 : if (bRet)
1800 : {
1801 3 : getIDocumentState().SetModified();
1802 3 : ::ClearFEShellTabCols();
1803 3 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
1804 3 : }
1805 : }
1806 :
1807 3 : if( pUndo )
1808 : {
1809 3 : if( bRet )
1810 : {
1811 3 : pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
1812 3 : GetIDocumentUndoRedo().AppendUndo( pUndo );
1813 : }
1814 : else
1815 0 : delete pUndo;
1816 : }
1817 3 : return bRet;
1818 :
1819 : }
1820 :
1821 : /**
1822 : * Deleting Columns/Rows
1823 : */
1824 1 : bool SwDoc::DeleteRow( const SwCursor& rCursor )
1825 : {
1826 : // Find the Boxes via the Layout
1827 1 : SwSelBoxes aBoxes;
1828 1 : GetTableSel( rCursor, aBoxes, nsSwTableSearchType::TBLSEARCH_ROW );
1829 1 : if( ::HasProtectedCells( aBoxes ))
1830 0 : return false;
1831 :
1832 : // Remove the Crsr from the to-be-deleted Section.
1833 : // The Cursor is placed after the table, except for
1834 : // - when there's another Line, we place it in that one
1835 : // - when a Line precedes it, we place it in that one
1836 : {
1837 1 : SwTableNode* pTableNd = rCursor.GetNode().FindTableNode();
1838 :
1839 1 : if( pTableNd->GetTable().ISA( SwDDETable ))
1840 0 : return false;
1841 :
1842 : // Find all Boxes/Lines
1843 1 : _FndBox aFndBox( 0, 0 );
1844 : {
1845 1 : _FndPara aPara( aBoxes, &aFndBox );
1846 1 : ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
1847 : }
1848 :
1849 1 : if( !aFndBox.GetLines().size() )
1850 0 : return false;
1851 :
1852 1 : SwEditShell* pESh = GetEditShell();
1853 1 : if( pESh )
1854 : {
1855 1 : pESh->KillPams();
1856 : // FIXME: Actually we should be interating over all Shells!
1857 : }
1858 :
1859 1 : _FndBox* pFndBox = &aFndBox;
1860 3 : while( 1 == pFndBox->GetLines().size() &&
1861 1 : 1 == pFndBox->GetLines().front().GetBoxes().size() )
1862 : {
1863 0 : _FndBox *const pTmp = & pFndBox->GetLines().front().GetBoxes()[0];
1864 0 : if( pTmp->GetBox()->GetSttNd() )
1865 0 : break; // Else it gets too far
1866 0 : pFndBox = pTmp;
1867 : }
1868 :
1869 1 : SwTableLine* pDelLine = pFndBox->GetLines().back().GetLine();
1870 1 : SwTableBox* pDelBox = pDelLine->GetTabBoxes().back();
1871 2 : while( !pDelBox->GetSttNd() )
1872 : {
1873 0 : SwTableLine* pLn = pDelBox->GetTabLines()[
1874 0 : pDelBox->GetTabLines().size()-1 ];
1875 0 : pDelBox = pLn->GetTabBoxes().back();
1876 : }
1877 1 : SwTableBox* pNextBox = pDelLine->FindNextBox( pTableNd->GetTable(),
1878 1 : pDelBox, true );
1879 3 : while( pNextBox &&
1880 1 : pNextBox->GetFrameFormat()->GetProtect().IsContentProtected() )
1881 0 : pNextBox = pNextBox->FindNextBox( pTableNd->GetTable(), pNextBox );
1882 :
1883 1 : if( !pNextBox ) // No succeeding Boxes? Then take the preceding one
1884 : {
1885 0 : pDelLine = pFndBox->GetLines().front().GetLine();
1886 0 : pDelBox = pDelLine->GetTabBoxes()[ 0 ];
1887 0 : while( !pDelBox->GetSttNd() )
1888 0 : pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
1889 0 : pNextBox = pDelLine->FindPreviousBox( pTableNd->GetTable(),
1890 0 : pDelBox, true );
1891 0 : while( pNextBox &&
1892 0 : pNextBox->GetFrameFormat()->GetProtect().IsContentProtected() )
1893 0 : pNextBox = pNextBox->FindPreviousBox( pTableNd->GetTable(), pNextBox );
1894 : }
1895 :
1896 : sal_uLong nIdx;
1897 1 : if( pNextBox ) // Place the Cursor here
1898 1 : nIdx = pNextBox->GetSttIdx() + 1;
1899 : else // Else after the Table
1900 0 : nIdx = pTableNd->EndOfSectionIndex() + 1;
1901 :
1902 2 : SwNodeIndex aIdx( GetNodes(), nIdx );
1903 1 : SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
1904 1 : if( !pCNd )
1905 0 : pCNd = GetNodes().GoNext( &aIdx );
1906 :
1907 1 : if( pCNd )
1908 : {
1909 : // Change the Shell's Cursor or the one passed?
1910 1 : SwPaM* pPam = const_cast<SwPaM*>(static_cast<SwPaM const *>(&rCursor));
1911 1 : pPam->GetPoint()->nNode = aIdx;
1912 1 : pPam->GetPoint()->nContent.Assign( pCNd, 0 );
1913 1 : pPam->SetMark(); // Both want a part of it
1914 1 : pPam->DeleteMark();
1915 1 : }
1916 : }
1917 :
1918 : // Thus delete the Rows
1919 2 : GetIDocumentUndoRedo().StartUndo(UNDO_ROW_DELETE, NULL);
1920 1 : bool bResult = DeleteRowCol( aBoxes );
1921 1 : GetIDocumentUndoRedo().EndUndo(UNDO_ROW_DELETE, NULL);
1922 :
1923 1 : return bResult;
1924 : }
1925 :
1926 0 : bool SwDoc::DeleteCol( const SwCursor& rCursor )
1927 : {
1928 : // Find the Boxes via the Layout
1929 0 : SwSelBoxes aBoxes;
1930 0 : GetTableSel( rCursor, aBoxes, nsSwTableSearchType::TBLSEARCH_COL );
1931 0 : if( ::HasProtectedCells( aBoxes ))
1932 0 : return false;
1933 :
1934 : // The Cursors need to be removed from the to-be-deleted range.
1935 : // Always place them after/on top of the Table; they are always set
1936 : // to the old position via the document position.
1937 0 : SwEditShell* pESh = GetEditShell();
1938 0 : if( pESh )
1939 : {
1940 0 : const SwNode* pNd = rCursor.GetNode().FindTableBoxStartNode();
1941 0 : pESh->ParkCrsr( SwNodeIndex( *pNd ) );
1942 : }
1943 :
1944 : // Thus delete the Columns
1945 0 : GetIDocumentUndoRedo().StartUndo(UNDO_COL_DELETE, NULL);
1946 0 : bool bResult = DeleteRowCol( aBoxes, true );
1947 0 : GetIDocumentUndoRedo().EndUndo(UNDO_COL_DELETE, NULL);
1948 :
1949 0 : return bResult;
1950 : }
1951 :
1952 4 : bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
1953 : {
1954 4 : if( ::HasProtectedCells( rBoxes ))
1955 0 : return false;
1956 :
1957 : OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1958 4 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1959 4 : if( !pTableNd )
1960 0 : return false;
1961 :
1962 4 : if( pTableNd->GetTable().ISA( SwDDETable ))
1963 0 : return false;
1964 :
1965 4 : ::ClearFEShellTabCols();
1966 4 : SwSelBoxes aSelBoxes( rBoxes );
1967 4 : SwTable &rTable = pTableNd->GetTable();
1968 4 : long nMin = 0;
1969 4 : long nMax = 0;
1970 4 : if( rTable.IsNewModel() )
1971 : {
1972 4 : if( bColumn )
1973 0 : rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax );
1974 : else
1975 4 : rTable.FindSuperfluousRows( aSelBoxes );
1976 : }
1977 :
1978 : // Are we deleting the whole Table?
1979 4 : const sal_uLong nTmpIdx1 = pTableNd->GetIndex();
1980 4 : const sal_uLong nTmpIdx2 = aSelBoxes.back()->GetSttNd()->EndOfSectionIndex() + 1;
1981 11 : if( pTableNd->GetTable().GetTabSortBoxes().size() == aSelBoxes.size() &&
1982 7 : aSelBoxes[0]->GetSttIdx()-1 == nTmpIdx1 &&
1983 3 : nTmpIdx2 == pTableNd->EndOfSectionIndex() )
1984 : {
1985 3 : bool bNewTextNd = false;
1986 : // Is it alone in a FlyFrame?
1987 3 : SwNodeIndex aIdx( *pTableNd, -1 );
1988 3 : const SwStartNode* pSttNd = aIdx.GetNode().GetStartNode();
1989 3 : if( pSttNd )
1990 : {
1991 3 : const sal_uLong nTableEnd = pTableNd->EndOfSectionIndex() + 1;
1992 3 : const sal_uLong nSectEnd = pSttNd->EndOfSectionIndex();
1993 3 : if( nTableEnd == nSectEnd )
1994 : {
1995 0 : if( SwFlyStartNode == pSttNd->GetStartNodeType() )
1996 : {
1997 0 : SwFrameFormat* pFormat = pSttNd->GetFlyFormat();
1998 0 : if( pFormat )
1999 : {
2000 : // That's the FlyFormat we're looking for
2001 0 : getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
2002 0 : return true;
2003 : }
2004 : }
2005 : // No Fly? Thus Header or Footer: always leave a TextNode
2006 : // We can forget about Undo then!
2007 0 : bNewTextNd = true;
2008 : }
2009 : }
2010 :
2011 : // No Fly? Then it is a Header or Footer, so keep always a TextNode
2012 3 : ++aIdx;
2013 3 : if (GetIDocumentUndoRedo().DoesUndo())
2014 : {
2015 3 : GetIDocumentUndoRedo().ClearRedo();
2016 3 : SwPaM aPaM( *pTableNd->EndOfSectionNode(), aIdx.GetNode() );
2017 :
2018 3 : if( bNewTextNd )
2019 : {
2020 0 : const SwNodeIndex aTmpIdx( *pTableNd->EndOfSectionNode(), 1 );
2021 0 : GetNodes().MakeTextNode( aTmpIdx,
2022 0 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
2023 : }
2024 :
2025 : // Save the cursors (UNO and otherwise)
2026 6 : SwPaM aSavePaM( SwNodeIndex( *pTableNd->EndOfSectionNode() ) );
2027 3 : if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
2028 : {
2029 0 : *aSavePaM.GetMark() = SwPosition( *pTableNd );
2030 0 : aSavePaM.Move( fnMoveBackward, fnGoNode );
2031 : }
2032 : {
2033 3 : SwPaM const tmpPaM(*pTableNd, *pTableNd->EndOfSectionNode());
2034 3 : ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2035 : }
2036 :
2037 : // Move hard PageBreaks to the succeeding Node
2038 3 : bool bSavePageBreak = false, bSavePageDesc = false;
2039 3 : sal_uLong nNextNd = pTableNd->EndOfSectionIndex()+1;
2040 3 : SwContentNode* pNextNd = GetNodes()[ nNextNd ]->GetContentNode();
2041 3 : if( pNextNd )
2042 : {
2043 : {
2044 3 : SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
2045 : const SfxPoolItem *pItem;
2046 3 : if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
2047 3 : false, &pItem ) )
2048 : {
2049 0 : pNextNd->SetAttr( *pItem );
2050 0 : bSavePageDesc = true;
2051 : }
2052 :
2053 3 : if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
2054 3 : false, &pItem ) )
2055 : {
2056 0 : pNextNd->SetAttr( *pItem );
2057 0 : bSavePageBreak = true;
2058 : }
2059 : }
2060 : }
2061 3 : SwUndoDelete* pUndo = new SwUndoDelete( aPaM );
2062 3 : if( bNewTextNd )
2063 0 : pUndo->SetTableDelLastNd();
2064 3 : pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
2065 3 : pUndo->SetTableName(pTableNd->GetTable().GetFrameFormat()->GetName());
2066 6 : GetIDocumentUndoRedo().AppendUndo( pUndo );
2067 : }
2068 : else
2069 : {
2070 0 : if( bNewTextNd )
2071 : {
2072 0 : const SwNodeIndex aTmpIdx( *pTableNd->EndOfSectionNode(), 1 );
2073 0 : GetNodes().MakeTextNode( aTmpIdx,
2074 0 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
2075 : }
2076 :
2077 : // Save the cursors (UNO and otherwise)
2078 0 : SwPaM aSavePaM( SwNodeIndex( *pTableNd->EndOfSectionNode() ) );
2079 0 : if( ! aSavePaM.Move( fnMoveForward, fnGoNode ) )
2080 : {
2081 0 : *aSavePaM.GetMark() = SwPosition( *pTableNd );
2082 0 : aSavePaM.Move( fnMoveBackward, fnGoNode );
2083 : }
2084 : {
2085 0 : SwPaM const tmpPaM(*pTableNd, *pTableNd->EndOfSectionNode());
2086 0 : ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2087 : }
2088 :
2089 : // Move hard PageBreaks to the succeeding Node
2090 0 : SwContentNode* pNextNd = GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]->GetContentNode();
2091 0 : if( pNextNd )
2092 : {
2093 0 : SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
2094 : const SfxPoolItem *pItem;
2095 0 : if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
2096 0 : false, &pItem ) )
2097 0 : pNextNd->SetAttr( *pItem );
2098 :
2099 0 : if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
2100 0 : false, &pItem ) )
2101 0 : pNextNd->SetAttr( *pItem );
2102 : }
2103 :
2104 0 : pTableNd->DelFrms();
2105 0 : getIDocumentContentOperations().DeleteSection( pTableNd );
2106 : }
2107 3 : getIDocumentState().SetModified();
2108 3 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
2109 3 : return true;
2110 : }
2111 :
2112 1 : SwUndoTableNdsChg* pUndo = 0;
2113 1 : if (GetIDocumentUndoRedo().DoesUndo())
2114 : {
2115 : pUndo = new SwUndoTableNdsChg( UNDO_TABLE_DELBOX, aSelBoxes, *pTableNd,
2116 1 : nMin, nMax, 0, false, false );
2117 : }
2118 :
2119 1 : bool bRet(false);
2120 : {
2121 1 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2122 :
2123 2 : SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
2124 1 : aMsgHint.eFlags = TBL_BOXPTR;
2125 1 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2126 :
2127 1 : if (rTable.IsNewModel())
2128 : {
2129 1 : if (bColumn)
2130 0 : rTable.PrepareDeleteCol( nMin, nMax );
2131 1 : rTable.FindSuperfluousRows( aSelBoxes );
2132 1 : if (pUndo)
2133 1 : pUndo->ReNewBoxes( aSelBoxes );
2134 : }
2135 1 : bRet = rTable.DeleteSel( this, aSelBoxes, 0, pUndo, true, true );
2136 1 : if (bRet)
2137 : {
2138 1 : getIDocumentState().SetModified();
2139 1 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
2140 1 : }
2141 : }
2142 :
2143 1 : if( pUndo )
2144 : {
2145 1 : if( bRet )
2146 : {
2147 1 : GetIDocumentUndoRedo().AppendUndo( pUndo );
2148 : }
2149 : else
2150 0 : delete pUndo;
2151 : }
2152 :
2153 1 : return bRet;
2154 : }
2155 :
2156 : /**
2157 : * Split up/merge Boxes in the Table
2158 : */
2159 2 : bool SwDoc::SplitTable( const SwSelBoxes& rBoxes, bool bVert, sal_uInt16 nCnt,
2160 : bool bSameHeight )
2161 : {
2162 : OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box list" );
2163 2 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
2164 2 : if( !pTableNd )
2165 0 : return false;
2166 :
2167 2 : SwTable& rTable = pTableNd->GetTable();
2168 2 : if( rTable.ISA( SwDDETable ))
2169 0 : return false;
2170 :
2171 2 : std::vector<sal_uLong> aNdsCnts;
2172 4 : SwTableSortBoxes aTmpLst;
2173 2 : SwUndoTableNdsChg* pUndo = 0;
2174 2 : if (GetIDocumentUndoRedo().DoesUndo())
2175 : {
2176 : pUndo = new SwUndoTableNdsChg( UNDO_TABLE_SPLIT, rBoxes, *pTableNd, 0, 0,
2177 2 : nCnt, bVert, bSameHeight );
2178 :
2179 2 : aTmpLst.insert( rTable.GetTabSortBoxes() );
2180 2 : if( !bVert )
2181 : {
2182 2 : for (size_t n = 0; n < rBoxes.size(); ++n)
2183 : {
2184 1 : const SwStartNode* pSttNd = rBoxes[ n ]->GetSttNd();
2185 2 : aNdsCnts.push_back( pSttNd->EndOfSectionIndex() -
2186 2 : pSttNd->GetIndex() );
2187 : }
2188 : }
2189 : }
2190 :
2191 2 : bool bRet(false);
2192 : {
2193 2 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2194 :
2195 4 : SwTableFormulaUpdate aMsgHint( &rTable );
2196 2 : aMsgHint.eFlags = TBL_BOXPTR;
2197 2 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2198 :
2199 2 : if (bVert)
2200 1 : bRet = rTable.SplitCol( this, rBoxes, nCnt );
2201 : else
2202 1 : bRet = rTable.SplitRow( this, rBoxes, nCnt, bSameHeight );
2203 :
2204 2 : if (bRet)
2205 : {
2206 2 : getIDocumentState().SetModified();
2207 2 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
2208 2 : }
2209 : }
2210 :
2211 2 : if( pUndo )
2212 : {
2213 2 : if( bRet )
2214 : {
2215 2 : if( bVert )
2216 1 : pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
2217 : else
2218 1 : pUndo->SaveNewBoxes( *pTableNd, aTmpLst, rBoxes, aNdsCnts );
2219 2 : GetIDocumentUndoRedo().AppendUndo( pUndo );
2220 : }
2221 : else
2222 0 : delete pUndo;
2223 : }
2224 :
2225 4 : return bRet;
2226 : }
2227 :
2228 3 : sal_uInt16 SwDoc::MergeTable( SwPaM& rPam )
2229 : {
2230 : // Check if the current cursor's Point/Mark are inside a Table
2231 3 : SwTableNode* pTableNd = rPam.GetNode().FindTableNode();
2232 3 : if( !pTableNd )
2233 0 : return TBLMERGE_NOSELECTION;
2234 3 : SwTable& rTable = pTableNd->GetTable();
2235 3 : if( rTable.ISA(SwDDETable) )
2236 0 : return TBLMERGE_NOSELECTION;
2237 3 : sal_uInt16 nRet = TBLMERGE_NOSELECTION;
2238 3 : if( !rTable.IsNewModel() )
2239 : {
2240 0 : nRet =::CheckMergeSel( rPam );
2241 0 : if( TBLMERGE_OK != nRet )
2242 0 : return nRet;
2243 0 : nRet = TBLMERGE_NOSELECTION;
2244 : }
2245 :
2246 : // #i33394#
2247 3 : GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_MERGE, NULL );
2248 :
2249 3 : RedlineMode_t eOld = getIDocumentRedlineAccess().GetRedlineMode();
2250 3 : getIDocumentRedlineAccess().SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
2251 :
2252 3 : SwUndoTableMerge *const pUndo( (GetIDocumentUndoRedo().DoesUndo())
2253 1 : ? new SwUndoTableMerge( rPam )
2254 4 : : 0 );
2255 :
2256 : // Find the Boxes via the Layout
2257 3 : SwSelBoxes aBoxes;
2258 6 : SwSelBoxes aMerged;
2259 : SwTableBox* pMergeBox;
2260 :
2261 3 : if( !rTable.PrepareMerge( rPam, aBoxes, aMerged, &pMergeBox, pUndo ) )
2262 : { // No cells found to merge
2263 0 : getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
2264 0 : if( pUndo )
2265 : {
2266 0 : delete pUndo;
2267 0 : SwUndoId nLastUndoId(UNDO_EMPTY);
2268 0 : if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
2269 0 : && (UNDO_REDLINE == nLastUndoId))
2270 : {
2271 : // FIXME: why is this horrible cleanup necessary?
2272 : SwUndoRedline *const pU = dynamic_cast<SwUndoRedline*>(
2273 0 : GetUndoManager().RemoveLastUndo());
2274 0 : if (pU && pU->GetRedlSaveCount())
2275 : {
2276 0 : SwEditShell *const pEditShell(GetEditShell());
2277 : OSL_ASSERT(pEditShell);
2278 0 : ::sw::UndoRedoContext context(*this, *pEditShell);
2279 0 : static_cast<SfxUndoAction *>(pU)->UndoWithContext(context);
2280 : }
2281 0 : delete pU;
2282 : }
2283 : }
2284 : }
2285 : else
2286 : {
2287 : // The PaMs need to be removed from the to-be-deleted range. Thus always place
2288 : // them at the end of/on top of the Table; it's always set to the old position via
2289 : // the Document Position.
2290 : // For a start remember an index for the temporary position, because we cannot
2291 : // access it after GetMergeSel
2292 : {
2293 3 : rPam.DeleteMark();
2294 3 : rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2295 3 : rPam.GetPoint()->nContent.Assign( 0, 0 );
2296 3 : rPam.SetMark();
2297 3 : rPam.DeleteMark();
2298 :
2299 3 : SwPaM* pTmp = &rPam;
2300 6 : while( &rPam != ( pTmp = static_cast<SwPaM*>(pTmp->GetNext()) ))
2301 0 : for( int i = 0; i < 2; ++i )
2302 0 : pTmp->GetBound( (bool)i ) = *rPam.GetPoint();
2303 : }
2304 :
2305 : // Merge them
2306 3 : SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
2307 3 : aMsgHint.eFlags = TBL_BOXPTR;
2308 3 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2309 :
2310 3 : if( pTableNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo ))
2311 : {
2312 3 : nRet = TBLMERGE_OK;
2313 3 : getIDocumentState().SetModified();
2314 3 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
2315 3 : if( pUndo )
2316 : {
2317 1 : GetIDocumentUndoRedo().AppendUndo( pUndo );
2318 : }
2319 : }
2320 : else
2321 0 : delete pUndo;
2322 :
2323 3 : rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2324 3 : rPam.Move();
2325 :
2326 3 : ::ClearFEShellTabCols();
2327 3 : getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
2328 : }
2329 3 : GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_MERGE, NULL );
2330 6 : return nRet;
2331 : }
2332 :
2333 1098 : SwTableNode::SwTableNode( const SwNodeIndex& rIdx )
2334 1098 : : SwStartNode( rIdx, ND_TABLENODE )
2335 : {
2336 1098 : pTable = new SwTable( 0 );
2337 1098 : }
2338 :
2339 3291 : SwTableNode::~SwTableNode()
2340 : {
2341 : // Notify UNO wrappers
2342 1097 : SwFrameFormat* pTableFormat = GetTable().GetFrameFormat();
2343 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
2344 1097 : pTableFormat );
2345 1097 : pTableFormat->ModifyNotification( &aMsgHint, &aMsgHint );
2346 1097 : DelFrms();
2347 1097 : delete pTable;
2348 2194 : }
2349 :
2350 765 : SwTabFrm *SwTableNode::MakeFrm( SwFrm* pSib )
2351 : {
2352 765 : return new SwTabFrm( *pTable, pSib );
2353 : }
2354 :
2355 : /**
2356 : * Creates all Views from the Document for the preceding Node. The resulting ContentFrames
2357 : * are added to the corresponding Layout.
2358 : */
2359 4 : void SwTableNode::MakeFrms(const SwNodeIndex & rIdx )
2360 : {
2361 4 : if( !GetTable().GetFrameFormat()->HasWriterListeners()) // Do we actually have Frame?
2362 4 : return;
2363 :
2364 : SwFrm *pFrm;
2365 4 : SwContentNode * pNode = rIdx.GetNode().GetContentNode();
2366 :
2367 : OSL_ENSURE( pNode, "No ContentNode or CopyNode and new Node is identical");
2368 :
2369 4 : bool bBefore = rIdx < GetIndex();
2370 :
2371 4 : SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
2372 :
2373 10 : while( 0 != (pFrm = aNode2Layout.NextFrm()) )
2374 : {
2375 2 : SwFrm *pNew = pNode->MakeFrm( pFrm );
2376 : // Will the Node receive Frames before or after?
2377 2 : if ( bBefore )
2378 : // The new one preceds me
2379 2 : pNew->Paste( pFrm->GetUpper(), pFrm );
2380 : else
2381 : // The new one succeeds me
2382 0 : pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
2383 4 : }
2384 : }
2385 :
2386 : /**
2387 : * Create a TableFrm for every Shell and insert before the corresponding ContentFrm.
2388 : */
2389 500 : void SwTableNode::MakeFrms( SwNodeIndex* pIdxBehind )
2390 : {
2391 : OSL_ENSURE( pIdxBehind, "No Index" );
2392 500 : *pIdxBehind = *this;
2393 500 : SwNode *pNd = GetNodes().FindPrvNxtFrmNode( *pIdxBehind, EndOfSectionNode() );
2394 500 : if( !pNd )
2395 928 : return ;
2396 :
2397 72 : SwFrm *pFrm( 0L );
2398 72 : SwLayoutFrm *pUpper( 0L );
2399 72 : SwNode2Layout aNode2Layout( *pNd, GetIndex() );
2400 210 : while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, *this )) )
2401 : {
2402 66 : SwTabFrm* pNew = MakeFrm( pUpper );
2403 66 : pNew->Paste( pUpper, pFrm );
2404 : // #i27138#
2405 : // notify accessibility paragraphs objects about changed
2406 : // CONTENT_FLOWS_FROM/_TO relation.
2407 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
2408 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2409 : {
2410 66 : SwViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
2411 132 : if ( pViewShell && pViewShell->GetLayout() &&
2412 66 : pViewShell->GetLayout()->IsAnyShellAccessible() )
2413 : {
2414 : pViewShell->InvalidateAccessibleParaFlowRelation(
2415 0 : dynamic_cast<SwTextFrm*>(pNew->FindNextCnt( true )),
2416 0 : dynamic_cast<SwTextFrm*>(pNew->FindPrevCnt( true )) );
2417 : }
2418 : }
2419 66 : pNew->RegistFlys();
2420 72 : }
2421 : }
2422 :
2423 1517 : void SwTableNode::DelFrms()
2424 : {
2425 : /* For a start, cut out and delete the TabFrms (which will also delete the Columns and Rows)
2426 : The TabFrms are attached to the FrameFormat of the SwTable.
2427 : We need to delete them in a more cumbersome way, for the Master to also delete the Follows. */
2428 :
2429 1517 : SwIterator<SwTabFrm,SwFormat> aIter( *(pTable->GetFrameFormat()) );
2430 1517 : SwTabFrm *pFrm = aIter.First();
2431 3058 : while ( pFrm )
2432 : {
2433 24 : bool bAgain = false;
2434 : {
2435 24 : if ( !pFrm->IsFollow() )
2436 : {
2437 48 : while ( pFrm->HasFollow() )
2438 0 : pFrm->JoinAndDelFollows();
2439 : // #i27138#
2440 : // notify accessibility paragraphs objects about changed
2441 : // CONTENT_FLOWS_FROM/_TO relation.
2442 : // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2443 : // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2444 : {
2445 24 : SwViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
2446 48 : if ( pViewShell && pViewShell->GetLayout() &&
2447 24 : pViewShell->GetLayout()->IsAnyShellAccessible() )
2448 : {
2449 : pViewShell->InvalidateAccessibleParaFlowRelation(
2450 0 : dynamic_cast<SwTextFrm*>(pFrm->FindNextCnt( true )),
2451 0 : dynamic_cast<SwTextFrm*>(pFrm->FindPrevCnt( true )) );
2452 : }
2453 : }
2454 24 : pFrm->Cut();
2455 24 : SwFrm::DestroyFrm(pFrm);
2456 24 : bAgain = true;
2457 : }
2458 : }
2459 24 : pFrm = bAgain ? aIter.First() : aIter.Next();
2460 1517 : }
2461 1517 : }
2462 :
2463 0 : void SwTableNode::SetNewTable( SwTable* pNewTable, bool bNewFrames )
2464 : {
2465 0 : DelFrms();
2466 0 : delete pTable;
2467 0 : pTable = pNewTable;
2468 0 : if( bNewFrames )
2469 : {
2470 0 : SwNodeIndex aIdx( *EndOfSectionNode());
2471 0 : GetNodes().GoNext( &aIdx );
2472 0 : MakeFrms( &aIdx );
2473 : }
2474 0 : }
2475 :
2476 1101 : void SwTableNode::RemoveRedlines()
2477 : {
2478 1101 : SwDoc* pDoc = GetDoc();
2479 1101 : if (pDoc)
2480 : {
2481 1101 : SwTable& rTable = GetTable();
2482 1101 : if ( pDoc->getIDocumentRedlineAccess().HasExtraRedlineTable() )
2483 1101 : pDoc->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteAllTableRedlines( pDoc, rTable, true, USHRT_MAX );
2484 : }
2485 1101 : }
2486 :
2487 1 : void SwDoc::GetTabCols( SwTabCols &rFill, const SwCursor* pCrsr,
2488 : const SwCellFrm* pBoxFrm )
2489 : {
2490 1 : const SwTableBox* pBox = 0;
2491 1 : SwTabFrm *pTab = 0;
2492 :
2493 1 : if( pBoxFrm )
2494 : {
2495 1 : pTab = const_cast<SwFrm*>(static_cast<SwFrm const *>(pBoxFrm))->ImplFindTabFrm();
2496 1 : pBox = pBoxFrm->GetTabBox();
2497 : }
2498 0 : else if( pCrsr )
2499 : {
2500 0 : const SwContentNode* pCNd = pCrsr->GetContentNode();
2501 0 : if( !pCNd )
2502 0 : return ;
2503 :
2504 0 : Point aPt;
2505 0 : const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
2506 0 : if( pShCrsr )
2507 0 : aPt = pShCrsr->GetPtPos();
2508 :
2509 0 : const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, 0, false );
2510 0 : do {
2511 0 : pTmpFrm = pTmpFrm->GetUpper();
2512 0 : } while ( !pTmpFrm->IsCellFrm() );
2513 :
2514 0 : pBoxFrm = static_cast<const SwCellFrm*>(pTmpFrm);
2515 0 : pTab = const_cast<SwFrm*>(static_cast<SwFrm const *>(pBoxFrm))->ImplFindTabFrm();
2516 0 : pBox = pBoxFrm->GetTabBox();
2517 : }
2518 0 : else if( !pCrsr && !pBoxFrm )
2519 : {
2520 : OSL_ENSURE( false, "One of them needs to be specified!" );
2521 0 : return ;
2522 : }
2523 :
2524 : // Set fixed points, LeftMin in Document coordinates, all others relative
2525 1 : SWRECTFN( pTab )
2526 1 : const SwPageFrm* pPage = pTab->FindPageFrm();
2527 2 : const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
2528 2 : (pPage->Frm().*fnRect->fnGetLeft)();
2529 2 : const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
2530 2 : (pPage->Frm().*fnRect->fnGetLeft)();
2531 :
2532 1 : rFill.SetLeftMin ( nLeftMin );
2533 1 : rFill.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() );
2534 1 : rFill.SetRight ( (pTab->Prt().*fnRect->fnGetRight)());
2535 1 : rFill.SetRightMax( nRightMax - nLeftMin );
2536 :
2537 1 : pTab->GetTable()->GetTabCols( rFill, pBox );
2538 : }
2539 :
2540 : // Here are some little helpers used in SwDoc::GetTabRows
2541 :
2542 : #define ROWFUZZY 25
2543 :
2544 : struct FuzzyCompare
2545 : {
2546 : bool operator() ( long s1, long s2 ) const;
2547 : };
2548 :
2549 30 : bool FuzzyCompare::operator() ( long s1, long s2 ) const
2550 : {
2551 30 : return ( s1 < s2 && std::abs( s1 - s2 ) > ROWFUZZY );
2552 : }
2553 :
2554 3 : static bool lcl_IsFrmInColumn( const SwCellFrm& rFrm, SwSelBoxes& rBoxes )
2555 : {
2556 4 : for (size_t i = 0; i < rBoxes.size(); ++i)
2557 : {
2558 4 : if ( rFrm.GetTabBox() == rBoxes[ i ] )
2559 3 : return true;
2560 : }
2561 :
2562 0 : return false;
2563 : }
2564 :
2565 1 : void SwDoc::GetTabRows( SwTabCols &rFill, const SwCursor* ,
2566 : const SwCellFrm* pBoxFrm )
2567 : {
2568 : OSL_ENSURE( pBoxFrm, "GetTabRows called without pBoxFrm" );
2569 :
2570 : // Make code robust:
2571 1 : if ( !pBoxFrm )
2572 0 : return;
2573 :
2574 : // #i39552# Collection of the boxes of the current
2575 : // column has to be done at the beginning of this function, because
2576 : // the table may be formatted in ::GetTableSel.
2577 1 : SwDeletionChecker aDelCheck( pBoxFrm );
2578 :
2579 1 : SwSelBoxes aBoxes;
2580 1 : const SwContentFrm* pContent = ::GetCellContent( *pBoxFrm );
2581 1 : if ( pContent && pContent->IsTextFrm() )
2582 : {
2583 1 : const SwPosition aPos( *static_cast<const SwTextFrm*>(pContent)->GetTextNode() );
2584 2 : const SwCursor aTmpCrsr( aPos, 0, false );
2585 2 : ::GetTableSel( aTmpCrsr, aBoxes, nsSwTableSearchType::TBLSEARCH_COL );
2586 : }
2587 :
2588 : // Make code robust:
2589 1 : if ( aDelCheck.HasBeenDeleted() )
2590 : {
2591 : OSL_FAIL( "Current box has been deleted during GetTabRows()" );
2592 0 : return;
2593 : }
2594 :
2595 : // Make code robust:
2596 1 : const SwTabFrm* pTab = pBoxFrm->FindTabFrm();
2597 : OSL_ENSURE( pTab, "GetTabRows called without a table" );
2598 1 : if ( !pTab )
2599 0 : return;
2600 :
2601 1 : const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
2602 :
2603 : // Set fixed points, LeftMin in Document coordinates, all others relative
2604 1 : SWRECTFN( pTab )
2605 1 : const SwPageFrm* pPage = pTab->FindPageFrm();
2606 : const long nLeftMin = ( bVert ?
2607 0 : pTab->GetPrtLeft() - pPage->Frm().Left() :
2608 1 : pTab->GetPrtTop() - pPage->Frm().Top() );
2609 1 : const long nLeft = bVert ? LONG_MAX : 0;
2610 1 : const long nRight = (pTab->Prt().*fnRect->fnGetHeight)();
2611 1 : const long nRightMax = bVert ? nRight : LONG_MAX;
2612 :
2613 1 : rFill.SetLeftMin( nLeftMin );
2614 1 : rFill.SetLeft( nLeft );
2615 1 : rFill.SetRight( nRight );
2616 1 : rFill.SetRightMax( nRightMax );
2617 :
2618 : typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap;
2619 2 : BoundaryMap aBoundaries;
2620 1 : BoundaryMap::iterator aIter;
2621 1 : std::pair< long, long > aPair;
2622 :
2623 : typedef std::map< long, bool > HiddenMap;
2624 2 : HiddenMap aHidden;
2625 1 : HiddenMap::iterator aHiddenIter;
2626 :
2627 6 : while ( pFrm && pTab->IsAnLower( pFrm ) )
2628 : {
2629 4 : if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
2630 : {
2631 : // upper and lower borders of current cell frame:
2632 4 : long nUpperBorder = (pFrm->Frm().*fnRect->fnGetTop)();
2633 4 : long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
2634 :
2635 : // get boundaries for nUpperBorder:
2636 4 : aIter = aBoundaries.find( nUpperBorder );
2637 4 : if ( aIter == aBoundaries.end() )
2638 : {
2639 1 : aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2640 1 : aBoundaries[ nUpperBorder ] = aPair;
2641 : }
2642 :
2643 : // get boundaries for nLowerBorder:
2644 4 : aIter = aBoundaries.find( nLowerBorder );
2645 4 : if ( aIter == aBoundaries.end() )
2646 : {
2647 2 : aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2648 : }
2649 : else
2650 : {
2651 2 : nLowerBorder = (*aIter).first;
2652 2 : long nNewLowerBorderUpperBoundary = std::max( (*aIter).second.first, nUpperBorder );
2653 2 : aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX;
2654 : }
2655 4 : aBoundaries[ nLowerBorder ] = aPair;
2656 :
2657 : // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2658 4 : long nTmpVal = nUpperBorder;
2659 12 : for ( sal_uInt8 i = 0; i < 2; ++i )
2660 : {
2661 8 : aHiddenIter = aHidden.find( nTmpVal );
2662 8 : if ( aHiddenIter == aHidden.end() )
2663 3 : aHidden[ nTmpVal ] = !lcl_IsFrmInColumn( *static_cast<const SwCellFrm*>(pFrm), aBoxes );
2664 : else
2665 : {
2666 5 : if ( aHidden[ nTmpVal ] &&
2667 0 : lcl_IsFrmInColumn( *static_cast<const SwCellFrm*>(pFrm), aBoxes ) )
2668 0 : aHidden[ nTmpVal ] = false;
2669 : }
2670 8 : nTmpVal = nLowerBorder;
2671 : }
2672 : }
2673 :
2674 4 : pFrm = pFrm->GetNextLayoutLeaf();
2675 : }
2676 :
2677 : // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2678 1 : size_t nIdx = 0;
2679 4 : for ( aIter = aBoundaries.begin(); aIter != aBoundaries.end(); ++aIter )
2680 : {
2681 3 : const long nTabTop = (pTab->*fnRect->fnGetPrtTop)();
2682 3 : const long nKey = (*fnRect->fnYDiff)( (*aIter).first, nTabTop );
2683 3 : const std::pair< long, long > aTmpPair = (*aIter).second;
2684 3 : const long nFirst = (*fnRect->fnYDiff)( aTmpPair.first, nTabTop );
2685 3 : const long nSecond = aTmpPair.second;
2686 :
2687 3 : aHiddenIter = aHidden.find( (*aIter).first );
2688 3 : const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second;
2689 3 : rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ );
2690 : }
2691 :
2692 : // delete first and last entry
2693 : OSL_ENSURE( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" );
2694 : // #i60818# There may be only one entry in rFill. Make
2695 : // code robust by checking count of rFill.
2696 1 : if ( rFill.Count() ) rFill.Remove( 0, 1 );
2697 1 : if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 , 1 );
2698 2 : rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() );
2699 : }
2700 :
2701 0 : void SwDoc::SetTabCols( const SwTabCols &rNew, bool bCurRowOnly,
2702 : const SwCursor* pCrsr, const SwCellFrm* pBoxFrm )
2703 : {
2704 0 : const SwTableBox* pBox = 0;
2705 0 : SwTabFrm *pTab = 0;
2706 :
2707 0 : if( pBoxFrm )
2708 : {
2709 0 : pTab = const_cast<SwFrm*>(static_cast<SwFrm const *>(pBoxFrm))->ImplFindTabFrm();
2710 0 : pBox = pBoxFrm->GetTabBox();
2711 : }
2712 0 : else if( pCrsr )
2713 : {
2714 0 : const SwContentNode* pCNd = pCrsr->GetContentNode();
2715 0 : if( !pCNd )
2716 0 : return ;
2717 :
2718 0 : Point aPt;
2719 0 : const SwShellCrsr *pShCrsr = dynamic_cast<const SwShellCrsr*>(pCrsr);
2720 0 : if( pShCrsr )
2721 0 : aPt = pShCrsr->GetPtPos();
2722 :
2723 0 : const SwFrm* pTmpFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, 0, false );
2724 0 : do {
2725 0 : pTmpFrm = pTmpFrm->GetUpper();
2726 0 : } while ( !pTmpFrm->IsCellFrm() );
2727 :
2728 0 : pBoxFrm = static_cast<const SwCellFrm*>(pTmpFrm);
2729 0 : pTab = const_cast<SwFrm*>(static_cast<SwFrm const *>(pBoxFrm))->ImplFindTabFrm();
2730 0 : pBox = pBoxFrm->GetTabBox();
2731 : }
2732 0 : else if( !pCrsr && !pBoxFrm )
2733 : {
2734 : OSL_ENSURE( false, "One of them needs to be specified!" );
2735 0 : return ;
2736 : }
2737 :
2738 : // If the Table is still using relative values (USHRT_MAX)
2739 : // we need to switch to absolute ones.
2740 0 : SwTable& rTab = *pTab->GetTable();
2741 0 : const SwFormatFrmSize& rTableFrmSz = rTab.GetFrameFormat()->GetFrmSize();
2742 0 : SWRECTFN( pTab )
2743 : // #i17174# - With fix for #i9040# the shadow size is taken
2744 : // from the table width. Thus, add its left and right size to current table
2745 : // printing area width in order to get the correct table size attribute.
2746 0 : SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
2747 : {
2748 0 : SvxShadowItem aShadow( rTab.GetFrameFormat()->GetShadow() );
2749 0 : nPrtWidth += aShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ) +
2750 0 : aShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT );
2751 : }
2752 0 : if( nPrtWidth != rTableFrmSz.GetWidth() )
2753 : {
2754 0 : SwFormatFrmSize aSz( rTableFrmSz );
2755 0 : aSz.SetWidth( nPrtWidth );
2756 0 : rTab.GetFrameFormat()->SetFormatAttr( aSz );
2757 : }
2758 :
2759 0 : SwTabCols aOld( rNew.Count() );
2760 :
2761 0 : const SwPageFrm* pPage = pTab->FindPageFrm();
2762 0 : const sal_uLong nLeftMin = (pTab->Frm().*fnRect->fnGetLeft)() -
2763 0 : (pPage->Frm().*fnRect->fnGetLeft)();
2764 0 : const sal_uLong nRightMax = (pTab->Frm().*fnRect->fnGetRight)() -
2765 0 : (pPage->Frm().*fnRect->fnGetLeft)();
2766 :
2767 : // Set fixed points, LeftMin in Document coordinates, all others relative
2768 0 : aOld.SetLeftMin ( nLeftMin );
2769 0 : aOld.SetLeft ( (pTab->Prt().*fnRect->fnGetLeft)() );
2770 0 : aOld.SetRight ( (pTab->Prt().*fnRect->fnGetRight)());
2771 0 : aOld.SetRightMax( nRightMax - nLeftMin );
2772 :
2773 0 : rTab.GetTabCols( aOld, pBox );
2774 0 : SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly );
2775 : }
2776 :
2777 0 : void SwDoc::SetTabRows( const SwTabCols &rNew, bool bCurColOnly, const SwCursor*,
2778 : const SwCellFrm* pBoxFrm )
2779 : {
2780 : SwTabFrm *pTab;
2781 :
2782 : OSL_ENSURE( pBoxFrm, "SetTabRows called without pBoxFrm" );
2783 :
2784 0 : pTab = const_cast<SwFrm*>(static_cast<SwFrm const *>(pBoxFrm))->ImplFindTabFrm();
2785 :
2786 : // If the Table is still using relative values (USHRT_MAX)
2787 : // we need to switch to absolute ones.
2788 0 : SWRECTFN( pTab )
2789 0 : SwTabCols aOld( rNew.Count() );
2790 :
2791 : // Set fixed points, LeftMin in Document coordinates, all others relative
2792 0 : const SwPageFrm* pPage = pTab->FindPageFrm();
2793 :
2794 0 : aOld.SetRight( (pTab->Prt().*fnRect->fnGetHeight)() );
2795 : long nLeftMin;
2796 0 : if ( bVert )
2797 : {
2798 0 : nLeftMin = pTab->GetPrtLeft() - pPage->Frm().Left();
2799 0 : aOld.SetLeft ( LONG_MAX );
2800 0 : aOld.SetRightMax( aOld.GetRight() );
2801 :
2802 : }
2803 : else
2804 : {
2805 0 : nLeftMin = pTab->GetPrtTop() - pPage->Frm().Top();
2806 0 : aOld.SetLeft ( 0 );
2807 0 : aOld.SetRightMax( LONG_MAX );
2808 : }
2809 0 : aOld.SetLeftMin ( nLeftMin );
2810 :
2811 0 : GetTabRows( aOld, 0, pBoxFrm );
2812 :
2813 0 : GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_ATTR, NULL );
2814 :
2815 : // check for differences between aOld and rNew:
2816 0 : const size_t nCount = rNew.Count();
2817 0 : const SwTable* pTable = pTab->GetTable();
2818 : OSL_ENSURE( pTable, "My colleague told me, this couldn't happen" );
2819 :
2820 0 : for ( size_t i = 0; i <= nCount; ++i )
2821 : {
2822 0 : const size_t nIdxStt = bVert ? nCount - i : i - 1;
2823 0 : const size_t nIdxEnd = bVert ? nCount - i - 1 : i;
2824 :
2825 0 : const long nOldRowStart = i == 0 ? 0 : aOld[ nIdxStt ];
2826 0 : const long nOldRowEnd = i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ];
2827 0 : const long nOldRowHeight = nOldRowEnd - nOldRowStart;
2828 :
2829 0 : const long nNewRowStart = i == 0 ? 0 : rNew[ nIdxStt ];
2830 0 : const long nNewRowEnd = i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ];
2831 0 : const long nNewRowHeight = nNewRowEnd - nNewRowStart;
2832 :
2833 0 : const long nDiff = nNewRowHeight - nOldRowHeight;
2834 0 : if ( std::abs( nDiff ) >= ROWFUZZY )
2835 : {
2836 : // For the old table model pTextFrm and pLine will be set for every box.
2837 : // For the new table model pTextFrm will be set if the box is not covered,
2838 : // but the pLine will be set if the box is not an overlapping box
2839 : // In the new table model the row height can be adjusted,
2840 : // when both variables are set.
2841 0 : const SwTextFrm* pTextFrm = 0;
2842 0 : const SwTableLine* pLine = 0;
2843 :
2844 : // Iterate over all SwCellFrms with Bottom = nOldPos
2845 0 : const SwFrm* pFrm = pTab->GetNextLayoutLeaf();
2846 0 : while ( pFrm && pTab->IsAnLower( pFrm ) )
2847 : {
2848 0 : if ( pFrm->IsCellFrm() && pFrm->FindTabFrm() == pTab )
2849 : {
2850 0 : const long nLowerBorder = (pFrm->Frm().*fnRect->fnGetBottom)();
2851 0 : const sal_uLong nTabTop = (pTab->*fnRect->fnGetPrtTop)();
2852 0 : if ( std::abs( (*fnRect->fnYInc)( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY )
2853 : {
2854 0 : if ( !bCurColOnly || pFrm == pBoxFrm )
2855 : {
2856 0 : const SwFrm* pContent = ::GetCellContent( static_cast<const SwCellFrm&>(*pFrm) );
2857 :
2858 0 : if ( pContent && pContent->IsTextFrm() )
2859 : {
2860 0 : const SwTableBox* pBox = static_cast<const SwCellFrm*>(pFrm)->GetTabBox();
2861 0 : const long nRowSpan = pBox->getRowSpan();
2862 0 : if( nRowSpan > 0 ) // Not overlapped
2863 0 : pTextFrm = static_cast<const SwTextFrm*>(pContent);
2864 0 : if( nRowSpan < 2 ) // Not overlapping for row height
2865 0 : pLine = pBox->GetUpper();
2866 0 : if( pLine && pTextFrm ) // always for old table model
2867 : {
2868 : // The new row height must not to be calculated from a overlapping box
2869 0 : SwFormatFrmSize aNew( pLine->GetFrameFormat()->GetFrmSize() );
2870 0 : const long nNewSize = (pFrm->Frm().*fnRect->fnGetHeight)() + nDiff;
2871 0 : if( nNewSize != aNew.GetHeight() )
2872 : {
2873 0 : aNew.SetHeight( nNewSize );
2874 0 : if ( ATT_VAR_SIZE == aNew.GetHeightSizeType() )
2875 0 : aNew.SetHeightSizeType( ATT_MIN_SIZE );
2876 : // This position must not be in an overlapped box
2877 0 : const SwPosition aPos( *static_cast<const SwTextFrm*>(pContent)->GetTextNode() );
2878 0 : const SwCursor aTmpCrsr( aPos, 0, false );
2879 0 : SetRowHeight( aTmpCrsr, aNew );
2880 : // For the new table model we're done, for the old one
2881 : // there might be another (sub)row to adjust...
2882 0 : if( pTable->IsNewModel() )
2883 0 : break;
2884 : }
2885 0 : pLine = 0;
2886 : }
2887 : }
2888 : }
2889 : }
2890 : }
2891 0 : pFrm = pFrm->GetNextLayoutLeaf();
2892 : }
2893 : }
2894 : }
2895 :
2896 0 : GetIDocumentUndoRedo().EndUndo( UNDO_TABLE_ATTR, NULL );
2897 :
2898 0 : ::ClearFEShellTabCols();
2899 0 : }
2900 :
2901 : /**
2902 : * Direct access for UNO
2903 : */
2904 2516 : void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld,
2905 : const SwTableBox *pStart, bool bCurRowOnly )
2906 : {
2907 2516 : if (GetIDocumentUndoRedo().DoesUndo())
2908 : {
2909 0 : GetIDocumentUndoRedo().AppendUndo(
2910 0 : new SwUndoAttrTable( *rTab.GetTableNode(), true ));
2911 : }
2912 2516 : rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
2913 2516 : ::ClearFEShellTabCols();
2914 2516 : getIDocumentState().SetModified();
2915 2516 : }
2916 :
2917 604 : void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet )
2918 : {
2919 604 : if( nSet == rTable.GetRowsToRepeat() )
2920 614 : return;
2921 :
2922 594 : if (GetIDocumentUndoRedo().DoesUndo())
2923 : {
2924 1 : GetIDocumentUndoRedo().AppendUndo(
2925 1 : new SwUndoTableHeadline(rTable, rTable.GetRowsToRepeat(), nSet) );
2926 : }
2927 :
2928 594 : SwMsgPoolItem aChg( RES_TBLHEADLINECHG );
2929 594 : rTable.SetRowsToRepeat( nSet );
2930 594 : rTable.GetFrameFormat()->ModifyNotification( &aChg, &aChg );
2931 594 : getIDocumentState().SetModified();
2932 : }
2933 :
2934 0 : void SwCollectTableLineBoxes::AddToUndoHistory( const SwContentNode& rNd )
2935 : {
2936 0 : if( pHst )
2937 0 : pHst->Add( rNd.GetFormatColl(), rNd.GetIndex(), ND_TEXTNODE );
2938 0 : }
2939 :
2940 0 : void SwCollectTableLineBoxes::AddBox( const SwTableBox& rBox )
2941 : {
2942 0 : aPosArr.push_back(nWidth);
2943 0 : SwTableBox* p = const_cast<SwTableBox*>(&rBox);
2944 0 : m_Boxes.push_back(p);
2945 0 : nWidth = nWidth + (sal_uInt16)rBox.GetFrameFormat()->GetFrmSize().GetWidth();
2946 0 : }
2947 :
2948 0 : const SwTableBox* SwCollectTableLineBoxes::GetBoxOfPos( const SwTableBox& rBox )
2949 : {
2950 0 : const SwTableBox* pRet = 0;
2951 :
2952 0 : if( !aPosArr.empty() )
2953 : {
2954 : std::vector<sal_uInt16>::size_type n;
2955 0 : for( n = 0; n < aPosArr.size(); ++n )
2956 0 : if( aPosArr[ n ] == nWidth )
2957 0 : break;
2958 0 : else if( aPosArr[ n ] > nWidth )
2959 : {
2960 0 : if( n )
2961 0 : --n;
2962 0 : break;
2963 : }
2964 :
2965 0 : if( n >= aPosArr.size() )
2966 0 : --n;
2967 :
2968 0 : nWidth = nWidth + (sal_uInt16)rBox.GetFrameFormat()->GetFrmSize().GetWidth();
2969 0 : pRet = m_Boxes[ n ];
2970 : }
2971 0 : return pRet;
2972 : }
2973 :
2974 0 : bool SwCollectTableLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth )
2975 : {
2976 0 : if( !aPosArr.empty() )
2977 : {
2978 : std::vector<sal_uInt16>::size_type n;
2979 0 : for( n = 0; n < aPosArr.size(); ++n )
2980 : {
2981 0 : if( aPosArr[ n ] == nOffset )
2982 0 : break;
2983 0 : else if( aPosArr[ n ] > nOffset )
2984 : {
2985 0 : if( n )
2986 0 : --n;
2987 0 : break;
2988 : }
2989 : }
2990 :
2991 0 : aPosArr.erase( aPosArr.begin(), aPosArr.begin() + n );
2992 0 : m_Boxes.erase(m_Boxes.begin(), m_Boxes.begin() + n);
2993 :
2994 0 : size_t nArrSize = aPosArr.size();
2995 0 : if (nArrSize)
2996 : {
2997 0 : if (nOldWidth == 0)
2998 0 : throw o3tl::divide_by_zero();
2999 :
3000 : // Adapt the positions to the new Size
3001 0 : for( n = 0; n < nArrSize; ++n )
3002 : {
3003 0 : sal_uLong nSize = nWidth;
3004 0 : nSize *= ( aPosArr[ n ] - nOffset );
3005 0 : nSize /= nOldWidth;
3006 0 : aPosArr[ n ] = sal_uInt16( nSize );
3007 : }
3008 : }
3009 : }
3010 0 : return !aPosArr.empty();
3011 : }
3012 :
3013 0 : bool sw_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
3014 : {
3015 0 : SwCollectTableLineBoxes* pSplPara = static_cast<SwCollectTableLineBoxes*>(pPara);
3016 0 : if( pSplPara->IsGetValues() )
3017 0 : for( SwTableBoxes::iterator it = const_cast<SwTableLine*>(rpLine)->GetTabBoxes().begin();
3018 0 : it != const_cast<SwTableLine*>(rpLine)->GetTabBoxes().end(); ++it)
3019 0 : sw_Box_CollectBox(*it, pSplPara );
3020 : else
3021 0 : for( SwTableBoxes::iterator it = const_cast<SwTableLine*>(rpLine)->GetTabBoxes().begin();
3022 0 : it != const_cast<SwTableLine*>(rpLine)->GetTabBoxes().end(); ++it)
3023 0 : sw_BoxSetSplitBoxFormats(*it, pSplPara );
3024 0 : return true;
3025 : }
3026 :
3027 0 : void sw_Box_CollectBox( const SwTableBox* pBox, SwCollectTableLineBoxes* pSplPara )
3028 : {
3029 0 : auto nLen = pBox->GetTabLines().size();
3030 0 : if( nLen )
3031 : {
3032 : // Continue with the actual Line
3033 0 : if( pSplPara->IsGetFromTop() )
3034 0 : nLen = 0;
3035 : else
3036 0 : --nLen;
3037 :
3038 0 : const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3039 0 : sw_Line_CollectBox( pLn, pSplPara );
3040 : }
3041 : else
3042 0 : pSplPara->AddBox( *pBox );
3043 0 : }
3044 :
3045 0 : void sw_BoxSetSplitBoxFormats( SwTableBox* pBox, SwCollectTableLineBoxes* pSplPara )
3046 : {
3047 0 : auto nLen = pBox->GetTabLines().size();
3048 0 : if( nLen )
3049 : {
3050 : // Continue with the actual Line
3051 0 : if( pSplPara->IsGetFromTop() )
3052 0 : nLen = 0;
3053 : else
3054 0 : --nLen;
3055 :
3056 0 : const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3057 0 : sw_Line_CollectBox( pLn, pSplPara );
3058 : }
3059 : else
3060 : {
3061 0 : const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *pBox );
3062 0 : SwFrameFormat* pFormat = pSrcBox->GetFrameFormat();
3063 :
3064 0 : if( HEADLINE_BORDERCOPY == pSplPara->GetMode() )
3065 : {
3066 0 : const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
3067 0 : if( !rBoxItem.GetTop() )
3068 : {
3069 0 : SvxBoxItem aNew( rBoxItem );
3070 0 : aNew.SetLine( pFormat->GetBox().GetBottom(), SvxBoxItemLine::TOP );
3071 0 : if( aNew != rBoxItem )
3072 0 : pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
3073 : }
3074 : }
3075 : else
3076 : {
3077 : sal_uInt16 aTableSplitBoxSetRange[] = {
3078 : RES_LR_SPACE, RES_UL_SPACE,
3079 : RES_BACKGROUND, RES_SHADOW,
3080 : RES_PROTECT, RES_PROTECT,
3081 : RES_VERT_ORIENT, RES_VERT_ORIENT,
3082 0 : 0 };
3083 :
3084 0 : SfxItemSet aTmpSet( pFormat->GetDoc()->GetAttrPool(),
3085 0 : aTableSplitBoxSetRange );
3086 0 : aTmpSet.Put( pFormat->GetAttrSet() );
3087 0 : if( aTmpSet.Count() )
3088 0 : pBox->ClaimFrameFormat()->SetFormatAttr( aTmpSet );
3089 :
3090 0 : if( HEADLINE_BOXATRCOLLCOPY == pSplPara->GetMode() )
3091 : {
3092 0 : SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
3093 0 : SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3094 0 : if( !pCNd )
3095 0 : pCNd = aIdx.GetNodes().GoNext( &aIdx );
3096 0 : aIdx = *pBox->GetSttNd();
3097 0 : SwContentNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );
3098 :
3099 : // If the Node is alone in the Section
3100 0 : if( 2 == pDNd->EndOfSectionIndex() -
3101 0 : pDNd->StartOfSectionIndex() )
3102 : {
3103 0 : pSplPara->AddToUndoHistory( *pDNd );
3104 0 : pDNd->ChgFormatColl( pCNd->GetFormatColl() );
3105 0 : }
3106 : }
3107 :
3108 : // note conditional template
3109 0 : pBox->GetSttNd()->CheckSectionCondColl();
3110 : }
3111 : }
3112 0 : }
3113 :
3114 : /**
3115 : * Splits a Table in the top-level Line which contains the Index.
3116 : * All succeeding top-level Lines go into a new Table/Node.
3117 : *
3118 : * @param bCalcNewSize true
3119 : * Calculate the new Size for both from the
3120 : * Boxes' Max; but only if Size is using absolute
3121 : * values (USHRT_MAX)
3122 : */
3123 0 : bool SwDoc::SplitTable( const SwPosition& rPos, sal_uInt16 eHdlnMode,
3124 : bool bCalcNewSize )
3125 : {
3126 0 : SwNode* pNd = &rPos.nNode.GetNode();
3127 0 : SwTableNode* pTNd = pNd->FindTableNode();
3128 0 : if( !pTNd || pNd->IsTableNode() )
3129 0 : return false;
3130 :
3131 0 : if( pTNd->GetTable().ISA( SwDDETable ))
3132 0 : return false;
3133 :
3134 0 : SwTable& rTable = pTNd->GetTable();
3135 0 : rTable.SetHTMLTableLayout( 0 ); // Delete HTML Layout
3136 :
3137 0 : SwTableFormulaUpdate aMsgHint( &rTable );
3138 :
3139 0 : SwHistory aHistory;
3140 0 : if (GetIDocumentUndoRedo().DoesUndo())
3141 : {
3142 0 : aMsgHint.pHistory = &aHistory;
3143 : }
3144 :
3145 : {
3146 0 : sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3147 :
3148 : // Find top-level Line
3149 0 : SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3150 0 : if( pBox )
3151 : {
3152 0 : SwTableLine* pLine = pBox->GetUpper();
3153 0 : while( pLine->GetUpper() )
3154 0 : pLine = pLine->GetUpper()->GetUpper();
3155 :
3156 : // pLine contains the top-level Line now
3157 0 : aMsgHint.nSplitLine = rTable.GetTabLines().GetPos( pLine );
3158 : }
3159 :
3160 0 : OUString sNewTableNm( GetUniqueTableName() );
3161 0 : aMsgHint.DATA.pNewTableNm = &sNewTableNm;
3162 0 : aMsgHint.eFlags = TBL_SPLITTBL;
3163 0 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
3164 : }
3165 :
3166 : // Find Lines for the Layout update
3167 0 : _FndBox aFndBox( 0, 0 );
3168 0 : aFndBox.SetTableLines( rTable );
3169 0 : aFndBox.DelFrms( rTable );
3170 :
3171 0 : SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, false, bCalcNewSize );
3172 :
3173 0 : if( pNew )
3174 : {
3175 0 : SwSaveRowSpan* pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTable.GetTabLines().size() );
3176 0 : SwUndoSplitTable* pUndo = 0;
3177 0 : if (GetIDocumentUndoRedo().DoesUndo())
3178 : {
3179 : pUndo = new SwUndoSplitTable(
3180 0 : *pNew, pSaveRowSp, eHdlnMode, bCalcNewSize);
3181 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
3182 0 : if( aHistory.Count() )
3183 0 : pUndo->SaveFormula( aHistory );
3184 : }
3185 :
3186 0 : switch( eHdlnMode )
3187 : {
3188 : // Set the lower Border of the preceding Line to
3189 : // the upper Border of the current one
3190 : case HEADLINE_BORDERCOPY:
3191 : {
3192 0 : SwCollectTableLineBoxes aPara( false, eHdlnMode );
3193 0 : SwTableLine* pLn = rTable.GetTabLines()[
3194 0 : rTable.GetTabLines().size() - 1 ];
3195 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
3196 0 : it != pLn->GetTabBoxes().end(); ++it)
3197 0 : sw_Box_CollectBox(*it, &aPara );
3198 :
3199 0 : aPara.SetValues( true );
3200 0 : pLn = pNew->GetTable().GetTabLines()[ 0 ];
3201 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
3202 0 : it != pLn->GetTabBoxes().end(); ++it)
3203 0 : sw_BoxSetSplitBoxFormats(*it, &aPara );
3204 :
3205 : // Switch off repeating Header
3206 0 : pNew->GetTable().SetRowsToRepeat( 0 );
3207 : }
3208 0 : break;
3209 :
3210 : // Take over the Attributes of the first Line to the new one
3211 : case HEADLINE_BOXATTRCOPY:
3212 : case HEADLINE_BOXATRCOLLCOPY:
3213 : {
3214 0 : SwHistory* pHst = 0;
3215 0 : if( HEADLINE_BOXATRCOLLCOPY == eHdlnMode && pUndo )
3216 0 : pHst = pUndo->GetHistory();
3217 :
3218 0 : SwCollectTableLineBoxes aPara( true, eHdlnMode, pHst );
3219 0 : SwTableLine* pLn = rTable.GetTabLines()[ 0 ];
3220 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
3221 0 : it != pLn->GetTabBoxes().end(); ++it)
3222 0 : sw_Box_CollectBox(*it, &aPara );
3223 :
3224 0 : aPara.SetValues( true );
3225 0 : pLn = pNew->GetTable().GetTabLines()[ 0 ];
3226 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
3227 0 : it != pLn->GetTabBoxes().end(); ++it)
3228 0 : sw_BoxSetSplitBoxFormats(*it, &aPara );
3229 : }
3230 0 : break;
3231 :
3232 : case HEADLINE_CNTNTCOPY:
3233 0 : rTable.CopyHeadlineIntoTable( *pNew );
3234 0 : if( pUndo )
3235 0 : pUndo->SetTableNodeOffset( pNew->GetIndex() );
3236 0 : break;
3237 :
3238 : case HEADLINE_NONE:
3239 : // Switch off repeating the Header
3240 0 : pNew->GetTable().SetRowsToRepeat( 0 );
3241 0 : break;
3242 : }
3243 :
3244 : // And insert Frms
3245 0 : SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() );
3246 0 : GetNodes().GoNext( &aNdIdx ); // To the next ContentNode
3247 0 : pNew->MakeFrms( &aNdIdx );
3248 :
3249 : // Insert a paragraph between the Table
3250 0 : GetNodes().MakeTextNode( SwNodeIndex( *pNew ),
3251 0 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
3252 : }
3253 :
3254 : // Update Layout
3255 0 : aFndBox.MakeFrms( rTable );
3256 :
3257 : // TL_CHART2: need to inform chart of probably changed cell names
3258 0 : UpdateCharts( rTable.GetFrameFormat()->GetName() );
3259 :
3260 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
3261 :
3262 0 : return 0 != pNew;
3263 : }
3264 :
3265 0 : static bool lcl_ChgTableSize( SwTable& rTable )
3266 : {
3267 : // The Attribute must not be set via the Modify or else all Boxes are
3268 : // set back to 0.
3269 : // So lock the Format.
3270 0 : SwFrameFormat* pFormat = rTable.GetFrameFormat();
3271 0 : SwFormatFrmSize aTableMaxSz( pFormat->GetFrmSize() );
3272 :
3273 0 : if( USHRT_MAX == aTableMaxSz.GetWidth() )
3274 0 : return false;
3275 :
3276 0 : bool bLocked = pFormat->IsModifyLocked();
3277 0 : pFormat->LockModify();
3278 :
3279 0 : aTableMaxSz.SetWidth( 0 );
3280 :
3281 0 : SwTableLines& rLns = rTable.GetTabLines();
3282 0 : for( auto pLn : rLns )
3283 : {
3284 0 : SwTwips nMaxLnWidth = 0;
3285 0 : SwTableBoxes& rBoxes = pLn->GetTabBoxes();
3286 0 : for( auto pBox : rBoxes )
3287 0 : nMaxLnWidth += pBox->GetFrameFormat()->GetFrmSize().GetWidth();
3288 :
3289 0 : if( nMaxLnWidth > aTableMaxSz.GetWidth() )
3290 0 : aTableMaxSz.SetWidth( nMaxLnWidth );
3291 : }
3292 0 : pFormat->SetFormatAttr( aTableMaxSz );
3293 0 : if( !bLocked ) // Release the Lock if appropriate
3294 0 : pFormat->UnlockModify();
3295 :
3296 0 : return true;
3297 : }
3298 :
3299 0 : class _SplitTable_Para
3300 : {
3301 : std::map<SwFrameFormat*, SwFrameFormat*> aSrcDestMap;
3302 : SwTableNode* pNewTableNd;
3303 : SwTable& rOldTable;
3304 :
3305 : public:
3306 0 : _SplitTable_Para( SwTableNode* pNew, SwTable& rOld )
3307 0 : : aSrcDestMap(), pNewTableNd( pNew ), rOldTable( rOld )
3308 0 : {}
3309 0 : SwFrameFormat* GetDestFormat( SwFrameFormat* pSrcFormat ) const
3310 : {
3311 0 : std::map<SwFrameFormat*, SwFrameFormat*>::const_iterator it = aSrcDestMap.find( pSrcFormat );
3312 0 : return it == aSrcDestMap.end() ? NULL : it->second;
3313 : }
3314 :
3315 0 : void InsertSrcDest( SwFrameFormat* pSrcFormat, SwFrameFormat* pDestFormat )
3316 0 : { aSrcDestMap[ pSrcFormat ] = pDestFormat; }
3317 :
3318 0 : void ChgBox( SwTableBox* pBox )
3319 : {
3320 0 : rOldTable.GetTabSortBoxes().erase( pBox );
3321 0 : pNewTableNd->GetTable().GetTabSortBoxes().insert( pBox );
3322 0 : }
3323 : };
3324 :
3325 : static void lcl_SplitTable_CpyBox( SwTableBox* pBox, _SplitTable_Para* pPara );
3326 :
3327 0 : static void lcl_SplitTable_CpyLine( SwTableLine* pLn, _SplitTable_Para* pPara )
3328 : {
3329 0 : SwFrameFormat *pSrcFormat = pLn->GetFrameFormat();
3330 0 : SwTableLineFormat* pDestFormat = static_cast<SwTableLineFormat*>( pPara->GetDestFormat( pSrcFormat ) );
3331 0 : if( pDestFormat == NULL )
3332 : {
3333 0 : pPara->InsertSrcDest( pSrcFormat, pLn->ClaimFrameFormat() );
3334 : }
3335 : else
3336 0 : pLn->ChgFrameFormat( pDestFormat );
3337 :
3338 0 : for( SwTableBoxes::iterator it = pLn->GetTabBoxes().begin();
3339 0 : it != pLn->GetTabBoxes().end(); ++it)
3340 0 : lcl_SplitTable_CpyBox(*it, pPara );
3341 0 : }
3342 :
3343 0 : static void lcl_SplitTable_CpyBox( SwTableBox* pBox, _SplitTable_Para* pPara )
3344 : {
3345 0 : SwFrameFormat *pSrcFormat = pBox->GetFrameFormat();
3346 0 : SwTableBoxFormat* pDestFormat = static_cast<SwTableBoxFormat*>(pPara->GetDestFormat( pSrcFormat ));
3347 0 : if( pDestFormat == NULL )
3348 : {
3349 0 : pPara->InsertSrcDest( pSrcFormat, pBox->ClaimFrameFormat() );
3350 : }
3351 : else
3352 0 : pBox->ChgFrameFormat( pDestFormat );
3353 :
3354 0 : if( pBox->GetSttNd() )
3355 0 : pPara->ChgBox( pBox );
3356 : else
3357 0 : for( SwTableLine* pLine : pBox->GetTabLines() )
3358 0 : lcl_SplitTable_CpyLine( pLine, pPara );
3359 0 : }
3360 :
3361 0 : SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, bool bAfter,
3362 : bool bCalcNewSize )
3363 : {
3364 0 : SwNode* pNd = &rPos.GetNode();
3365 0 : SwTableNode* pTNd = pNd->FindTableNode();
3366 0 : if( !pTNd || pNd->IsTableNode() )
3367 0 : return 0;
3368 :
3369 0 : sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3370 :
3371 : // Find this Box/top-level line
3372 0 : SwTable& rTable = pTNd->GetTable();
3373 0 : SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3374 0 : if( !pBox )
3375 0 : return 0;
3376 :
3377 0 : SwTableLine* pLine = pBox->GetUpper();
3378 0 : while( pLine->GetUpper() )
3379 0 : pLine = pLine->GetUpper()->GetUpper();
3380 :
3381 : // pLine now contains the top-level line
3382 0 : sal_uInt16 nLinePos = rTable.GetTabLines().GetPos( pLine );
3383 0 : if( USHRT_MAX == nLinePos ||
3384 0 : ( bAfter ? ++nLinePos >= rTable.GetTabLines().size() : !nLinePos ))
3385 0 : return 0; // Not found or last Line!
3386 :
3387 : // Find the first Box of the succeeding Line
3388 0 : SwTableLine* pNextLine = rTable.GetTabLines()[ nLinePos ];
3389 0 : pBox = pNextLine->GetTabBoxes()[0];
3390 0 : while( !pBox->GetSttNd() )
3391 0 : pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
3392 :
3393 : // Insert an EndNode and TableNode into the Nodes Array
3394 : SwTableNode * pNewTableNd;
3395 : {
3396 0 : SwEndNode* pOldTableEndNd = pTNd->EndOfSectionNode()->GetEndNode();
3397 : OSL_ENSURE( pOldTableEndNd, "Where is the EndNode?" );
3398 :
3399 0 : SwNodeIndex aIdx( *pBox->GetSttNd() );
3400 0 : new SwEndNode( aIdx, *pTNd );
3401 0 : pNewTableNd = new SwTableNode( aIdx );
3402 0 : pNewTableNd->GetTable().SetTableModel( rTable.IsNewModel() );
3403 :
3404 0 : pOldTableEndNd->pStartOfSection = pNewTableNd;
3405 0 : pNewTableNd->pEndOfSection = pOldTableEndNd;
3406 :
3407 0 : SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3408 0 : do {
3409 : OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3410 0 : pBoxNd->pStartOfSection = pNewTableNd;
3411 0 : pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3412 0 : } while( pBoxNd != pOldTableEndNd );
3413 : }
3414 :
3415 : {
3416 : // Move the Lines
3417 0 : SwTable& rNewTable = pNewTableNd->GetTable();
3418 0 : rNewTable.GetTabLines().insert( rNewTable.GetTabLines().begin(),
3419 0 : rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3420 :
3421 : /* From the back (bottom right) to the front (top left) deregister all Boxes from the
3422 : Chart Data Provider. The Modify event is triggered in the calling function.
3423 : TL_CHART2: */
3424 0 : SwChartDataProvider *pPCD = rTable.GetFrameFormat()->getIDocumentChartDataProviderAccess()->GetChartDataProvider();
3425 0 : if( pPCD )
3426 : {
3427 0 : for (SwTableLines::size_type k = nLinePos; k < rTable.GetTabLines().size(); ++k)
3428 : {
3429 0 : const SwTableLines::size_type nLineIdx = (rTable.GetTabLines().size() - 1) - k + nLinePos;
3430 0 : const SwTableBoxes::size_type nBoxCnt = rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes().size();
3431 0 : for (SwTableBoxes::size_type j = 0; j < nBoxCnt; ++j)
3432 : {
3433 0 : const SwTableBoxes::size_type nIdx = nBoxCnt - 1 - j;
3434 0 : pPCD->DeleteBox( &rTable, *rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] );
3435 : }
3436 : }
3437 : }
3438 :
3439 : // Delete
3440 0 : sal_uInt16 nDeleted = rTable.GetTabLines().size() - nLinePos;
3441 0 : rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3442 :
3443 : // Move the affected Boxes. Make the Formats unique and correct the StartNodes
3444 0 : _SplitTable_Para aPara( pNewTableNd, rTable );
3445 0 : for( SwTableLine* pNewLine : rNewTable.GetTabLines() )
3446 0 : lcl_SplitTable_CpyLine( pNewLine, &aPara );
3447 0 : rTable.CleanUpBottomRowSpan( nDeleted );
3448 : }
3449 :
3450 : {
3451 : // Copy the Table FrmFormat
3452 0 : SwFrameFormat* pOldTableFormat = rTable.GetFrameFormat();
3453 : SwFrameFormat* pNewTableFormat = pOldTableFormat->GetDoc()->MakeTableFrameFormat(
3454 : pOldTableFormat->GetDoc()->GetUniqueTableName(),
3455 0 : pOldTableFormat->GetDoc()->GetDfltFrameFormat() );
3456 :
3457 0 : *pNewTableFormat = *pOldTableFormat;
3458 0 : pNewTableNd->GetTable().RegisterToFormat( *pNewTableFormat );
3459 :
3460 : // Calculate a new Size?
3461 : // lcl_ChgTableSize: Only execute the second call if the first call was
3462 : // successful, thus has an absolute Size
3463 0 : if( bCalcNewSize && lcl_ChgTableSize( rTable ) )
3464 0 : lcl_ChgTableSize( pNewTableNd->GetTable() );
3465 : }
3466 :
3467 : // TL_CHART2: need to inform chart of probably changed cell names
3468 0 : rTable.UpdateCharts();
3469 :
3470 0 : return pNewTableNd; // That's it!
3471 : }
3472 :
3473 : /**
3474 : * rPos needs to be in the Table that remains
3475 : *
3476 : * @param bWithPrev merge the current Table with the preceding
3477 : * or succeeding one
3478 : */
3479 0 : bool SwDoc::MergeTable( const SwPosition& rPos, bool bWithPrev, sal_uInt16 nMode )
3480 : {
3481 0 : SwTableNode* pTableNd = rPos.nNode.GetNode().FindTableNode(), *pDelTableNd;
3482 0 : if( !pTableNd )
3483 0 : return false;
3484 :
3485 0 : SwNodes& rNds = GetNodes();
3486 0 : if( bWithPrev )
3487 0 : pDelTableNd = rNds[ pTableNd->GetIndex() - 1 ]->FindTableNode();
3488 : else
3489 0 : pDelTableNd = rNds[ pTableNd->EndOfSectionIndex() + 1 ]->GetTableNode();
3490 0 : if( !pDelTableNd )
3491 0 : return false;
3492 :
3493 0 : if( pTableNd->GetTable().ISA( SwDDETable ) ||
3494 0 : pDelTableNd->GetTable().ISA( SwDDETable ))
3495 0 : return false;
3496 :
3497 : // Delete HTML Layout
3498 0 : pTableNd->GetTable().SetHTMLTableLayout( 0 );
3499 0 : pDelTableNd->GetTable().SetHTMLTableLayout( 0 );
3500 :
3501 : // Both Tables are present; we can start
3502 0 : SwUndoMergeTable* pUndo = 0;
3503 0 : SwHistory* pHistory = 0;
3504 0 : if (GetIDocumentUndoRedo().DoesUndo())
3505 : {
3506 0 : pUndo = new SwUndoMergeTable( *pTableNd, *pDelTableNd, bWithPrev, nMode );
3507 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
3508 0 : pHistory = new SwHistory;
3509 : }
3510 :
3511 : // Adapt all "TableFormulas"
3512 0 : SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3513 0 : aMsgHint.DATA.pDelTable = &pDelTableNd->GetTable();
3514 0 : aMsgHint.eFlags = TBL_MERGETBL;
3515 0 : aMsgHint.pHistory = pHistory;
3516 0 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
3517 :
3518 : // The actual merge
3519 0 : SwNodeIndex aIdx( bWithPrev ? *pTableNd : *pDelTableNd );
3520 0 : bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode, pHistory );
3521 :
3522 0 : if( pHistory )
3523 : {
3524 0 : if( pHistory->Count() )
3525 0 : pUndo->SaveFormula( *pHistory );
3526 0 : delete pHistory;
3527 : }
3528 0 : if( bRet )
3529 : {
3530 0 : getIDocumentState().SetModified();
3531 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
3532 : }
3533 0 : return bRet;
3534 : }
3535 :
3536 0 : bool SwNodes::MergeTable( const SwNodeIndex& rPos, bool bWithPrev,
3537 : sal_uInt16 nMode, SwHistory* )
3538 : {
3539 0 : SwTableNode* pDelTableNd = rPos.GetNode().GetTableNode();
3540 : OSL_ENSURE( pDelTableNd, "Where did the TableNode go?" );
3541 :
3542 0 : SwTableNode* pTableNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode();
3543 : OSL_ENSURE( pTableNd, "Where did the TableNode go?" );
3544 :
3545 0 : if( !pDelTableNd || !pTableNd )
3546 0 : return false;
3547 :
3548 0 : pDelTableNd->DelFrms();
3549 :
3550 0 : SwTable& rDelTable = pDelTableNd->GetTable();
3551 0 : SwTable& rTable = pTableNd->GetTable();
3552 :
3553 : // Find Lines for the Layout update
3554 0 : _FndBox aFndBox( 0, 0 );
3555 0 : aFndBox.SetTableLines( rTable );
3556 0 : aFndBox.DelFrms( rTable );
3557 :
3558 : // TL_CHART2:
3559 : // tell the charts about the table to be deleted and have them use their own data
3560 0 : GetDoc()->getIDocumentChartDataProviderAccess().CreateChartInternalDataProviders( &rDelTable );
3561 :
3562 : // Sync the TableFormat's Width
3563 : {
3564 0 : const SwFormatFrmSize& rTableSz = rTable.GetFrameFormat()->GetFrmSize();
3565 0 : const SwFormatFrmSize& rDelTableSz = rDelTable.GetFrameFormat()->GetFrmSize();
3566 0 : if( rTableSz != rDelTableSz )
3567 : {
3568 : // The needs correction
3569 0 : if( bWithPrev )
3570 0 : rDelTable.GetFrameFormat()->SetFormatAttr( rTableSz );
3571 : else
3572 0 : rTable.GetFrameFormat()->SetFormatAttr( rDelTableSz );
3573 : }
3574 : }
3575 :
3576 0 : if( !bWithPrev )
3577 : {
3578 : // Transfer all Attributes of the succeeding Table to the preceding one
3579 : // We do this, because the succeeding one is deleted when deleting the Node
3580 0 : rTable.SetRowsToRepeat( rDelTable.GetRowsToRepeat() );
3581 0 : rTable.SetTableChgMode( rDelTable.GetTableChgMode() );
3582 :
3583 0 : rTable.GetFrameFormat()->LockModify();
3584 0 : *rTable.GetFrameFormat() = *rDelTable.GetFrameFormat();
3585 : // Also switch the Name
3586 0 : rTable.GetFrameFormat()->SetName( rDelTable.GetFrameFormat()->GetName() );
3587 0 : rTable.GetFrameFormat()->UnlockModify();
3588 : }
3589 :
3590 : // Move the Lines and Boxes
3591 0 : SwTableLines::size_type nOldSize = rTable.GetTabLines().size();
3592 0 : rTable.GetTabLines().insert( rTable.GetTabLines().begin() + nOldSize,
3593 0 : rDelTable.GetTabLines().begin(), rDelTable.GetTabLines().end() );
3594 0 : rDelTable.GetTabLines().clear();
3595 :
3596 0 : rTable.GetTabSortBoxes().insert( rDelTable.GetTabSortBoxes() );
3597 0 : rDelTable.GetTabSortBoxes().clear();
3598 :
3599 : // The preceding Table always remains, while the succeeding one is deleted
3600 0 : SwEndNode* pTableEndNd = pDelTableNd->EndOfSectionNode();
3601 0 : pTableNd->pEndOfSection = pTableEndNd;
3602 :
3603 0 : SwNodeIndex aIdx( *pDelTableNd, 1 );
3604 :
3605 0 : SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3606 0 : do {
3607 : OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3608 0 : pBoxNd->pStartOfSection = pTableNd;
3609 0 : pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3610 : } while( pBoxNd != pTableEndNd );
3611 0 : pBoxNd->pStartOfSection = pTableNd;
3612 :
3613 0 : aIdx -= 2;
3614 0 : DelNodes( aIdx, 2 );
3615 :
3616 : // tweak the conditional styles at the first inserted Line
3617 0 : const SwTableLine* pFirstLn = rTable.GetTabLines()[ nOldSize ];
3618 : if( 1 == nMode )
3619 : {
3620 : // Set Header Template in the Line and save in the History
3621 : // if needed for Undo!
3622 : }
3623 0 : sw_LineSetHeadCondColl( pFirstLn );
3624 :
3625 : // Clean up the Borders
3626 0 : if( nOldSize )
3627 : {
3628 0 : _SwGCLineBorder aPara( rTable );
3629 0 : aPara.nLinePos = --nOldSize;
3630 0 : pFirstLn = rTable.GetTabLines()[ nOldSize ];
3631 0 : sw_GC_Line_Border( pFirstLn, &aPara );
3632 : }
3633 :
3634 : // Update Layout
3635 0 : aFndBox.MakeFrms( rTable );
3636 :
3637 0 : return true;
3638 : }
3639 :
3640 : // Use the PtrArray's ForEach method
3641 : struct _SetAFormatTabPara
3642 : {
3643 : SwTableAutoFormat& rTableFormat;
3644 : SwUndoTableAutoFormat* pUndo;
3645 : sal_uInt16 nEndBox, nCurBox;
3646 : sal_uInt8 nAFormatLine, nAFormatBox;
3647 :
3648 0 : explicit _SetAFormatTabPara( const SwTableAutoFormat& rNew )
3649 : : rTableFormat( (SwTableAutoFormat&)rNew ), pUndo( 0 ),
3650 0 : nEndBox( 0 ), nCurBox( 0 ), nAFormatLine( 0 ), nAFormatBox( 0 )
3651 0 : {}
3652 : };
3653 :
3654 : // Forward declare so that the Lines and Boxes can use recursion
3655 : static bool lcl_SetAFormatBox(_FndBox &, _SetAFormatTabPara *pSetPara);
3656 : static bool lcl_SetAFormatLine(_FndLine &, _SetAFormatTabPara *pPara);
3657 :
3658 0 : static bool lcl_SetAFormatLine(_FndLine & rLine, _SetAFormatTabPara *pPara)
3659 : {
3660 0 : for (_FndBoxes::iterator it = rLine.GetBoxes().begin();
3661 0 : it != rLine.GetBoxes().end(); ++it)
3662 : {
3663 0 : lcl_SetAFormatBox(*it, pPara);
3664 : }
3665 0 : return true;
3666 : }
3667 :
3668 0 : static bool lcl_SetAFormatBox( _FndBox & rBox, _SetAFormatTabPara *pSetPara )
3669 : {
3670 0 : if (!rBox.GetUpper()->GetUpper()) // Box on first level?
3671 : {
3672 0 : if( !pSetPara->nCurBox )
3673 0 : pSetPara->nAFormatBox = 0;
3674 0 : else if( pSetPara->nCurBox == pSetPara->nEndBox )
3675 0 : pSetPara->nAFormatBox = 3;
3676 : else
3677 0 : pSetPara->nAFormatBox = (sal_uInt8)(1 + ((pSetPara->nCurBox-1) & 1));
3678 : }
3679 :
3680 0 : if (rBox.GetBox()->GetSttNd())
3681 : {
3682 0 : SwTableBox* pSetBox = static_cast<SwTableBox*>(rBox.GetBox());
3683 0 : SwDoc* pDoc = pSetBox->GetFrameFormat()->GetDoc();
3684 0 : SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1 );
3685 0 : SfxItemSet aBoxSet( pDoc->GetAttrPool(), aTableBoxSetRange );
3686 0 : sal_uInt8 nPos = pSetPara->nAFormatLine * 4 + pSetPara->nAFormatBox;
3687 : pSetPara->rTableFormat.UpdateToSet( nPos, aCharSet,
3688 0 : SwTableAutoFormat::UPDATE_CHAR, 0 );
3689 : pSetPara->rTableFormat.UpdateToSet( nPos, aBoxSet,
3690 : SwTableAutoFormat::UPDATE_BOX,
3691 0 : pDoc->GetNumberFormatter( true ) );
3692 0 : if( aCharSet.Count() )
3693 : {
3694 0 : sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
3695 0 : sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
3696 0 : for( ; nSttNd < nEndNd; ++nSttNd )
3697 : {
3698 0 : SwContentNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetContentNode();
3699 0 : if( pNd )
3700 0 : pNd->SetAttr( aCharSet );
3701 : }
3702 : }
3703 :
3704 0 : if( aBoxSet.Count() )
3705 : {
3706 0 : if( pSetPara->pUndo &&
3707 0 : SfxItemState::SET == aBoxSet.GetItemState( RES_BOXATR_FORMAT ))
3708 0 : pSetPara->pUndo->SaveBoxContent( *pSetBox );
3709 :
3710 0 : pSetBox->ClaimFrameFormat()->SetFormatAttr( aBoxSet );
3711 0 : }
3712 : }
3713 : else
3714 : {
3715 0 : for( _FndLine& rFndLine : rBox.GetLines() )
3716 0 : lcl_SetAFormatLine( rFndLine, pSetPara );
3717 : }
3718 :
3719 0 : if (!rBox.GetUpper()->GetUpper()) // a BaseLine
3720 0 : ++pSetPara->nCurBox;
3721 0 : return true;
3722 : }
3723 :
3724 : /**
3725 : * AutoFormat for the Table/TableSelection
3726 : */
3727 0 : bool SwDoc::SetTableAutoFormat( const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew )
3728 : {
3729 : OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3730 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3731 0 : if( !pTableNd )
3732 0 : return false;
3733 :
3734 : // Find all Boxes/Lines
3735 0 : _FndBox aFndBox( 0, 0 );
3736 : {
3737 0 : _FndPara aPara( rBoxes, &aFndBox );
3738 0 : ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3739 : }
3740 0 : if( aFndBox.GetLines().empty() )
3741 0 : return false;
3742 :
3743 0 : SwTable &table = pTableNd->GetTable();
3744 0 : table.SetHTMLTableLayout( 0 );
3745 :
3746 0 : _FndBox* pFndBox = &aFndBox;
3747 0 : while( 1 == pFndBox->GetLines().size() &&
3748 0 : 1 == pFndBox->GetLines().front().GetBoxes().size() )
3749 : {
3750 0 : pFndBox = &pFndBox->GetLines().front().GetBoxes()[0];
3751 : }
3752 :
3753 0 : if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3754 0 : pFndBox = pFndBox->GetUpper()->GetUpper();
3755 :
3756 : // Disable Undo, but first store parameters
3757 0 : SwUndoTableAutoFormat* pUndo = 0;
3758 0 : bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3759 0 : if (bUndo)
3760 : {
3761 0 : pUndo = new SwUndoTableAutoFormat( *pTableNd, rNew );
3762 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
3763 0 : GetIDocumentUndoRedo().DoUndo(false);
3764 : }
3765 :
3766 0 : rNew.RestoreTableProperties(table);
3767 :
3768 0 : _SetAFormatTabPara aPara( rNew );
3769 0 : _FndLines& rFLns = pFndBox->GetLines();
3770 :
3771 0 : for( _FndLines::size_type n = 0; n < rFLns.size(); ++n )
3772 : {
3773 0 : _FndLine* pLine = &rFLns[n];
3774 :
3775 : // Set Upper to 0 (thus simulate BaseLine)
3776 0 : _FndBox* pSaveBox = pLine->GetUpper();
3777 0 : pLine->SetUpper( 0 );
3778 :
3779 0 : if( !n )
3780 0 : aPara.nAFormatLine = 0;
3781 0 : else if (static_cast<size_t>(n+1) == rFLns.size())
3782 0 : aPara.nAFormatLine = 3;
3783 : else
3784 0 : aPara.nAFormatLine = (sal_uInt8)(1 + ((n-1) & 1 ));
3785 :
3786 0 : aPara.nAFormatBox = 0;
3787 0 : aPara.nCurBox = 0;
3788 0 : aPara.nEndBox = pLine->GetBoxes().size()-1;
3789 0 : aPara.pUndo = pUndo;
3790 0 : for (_FndBoxes::iterator it = pLine->GetBoxes().begin();
3791 0 : it != pLine->GetBoxes().end(); ++it)
3792 : {
3793 0 : lcl_SetAFormatBox(*it, &aPara);
3794 : }
3795 :
3796 0 : pLine->SetUpper( pSaveBox );
3797 : }
3798 :
3799 0 : if( pUndo )
3800 : {
3801 0 : GetIDocumentUndoRedo().DoUndo(bUndo);
3802 : }
3803 :
3804 0 : getIDocumentState().SetModified();
3805 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
3806 :
3807 0 : return true;
3808 : }
3809 :
3810 : /**
3811 : * Find out who has the Attributes
3812 : */
3813 0 : bool SwDoc::GetTableAutoFormat( const SwSelBoxes& rBoxes, SwTableAutoFormat& rGet )
3814 : {
3815 : OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3816 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3817 0 : if( !pTableNd )
3818 0 : return false;
3819 :
3820 : // Find all Boxes/Lines
3821 0 : _FndBox aFndBox( 0, 0 );
3822 : {
3823 0 : _FndPara aPara( rBoxes, &aFndBox );
3824 0 : ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3825 : }
3826 0 : if( aFndBox.GetLines().empty() )
3827 0 : return false;
3828 :
3829 : // Store table properties
3830 0 : SwTable &table = pTableNd->GetTable();
3831 0 : rGet.StoreTableProperties(table);
3832 :
3833 0 : _FndBox* pFndBox = &aFndBox;
3834 0 : while( 1 == pFndBox->GetLines().size() &&
3835 0 : 1 == pFndBox->GetLines().front().GetBoxes().size() )
3836 : {
3837 0 : pFndBox = &pFndBox->GetLines().front().GetBoxes()[0];
3838 : }
3839 :
3840 0 : if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3841 0 : pFndBox = pFndBox->GetUpper()->GetUpper();
3842 :
3843 0 : _FndLines& rFLns = pFndBox->GetLines();
3844 :
3845 : sal_uInt16 aLnArr[4];
3846 0 : aLnArr[0] = 0;
3847 0 : aLnArr[1] = 1 < rFLns.size() ? 1 : 0;
3848 0 : aLnArr[2] = 2 < rFLns.size() ? 2 : aLnArr[1];
3849 0 : aLnArr[3] = rFLns.size() - 1;
3850 :
3851 0 : for( sal_uInt8 nLine = 0; nLine < 4; ++nLine )
3852 : {
3853 0 : _FndLine& rLine = rFLns[ aLnArr[ nLine ] ];
3854 :
3855 : sal_uInt16 aBoxArr[4];
3856 0 : aBoxArr[0] = 0;
3857 0 : aBoxArr[1] = 1 < rLine.GetBoxes().size() ? 1 : 0;
3858 0 : aBoxArr[2] = 2 < rLine.GetBoxes().size() ? 2 : aBoxArr[1];
3859 0 : aBoxArr[3] = rLine.GetBoxes().size() - 1;
3860 :
3861 0 : for( sal_uInt8 nBox = 0; nBox < 4; ++nBox )
3862 : {
3863 0 : SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ].GetBox();
3864 : // Always apply to the first ones
3865 0 : while( !pFBox->GetSttNd() )
3866 0 : pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0];
3867 :
3868 0 : sal_uInt8 nPos = nLine * 4 + nBox;
3869 0 : SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 );
3870 0 : SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3871 0 : if( !pCNd )
3872 0 : pCNd = GetNodes().GoNext( &aIdx );
3873 :
3874 0 : if( pCNd )
3875 0 : rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(),
3876 0 : SwTableAutoFormat::UPDATE_CHAR, 0 );
3877 0 : rGet.UpdateFromSet( nPos, pFBox->GetFrameFormat()->GetAttrSet(),
3878 : SwTableAutoFormat::UPDATE_BOX,
3879 0 : GetNumberFormatter( true ) );
3880 0 : }
3881 : }
3882 :
3883 0 : return true;
3884 : }
3885 :
3886 1064 : OUString SwDoc::GetUniqueTableName() const
3887 : {
3888 1064 : if( IsInMailMerge())
3889 : {
3890 : OUString newName = "MailMergeTable"
3891 0 : + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
3892 0 : + OUString::number( mpTableFrameFormatTable->size() + 1 );
3893 0 : return newName;
3894 : }
3895 :
3896 1064 : ResId aId( STR_TABLE_DEFNAME, *pSwResMgr );
3897 1064 : const OUString aName( aId );
3898 :
3899 1064 : const size_t nFlagSize = ( mpTableFrameFormatTable->size() / 8 ) + 2;
3900 :
3901 1064 : sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
3902 1064 : memset( pSetFlags, 0, nFlagSize );
3903 :
3904 3801 : for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3905 : {
3906 2737 : const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3907 10946 : if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3908 10942 : pFormat->GetName().startsWith( aName ) )
3909 : {
3910 : // Get number and set the Flag
3911 2719 : const sal_Int32 nNmLen = aName.getLength();
3912 2719 : size_t nNum = pFormat->GetName().copy( nNmLen ).toInt32();
3913 2719 : if( nNum-- && nNum < mpTableFrameFormatTable->size() )
3914 2472 : pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
3915 : }
3916 : }
3917 :
3918 : // All numbers are flagged properly, thus calculate the right number
3919 1064 : size_t nNum = mpTableFrameFormatTable->size();
3920 1167 : for( size_t n = 0; n < nFlagSize; ++n )
3921 : {
3922 1167 : auto nTmp = pSetFlags[ n ];
3923 1167 : if( nTmp != 0xFF )
3924 : {
3925 : // Calculate the number
3926 1064 : nNum = n * 8;
3927 3565 : while( nTmp & 1 )
3928 : {
3929 1437 : ++nNum;
3930 1437 : nTmp >>= 1;
3931 : }
3932 1064 : break;
3933 : }
3934 : }
3935 :
3936 1064 : delete [] pSetFlags;
3937 1064 : return aName + OUString::number( ++nNum );
3938 : }
3939 :
3940 116 : SwTableFormat* SwDoc::FindTableFormatByName( const OUString& rName, bool bAll ) const
3941 : {
3942 116 : const SwFormat* pRet = 0;
3943 116 : if( bAll )
3944 0 : pRet = FindFormatByName( *mpTableFrameFormatTable, rName );
3945 : else
3946 : {
3947 : // Only the ones set in the Doc
3948 705 : for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3949 : {
3950 609 : const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3951 2436 : if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3952 2436 : pFormat->GetName() == rName )
3953 : {
3954 20 : pRet = pFormat;
3955 20 : break;
3956 : }
3957 : }
3958 : }
3959 116 : return const_cast<SwTableFormat*>(static_cast<const SwTableFormat*>(pRet));
3960 : }
3961 :
3962 0 : bool SwDoc::SetColRowWidthHeight( SwTableBox& rAktBox, sal_uInt16 eType,
3963 : SwTwips nAbsDiff, SwTwips nRelDiff )
3964 : {
3965 0 : SwTableNode* pTableNd = const_cast<SwTableNode*>(rAktBox.GetSttNd()->FindTableNode());
3966 0 : SwUndo* pUndo = 0;
3967 :
3968 0 : if( nsTableChgWidthHeightType::WH_FLAG_INSDEL & eType && pTableNd->GetTable().ISA( SwDDETable ))
3969 0 : return false;
3970 :
3971 0 : SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3972 0 : aMsgHint.eFlags = TBL_BOXPTR;
3973 0 : getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
3974 :
3975 0 : bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3976 0 : bool bRet = false;
3977 0 : switch( eType & 0xff )
3978 : {
3979 : case nsTableChgWidthHeightType::WH_COL_LEFT:
3980 : case nsTableChgWidthHeightType::WH_COL_RIGHT:
3981 : case nsTableChgWidthHeightType::WH_CELL_LEFT:
3982 : case nsTableChgWidthHeightType::WH_CELL_RIGHT:
3983 : {
3984 0 : bRet = pTableNd->GetTable().SetColWidth( rAktBox,
3985 : eType, nAbsDiff, nRelDiff,
3986 0 : (bUndo) ? &pUndo : 0 );
3987 : }
3988 0 : break;
3989 : case nsTableChgWidthHeightType::WH_ROW_TOP:
3990 : case nsTableChgWidthHeightType::WH_ROW_BOTTOM:
3991 : case nsTableChgWidthHeightType::WH_CELL_TOP:
3992 : case nsTableChgWidthHeightType::WH_CELL_BOTTOM:
3993 0 : bRet = pTableNd->GetTable().SetRowHeight( rAktBox,
3994 : eType, nAbsDiff, nRelDiff,
3995 0 : (bUndo) ? &pUndo : 0 );
3996 0 : break;
3997 : }
3998 :
3999 0 : GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off
4000 0 : if( pUndo )
4001 : {
4002 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
4003 : }
4004 :
4005 0 : if( bRet )
4006 : {
4007 0 : getIDocumentState().SetModified();
4008 0 : if( nsTableChgWidthHeightType::WH_FLAG_INSDEL & eType )
4009 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
4010 : }
4011 0 : return bRet;
4012 : }
4013 :
4014 0 : void SwDoc::ChkBoxNumFormat( SwTableBox& rBox, bool bCallUpdate )
4015 : {
4016 : // Optimization: If the Box says it's Text, it remains Text
4017 0 : const SfxPoolItem* pNumFormatItem = 0;
4018 0 : if( SfxItemState::SET == rBox.GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT,
4019 0 : false, &pNumFormatItem ) && GetNumberFormatter()->IsTextFormat(
4020 0 : static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue() ))
4021 0 : return ;
4022 :
4023 0 : SwUndoTableNumFormat* pUndo = 0;
4024 :
4025 : bool bIsEmptyTextNd;
4026 0 : bool bChgd = true;
4027 : sal_uInt32 nFormatIdx;
4028 : double fNumber;
4029 0 : if( rBox.HasNumContent( fNumber, nFormatIdx, bIsEmptyTextNd ) )
4030 : {
4031 0 : if( !rBox.IsNumberChanged() )
4032 0 : bChgd = false;
4033 : else
4034 : {
4035 0 : if (GetIDocumentUndoRedo().DoesUndo())
4036 : {
4037 0 : GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
4038 0 : pUndo = new SwUndoTableNumFormat( rBox );
4039 0 : pUndo->SetNumFormat( nFormatIdx, fNumber );
4040 : }
4041 :
4042 0 : SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4043 0 : SfxItemSet aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
4044 :
4045 0 : bool bLockModify = true;
4046 0 : bool bSetNumberFormat = false;
4047 0 : const bool bForceNumberFormat = IsInsTableFormatNum() && IsInsTableChangeNumFormat();
4048 :
4049 : // if the user forced a number format in this cell previously,
4050 : // keep it, unless the user set that she wants the full number
4051 : // format recognition
4052 0 : if( pNumFormatItem && !bForceNumberFormat )
4053 : {
4054 0 : sal_uLong nOldNumFormat = static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue();
4055 0 : SvNumberFormatter* pNumFormatr = GetNumberFormatter();
4056 :
4057 0 : short nFormatType = pNumFormatr->GetType( nFormatIdx );
4058 0 : if( nFormatType == pNumFormatr->GetType( nOldNumFormat ) || css::util::NumberFormat::NUMBER == nFormatType )
4059 : {
4060 : // Current and specified NumFormat match
4061 : // -> keep old Format
4062 0 : nFormatIdx = nOldNumFormat;
4063 0 : bSetNumberFormat = true;
4064 : }
4065 : else
4066 : {
4067 : // Current and specified NumFormat do not match
4068 : // -> insert as Text
4069 0 : bLockModify = bSetNumberFormat = false;
4070 : }
4071 : }
4072 :
4073 0 : if( bSetNumberFormat || bForceNumberFormat )
4074 : {
4075 0 : pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4076 :
4077 0 : aBoxSet.Put( SwTableBoxValue( fNumber ));
4078 0 : aBoxSet.Put( SwTableBoxNumFormat( nFormatIdx ));
4079 : }
4080 :
4081 : // It's not enough to only reset the Formula.
4082 : // Make sure that the Text is formatted accordingly
4083 0 : if( !bSetNumberFormat && !bIsEmptyTextNd && pNumFormatItem )
4084 : {
4085 : // Just resetting Attributes is not enough
4086 : // Make sure that the Text is formatted accordingly
4087 0 : pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4088 : }
4089 :
4090 0 : if( bLockModify ) pBoxFormat->LockModify();
4091 0 : pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
4092 0 : if( bLockModify ) pBoxFormat->UnlockModify();
4093 :
4094 0 : if( bSetNumberFormat )
4095 0 : pBoxFormat->SetFormatAttr( aBoxSet );
4096 : }
4097 : }
4098 : else
4099 : {
4100 : // It's not a number
4101 0 : const SfxPoolItem* pValueItem = 0, *pFormatItem = 0;
4102 0 : SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4103 0 : if( SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_FORMAT,
4104 0 : false, &pFormatItem ) ||
4105 : SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_VALUE,
4106 0 : false, &pValueItem ))
4107 : {
4108 0 : if (GetIDocumentUndoRedo().DoesUndo())
4109 : {
4110 0 : GetIDocumentUndoRedo().StartUndo( UNDO_TABLE_AUTOFMT, NULL );
4111 0 : pUndo = new SwUndoTableNumFormat( rBox );
4112 : }
4113 :
4114 0 : pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4115 :
4116 : // Remove all number formats
4117 0 : sal_uInt16 nWhich1 = RES_BOXATR_FORMULA;
4118 0 : if( !bIsEmptyTextNd )
4119 : {
4120 0 : nWhich1 = RES_BOXATR_FORMAT;
4121 :
4122 : // Just resetting Attributes is not enough
4123 : // Make sure that the Text is formatted accordingly
4124 0 : pBoxFormat->SetFormatAttr( *GetDfltAttr( nWhich1 ));
4125 : }
4126 0 : pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4127 : }
4128 : else
4129 0 : bChgd = false;
4130 : }
4131 :
4132 0 : if( bChgd )
4133 : {
4134 0 : if( pUndo )
4135 : {
4136 0 : pUndo->SetBox( rBox );
4137 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
4138 0 : GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
4139 : }
4140 :
4141 0 : const SwTableNode* pTableNd = rBox.GetSttNd()->FindTableNode();
4142 0 : if( bCallUpdate )
4143 : {
4144 0 : SwTableFormulaUpdate aTableUpdate( &pTableNd->GetTable() );
4145 0 : getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate );
4146 :
4147 : // TL_CHART2: update charts (when cursor leaves cell and
4148 : // automatic update is enabled)
4149 0 : if (AUTOUPD_FIELD_AND_CHARTS == GetDocumentSettingManager().getFieldUpdateFlags(true))
4150 0 : pTableNd->GetTable().UpdateCharts();
4151 : }
4152 0 : getIDocumentState().SetModified();
4153 : }
4154 : }
4155 :
4156 90 : void SwDoc::SetTableBoxFormulaAttrs( SwTableBox& rBox, const SfxItemSet& rSet )
4157 : {
4158 90 : if (GetIDocumentUndoRedo().DoesUndo())
4159 : {
4160 90 : GetIDocumentUndoRedo().AppendUndo( new SwUndoTableNumFormat(rBox, &rSet) );
4161 : }
4162 :
4163 90 : SwFrameFormat* pBoxFormat = rBox.ClaimFrameFormat();
4164 90 : if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
4165 : {
4166 0 : pBoxFormat->LockModify();
4167 0 : pBoxFormat->ResetFormatAttr( RES_BOXATR_VALUE );
4168 0 : pBoxFormat->UnlockModify();
4169 : }
4170 90 : else if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE ))
4171 : {
4172 90 : pBoxFormat->LockModify();
4173 90 : pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMULA );
4174 90 : pBoxFormat->UnlockModify();
4175 : }
4176 90 : pBoxFormat->SetFormatAttr( rSet );
4177 90 : getIDocumentState().SetModified();
4178 90 : }
4179 :
4180 44 : void SwDoc::ClearLineNumAttrs( SwPosition & rPos )
4181 : {
4182 44 : SwPaM aPam(rPos);
4183 44 : aPam.Move(fnMoveBackward);
4184 44 : SwContentNode *pNode = aPam.GetContentNode();
4185 44 : if ( 0 == pNode )
4186 44 : return ;
4187 44 : if( pNode->IsTextNode() )
4188 : {
4189 44 : SwTextNode * pTextNode = pNode->GetTextNode();
4190 88 : if (pTextNode && pTextNode->IsNumbered()
4191 53 : && pTextNode->GetText().isEmpty())
4192 : {
4193 0 : const SfxPoolItem* pFormatItem = 0;
4194 0 : SfxItemSet rSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
4195 : RES_PARATR_BEGIN, RES_PARATR_END - 1,
4196 0 : 0);
4197 0 : pTextNode->SwContentNode::GetAttr( rSet );
4198 0 : if ( SfxItemState::SET == rSet.GetItemState( RES_PARATR_NUMRULE , false , &pFormatItem ) )
4199 : {
4200 : SwUndoDelNum * pUndo;
4201 0 : if( GetIDocumentUndoRedo().DoesUndo() )
4202 : {
4203 0 : GetIDocumentUndoRedo().ClearRedo();
4204 0 : GetIDocumentUndoRedo().AppendUndo( pUndo = new SwUndoDelNum( aPam ) );
4205 : }
4206 : else
4207 0 : pUndo = 0;
4208 0 : SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
4209 0 : aRegH.RegisterInModify( pTextNode , *pTextNode );
4210 0 : if ( pUndo )
4211 0 : pUndo->AddNode( *pTextNode , false );
4212 0 : SfxStringItem * pNewItem = static_cast<SfxStringItem*>(pFormatItem->Clone());
4213 0 : pNewItem->SetValue(OUString());
4214 0 : rSet.Put( *pNewItem );
4215 0 : pTextNode->SetAttr( rSet );
4216 0 : delete pNewItem;
4217 0 : }
4218 : }
4219 44 : }
4220 : }
4221 :
4222 5015 : void SwDoc::ClearBoxNumAttrs( const SwNodeIndex& rNode )
4223 : {
4224 : SwStartNode* pSttNd;
4225 10030 : if( 0 != ( pSttNd = rNode.GetNode().
4226 5992 : FindSttNodeByType( SwTableBoxStartNode )) &&
4227 977 : 2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() )
4228 : {
4229 938 : SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
4230 1876 : GetTableBox( pSttNd->GetIndex() );
4231 :
4232 938 : const SfxPoolItem* pFormatItem = 0;
4233 938 : const SfxItemSet& rSet = pBox->GetFrameFormat()->GetAttrSet();
4234 2813 : if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT, false, &pFormatItem ) ||
4235 1875 : SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA, false ) ||
4236 937 : SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE, false ))
4237 : {
4238 1 : if (GetIDocumentUndoRedo().DoesUndo())
4239 : {
4240 1 : GetIDocumentUndoRedo().AppendUndo(new SwUndoTableNumFormat(*pBox));
4241 : }
4242 :
4243 1 : SwFrameFormat* pBoxFormat = pBox->ClaimFrameFormat();
4244 :
4245 : // Keep TextFormats!
4246 1 : sal_uInt16 nWhich1 = RES_BOXATR_FORMAT;
4247 2 : if( pFormatItem && GetNumberFormatter()->IsTextFormat(
4248 1 : static_cast<const SwTableBoxNumFormat*>(pFormatItem)->GetValue() ))
4249 0 : nWhich1 = RES_BOXATR_FORMULA;
4250 : else
4251 : // Just resetting Attributes is not enough
4252 : // Make sure that the Text is formatted accordingly
4253 1 : pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4254 :
4255 1 : pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4256 1 : getIDocumentState().SetModified();
4257 : }
4258 : }
4259 5015 : }
4260 :
4261 : /**
4262 : * Copies a Table from the same or another Doc into itself
4263 : * We create a new Table or an existing one is filled with the Content.
4264 : * We either fill in the Content from a certain Box or a certain TableSelection
4265 : *
4266 : * This method is called by edglss.cxx/fecopy.cxx
4267 : */
4268 0 : bool SwDoc::InsCopyOfTable( SwPosition& rInsPos, const SwSelBoxes& rBoxes,
4269 : const SwTable* pCpyTable, bool bCpyName, bool bCorrPos )
4270 : {
4271 : bool bRet;
4272 :
4273 : const SwTableNode* pSrcTableNd = pCpyTable
4274 : ? pCpyTable->GetTableNode()
4275 0 : : rBoxes[ 0 ]->GetSttNd()->FindTableNode();
4276 :
4277 0 : SwTableNode * pInsTableNd = rInsPos.nNode.GetNode().FindTableNode();
4278 :
4279 0 : bool const bUndo( GetIDocumentUndoRedo().DoesUndo() );
4280 0 : if( !pCpyTable && !pInsTableNd )
4281 : {
4282 0 : SwUndoCpyTable* pUndo = 0;
4283 0 : if (bUndo)
4284 : {
4285 0 : GetIDocumentUndoRedo().ClearRedo();
4286 0 : pUndo = new SwUndoCpyTable;
4287 : }
4288 :
4289 : {
4290 0 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
4291 0 : bRet = pSrcTableNd->GetTable().MakeCopy( this, rInsPos, rBoxes,
4292 0 : true, bCpyName );
4293 : }
4294 :
4295 0 : if( pUndo )
4296 : {
4297 0 : if( !bRet )
4298 : {
4299 0 : delete pUndo;
4300 0 : pUndo = 0;
4301 : }
4302 : else
4303 : {
4304 0 : pInsTableNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode();
4305 :
4306 0 : pUndo->SetTableSttIdx( pInsTableNd->GetIndex() );
4307 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
4308 : }
4309 0 : }
4310 : }
4311 : else
4312 : {
4313 0 : RedlineMode_t eOld = getIDocumentRedlineAccess().GetRedlineMode();
4314 0 : if( getIDocumentRedlineAccess().IsRedlineOn() )
4315 0 : getIDocumentRedlineAccess().SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON |
4316 : nsRedlineMode_t::REDLINE_SHOW_INSERT |
4317 0 : nsRedlineMode_t::REDLINE_SHOW_DELETE));
4318 :
4319 0 : SwUndoTableCpyTable* pUndo = 0;
4320 0 : if (bUndo)
4321 : {
4322 0 : GetIDocumentUndoRedo().ClearRedo();
4323 0 : pUndo = new SwUndoTableCpyTable;
4324 0 : GetIDocumentUndoRedo().DoUndo(false);
4325 : }
4326 :
4327 0 : SwDoc* pCpyDoc = const_cast<SwDoc*>(pSrcTableNd->GetDoc());
4328 0 : bool bDelCpyDoc = pCpyDoc == this;
4329 :
4330 0 : if( bDelCpyDoc )
4331 : {
4332 : // Copy the Table into a temporary Doc
4333 0 : pCpyDoc = new SwDoc;
4334 0 : pCpyDoc->acquire();
4335 :
4336 0 : SwPosition aPos( SwNodeIndex( pCpyDoc->GetNodes().GetEndOfContent() ));
4337 0 : if( !pSrcTableNd->GetTable().MakeCopy( pCpyDoc, aPos, rBoxes, true, true ))
4338 : {
4339 0 : if( pCpyDoc->release() == 0 )
4340 0 : delete pCpyDoc;
4341 :
4342 0 : if( pUndo )
4343 : {
4344 0 : GetIDocumentUndoRedo().DoUndo(bUndo);
4345 0 : delete pUndo;
4346 0 : pUndo = 0;
4347 : }
4348 0 : return false;
4349 : }
4350 0 : aPos.nNode -= 1; // Set to the Table's EndNode
4351 0 : pSrcTableNd = aPos.nNode.GetNode().FindTableNode();
4352 : }
4353 :
4354 0 : const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
4355 :
4356 0 : rInsPos.nContent.Assign( 0, 0 );
4357 :
4358 : // no complex into complex, but copy into or from new model is welcome
4359 0 : if( ( !pSrcTableNd->GetTable().IsTableComplex() || pInsTableNd->GetTable().IsNewModel() )
4360 0 : && ( bDelCpyDoc || !rBoxes.empty() ) )
4361 : {
4362 : // Copy the Table "relatively"
4363 : const SwSelBoxes* pBoxes;
4364 0 : SwSelBoxes aBoxes;
4365 :
4366 0 : if( bDelCpyDoc )
4367 : {
4368 0 : SwTableBox* pBox = pInsTableNd->GetTable().GetTableBox(
4369 0 : pSttNd->GetIndex() );
4370 : OSL_ENSURE( pBox, "Box is not in this Table" );
4371 0 : aBoxes.insert( pBox );
4372 0 : pBoxes = &aBoxes;
4373 : }
4374 : else
4375 0 : pBoxes = &rBoxes;
4376 :
4377 : // Copy Table to the selected Lines
4378 0 : bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4379 0 : *pBoxes, pUndo );
4380 : }
4381 : else
4382 : {
4383 0 : SwNodeIndex aNdIdx( *pSttNd, 1 );
4384 0 : bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4385 0 : aNdIdx, pUndo );
4386 : }
4387 :
4388 0 : if( bDelCpyDoc )
4389 : {
4390 0 : if( pCpyDoc->release() == 0 )
4391 0 : delete pCpyDoc;
4392 : }
4393 :
4394 0 : if( pUndo )
4395 : {
4396 : // If the Table could not be copied, delete the Undo object
4397 0 : GetIDocumentUndoRedo().DoUndo(bUndo);
4398 0 : if( !bRet && pUndo->IsEmpty() )
4399 0 : delete pUndo;
4400 : else
4401 : {
4402 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
4403 : }
4404 : }
4405 :
4406 0 : if( bCorrPos )
4407 : {
4408 0 : rInsPos.nNode = *pSttNd;
4409 0 : rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 );
4410 : }
4411 0 : getIDocumentRedlineAccess().SetRedlineMode( eOld );
4412 : }
4413 :
4414 0 : if( bRet )
4415 : {
4416 0 : getIDocumentState().SetModified();
4417 0 : getIDocumentFieldsAccess().SetFieldsDirty( true, NULL, 0 );
4418 : }
4419 0 : return bRet;
4420 : }
4421 :
4422 0 : bool SwDoc::_UnProtectTableCells( SwTable& rTable )
4423 : {
4424 0 : bool bChgd = false;
4425 0 : SwUndoAttrTable *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
4426 0 : ? new SwUndoAttrTable( *rTable.GetTableNode() )
4427 0 : : 0;
4428 :
4429 0 : SwTableSortBoxes& rSrtBox = rTable.GetTabSortBoxes();
4430 0 : for (size_t i = rSrtBox.size(); i; )
4431 : {
4432 0 : SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4433 0 : if( pBoxFormat->GetProtect().IsContentProtected() )
4434 : {
4435 0 : pBoxFormat->ResetFormatAttr( RES_PROTECT );
4436 0 : bChgd = true;
4437 : }
4438 : }
4439 :
4440 0 : if( pUndo )
4441 : {
4442 0 : if( bChgd )
4443 : {
4444 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
4445 : }
4446 : else
4447 0 : delete pUndo;
4448 : }
4449 0 : return bChgd;
4450 : }
4451 :
4452 0 : bool SwDoc::UnProtectCells( const OUString& rName )
4453 : {
4454 0 : bool bChgd = false;
4455 0 : SwTableFormat* pFormat = FindTableFormatByName( rName );
4456 0 : if( pFormat )
4457 : {
4458 0 : bChgd = _UnProtectTableCells( *SwTable::FindTable( pFormat ) );
4459 0 : if( bChgd )
4460 0 : getIDocumentState().SetModified();
4461 : }
4462 :
4463 0 : return bChgd;
4464 : }
4465 :
4466 0 : bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes )
4467 : {
4468 0 : bool bChgd = false;
4469 0 : if( !rBoxes.empty() )
4470 : {
4471 0 : SwUndoAttrTable *const pUndo = (GetIDocumentUndoRedo().DoesUndo())
4472 0 : ? new SwUndoAttrTable( *rBoxes[0]->GetSttNd()->FindTableNode() )
4473 0 : : 0;
4474 :
4475 0 : std::map<SwFrameFormat*, SwTableBoxFormat*> aFormatsMap;
4476 0 : for (size_t i = rBoxes.size(); i; )
4477 : {
4478 0 : SwTableBox* pBox = rBoxes[ --i ];
4479 0 : SwFrameFormat* pBoxFormat = pBox->GetFrameFormat();
4480 0 : if( pBoxFormat->GetProtect().IsContentProtected() )
4481 : {
4482 : std::map<SwFrameFormat*, SwTableBoxFormat*>::const_iterator const it =
4483 0 : aFormatsMap.find(pBoxFormat);
4484 0 : if (aFormatsMap.end() != it)
4485 0 : pBox->ChgFrameFormat(it->second);
4486 : else
4487 : {
4488 : SwTableBoxFormat *const pNewBoxFormat(
4489 0 : static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat()));
4490 0 : pNewBoxFormat->ResetFormatAttr( RES_PROTECT );
4491 0 : aFormatsMap.insert(std::make_pair(pBoxFormat, pNewBoxFormat));
4492 : }
4493 0 : bChgd = true;
4494 : }
4495 : }
4496 :
4497 0 : if( pUndo )
4498 : {
4499 0 : if( bChgd )
4500 : {
4501 0 : GetIDocumentUndoRedo().AppendUndo( pUndo );
4502 : }
4503 : else
4504 0 : delete pUndo;
4505 0 : }
4506 : }
4507 0 : return bChgd;
4508 : }
4509 :
4510 0 : bool SwDoc::UnProtectTables( const SwPaM& rPam )
4511 : {
4512 0 : GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
4513 :
4514 0 : bool bChgd = false, bHasSel = rPam.HasMark() ||
4515 0 : rPam.GetNext() != &rPam;
4516 0 : SwFrameFormats& rFormats = *GetTableFrameFormats();
4517 : SwTable* pTable;
4518 : const SwTableNode* pTableNd;
4519 0 : for( auto n = rFormats.size(); n ; )
4520 0 : if( 0 != (pTable = SwTable::FindTable( rFormats[ --n ] )) &&
4521 0 : 0 != (pTableNd = pTable->GetTableNode() ) &&
4522 0 : pTableNd->GetNodes().IsDocNodes() )
4523 : {
4524 0 : sal_uLong nTableIdx = pTableNd->GetIndex();
4525 :
4526 : // Check whether the Table is within the Selection
4527 0 : if( bHasSel )
4528 : {
4529 0 : bool bFound = false;
4530 0 : SwPaM* pTmp = const_cast<SwPaM*>(&rPam);
4531 0 : do {
4532 0 : const SwPosition *pStt = pTmp->Start(),
4533 0 : *pEnd = pTmp->End();
4534 0 : bFound = pStt->nNode.GetIndex() < nTableIdx &&
4535 0 : nTableIdx < pEnd->nNode.GetIndex();
4536 :
4537 0 : } while( !bFound && &rPam != ( pTmp = static_cast<SwPaM*>(pTmp->GetNext()) ) );
4538 0 : if( !bFound )
4539 0 : continue; // Continue searching
4540 : }
4541 :
4542 : // Lift the protection
4543 0 : bChgd |= _UnProtectTableCells( *pTable );
4544 : }
4545 :
4546 0 : GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
4547 0 : if( bChgd )
4548 0 : getIDocumentState().SetModified();
4549 :
4550 0 : return bChgd;
4551 : }
4552 :
4553 0 : bool SwDoc::HasTableAnyProtection( const SwPosition* pPos,
4554 : const OUString* pTableName,
4555 : bool* pFullTableProtection )
4556 : {
4557 0 : bool bHasProtection = false;
4558 0 : SwTable* pTable = 0;
4559 0 : if( pTableName )
4560 0 : pTable = SwTable::FindTable( FindTableFormatByName( *pTableName ) );
4561 0 : else if( pPos )
4562 : {
4563 0 : SwTableNode* pTableNd = pPos->nNode.GetNode().FindTableNode();
4564 0 : if( pTableNd )
4565 0 : pTable = &pTableNd->GetTable();
4566 : }
4567 :
4568 0 : if( pTable )
4569 : {
4570 0 : SwTableSortBoxes& rSrtBox = pTable->GetTabSortBoxes();
4571 0 : for (size_t i = rSrtBox.size(); i; )
4572 : {
4573 0 : SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4574 0 : if( pBoxFormat->GetProtect().IsContentProtected() )
4575 : {
4576 0 : if( !bHasProtection )
4577 : {
4578 0 : bHasProtection = true;
4579 0 : if( !pFullTableProtection )
4580 0 : break;
4581 0 : *pFullTableProtection = true;
4582 : }
4583 : }
4584 0 : else if( bHasProtection && pFullTableProtection )
4585 : {
4586 0 : *pFullTableProtection = false;
4587 0 : break;
4588 : }
4589 : }
4590 : }
4591 0 : return bHasProtection;
4592 177 : }
4593 :
4594 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|