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