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