1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndtbl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <com/sun/star/chart2/XChartDocument.hpp>
37 #define private public
39 #include <hintids.hxx>
42 #include <svx/lrspitem.hxx>
43 #include <svx/brkitem.hxx>
44 #include <svx/protitem.hxx>
45 #include <svx/boxitem.hxx>
46 #include <svtools/stritem.hxx>
47 // OD 06.08.2003 #i17174#
48 #include <svx/shaditem.hxx>
49 #include <fmtfsize.hxx>
50 #include <fmtornt.hxx>
51 #include <fmtfordr.hxx>
52 #include <fmtpdsc.hxx>
53 #include <fmtanchr.hxx>
54 #include <fmtlsplt.hxx>
56 #include <charatr.hxx>
57 #include <cellfrm.hxx>
58 #include <pagefrm.hxx>
65 #include <swtable.hxx>
70 #include <poolfmt.hxx>
73 #include <tblafmt.hxx>
74 #include <swcache.hxx>
77 #include <cellatr.hxx>
78 #include <swtblfmt.hxx>
79 #include <swddetbl.hxx>
82 #include <redline.hxx>
84 #include <tblrwcl.hxx>
88 #include <section.hxx>
89 #include <frmtool.hxx>
90 #include <node2lay.hxx>
92 #include <comcore.hrc>
98 #include <unochart.hxx>
105 // --> OD 2005-12-05 #i27138#
106 #include <rootfrm.hxx>
109 #define CHECK_TABLE(t)
112 #define CHECK_TABLE(t) (t).CheckConsistency();
114 #define CHECK_TABLE(t)
117 #include <fldupde.hxx>
120 using namespace ::com::sun::star
;
122 // #i17764# delete table redlines when modifying the table structure?
123 // #define DEL_TABLE_REDLINES 1
125 const sal_Unicode T2T_PARA
= 0x0a;
127 extern void ClearFEShellTabCols();
129 // steht im gctable.cxx
130 extern BOOL
lcl_GC_Line_Border( const SwTableLine
*& , void* pPara
);
132 #ifdef DEL_TABLE_REDLINES
133 class lcl_DelRedlines
137 lcl_DelRedlines( const SwTableNode
& rNd
, BOOL bCheckForOwnRedline
);
138 lcl_DelRedlines( SwPaM
& rPam
);
140 ~lcl_DelRedlines() { pDoc
->EndUndo(UNDO_EMPTY
, NULL
); }
143 lcl_DelRedlines::lcl_DelRedlines( SwPaM
& rPam
) : pDoc( rPam
.GetDoc() )
145 pDoc
->StartUndo(UNDO_EMPTY
, NULL
);
146 if( !pDoc
->IsIgnoreRedline() && pDoc
->GetRedlineTbl().Count() )
147 pDoc
->AcceptRedline( rPam
, true );
151 void lcl_SetDfltBoxAttr( SwFrmFmt
& rFmt
, BYTE nId
)
153 BOOL bTop
= FALSE
, bBottom
= FALSE
, bLeft
= FALSE
, bRight
= FALSE
;
156 case 0: bTop
= bBottom
= bLeft
= TRUE
; break;
157 case 1: bTop
= bBottom
= bLeft
= bRight
= TRUE
; break;
158 case 2: bBottom
= bLeft
= TRUE
; break;
159 case 3: bBottom
= bLeft
= bRight
= TRUE
; break;
162 const BOOL bHTML
= rFmt
.getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE
);
163 Color
aCol( bHTML
? COL_GRAY
: COL_BLACK
);
164 SvxBorderLine
aLine( &aCol
, DEF_LINE_WIDTH_0
);
167 aLine
.SetOutWidth( DEF_DOUBLE_LINE7_OUT
);
168 aLine
.SetInWidth ( DEF_DOUBLE_LINE7_IN
);
169 aLine
.SetDistance( DEF_DOUBLE_LINE7_DIST
);
171 SvxBoxItem
aBox(RES_BOX
); aBox
.SetDistance( 55 );
173 aBox
.SetLine( &aLine
, BOX_LINE_TOP
);
175 aBox
.SetLine( &aLine
, BOX_LINE_BOTTOM
);
177 aBox
.SetLine( &aLine
, BOX_LINE_LEFT
);
179 aBox
.SetLine( &aLine
, BOX_LINE_RIGHT
);
180 rFmt
.SetFmtAttr( aBox
);
183 void lcl_SetDfltBoxAttr( SwTableBox
& rBox
, SvPtrarr
&rBoxFmtArr
, BYTE nId
,
184 const SwTableAutoFmt
* pAutoFmt
= 0 )
186 SvPtrarr
* pArr
= (SvPtrarr
*)rBoxFmtArr
[ nId
];
190 rBoxFmtArr
.Replace( pArr
, nId
);
193 SwTableBoxFmt
* pNewBoxFmt
= 0;
194 SwFrmFmt
* pBoxFmt
= rBox
.GetFrmFmt();
195 for( USHORT n
= 0; n
< pArr
->Count(); n
+= 2 )
196 if( pArr
->GetObject( n
) == pBoxFmt
)
198 pNewBoxFmt
= (SwTableBoxFmt
*)pArr
->GetObject( n
+ 1 );
204 SwDoc
* pDoc
= pBoxFmt
->GetDoc();
205 // das Format ist also nicht vorhanden, also neu erzeugen
206 pNewBoxFmt
= pDoc
->MakeTableBoxFmt();
207 pNewBoxFmt
->SetFmtAttr( pBoxFmt
->GetAttrSet().Get( RES_FRM_SIZE
) );
210 pAutoFmt
->UpdateToSet( nId
, (SfxItemSet
&)pNewBoxFmt
->GetAttrSet(),
211 SwTableAutoFmt::UPDATE_BOX
,
212 pDoc
->GetNumberFormatter( TRUE
) );
214 ::lcl_SetDfltBoxAttr( *pNewBoxFmt
, nId
);
217 pArr
->Insert( p
, pArr
->Count() );
219 pArr
->Insert( p
, pArr
->Count() );
221 rBox
.ChgFrmFmt( pNewBoxFmt
);
224 SwTableBoxFmt
*lcl_CreateDfltBoxFmt( SwDoc
&rDoc
, SvPtrarr
&rBoxFmtArr
,
225 USHORT nCols
, BYTE nId
)
227 if ( !rBoxFmtArr
[nId
] )
229 SwTableBoxFmt
* pBoxFmt
= rDoc
.MakeTableBoxFmt();
230 if( USHRT_MAX
!= nCols
)
231 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
232 USHRT_MAX
/ nCols
, 0 ));
233 ::lcl_SetDfltBoxAttr( *pBoxFmt
, nId
);
234 rBoxFmtArr
.Replace( pBoxFmt
, nId
);
236 return (SwTableBoxFmt
*)rBoxFmtArr
[nId
];
239 SwTableBoxFmt
*lcl_CreateAFmtBoxFmt( SwDoc
&rDoc
, SvPtrarr
&rBoxFmtArr
,
240 const SwTableAutoFmt
& rAutoFmt
,
241 USHORT nCols
, BYTE nId
)
243 if( !rBoxFmtArr
[nId
] )
245 SwTableBoxFmt
* pBoxFmt
= rDoc
.MakeTableBoxFmt();
246 rAutoFmt
.UpdateToSet( nId
, (SfxItemSet
&)pBoxFmt
->GetAttrSet(),
247 SwTableAutoFmt::UPDATE_BOX
,
248 rDoc
.GetNumberFormatter( TRUE
) );
249 if( USHRT_MAX
!= nCols
)
250 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
251 USHRT_MAX
/ nCols
, 0 ));
252 rBoxFmtArr
.Replace( pBoxFmt
, nId
);
254 return (SwTableBoxFmt
*)rBoxFmtArr
[nId
];
257 SwTableNode
* SwDoc::IsIdxInTbl(const SwNodeIndex
& rIdx
)
259 SwTableNode
* pTableNd
= 0;
260 ULONG nIndex
= rIdx
.GetIndex();
262 SwNode
* pNd
= (SwNode
*)GetNodes()[ nIndex
]->StartOfSectionNode();
263 if( 0 != ( pTableNd
= pNd
->GetTableNode() ) )
266 nIndex
= pNd
->GetIndex();
272 // --------------- einfuegen einer neuen Box --------------
274 // fuege in der Line, vor der InsPos eine neue Box ein.
276 BOOL
SwNodes::InsBoxen( SwTableNode
* pTblNd
,
278 SwTableBoxFmt
* pBoxFmt
,
279 SwTxtFmtColl
* pTxtColl
,
280 const SfxItemSet
* pAutoAttr
,
286 ASSERT( pLine
, "keine gueltige Zeile" );
288 // Index hinter die letzte Box der Line
290 SwTableBox
*pPrvBox
= 0, *pNxtBox
= 0;
291 if( pLine
->GetTabBoxes().Count() )
293 if( nInsPos
< pLine
->GetTabBoxes().Count() )
295 if( 0 == (pPrvBox
= pLine
->FindPreviousBox( pTblNd
->GetTable(),
296 pLine
->GetTabBoxes()[ nInsPos
] )))
297 pPrvBox
= pLine
->FindPreviousBox( pTblNd
->GetTable() );
299 else if( 0 == ( pNxtBox
= pLine
->FindNextBox( pTblNd
->GetTable(),
300 pLine
->GetTabBoxes()[ nInsPos
-1 ] )))
301 pNxtBox
= pLine
->FindNextBox( pTblNd
->GetTable() );
303 else if( 0 == ( pNxtBox
= pLine
->FindNextBox( pTblNd
->GetTable() )))
304 pPrvBox
= pLine
->FindPreviousBox( pTblNd
->GetTable() );
306 if( !pPrvBox
&& !pNxtBox
)
308 BOOL bSetIdxPos
= TRUE
;
309 if( pTblNd
->GetTable().GetTabLines().Count() && !nInsPos
)
311 const SwTableLine
* pTblLn
= pLine
;
312 while( pTblLn
->GetUpper() )
313 pTblLn
= pTblLn
->GetUpper()->GetUpper();
315 if( pTblNd
->GetTable().GetTabLines()[ 0 ] == pTblLn
)
317 // also vor die erste Box der Tabelle
318 while( ( pNxtBox
= pLine
->GetTabBoxes()[0])->GetTabLines().Count() )
319 pLine
= pNxtBox
->GetTabLines()[0];
320 nIdxPos
= pNxtBox
->GetSttIdx();
325 // Tabelle ohne irgendeinen Inhalt oder am Ende, also vors Ende
326 nIdxPos
= pTblNd
->EndOfSectionIndex();
328 else if( pNxtBox
) // es gibt einen Nachfolger
329 nIdxPos
= pNxtBox
->GetSttIdx();
330 else // es gibt einen Vorgaenger
331 nIdxPos
= pPrvBox
->GetSttNd()->EndOfSectionIndex() + 1;
333 SwNodeIndex
aEndIdx( *this, nIdxPos
);
334 for( USHORT n
= 0; n
< nCnt
; ++n
)
336 SwStartNode
* pSttNd
= new SwStartNode( aEndIdx
, ND_STARTNODE
,
337 SwTableBoxStartNode
);
338 pSttNd
->pStartOfSection
= pTblNd
;
339 new SwEndNode( aEndIdx
, *pSttNd
);
341 pPrvBox
= new SwTableBox( pBoxFmt
, *pSttNd
, pLine
);
342 pLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pPrvBox
, nInsPos
+ n
);
344 //if( NO_NUMBERING == pTxtColl->GetOutlineLevel()//#outline level,zhaojianwei
345 if( ! pTxtColl
->IsAssignedToListLevelOfOutlineStyle()//<-end,zhaojianwei
347 && RES_CONDTXTFMTCOLL
!= pTxtColl
->Which()
350 new SwTxtNode( SwNodeIndex( *pSttNd
->EndOfSectionNode() ),
351 pTxtColl
, pAutoAttr
);
354 // Outline-Numerierung richtig behandeln !!!
355 SwTxtNode
* pTNd
= new SwTxtNode(
356 SwNodeIndex( *pSttNd
->EndOfSectionNode() ),
357 (SwTxtFmtColl
*)GetDoc()->GetDfltTxtFmtColl(),
359 pTNd
->ChgFmtColl( pTxtColl
);
365 // --------------- einfuegen einer neuen Tabelle --------------
367 const SwTable
* SwDoc::InsertTable( const SwInsertTableOptions
& rInsTblOpts
,
368 const SwPosition
& rPos
, USHORT nRows
,
369 USHORT nCols
, sal_Int16 eAdjust
,
370 const SwTableAutoFmt
* pTAFmt
,
371 const SvUShorts
* pColArr
,
372 BOOL bCalledFromShell
,
375 ASSERT( nRows
, "Tabelle ohne Zeile?" );
376 ASSERT( nCols
, "Tabelle ohne Spalten?" );
379 // nicht in Fussnoten kopieren !!
380 if( rPos
.nNode
< GetNodes().GetEndOfInserts().GetIndex() &&
381 rPos
.nNode
>= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
384 // sollte das ColumnArray die falsche Anzahl haben wird es ignoriert!
386 (nCols
+ ( text::HoriOrientation::NONE
== eAdjust
? 2 : 1 )) != pColArr
->Count() )
390 String aTblName
= GetUniqueTblName();
395 AppendUndo( new SwUndoInsTbl( rPos
, nCols
, nRows
, static_cast<USHORT
>(eAdjust
),
396 rInsTblOpts
, pTAFmt
, pColArr
,
400 // fuege erstmal die Nodes ein
401 // hole das Auto-Format fuer die Tabelle
402 SwTxtFmtColl
*pBodyColl
= GetTxtCollFromPool( RES_POOLCOLL_TABLE
),
403 *pHeadColl
= pBodyColl
;
405 BOOL bDfltBorders
= 0 != ( rInsTblOpts
.mnInsMode
& tabopts::DEFAULT_BORDER
);
407 if( (rInsTblOpts
.mnInsMode
& tabopts::HEADLINE
) && (1 != nRows
|| !bDfltBorders
) )
408 pHeadColl
= GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN
);
410 const USHORT nRowsToRepeat
=
411 tabopts::HEADLINE
== (rInsTblOpts
.mnInsMode
& tabopts::HEADLINE
) ?
412 rInsTblOpts
.mnRowsToRepeat
:
415 /* #106283# Save content node to extract FRAMEDIR from. */
416 const SwCntntNode
* pCntntNd
= rPos
.nNode
.GetNode().GetCntntNode();
418 /* #109161# If we are called from a shell pass the attrset from
419 pCntntNd (aka the node the table is inserted at) thus causing
420 SwNodes::InsertTable to propagate an adjust item if
422 SwTableNode
*pTblNd
= GetNodes().InsertTable(
429 bCalledFromShell
? &pCntntNd
->GetSwAttrSet() : 0 );
431 // dann erstelle die Box/Line/Table-Struktur
432 SwTableLineFmt
* pLineFmt
= MakeTableLineFmt();
433 SwTableFmt
* pTableFmt
= MakeTblFrmFmt( aTblName
, GetDfltFrmFmt() );
435 /* #106283# If the node to insert the table at is a context node and has a
436 non-default FRAMEDIR propagate it to the table. */
439 const SwAttrSet
& aNdSet
= pCntntNd
->GetSwAttrSet();
440 const SfxPoolItem
*pItem
= NULL
;
442 if (SFX_ITEM_SET
== aNdSet
.GetItemState( RES_FRAMEDIR
, TRUE
, &pItem
)
445 pTableFmt
->SetFmtAttr( *pItem
);
449 //Orientation am Fmt der Table setzen
450 pTableFmt
->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust
) );
451 // alle Zeilen haben die Fill-Order von links nach rechts !
452 pLineFmt
->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT
));
454 // die Tabelle bekommt USHRT_MAX als default SSize
455 SwTwips nWidth
= USHRT_MAX
;
458 USHORT nSttPos
= (*pColArr
)[ 0 ];
459 USHORT nLastPos
= (*pColArr
)[ USHORT(pColArr
->Count()-1)];
460 if( text::HoriOrientation::NONE
== eAdjust
)
462 USHORT nFrmWidth
= nLastPos
;
463 nLastPos
= (*pColArr
)[ USHORT(pColArr
->Count()-2)];
464 pTableFmt
->SetFmtAttr( SvxLRSpaceItem( nSttPos
, nFrmWidth
- nLastPos
, 0, 0, RES_LR_SPACE
) );
466 nWidth
= nLastPos
- nSttPos
;
471 nWidth
*= nCols
; // to avoid rounding problems
473 pTableFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nWidth
));
474 if( !(rInsTblOpts
.mnInsMode
& tabopts::SPLIT_LAYOUT
) )
475 pTableFmt
->SetFmtAttr( SwFmtLayoutSplit( FALSE
));
477 // verschiebe ggfs. die harten PageDesc/PageBreak Attribute:
478 SwCntntNode
* pNextNd
= GetNodes()[ pTblNd
->EndOfSectionIndex()+1 ]
480 if( pNextNd
&& pNextNd
->HasSwAttrSet() )
482 const SfxItemSet
* pNdSet
= pNextNd
->GetpSwAttrSet();
483 const SfxPoolItem
*pItem
;
484 if( SFX_ITEM_SET
== pNdSet
->GetItemState( RES_PAGEDESC
, FALSE
,
487 pTableFmt
->SetFmtAttr( *pItem
);
488 pNextNd
->ResetAttr( RES_PAGEDESC
);
489 pNdSet
= pNextNd
->GetpSwAttrSet();
491 if( pNdSet
&& SFX_ITEM_SET
== pNdSet
->GetItemState( RES_BREAK
, FALSE
,
494 pTableFmt
->SetFmtAttr( *pItem
);
495 pNextNd
->ResetAttr( RES_BREAK
);
499 SwTable
* pNdTbl
= &pTblNd
->GetTable();
500 pTableFmt
->Add( pNdTbl
); // das Frame-Format setzen
502 pNdTbl
->SetRowsToRepeat( nRowsToRepeat
);
503 pNdTbl
->SetTableModel( bNewModel
);
505 SvPtrarr
aBoxFmtArr( 0, 16 );
506 SwTableBoxFmt
* pBoxFmt
= 0;
507 if( !bDfltBorders
&& !pTAFmt
)
509 pBoxFmt
= MakeTableBoxFmt();
510 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, USHRT_MAX
/ nCols
, 0 ));
514 const USHORT nBoxArrLen
= pTAFmt
? 16 : 4;
515 for( USHORT i
= 0; i
< nBoxArrLen
; ++i
)
516 aBoxFmtArr
.Insert( (void*)0, i
);
518 // --> OD 2008-02-25 #refactorlists#
519 // SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
520 SfxItemSet
aCharSet( GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_LIST_END
-1 );
523 SwNodeIndex
aNdIdx( *pTblNd
, 1 ); // auf den ersten Box-StartNode
524 SwTableLines
& rLines
= pNdTbl
->GetTabLines();
525 for( USHORT n
= 0; n
< nRows
; ++n
)
527 SwTableLine
* pLine
= new SwTableLine( pLineFmt
, nCols
, 0 );
528 rLines
.C40_INSERT( SwTableLine
, pLine
, n
);
529 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
530 for( USHORT i
= 0; i
< nCols
; ++i
)
532 SwTableBoxFmt
*pBoxF
;
535 BYTE nId
= static_cast<BYTE
>(!n
? 0 : (( n
+1 == nRows
)
536 ? 12 : (4 * (1 + ((n
-1) & 1 )))));
537 nId
= nId
+ static_cast<BYTE
>( !i
? 0 :
538 ( i
+1 == nCols
? 3 : (1 + ((i
-1) & 1))));
539 pBoxF
= ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr
, *pTAFmt
,
542 // ggfs. noch die Absatz/ZeichenAttribute setzen
543 if( pTAFmt
->IsFont() || pTAFmt
->IsJustify() )
545 aCharSet
.ClearItem();
546 pTAFmt
->UpdateToSet( nId
, aCharSet
,
547 SwTableAutoFmt::UPDATE_CHAR
, 0 );
548 if( aCharSet
.Count() )
549 GetNodes()[ aNdIdx
.GetIndex()+1 ]->GetCntntNode()->
553 else if( bDfltBorders
)
555 BYTE nBoxId
= (i
< nCols
- 1 ? 0 : 1) + (n
? 2 : 0 );
556 pBoxF
= ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr
, nCols
, nBoxId
);
561 // fuer AutoFormat bei der Eingabe: beim Einfuegen der Tabelle
562 // werden gleich die Spalten gesetzt. Im Array stehen die
563 // Positionen der Spalten!! (nicht deren Breite!)
566 nWidth
= (*pColArr
)[ USHORT(i
+ 1) ] - (*pColArr
)[ i
];
567 if( pBoxF
->GetFrmSize().GetWidth() != nWidth
)
569 if( pBoxF
->GetDepends() ) // neues Format erzeugen!
571 SwTableBoxFmt
*pNewFmt
= MakeTableBoxFmt();
575 pBoxF
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nWidth
));
579 SwTableBox
*pBox
= new SwTableBox( pBoxF
, aNdIdx
, pLine
);
580 rBoxes
.C40_INSERT( SwTableBox
, pBox
, i
);
581 aNdIdx
+= 3; // StartNode, TextNode, EndNode == 3 Nodes
584 // und Frms einfuegen.
585 GetNodes().GoNext( &aNdIdx
); // zum naechsten ContentNode
586 pTblNd
->MakeFrms( &aNdIdx
);
588 if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl
->Count() ))
590 SwPaM
aPam( *pTblNd
->EndOfSectionNode(), *pTblNd
, 1 );
592 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT
, aPam
), true);
594 SplitRedline( aPam
);
598 CHECK_TABLE( *pNdTbl
);
602 SwTableNode
* SwNodes::InsertTable( const SwNodeIndex
& rNdIdx
,
604 SwTxtFmtColl
* pCntntTxtColl
,
607 SwTxtFmtColl
* pHeadlineTxtColl
,
608 const SwAttrSet
* pAttrSet
)
613 // wenn Lines angegeben, erzeuge die Matrix aus Lines & Boxen
614 if( !pHeadlineTxtColl
|| !nLines
)
615 pHeadlineTxtColl
= pCntntTxtColl
;
617 SwTableNode
* pTblNd
= new SwTableNode( rNdIdx
);
618 SwEndNode
* pEndNd
= new SwEndNode( rNdIdx
, *pTblNd
);
620 if( !nLines
) // fuer die FOR-Schleife
623 SwNodeIndex
aIdx( *pEndNd
);
624 SwTxtFmtColl
* pTxtColl
= pHeadlineTxtColl
;
625 for( USHORT nL
= 0; nL
< nLines
; ++nL
)
627 for( USHORT nB
= 0; nB
< nBoxes
; ++nB
)
629 SwStartNode
* pSttNd
= new SwStartNode( aIdx
, ND_STARTNODE
,
630 SwTableBoxStartNode
);
631 pSttNd
->pStartOfSection
= pTblNd
;
633 SwTxtNode
* pTmpNd
= new SwTxtNode( aIdx
, pTxtColl
);
635 // --> FME 2006-04-13 #i60422# Propagate some more attributes.
636 // Adjustment was done for #109161#
637 const SfxPoolItem
* pItem
= NULL
;
638 if ( NULL
!= pAttrSet
)
640 static const USHORT aPropagateItems
[] = {
642 RES_CHRATR_FONT
, RES_CHRATR_FONTSIZE
,
643 RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONTSIZE
,
644 RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONTSIZE
, 0 };
646 const USHORT
* pIdx
= aPropagateItems
;
649 if ( SFX_ITEM_SET
!= pTmpNd
->GetSwAttrSet().GetItemState( *pIdx
) &&
650 SFX_ITEM_SET
== pAttrSet
->GetItemState( *pIdx
, TRUE
, &pItem
) )
651 static_cast<SwCntntNode
*>(pTmpNd
)->SetAttr(*pItem
);
657 new SwEndNode( aIdx
, *pSttNd
);
659 if ( nL
+ 1 >= nRepeat
)
660 pTxtColl
= pCntntTxtColl
;
666 //---------------- Text -> Tabelle -----------------------
668 const SwTable
* SwDoc::TextToTable( const SwInsertTableOptions
& rInsTblOpts
,
669 const SwPaM
& rRange
, sal_Unicode cCh
,
671 const SwTableAutoFmt
* pTAFmt
)
673 // pruefe ob in der Selection eine Tabelle liegt
674 const SwPosition
*pStt
= rRange
.Start(), *pEnd
= rRange
.End();
676 ULONG nCnt
= pStt
->nNode
.GetIndex();
677 for( ; nCnt
<= pEnd
->nNode
.GetIndex(); ++nCnt
)
678 if( !GetNodes()[ nCnt
]->IsTxtNode() )
682 /* #106283# Save first node in the selection if it is a context node. */
683 SwCntntNode
* pSttCntntNd
= pStt
->nNode
.GetNode().GetCntntNode();
685 SwPaM
aOriginal( *pStt
, *pEnd
);
686 pStt
= aOriginal
.GetMark();
687 pEnd
= aOriginal
.GetPoint();
689 #ifdef DEL_TABLE_REDLINES
690 lcl_DelRedlines
aDelRedl( aOriginal
);
693 SwUndoTxtToTbl
* pUndo
= 0;
696 StartUndo( UNDO_TEXTTOTABLE
, NULL
);
697 pUndo
= new SwUndoTxtToTbl( aOriginal
, rInsTblOpts
, cCh
,
698 static_cast<USHORT
>(eAdjust
), pTAFmt
);
701 // das Splitten vom TextNode nicht in die Undohistory aufnehmen
705 ::PaMCorrAbs( aOriginal
, *pEnd
);
707 // sorge dafuer, das der Bereich auf Node-Grenzen liegt
708 SwNodeRange
aRg( pStt
->nNode
, pEnd
->nNode
);
709 if( pStt
->nContent
.GetIndex() )
710 SplitNode( *pStt
, false );
712 BOOL bEndCntnt
= 0 != pEnd
->nContent
.GetIndex();
713 // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
716 if( pEnd
->nNode
.GetNode().GetCntntNode()->Len() != pEnd
->nContent
.GetIndex()
717 || pEnd
->nNode
.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
719 SplitNode( *pEnd
, false );
720 ((SwNodeIndex
&)pEnd
->nNode
)--;
721 ((SwIndex
&)pEnd
->nContent
).Assign(
722 pEnd
->nNode
.GetNode().GetCntntNode(), 0 );
723 // ein Node und am Ende ??
724 if( pStt
->nNode
.GetIndex() >= pEnd
->nNode
.GetIndex() )
732 if( aRg
.aEnd
.GetIndex() == aRg
.aStart
.GetIndex() )
734 ASSERT( FALSE
, "Kein Bereich" );
738 // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
739 SwNode2Layout
aNode2Layout( aRg
.aStart
.GetNode() );
741 DoUndo( 0 != pUndo
);
743 // dann erstelle die Box/Line/Table-Struktur
744 SwTableBoxFmt
* pBoxFmt
= MakeTableBoxFmt();
745 SwTableLineFmt
* pLineFmt
= MakeTableLineFmt();
746 SwTableFmt
* pTableFmt
= MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
748 // alle Zeilen haben die Fill-Order von links nach rechts !
749 pLineFmt
->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT
));
750 // die Tabelle bekommt USHRT_MAX als default SSize
751 pTableFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, USHRT_MAX
));
752 if( !(rInsTblOpts
.mnInsMode
& tabopts::SPLIT_LAYOUT
) )
753 pTableFmt
->SetFmtAttr( SwFmtLayoutSplit( FALSE
));
755 /* #106283# If the first node in the selection is a context node and if it
756 has an item FRAMEDIR set (no default) propagate the item to the
760 const SwAttrSet
& aNdSet
= pSttCntntNd
->GetSwAttrSet();
761 const SfxPoolItem
*pItem
= NULL
;
763 if (SFX_ITEM_SET
== aNdSet
.GetItemState( RES_FRAMEDIR
, TRUE
, &pItem
)
766 pTableFmt
->SetFmtAttr( *pItem
);
770 SwTableNode
* pTblNd
= GetNodes().TextToTable(
771 aRg
, cCh
, pTableFmt
, pLineFmt
, pBoxFmt
,
772 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
), pUndo
);
774 SwTable
* pNdTbl
= &pTblNd
->GetTable();
775 ASSERT( pNdTbl
, "kein Tabellen-Node angelegt." )
777 const USHORT nRowsToRepeat
=
778 tabopts::HEADLINE
== (rInsTblOpts
.mnInsMode
& tabopts::HEADLINE
) ?
779 rInsTblOpts
.mnRowsToRepeat
:
781 pNdTbl
->SetRowsToRepeat( nRowsToRepeat
);
783 BOOL bUseBoxFmt
= FALSE
;
784 if( !pBoxFmt
->GetDepends() )
786 // die Formate an den Boxen haben schon die richtige Size, es darf
787 // also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
789 pTableFmt
->SetFmtAttr( pBoxFmt
->GetFrmSize() );
791 eAdjust
= text::HoriOrientation::NONE
;
794 //Orientation am Fmt der Table setzen
795 pTableFmt
->SetFmtAttr( SwFmtHoriOrient( 0, eAdjust
) );
796 pTableFmt
->Add( pNdTbl
); // das Frame-Format setzen
798 if( pTAFmt
|| ( rInsTblOpts
.mnInsMode
& tabopts::DEFAULT_BORDER
) )
800 BYTE nBoxArrLen
= pTAFmt
? 16 : 4;
801 SvPtrarr
aBoxFmtArr( nBoxArrLen
, 0 );
803 for( BYTE i
= 0; i
< nBoxArrLen
; ++i
)
804 aBoxFmtArr
.Insert( (void*)0, i
);
807 // --> OD 2008-02-25 #refactorlists#
808 // SfxItemSet aCharSet( GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
809 SfxItemSet
aCharSet( GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_LIST_END
-1 );
811 SwHistory
* pHistory
= pUndo
? &pUndo
->GetHistory() : 0;
813 SwTableBoxFmt
*pBoxF
= 0;
814 SwTableLines
& rLines
= pNdTbl
->GetTabLines();
815 USHORT nRows
= rLines
.Count();
816 for( USHORT n
= 0; n
< nRows
; ++n
)
818 SwTableBoxes
& rBoxes
= rLines
[ n
]->GetTabBoxes();
819 USHORT nCols
= rBoxes
.Count();
820 for( USHORT i
= 0; i
< nCols
; ++i
)
822 SwTableBox
* pBox
= rBoxes
[ i
];
827 BYTE nId
= static_cast<BYTE
>(!n
? 0 : (( n
+1 == nRows
)
828 ? 12 : (4 * (1 + ((n
-1) & 1 )))));
829 nId
= nId
+ static_cast<BYTE
>(!i
? 0 :
830 ( i
+1 == nCols
? 3 : (1 + ((i
-1) & 1))));
832 ::lcl_SetDfltBoxAttr( *pBox
, aBoxFmtArr
, nId
, pTAFmt
);
835 bChgSz
= 0 == aBoxFmtArr
[ nId
];
836 pBoxF
= ::lcl_CreateAFmtBoxFmt( *this, aBoxFmtArr
,
837 *pTAFmt
, USHRT_MAX
, nId
);
840 // ggfs. noch die Absatz/ZeichenAttribute setzen
841 if( pTAFmt
->IsFont() || pTAFmt
->IsJustify() )
843 aCharSet
.ClearItem();
844 pTAFmt
->UpdateToSet( nId
, aCharSet
,
845 SwTableAutoFmt::UPDATE_CHAR
, 0 );
846 if( aCharSet
.Count() )
848 ULONG nSttNd
= pBox
->GetSttIdx()+1;
849 ULONG nEndNd
= pBox
->GetSttNd()->EndOfSectionIndex();
850 for( ; nSttNd
< nEndNd
; ++nSttNd
)
852 SwCntntNode
* pNd
= GetNodes()[ nSttNd
]->GetCntntNode();
857 SwRegHistory
aReg( pNd
, *pNd
, pHistory
);
858 pNd
->SetAttr( aCharSet
);
861 pNd
->SetAttr( aCharSet
);
869 BYTE nId
= (i
< nCols
- 1 ? 0 : 1) + (n
? 2 : 0 );
871 ::lcl_SetDfltBoxAttr( *pBox
, aBoxFmtArr
, nId
);
874 bChgSz
= 0 == aBoxFmtArr
[ nId
];
875 pBoxF
= ::lcl_CreateDfltBoxFmt( *this, aBoxFmtArr
,
883 pBoxF
->SetFmtAttr( pBox
->GetFrmFmt()->GetFrmSize() );
884 pBox
->ChgFrmFmt( pBoxF
);
891 for( BYTE i
= 0; i
< nBoxArrLen
; ++i
)
893 SvPtrarr
* pArr
= (SvPtrarr
*)aBoxFmtArr
[ i
];
899 // JP 03.04.97: Inhalt der Boxen auf Zahlen abpruefen
900 if( IsInsTblFormatNum() )
902 for( USHORT nBoxes
= pNdTbl
->GetTabSortBoxes().Count(); nBoxes
; )
903 ChkBoxNumFmt( *pNdTbl
->GetTabSortBoxes()[ --nBoxes
], FALSE
);
906 ULONG nIdx
= pTblNd
->GetIndex();
907 aNode2Layout
.RestoreUpperFrms( GetNodes(), nIdx
, nIdx
+ 1 );
910 SwPaM
& rTmp
= (SwPaM
&)rRange
; // Point immer an den Anfang
912 rTmp
.GetPoint()->nNode
= *pTblNd
;
913 SwCntntNode
* pCNd
= GetNodes().GoNext( &rTmp
.GetPoint()->nNode
);
914 rTmp
.GetPoint()->nContent
.Assign( pCNd
, 0 );
918 EndUndo( UNDO_TEXTTOTABLE
, NULL
);
921 SetFieldsDirty(true, NULL
, 0);
925 SwTableNode
* SwNodes::TextToTable( const SwNodeRange
& rRange
, sal_Unicode cCh
,
927 SwTableLineFmt
* pLineFmt
,
928 SwTableBoxFmt
* pBoxFmt
,
929 SwTxtFmtColl
* pTxtColl
,
930 SwUndoTxtToTbl
* pUndo
)
932 if( rRange
.aStart
>= rRange
.aEnd
)
935 SwTableNode
* pTblNd
= new SwTableNode( rRange
.aStart
);
936 new SwEndNode( rRange
.aEnd
, *pTblNd
);
938 SwDoc
* pDoc
= GetDoc();
939 SvUShorts
aPosArr( 0, 16 );
940 SwTable
* pTable
= &pTblNd
->GetTable();
943 USHORT nBoxes
, nLines
, nMaxBoxes
= 0;
945 SwNodeIndex
aSttIdx( *pTblNd
, 1 );
946 SwNodeIndex
aEndIdx( rRange
.aEnd
, -1 );
947 for( nLines
= 0, nBoxes
= 0;
948 aSttIdx
.GetIndex() < aEndIdx
.GetIndex();
949 aSttIdx
+= 2, nLines
++, nBoxes
= 0 )
951 SwTxtNode
* pTxtNd
= aSttIdx
.GetNode().GetTxtNode();
952 ASSERT( pTxtNd
, "nur TextNodes in der Tabelle aufnehmen" );
954 if( !nLines
&& 0x0b == cCh
)
958 // JP 28.10.96: vom 1. Node die Positionen des Trenners besorgen,
959 // damit die Boxen entsprechend eingestellt werden
960 SwTxtFrmInfo
aFInfo( (SwTxtFrm
*)pTxtNd
->GetFrm() );
961 if( aFInfo
.IsOneLine() ) // nur dann sinnvoll!
963 const sal_Unicode
* pTxt
= pTxtNd
->GetTxt().GetBuffer();
964 for( xub_StrLen nChPos
= 0; *pTxt
; ++nChPos
, ++pTxt
)
968 aPosArr
.Insert( static_cast<USHORT
>(
969 aFInfo
.GetCharPos( nChPos
+1, FALSE
)),
974 aPosArr
.Insert( /*aFInfo.GetFrm()->Frm().Left() +*/
975 static_cast<USHORT
>(aFInfo
.GetFrm()->IsVertical() ?
976 aFInfo
.GetFrm()->Prt().Bottom() :
977 aFInfo
.GetFrm()->Prt().Right()),
982 // die alten Frames loeschen, es werden neue erzeugt
985 // PageBreaks/PageDesc/ColBreak rausschmeissen.
986 const SfxItemSet
* pSet
= pTxtNd
->GetpSwAttrSet();
989 // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle
990 // erfolgen, denn sonst stehen sie falsch in der History !!!
991 // SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory );
992 const SfxPoolItem
* pItem
;
993 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
, FALSE
, &pItem
) )
996 pTblFmt
->SetFmtAttr( *pItem
);
997 pTxtNd
->ResetAttr( RES_BREAK
);
998 pSet
= pTxtNd
->GetpSwAttrSet();
1001 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState(
1002 RES_PAGEDESC
, FALSE
, &pItem
) &&
1003 ((SwFmtPageDesc
*)pItem
)->GetPageDesc() )
1006 pTblFmt
->SetFmtAttr( *pItem
);
1007 pTxtNd
->ResetAttr( RES_PAGEDESC
);
1011 // setze den bei allen TextNode in der Tabelle den TableNode
1013 pTxtNd
->pStartOfSection
= pTblNd
;
1015 pLine
= new SwTableLine( pLineFmt
, 1, 0 );
1016 pTable
->GetTabLines().C40_INSERT( SwTableLine
, pLine
, nLines
);
1018 SwStartNode
* pSttNd
;
1019 SwPosition
aCntPos( aSttIdx
, SwIndex( pTxtNd
));
1021 SvULongs
aBkmkArr( 15, 15 );
1022 _SaveCntntIdx( pDoc
, aSttIdx
.GetIndex(), pTxtNd
->GetTxt().Len(), aBkmkArr
);
1024 const sal_Unicode
* pTxt
= pTxtNd
->GetTxt().GetBuffer();
1026 if( T2T_PARA
!= cCh
)
1027 for( xub_StrLen nChPos
= 0; *pTxt
; ++nChPos
, ++pTxt
)
1030 aCntPos
.nContent
= nChPos
;
1031 SwCntntNode
* pNewNd
= pTxtNd
->SplitCntntNode( aCntPos
);
1033 if( aBkmkArr
.Count() )
1034 _RestoreCntntIdx( aBkmkArr
, *pNewNd
, nChPos
,
1037 // Trennzeichen loeschen und SuchString korrigieren
1038 pTxtNd
->EraseText( aCntPos
.nContent
, 1 );
1039 pTxt
= pTxtNd
->GetTxt().GetBuffer();
1041 --nChPos
, --pTxt
; // for the ++ in the for loop !!!
1043 // setze bei allen TextNodes in der Tabelle den TableNode
1045 const SwNodeIndex
aTmpIdx( aCntPos
.nNode
, -1 );
1046 pSttNd
= new SwStartNode( aTmpIdx
, ND_STARTNODE
,
1047 SwTableBoxStartNode
);
1048 new SwEndNode( aCntPos
.nNode
, *pSttNd
);
1049 pNewNd
->pStartOfSection
= pSttNd
;
1051 // Section der Box zuweisen
1052 pBox
= new SwTableBox( pBoxFmt
, *pSttNd
, pLine
);
1053 pLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pBox
, nBoxes
++ );
1056 // und jetzt den letzten Teil-String
1057 if( aBkmkArr
.Count() )
1058 _RestoreCntntIdx( aBkmkArr
, *pTxtNd
, pTxtNd
->GetTxt().Len(),
1059 pTxtNd
->GetTxt().Len()+1 );
1061 pSttNd
= new SwStartNode( aCntPos
.nNode
, ND_STARTNODE
, SwTableBoxStartNode
);
1062 const SwNodeIndex
aTmpIdx( aCntPos
.nNode
, 1 );
1063 new SwEndNode( aTmpIdx
, *pSttNd
);
1064 pTxtNd
->pStartOfSection
= pSttNd
;
1066 pBox
= new SwTableBox( pBoxFmt
, *pSttNd
, pLine
);
1067 pLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pBox
, nBoxes
++ );
1068 if( nMaxBoxes
< nBoxes
)
1072 // die Tabelle ausgleichen, leere Sections einfuegen
1075 for( n
= 0; n
< pTable
->GetTabLines().Count(); ++n
)
1077 SwTableLine
* pCurrLine
= pTable
->GetTabLines()[ n
];
1078 if( nMaxBoxes
!= ( nBoxes
= pCurrLine
->GetTabBoxes().Count() ))
1080 InsBoxen( pTblNd
, pCurrLine
, pBoxFmt
, pTxtColl
, 0,
1081 nBoxes
, nMaxBoxes
- nBoxes
);
1084 for( USHORT i
= nBoxes
; i
< nMaxBoxes
; ++i
)
1085 pUndo
->AddFillBox( *pCurrLine
->GetTabBoxes()[ i
] );
1087 // fehlen der 1. Line Boxen, dann kann man das Breiten Array
1090 aPosArr
.Remove( 0, aPosArr
.Count() );
1094 if( aPosArr
.Count() )
1096 SwTableLines
& rLns
= pTable
->GetTabLines();
1097 USHORT nLastPos
= 0;
1098 for( n
= 0; n
< aPosArr
.Count(); ++n
)
1100 SwTableBoxFmt
*pNewFmt
= pDoc
->MakeTableBoxFmt();
1101 pNewFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
1102 aPosArr
[ n
] - nLastPos
));
1103 for( USHORT nTmpLine
= 0; nTmpLine
< rLns
.Count(); ++nTmpLine
)
1104 //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
1105 // von der rufenden Methode noch gebraucht wird!
1106 pNewFmt
->Add( rLns
[ nTmpLine
]->GetTabBoxes()[ n
] );
1108 nLastPos
= aPosArr
[ n
];
1111 // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
1112 // Groesse nach "oben" transportieren.
1113 ASSERT( !pBoxFmt
->GetDepends(), "wer ist in dem Format noch angemeldet" );
1114 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nLastPos
));
1117 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, USHRT_MAX
/ nMaxBoxes
));
1119 // das wars doch wohl ??
1122 /*-- 18.05.2006 10:30:29---------------------------------------------------
1124 -----------------------------------------------------------------------*/
1125 const SwTable
* SwDoc::TextToTable( const std::vector
< std::vector
<SwNodeRange
> >& rTableNodes
)
1127 /* #106283# Save first node in the selection if it is a content node. */
1128 SwCntntNode
* pSttCntntNd
= rTableNodes
.begin()->begin()->aStart
.GetNode().GetCntntNode();
1131 #if OSL_DEBUG_LEVEL > 1
1132 const SwNodeRange
& rStartRange
= *rTableNodes
.begin()->begin();
1133 const SwNodeRange
& rEndRange
= *rTableNodes
.rbegin()->rbegin();
1139 //!!! not necessarily TextNodes !!!
1140 SwPaM
aOriginal( rTableNodes
.begin()->begin()->aStart
, rTableNodes
.rbegin()->rbegin()->aEnd
);
1141 const SwPosition
*pStt
= aOriginal
.GetMark();
1142 const SwPosition
*pEnd
= aOriginal
.GetPoint();
1144 #ifdef DEL_TABLE_REDLINES
1145 lcl_DelRedlines
aDelRedl( aOriginal
);
1148 SwUndoTxtToTbl
* pUndo
= 0;
1151 // StartUndo( UNDO_TEXTTOTABLE );
1152 // pUndo = new SwUndoTxtToTbl( aOriginal, rInsTblOpts, cCh, eAdjust, pTAFmt );
1153 // AppendUndo( pUndo );
1155 // das Splitten vom TextNode nicht in die Undohistory aufnehmen
1159 ::PaMCorrAbs( aOriginal
, *pEnd
);
1161 // sorge dafuer, das der Bereich auf Node-Grenzen liegt
1162 SwNodeRange
aRg( pStt
->nNode
, pEnd
->nNode
);
1163 if( pStt
->nContent
.GetIndex() )
1164 SplitNode( *pStt
, false );
1166 BOOL bEndCntnt
= 0 != pEnd
->nContent
.GetIndex();
1167 // nicht splitten am Ende der Zeile (aber am Ende vom Doc!!)
1170 if( pEnd
->nNode
.GetNode().GetCntntNode()->Len() != pEnd
->nContent
.GetIndex()
1171 || pEnd
->nNode
.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
1173 SplitNode( *pEnd
, false );
1174 ((SwNodeIndex
&)pEnd
->nNode
)--;
1175 ((SwIndex
&)pEnd
->nContent
).Assign(
1176 pEnd
->nNode
.GetNode().GetCntntNode(), 0 );
1177 // ein Node und am Ende ??
1178 if( pStt
->nNode
.GetIndex() >= pEnd
->nNode
.GetIndex() )
1186 if( aRg
.aEnd
.GetIndex() == aRg
.aStart
.GetIndex() )
1188 ASSERT( FALSE
, "Kein Bereich" );
1192 // Wir gehen jetzt immer ueber die Upper, um die Tabelle einzufuegen:
1193 SwNode2Layout
aNode2Layout( aRg
.aStart
.GetNode() );
1195 DoUndo( 0 != pUndo
);
1197 // dann erstelle die Box/Line/Table-Struktur
1198 SwTableBoxFmt
* pBoxFmt
= MakeTableBoxFmt();
1199 SwTableLineFmt
* pLineFmt
= MakeTableLineFmt();
1200 SwTableFmt
* pTableFmt
= MakeTblFrmFmt( GetUniqueTblName(), GetDfltFrmFmt() );
1202 // alle Zeilen haben die Fill-Order von links nach rechts !
1203 pLineFmt
->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT
));
1204 // die Tabelle bekommt USHRT_MAX als default SSize
1205 pTableFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, USHRT_MAX
));
1206 // if( !(rInsTblOpts.mnInsMode & tabopts::SPLIT_LAYOUT) )
1207 // pTableFmt->SetAttr( SwFmtLayoutSplit( FALSE ));
1209 /* #106283# If the first node in the selection is a context node and if it
1210 has an item FRAMEDIR set (no default) propagate the item to the
1214 const SwAttrSet
& aNdSet
= pSttCntntNd
->GetSwAttrSet();
1215 const SfxPoolItem
*pItem
= NULL
;
1217 if (SFX_ITEM_SET
== aNdSet
.GetItemState( RES_FRAMEDIR
, TRUE
, &pItem
)
1220 pTableFmt
->SetFmtAttr( *pItem
);
1224 SwTableNode
* pTblNd
= GetNodes().TextToTable(
1225 rTableNodes
, pTableFmt
, pLineFmt
, pBoxFmt
,
1226 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
)/*, pUndo*/ );
1228 SwTable
* pNdTbl
= &pTblNd
->GetTable();
1229 ASSERT( pNdTbl
, "kein Tabellen-Node angelegt." )
1230 pTableFmt
->Add( pNdTbl
); // das Frame-Format setzen
1232 // const USHORT nRowsToRepeat =
1233 // tabopts::HEADLINE == (rInsTblOpts.mnInsMode & tabopts::HEADLINE) ?
1234 // rInsTblOpts.mnRowsToRepeat :
1236 // pNdTbl->SetRowsToRepeat( nRowsToRepeat );
1238 BOOL bUseBoxFmt
= FALSE
;
1239 if( !pBoxFmt
->GetDepends() )
1241 // die Formate an den Boxen haben schon die richtige Size, es darf
1242 // also nur noch die richtige Umrandung/AutoFmt gesetzt werden.
1244 pTableFmt
->SetFmtAttr( pBoxFmt
->GetFrmSize() );
1246 // eAdjust = HORI_NONE;
1249 //Orientation am Fmt der Table setzen
1250 // pTableFmt->SetAttr( SwFmtHoriOrient( 0, eAdjust ) );
1251 // pTableFmt->Add( pNdTbl ); // das Frame-Format setzen
1254 ULONG nIdx
= pTblNd
->GetIndex();
1255 aNode2Layout
.RestoreUpperFrms( GetNodes(), nIdx
, nIdx
+ 1 );
1258 // SwPaM& rTmp = (SwPaM&)rRange; // Point immer an den Anfang
1259 // rTmp.DeleteMark();
1260 // rTmp.GetPoint()->nNode = *pTblNd;
1261 // SwCntntNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode );
1262 // rTmp.GetPoint()->nContent.Assign( pCNd, 0 );
1266 // EndUndo( UNDO_TEXTTOTABLE );
1269 SetFieldsDirty( true, NULL
, 0 );
1273 /*-- 18.05.2006 08:23:28---------------------------------------------------
1275 -----------------------------------------------------------------------*/
1276 SwTableNode
* SwNodes::TextToTable( const std::vector
< std::vector
<SwNodeRange
> >& rTableNodes
,
1277 SwTableFmt
* pTblFmt
,
1278 SwTableLineFmt
* pLineFmt
,
1279 SwTableBoxFmt
* pBoxFmt
,
1280 SwTxtFmtColl
* /*pTxtColl*/ /*, SwUndo... pUndo*/ )
1282 if( !rTableNodes
.size() )
1285 SwTableNode
* pTblNd
= new SwTableNode( rTableNodes
.begin()->begin()->aStart
);
1286 //insert the end node after the last text node
1287 SwNodeIndex
aInsertIndex( rTableNodes
.rbegin()->rbegin()->aEnd
);
1290 //!! owner ship will be transferred in c-tor to SwNodes array.
1291 //!! Thus no real problem here...
1292 new SwEndNode( aInsertIndex
, *pTblNd
);
1294 #if OSL_DEBUG_LEVEL > 1
1296 const SwNodeRange
& rStartRange
= *rTableNodes
.begin()->begin();
1297 const SwNodeRange
& rEndRange
= *rTableNodes
.rbegin()->rbegin();
1303 SwDoc
* pDoc
= GetDoc();
1304 SvUShorts
aPosArr( 0, 16 );
1305 SwTable
* pTable
= &pTblNd
->GetTable();
1308 USHORT nBoxes
, nLines
, nMaxBoxes
= 0;
1310 // SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : 0;
1313 SwNodeIndex aNodeIndex
= rTableNodes
.begin()->begin()->aStart
;
1314 // delete frames of all contained content nodes
1315 for( nLines
= 0; aNodeIndex
<= rTableNodes
.rbegin()->rbegin()->aEnd
; ++aNodeIndex
,++nLines
)
1317 SwNode
& rNode
= aNodeIndex
.GetNode();
1318 if( rNode
.IsCntntNode() )
1320 static_cast<SwCntntNode
&>(rNode
).DelFrms();
1321 if(rNode
.IsTxtNode())
1323 SwTxtNode
& rTxtNode
= static_cast<SwTxtNode
&>(rNode
);
1324 // setze den bei allen TextNode in der Tabelle den TableNode
1326 // FIXME: this is setting wrong node StartOfSections in nested tables.
1327 // rTxtNode.pStartOfSection = pTblNd;
1328 // remove PageBreaks/PageDesc/ColBreak
1329 const SwAttrSet
* pSet
= rTxtNode
.GetpSwAttrSet();
1332 // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle
1333 // erfolgen, denn sonst stehen sie falsch in der History !!!
1334 // SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory );
1335 const SfxPoolItem
* pItem
;
1336 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
, FALSE
, &pItem
) )
1339 pTblFmt
->SetFmtAttr( *pItem
);
1340 rTxtNode
.ResetAttr( RES_BREAK
);
1341 pSet
= rTxtNode
.GetpSwAttrSet();
1344 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState(
1345 RES_PAGEDESC
, FALSE
, &pItem
) &&
1346 ((SwFmtPageDesc
*)pItem
)->GetPageDesc() )
1349 pTblFmt
->SetFmtAttr( *pItem
);
1350 rTxtNode
.ResetAttr( RES_PAGEDESC
);
1357 // SwNodeIndex aSttIdx( *pTblNd, 1 );
1358 // SwNodeIndex aEndIdx( rlNodes.rbegin()->aEnd, -1 );
1359 std::vector
<std::vector
< SwNodeRange
> >::const_iterator aRowIter
= rTableNodes
.begin();
1360 for( nLines
= 0, nBoxes
= 0;
1361 aRowIter
!= rTableNodes
.end();
1362 ++aRowIter
, /*aSttIdx += 2, */nLines
++, nBoxes
= 0 )
1364 // SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
1365 // ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" );
1367 pLine
= new SwTableLine( pLineFmt
, 1, 0 );
1368 pTable
->GetTabLines().C40_INSERT( SwTableLine
, pLine
, nLines
);
1370 // SwStartNode* pSttNd;
1371 // SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd ));
1373 std::vector
< SwNodeRange
>::const_iterator aCellIter
= aRowIter
->begin();
1374 // SvULongs aBkmkArr( 15, 15 );
1375 // _SaveCntntIdx( pDoc, aCellIter->aStart.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr );
1376 // const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
1378 for( ; aCellIter
!= aRowIter
->end(); ++aCellIter
)
1380 // aCellIter->aStart aCellIter->aEnd
1381 // aCntPos.nContent = nChPos;
1382 // SwCntntNode* pNewNd = pTxtNd->SplitNode( aCntPos );
1385 // if( aBkmkArr.Count() )
1386 // _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos,
1389 const SwNodeIndex
aTmpIdx( aCellIter
->aStart
, 0 );
1391 SwNodeIndex
aCellEndIdx(aCellIter
->aEnd
);
1393 SwStartNode
* pSttNd
= new SwStartNode( aTmpIdx
, ND_STARTNODE
,
1394 SwTableBoxStartNode
);
1395 new SwEndNode( aCellEndIdx
, *pSttNd
);
1396 //set the start node on all node of the current cell
1397 SwNodeIndex aCellNodeIdx
= aCellIter
->aStart
;
1398 for(;aCellNodeIdx
<= aCellIter
->aEnd
; ++aCellNodeIdx
)
1400 aCellNodeIdx
.GetNode().pStartOfSection
= pSttNd
;
1401 //skip start/end node pairs
1402 if( aCellNodeIdx
.GetNode().IsStartNode() )
1403 aCellNodeIdx
= SwNodeIndex( *aCellNodeIdx
.GetNode().EndOfSectionNode() );
1406 // Section der Box zuweisen
1407 pBox
= new SwTableBox( pBoxFmt
, *pSttNd
, pLine
);
1408 pLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pBox
, nBoxes
++ );
1410 if( nMaxBoxes
< nBoxes
)
1414 // die Tabelle ausgleichen, leere Sections einfuegen
1417 if( aPosArr
.Count() )
1419 SwTableLines
& rLns
= pTable
->GetTabLines();
1420 USHORT nLastPos
= 0;
1421 for( n
= 0; n
< aPosArr
.Count(); ++n
)
1423 SwTableBoxFmt
*pNewFmt
= pDoc
->MakeTableBoxFmt();
1424 pNewFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
1425 aPosArr
[ n
] - nLastPos
));
1426 for( USHORT nLines2
= 0; nLines2
< rLns
.Count(); ++nLines2
)
1427 //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat
1428 // von der rufenden Methode noch gebraucht wird!
1429 pNewFmt
->Add( rLns
[ nLines2
]->GetTabBoxes()[ n
] );
1431 nLastPos
= aPosArr
[ n
];
1434 // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die
1435 // Groesse nach "oben" transportieren.
1436 ASSERT( !pBoxFmt
->GetDepends(), "wer ist in dem Format noch angemeldet" );
1437 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nLastPos
));
1440 pBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, USHRT_MAX
/ nMaxBoxes
));
1442 // das wars doch wohl ??
1447 //---------------- Tabelle -> Text -----------------------
1450 BOOL
SwDoc::TableToText( const SwTableNode
* pTblNd
, sal_Unicode cCh
)
1455 // --> FME 2004-09-28 #i34471#
1456 // If this is trigged by SwUndoTblToTxt::Repeat() nobody ever deleted
1457 // the table cursor.
1458 SwEditShell
* pESh
= GetEditShell();
1459 if( pESh
&& pESh
->IsTableMode() )
1463 #ifdef DEL_TABLE_REDLINES
1464 lcl_DelRedlines
aDelRedl( *pTblNd
, FALSE
);
1467 SwNodeRange
aRg( *pTblNd
, 0, *pTblNd
->EndOfSectionNode() );
1468 SwUndoTblToTxt
* pUndo
= 0;
1469 SwNodeRange
* pUndoRg
= 0;
1473 pUndoRg
= new SwNodeRange( aRg
.aStart
, -1, aRg
.aEnd
, +1 );
1474 pUndo
= new SwUndoTblToTxt( pTblNd
->GetTable(), cCh
);
1477 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
1478 aMsgHnt
.eFlags
= TBL_BOXNAME
;
1479 UpdateTblFlds( &aMsgHnt
);
1481 BOOL bRet
= GetNodes().TableToText( aRg
, cCh
, pUndo
);
1486 pUndo
->SetRange( *pUndoRg
);
1487 AppendUndo( pUndo
);
1497 // -- benutze die ForEach Methode vom PtrArray um aus einer Tabelle wieder
1498 // Text zuerzeugen. (Die Boxen koennen auch noch Lines enthalten !!)
1503 SwUndoTblToTxt
* pUndo
;
1506 _DelTabPara( SwNodes
& rNodes
, sal_Unicode cChar
, SwUndoTblToTxt
* pU
) :
1507 pLastNd(0), rNds( rNodes
), pUndo( pU
), cCh( cChar
) {}
1508 _DelTabPara( const _DelTabPara
& rPara
) :
1509 pLastNd(rPara
.pLastNd
), rNds( rPara
.rNds
),
1510 pUndo( rPara
.pUndo
), cCh( rPara
.cCh
) {}
1513 // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
1515 BOOL
lcl_DelBox( const SwTableBox
*&, void *pPara
);
1517 BOOL
lcl_DelLine( const SwTableLine
*& rpLine
, void* pPara
)
1519 ASSERT( pPara
, "die Parameter fehlen" );
1520 _DelTabPara
aPara( *(_DelTabPara
*)pPara
);
1521 ((SwTableLine
*&)rpLine
)->GetTabBoxes().ForEach( &lcl_DelBox
, &aPara
);
1522 if( rpLine
->GetUpper() ) // gibt es noch eine uebergeordnete Box ??
1523 // dann gebe den letzten TextNode zurueck
1524 ((_DelTabPara
*)pPara
)->pLastNd
= aPara
.pLastNd
;
1529 BOOL
lcl_DelBox( const SwTableBox
*& rpBox
, void* pPara
)
1531 ASSERT( pPara
, "die Parameter fehlen" );
1533 // loesche erstmal die Lines der Box
1534 _DelTabPara
* pDelPara
= (_DelTabPara
*)pPara
;
1535 if( rpBox
->GetTabLines().Count() )
1536 ((SwTableBox
*&)rpBox
)->GetTabLines().ForEach( &lcl_DelLine
, pDelPara
);
1539 SwDoc
* pDoc
= pDelPara
->rNds
.GetDoc();
1540 SwNodeRange
aDelRg( *rpBox
->GetSttNd(), 0,
1541 *rpBox
->GetSttNd()->EndOfSectionNode() );
1542 // loesche die Section
1543 pDelPara
->rNds
.SectionUp( &aDelRg
);
1544 const SwTxtNode
* pCurTxtNd
;
1545 if( T2T_PARA
!= pDelPara
->cCh
&& pDelPara
->pLastNd
&&
1546 0 != ( pCurTxtNd
= aDelRg
.aStart
.GetNode().GetTxtNode() ))
1548 // Join the current text node with the last from the previous box if possible
1549 ULONG nNdIdx
= aDelRg
.aStart
.GetIndex();
1551 if( pDelPara
->pLastNd
== &aDelRg
.aStart
.GetNode() )
1553 // Inserting the seperator
1554 SwIndex
aCntIdx( pDelPara
->pLastNd
, pDelPara
->pLastNd
->GetTxt().Len());
1555 pDelPara
->pLastNd
->InsertText( pDelPara
->cCh
, aCntIdx
,
1556 IDocumentContentOperations::INS_EMPTYEXPAND
);
1557 if( pDelPara
->pUndo
)
1558 pDelPara
->pUndo
->AddBoxPos( *pDoc
, nNdIdx
, aDelRg
.aEnd
.GetIndex(),
1559 aCntIdx
.GetIndex() );
1561 SvULongs
aBkmkArr( 4, 4 );
1562 xub_StrLen nOldTxtLen
= aCntIdx
.GetIndex();
1563 _SaveCntntIdx( pDoc
, nNdIdx
, pCurTxtNd
->GetTxt().Len(),
1566 pDelPara
->pLastNd
->JoinNext();
1568 if( aBkmkArr
.Count() )
1569 _RestoreCntntIdx( pDoc
, aBkmkArr
,
1570 pDelPara
->pLastNd
->GetIndex(),
1573 else if( pDelPara
->pUndo
)
1576 pDelPara
->pUndo
->AddBoxPos( *pDoc
, nNdIdx
, aDelRg
.aEnd
.GetIndex() );
1579 else if( pDelPara
->pUndo
)
1580 pDelPara
->pUndo
->AddBoxPos( *pDoc
, aDelRg
.aStart
.GetIndex(), aDelRg
.aEnd
.GetIndex() );
1582 pDelPara
->pLastNd
= aDelRg
.aEnd
.GetNode().GetTxtNode();
1584 //JP 03.04.97: die Ausrichtung der ZahlenFormatierung auf
1585 // keinen Fall uebernehmen
1586 if( pDelPara
->pLastNd
&& pDelPara
->pLastNd
->HasSwAttrSet() )
1587 pDelPara
->pLastNd
->ResetAttr( RES_PARATR_ADJUST
);
1593 BOOL
SwNodes::TableToText( const SwNodeRange
& rRange
, sal_Unicode cCh
,
1594 SwUndoTblToTxt
* pUndo
)
1596 // ist eine Tabelle selektiert ?
1597 SwTableNode
* pTblNd
;
1598 if( rRange
.aStart
.GetIndex() >= rRange
.aEnd
.GetIndex() ||
1599 0 == ( pTblNd
= (*this)[ rRange
.aStart
]->GetTableNode()) ||
1600 &rRange
.aEnd
.GetNode() != pTblNd
->EndOfSectionNode() )
1603 // stand die Tabelle ganz alleine in einer Section ?
1604 // dann ueber den Upper der Tabelle die Frames anlegen
1605 SwNode2Layout
* pNode2Layout
= 0;
1606 SwNodeIndex
aFrmIdx( rRange
.aStart
);
1607 SwNode
* pFrmNd
= FindPrvNxtFrmNode( aFrmIdx
, &rRange
.aEnd
.GetNode() );
1609 // dann sammel mal alle Uppers ein
1610 pNode2Layout
= new SwNode2Layout( *pTblNd
);
1612 // loesche schon mal die Frames
1615 // dann "loeschen" die Tabellen und fasse alle Lines/Boxen zusammen
1616 _DelTabPara
aDelPara( *this, cCh
, pUndo
);
1617 pTblNd
->pTable
->GetTabLines().ForEach( &lcl_DelLine
, &aDelPara
);
1619 // jetzt ist aus jeder TableLine ein TextNode mit dem entsprechenden
1620 // Trenner erzeugt worden. Es braucht nur noch die Table-Section
1621 // geloescht und fuer die neuen TextNode die Frames erzeugt werden.
1622 SwNodeRange
aDelRg( rRange
.aStart
, rRange
.aEnd
);
1624 // JP 14.01.97: hat die Tabelle PageDesc-/Break-Attribute? Dann in den
1625 // ersten TextNode uebernehmen
1627 // was ist mit UNDO???
1628 const SfxItemSet
& rTblSet
= pTblNd
->pTable
->GetFrmFmt()->GetAttrSet();
1629 const SfxPoolItem
*pBreak
, *pDesc
;
1630 if( SFX_ITEM_SET
!= rTblSet
.GetItemState( RES_PAGEDESC
, FALSE
, &pDesc
))
1632 if( SFX_ITEM_SET
!= rTblSet
.GetItemState( RES_BREAK
, FALSE
, &pBreak
))
1635 if( pBreak
|| pDesc
)
1637 SwNodeIndex
aIdx( *pTblNd
);
1638 SwCntntNode
* pCNd
= GoNext( &aIdx
);
1640 pCNd
->SetAttr( *pBreak
);
1642 pCNd
->SetAttr( *pDesc
);
1646 SectionUp( &aDelRg
); // loesche die Section und damit die Tabelle
1648 ULONG nStt
= aDelRg
.aStart
.GetIndex(), nEnd
= aDelRg
.aEnd
.GetIndex();
1651 pNode2Layout
->RestoreUpperFrms( *this,
1652 aDelRg
.aStart
.GetIndex(), aDelRg
.aEnd
.GetIndex() );
1653 delete pNode2Layout
;
1658 SwSectionNode
*pSNd
;
1659 while( aDelRg
.aStart
.GetIndex() < nEnd
)
1661 if( 0 != ( pCNd
= aDelRg
.aStart
.GetNode().GetCntntNode()))
1663 if( pFrmNd
->IsCntntNode() )
1664 ((SwCntntNode
*)pFrmNd
)->MakeFrms( *pCNd
);
1665 else if( pFrmNd
->IsTableNode() )
1666 ((SwTableNode
*)pFrmNd
)->MakeFrms( aDelRg
.aStart
);
1667 else if( pFrmNd
->IsSectionNode() )
1668 ((SwSectionNode
*)pFrmNd
)->MakeFrms( aDelRg
.aStart
);
1671 else if( 0 != ( pSNd
= aDelRg
.aStart
.GetNode().GetSectionNode()))
1673 if( !pSNd
->GetSection().IsHidden() && !pSNd
->IsCntntHidden() )
1675 pSNd
->MakeFrms( &aFrmIdx
, &aDelRg
.aEnd
);
1679 aDelRg
.aStart
= *pSNd
->EndOfSectionNode();
1685 // #i28006# Fly frames have to be restored even if the table was
1686 // #alone in the section
1687 const SwSpzFrmFmts
& rFlyArr
= *GetDoc()->GetSpzFrmFmts();
1688 const SwPosition
* pAPos
;
1689 for( USHORT n
= 0; n
< rFlyArr
.Count(); ++n
)
1691 SwFrmFmt
* pFmt
= (SwFrmFmt
*)rFlyArr
[n
];
1692 const SwFmtAnchor
& rAnchor
= pFmt
->GetAnchor();
1693 if( ( FLY_AT_CNTNT
== rAnchor
.GetAnchorId() ||
1694 FLY_AUTO_CNTNT
== rAnchor
.GetAnchorId() ) &&
1695 0 != ( pAPos
= rAnchor
.GetCntntAnchor() ) &&
1696 nStt
<= pAPos
->nNode
.GetIndex() &&
1697 pAPos
->nNode
.GetIndex() < nEnd
)
1705 // ----- einfuegen von Spalten/Zeilen ------------------------
1707 BOOL
SwDoc::InsertCol( const SwCursor
& rCursor
, USHORT nCnt
, BOOL bBehind
)
1709 if( !::CheckSplitCells( rCursor
, nCnt
+ 1, nsSwTblSearchType::TBLSEARCH_COL
) )
1712 // lasse ueber das Layout die Boxen suchen
1714 ::GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
1717 if( aBoxes
.Count() )
1718 bRet
= InsertCol( aBoxes
, nCnt
, bBehind
);
1722 BOOL
SwDoc::InsertCol( const SwSelBoxes
& rBoxes
, USHORT nCnt
, BOOL bBehind
)
1724 // uebers SwDoc fuer Undo !!
1725 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1726 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1730 SwTable
& rTbl
= pTblNd
->GetTable();
1731 if( rTbl
.ISA( SwDDETable
))
1734 #ifdef DEL_TABLE_REDLINES
1735 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
1738 SwTableSortBoxes
aTmpLst( 0, 5 );
1739 SwUndoTblNdsChg
* pUndo
= 0;
1743 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_INSCOL
, rBoxes
, *pTblNd
,
1744 0, 0, nCnt
, bBehind
, FALSE
);
1745 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
1748 SwTableFmlUpdate
aMsgHnt( &rTbl
);
1749 aMsgHnt
.eFlags
= TBL_BOXPTR
;
1750 UpdateTblFlds( &aMsgHnt
);
1752 BOOL bRet
= rTbl
.InsertCol( this, rBoxes
, nCnt
, bBehind
);
1756 ::ClearFEShellTabCols();
1757 SetFieldsDirty( true, NULL
, 0 );
1766 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
1767 AppendUndo( pUndo
);
1775 BOOL
SwDoc::InsertRow( const SwCursor
& rCursor
, USHORT nCnt
, BOOL bBehind
)
1777 // lasse ueber das Layout die Boxen suchen
1779 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_ROW
);
1782 if( aBoxes
.Count() )
1783 bRet
= InsertRow( aBoxes
, nCnt
, bBehind
);
1787 BOOL
SwDoc::InsertRow( const SwSelBoxes
& rBoxes
, USHORT nCnt
, BOOL bBehind
)
1789 // uebers SwDoc fuer Undo !!
1790 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1791 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1795 SwTable
& rTbl
= pTblNd
->GetTable();
1796 if( rTbl
.ISA( SwDDETable
))
1799 #ifdef DEL_TABLE_REDLINES
1800 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
1803 SwTableSortBoxes
aTmpLst( 0, 5 );
1804 SwUndoTblNdsChg
* pUndo
= 0;
1808 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_INSROW
,rBoxes
, *pTblNd
,
1809 0, 0, nCnt
, bBehind
, FALSE
);
1810 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
1813 SwTableFmlUpdate
aMsgHnt( &rTbl
);
1814 aMsgHnt
.eFlags
= TBL_BOXPTR
;
1815 UpdateTblFlds( &aMsgHnt
);
1817 BOOL bRet
= rTbl
.InsertRow( this, rBoxes
, nCnt
, bBehind
);
1821 ::ClearFEShellTabCols();
1822 SetFieldsDirty( true, NULL
, 0 );
1831 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
1832 AppendUndo( pUndo
);
1841 // ----- loeschen von Spalten/Zeilen ------------------------
1843 BOOL
SwDoc::DeleteRow( const SwCursor
& rCursor
)
1845 // lasse ueber das Layout die Boxen suchen
1847 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_ROW
);
1848 if( ::HasProtectedCells( aBoxes
))
1851 // die Crsr aus dem Loeschbereich entfernen.
1852 // Der Cursor steht danach:
1853 // - es folgt noch eine Zeile, in dieser
1854 // - vorher steht noch eine Zeile, in dieser
1855 // - sonst immer dahinter
1857 SwTableNode
* pTblNd
= rCursor
.GetNode()->FindTableNode();
1859 if( pTblNd
->GetTable().ISA( SwDDETable
))
1862 // suche alle Boxen / Lines
1863 _FndBox
aFndBox( 0, 0 );
1865 _FndPara
aPara( aBoxes
, &aFndBox
);
1866 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
1869 if( !aFndBox
.GetLines().Count() )
1872 SwEditShell
* pESh
= GetEditShell();
1876 // JP: eigentlich sollte man ueber alle Shells iterieren!!
1879 _FndBox
* pFndBox
= &aFndBox
;
1880 while( 1 == pFndBox
->GetLines().Count() &&
1881 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
1883 _FndBox
* pTmp
= pFndBox
->GetLines()[0]->GetBoxes()[0];
1884 if( pTmp
->GetBox()->GetSttNd() )
1885 break; // das ist sonst zu weit
1889 SwTableLine
* pDelLine
= pFndBox
->GetLines()[
1890 pFndBox
->GetLines().Count()-1 ]->GetLine();
1891 SwTableBox
* pDelBox
= pDelLine
->GetTabBoxes()[
1892 pDelLine
->GetTabBoxes().Count() - 1 ];
1893 while( !pDelBox
->GetSttNd() )
1895 SwTableLine
* pLn
= pDelBox
->GetTabLines()[
1896 pDelBox
->GetTabLines().Count()-1 ];
1897 pDelBox
= pLn
->GetTabBoxes()[ pLn
->GetTabBoxes().Count() - 1 ];
1899 SwTableBox
* pNextBox
= pDelLine
->FindNextBox( pTblNd
->GetTable(),
1902 pNextBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
1903 pNextBox
= pNextBox
->FindNextBox( pTblNd
->GetTable(), pNextBox
);
1905 if( !pNextBox
) // keine nachfolgende? dann die vorhergehende
1907 pDelLine
= pFndBox
->GetLines()[ 0 ]->GetLine();
1908 pDelBox
= pDelLine
->GetTabBoxes()[ 0 ];
1909 while( !pDelBox
->GetSttNd() )
1910 pDelBox
= pDelBox
->GetTabLines()[0]->GetTabBoxes()[0];
1911 pNextBox
= pDelLine
->FindPreviousBox( pTblNd
->GetTable(),
1914 pNextBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
1915 pNextBox
= pNextBox
->FindPreviousBox( pTblNd
->GetTable(), pNextBox
);
1919 if( pNextBox
) // dann den Cursor hier hinein
1920 nIdx
= pNextBox
->GetSttIdx() + 1;
1921 else // ansonsten hinter die Tabelle
1922 nIdx
= pTblNd
->EndOfSectionIndex() + 1;
1924 SwNodeIndex
aIdx( GetNodes(), nIdx
);
1925 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
1927 pCNd
= GetNodes().GoNext( &aIdx
);
1931 // die Cursor von der Shell oder den uebergebenen Cursor aendern?
1932 SwPaM
* pPam
= (SwPaM
*)&rCursor
;
1933 pPam
->GetPoint()->nNode
= aIdx
;
1934 pPam
->GetPoint()->nContent
.Assign( pCNd
, 0 );
1935 pPam
->SetMark(); // beide wollen etwas davon haben
1940 // dann loesche doch die Zeilen
1942 StartUndo(UNDO_ROW_DELETE
, NULL
);
1943 BOOL bResult
= DeleteRowCol( aBoxes
);
1944 EndUndo(UNDO_ROW_DELETE
, NULL
);
1949 BOOL
SwDoc::DeleteCol( const SwCursor
& rCursor
)
1951 // lasse ueber das Layout die Boxen suchen
1953 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
1954 if( ::HasProtectedCells( aBoxes
))
1957 // die Crsr muessen noch aus dem Loesch Bereich entfernt
1958 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
1959 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
1960 SwEditShell
* pESh
= GetEditShell();
1963 const SwNode
* pNd
= rCursor
.GetNode()->FindTableBoxStartNode();
1964 pESh
->ParkCrsr( SwNodeIndex( *pNd
) );
1967 // dann loesche doch die Spalten
1968 StartUndo(UNDO_COL_DELETE
, NULL
);
1969 BOOL bResult
= DeleteRowCol( aBoxes
, true );
1970 EndUndo(UNDO_COL_DELETE
, NULL
);
1975 BOOL
SwDoc::DeleteRowCol( const SwSelBoxes
& rBoxes
, bool bColumn
)
1977 if( ::HasProtectedCells( rBoxes
))
1980 // uebers SwDoc fuer Undo !!
1981 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1982 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1986 if( pTblNd
->GetTable().ISA( SwDDETable
))
1989 ::ClearFEShellTabCols();
1990 SwSelBoxes aSelBoxes
;
1991 aSelBoxes
.Insert(rBoxes
.GetData(), rBoxes
.Count());
1992 SwTable
&rTable
= pTblNd
->GetTable();
1995 if( rTable
.IsNewModel() )
1998 rTable
.ExpandColumnSelection( aSelBoxes
, nMin
, nMax
);
2000 rTable
.FindSuperfluousRows( aSelBoxes
);
2003 #ifdef DEL_TABLE_REDLINES
2004 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
2007 // soll die gesamte Tabelle geloescht werden ??
2008 const ULONG nTmpIdx1
= pTblNd
->GetIndex();
2009 const ULONG nTmpIdx2
= aSelBoxes
[ aSelBoxes
.Count()-1 ]->GetSttNd()->
2010 EndOfSectionIndex()+1;
2011 if( pTblNd
->GetTable().GetTabSortBoxes().Count() == aSelBoxes
.Count() &&
2012 aSelBoxes
[0]->GetSttIdx()-1 == nTmpIdx1
&&
2013 nTmpIdx2
== pTblNd
->EndOfSectionIndex() )
2015 BOOL bNewTxtNd
= FALSE
;
2016 // steht diese auch noch alleine in einem FlyFrame ?
2017 SwNodeIndex
aIdx( *pTblNd
, -1 );
2018 const SwStartNode
* pSttNd
= aIdx
.GetNode().GetStartNode();
2021 const ULONG nTblEnd
= pTblNd
->EndOfSectionIndex() + 1;
2022 const ULONG nSectEnd
= pSttNd
->EndOfSectionIndex();
2023 if( nTblEnd
== nSectEnd
)
2025 if( SwFlyStartNode
== pSttNd
->GetStartNodeType() )
2027 SwFrmFmt
* pFmt
= pSttNd
->GetFlyFmt();
2030 // Ok, das ist das gesuchte FlyFormat
2031 DelLayoutFmt( pFmt
);
2035 // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2036 // TextNode ueberig lassen.
2037 // Undo koennen wir dann vergessen !!
2042 // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2043 // TextNode ueberig lassen.
2048 SwPaM
aPaM( *pTblNd
->EndOfSectionNode(), aIdx
.GetNode() );
2052 const SwNodeIndex
aTmpIdx( *pTblNd
->EndOfSectionNode(), 1 );
2053 GetNodes().MakeTxtNode( aTmpIdx
,
2054 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
) );
2057 // save the cursors (UNO and otherwise)
2058 SwPaM
aSavePaM( SwNodeIndex( *pTblNd
->EndOfSectionNode() ) );
2059 if( ! aSavePaM
.Move( fnMoveForward
, fnGoNode
) )
2061 *aSavePaM
.GetMark() = SwPosition( *pTblNd
);
2062 aSavePaM
.Move( fnMoveBackward
, fnGoNode
);
2064 ::PaMCorrAbs( SwNodeIndex( *pTblNd
),
2065 SwNodeIndex( *pTblNd
->EndOfSectionNode() ),
2066 *aSavePaM
.GetMark() );
2068 // harte SeitenUmbrueche am nachfolgenden Node verschieben
2069 BOOL bSavePageBreak
= FALSE
, bSavePageDesc
= FALSE
;
2070 ULONG nNextNd
= pTblNd
->EndOfSectionIndex()+1;
2071 SwCntntNode
* pNextNd
= GetNodes()[ nNextNd
]->GetCntntNode();
2074 //JP 24.08.98: will man wirklich den PageDesc/Break vom
2075 // nachfolgen Absatz ueberbuegeln?
2076 // const SwAttrSet& rAttrSet = pNextNd->GetSwAttrSet();
2077 // if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
2078 // SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
2080 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2081 const SfxPoolItem
*pItem
;
2082 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_PAGEDESC
,
2085 pNextNd
->SetAttr( *pItem
);
2086 bSavePageDesc
= TRUE
;
2089 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_BREAK
,
2092 pNextNd
->SetAttr( *pItem
);
2093 bSavePageBreak
= TRUE
;
2097 SwUndoDelete
* pUndo
= new SwUndoDelete( aPaM
);
2099 pUndo
->SetTblDelLastNd();
2100 pUndo
->SetPgBrkFlags( bSavePageBreak
, bSavePageDesc
);
2101 pUndo
->SetTableName(pTblNd
->GetTable().GetFrmFmt()->GetName());
2102 AppendUndo( pUndo
);
2108 const SwNodeIndex
aTmpIdx( *pTblNd
->EndOfSectionNode(), 1 );
2109 GetNodes().MakeTxtNode( aTmpIdx
,
2110 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
) );
2113 // save the cursors (UNO and otherwise)
2114 SwPaM
aSavePaM( SwNodeIndex( *pTblNd
->EndOfSectionNode() ) );
2115 if( ! aSavePaM
.Move( fnMoveForward
, fnGoNode
) )
2117 *aSavePaM
.GetMark() = SwPosition( *pTblNd
);
2118 aSavePaM
.Move( fnMoveBackward
, fnGoNode
);
2120 ::PaMCorrAbs( SwNodeIndex( *pTblNd
),
2121 SwNodeIndex( *pTblNd
->EndOfSectionNode() ),
2122 *aSavePaM
.GetMark() );
2124 // harte SeitenUmbrueche am nachfolgenden Node verschieben
2125 SwCntntNode
* pNextNd
= GetNodes()[ pTblNd
->EndOfSectionIndex()+1 ]->GetCntntNode();
2128 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2129 const SfxPoolItem
*pItem
;
2130 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_PAGEDESC
,
2132 pNextNd
->SetAttr( *pItem
);
2134 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_BREAK
,
2136 pNextNd
->SetAttr( *pItem
);
2140 DeleteSection( pTblNd
);
2143 SetFieldsDirty( true, NULL
, 0 );
2147 SwUndoTblNdsChg
* pUndo
= 0;
2151 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_DELBOX
, aSelBoxes
, *pTblNd
,
2152 nMin
, nMax
, 0, FALSE
, FALSE
);
2155 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
2156 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2157 UpdateTblFlds( &aMsgHnt
);
2159 if( rTable
.IsNewModel() )
2162 rTable
.PrepareDeleteCol( nMin
, nMax
);
2163 rTable
.FindSuperfluousRows( aSelBoxes
);
2165 pUndo
->ReNewBoxes( aSelBoxes
);
2167 const BOOL bRet
= rTable
.DeleteSel( this, aSelBoxes
, 0, pUndo
, TRUE
, TRUE
);
2171 SetFieldsDirty( true, NULL
, 0 );
2180 AppendUndo( pUndo
);
2190 // ---------- teilen / zusammenfassen von Boxen in der Tabelle --------
2192 BOOL
SwDoc::SplitTbl( const SwSelBoxes
& rBoxes
, sal_Bool bVert
, USHORT nCnt
,
2193 sal_Bool bSameHeight
)
2195 // uebers SwDoc fuer Undo !!
2196 ASSERT( rBoxes
.Count() && nCnt
, "keine gueltige Box-Liste" );
2197 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
2201 SwTable
& rTbl
= pTblNd
->GetTable();
2202 if( rTbl
.ISA( SwDDETable
))
2205 #ifdef DEL_TABLE_REDLINES
2206 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
2210 SwTableSortBoxes
aTmpLst( 0, 5 );
2211 SwUndoTblNdsChg
* pUndo
= 0;
2212 BOOL bDoUndo
= DoesUndo();
2216 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_SPLIT
, rBoxes
, *pTblNd
, 0, 0,
2217 nCnt
, bVert
, bSameHeight
);
2219 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
2222 for( USHORT n
= 0; n
< rBoxes
.Count(); ++n
)
2224 const SwStartNode
* pSttNd
= rBoxes
[ n
]->GetSttNd();
2225 aNdsCnts
.Insert( pSttNd
->EndOfSectionIndex() -
2226 pSttNd
->GetIndex(), n
);
2231 SwTableFmlUpdate
aMsgHnt( &rTbl
);
2232 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2233 UpdateTblFlds( &aMsgHnt
);
2237 bRet
= rTbl
.SplitCol( this, rBoxes
, nCnt
);
2239 bRet
= rTbl
.SplitRow( this, rBoxes
, nCnt
, bSameHeight
);
2244 SetFieldsDirty( true, NULL
, 0 );
2254 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
2256 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
, rBoxes
, aNdsCnts
);
2257 AppendUndo( pUndo
);
2267 USHORT
SwDoc::MergeTbl( SwPaM
& rPam
)
2269 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
2270 SwTableNode
* pTblNd
= rPam
.GetNode()->FindTableNode();
2272 return TBLMERGE_NOSELECTION
;
2273 SwTable
& rTable
= pTblNd
->GetTable();
2274 if( rTable
.ISA(SwDDETable
) )
2275 return TBLMERGE_NOSELECTION
;
2276 USHORT nRet
= TBLMERGE_NOSELECTION
;
2277 if( !rTable
.IsNewModel() )
2279 nRet
=::CheckMergeSel( rPam
);
2280 if( TBLMERGE_OK
!= nRet
)
2282 nRet
= TBLMERGE_NOSELECTION
;
2285 // --> FME 2004-10-08 #i33394#
2286 StartUndo( UNDO_TABLE_MERGE
, NULL
);
2289 #ifdef DEL_TABLE_REDLINES
2290 if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
2291 DeleteRedline( *pTblNd
, true, USHRT_MAX
);
2293 RedlineMode_t eOld
= GetRedlineMode();
2294 SetRedlineMode_intern((RedlineMode_t
)(eOld
| nsRedlineMode_t::REDLINE_IGNORE
));
2296 SwUndoTblMerge
* pUndo
= 0;
2298 pUndo
= new SwUndoTblMerge( rPam
);
2300 // lasse ueber das Layout die Boxen suchen
2303 SwTableBox
* pMergeBox
;
2305 if( !rTable
.PrepareMerge( rPam
, aBoxes
, aMerged
, &pMergeBox
, pUndo
) )
2306 { // no cells found to merge
2307 SetRedlineMode_intern( eOld
);
2311 if( UNDO_REDLINE
== GetUndoIds(NULL
, NULL
) )
2313 SwUndoRedline
* pU
= (SwUndoRedline
*)RemoveLastUndo( UNDO_REDLINE
);
2314 if( pU
->GetRedlSaveCount() )
2316 SwUndoIter
aUndoIter( &rPam
, UNDO_REDLINE
);
2317 pU
->Undo( aUndoIter
);
2325 // die PaMs muessen noch aus dem Loesch Bereich entfernt
2326 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
2327 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
2328 // Erstmal einen Index auf die Parkposition merken, denn nach GetMergeSel
2329 // komme ich nicht mehr dran.
2332 rPam
.GetPoint()->nNode
= *pMergeBox
->GetSttNd();
2333 rPam
.GetPoint()->nContent
.Assign( 0, 0 );
2337 SwPaM
* pTmp
= &rPam
;
2338 while( &rPam
!= ( pTmp
= (SwPaM
*)pTmp
->GetNext() ))
2339 for( int i
= 0; i
< 2; ++i
)
2340 pTmp
->GetBound( (BOOL
)i
) = *rPam
.GetPoint();
2343 // dann fuege sie zusammen
2344 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
2345 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2346 UpdateTblFlds( &aMsgHnt
);
2348 if( pTblNd
->GetTable().Merge( this, aBoxes
, aMerged
, pMergeBox
, pUndo
))
2352 SetFieldsDirty( true, NULL
, 0 );
2354 AppendUndo( pUndo
);
2359 rPam
.GetPoint()->nNode
= *pMergeBox
->GetSttNd();
2362 ::ClearFEShellTabCols();
2363 SetRedlineMode_intern( eOld
);
2365 EndUndo( UNDO_TABLE_MERGE
, NULL
);
2371 // -------------------------------------------------------
2377 SwTableNode::SwTableNode( const SwNodeIndex
& rIdx
)
2378 : SwStartNode( rIdx
, ND_TABLENODE
)
2380 pTable
= new SwTable( 0 );
2383 SwTableNode::~SwTableNode()
2385 //don't forget to notify uno wrappers
2386 SwFrmFmt
* pTblFmt
= GetTable().GetFrmFmt();
2387 SwPtrMsgPoolItem
aMsgHint( RES_REMOVE_UNO_OBJECT
,
2389 pTblFmt
->Modify( &aMsgHint
, &aMsgHint
);
2394 SwTabFrm
*SwTableNode::MakeFrm()
2396 return new SwTabFrm( *pTable
);
2399 //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
2400 //Dokument. Die erzeugten Contentframes werden in das entsprechende
2402 void SwTableNode::MakeFrms(const SwNodeIndex
& rIdx
)
2404 if( !GetTable().GetFrmFmt()->GetDepends())//gibt es ueberhaupt Frames ??
2408 SwCntntNode
* pNode
= rIdx
.GetNode().GetCntntNode();
2410 ASSERT( pNode
, "Kein Contentnode oder Copy-Node und neuer Node identisch.");
2412 BOOL bBefore
= rIdx
< GetIndex();
2414 SwNode2Layout
aNode2Layout( *this, rIdx
.GetIndex() );
2416 while( 0 != (pFrm
= aNode2Layout
.NextFrm()) )
2418 pNew
= pNode
->MakeFrm();
2419 // wird ein Node vorher oder nachher mit Frames versehen
2421 // der neue liegt vor mir
2422 pNew
->Paste( pFrm
->GetUpper(), pFrm
);
2424 // der neue liegt hinter mir
2425 pNew
->Paste( pFrm
->GetUpper(), pFrm
->GetNext() );
2429 //Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden
2432 void SwTableNode::MakeFrms( SwNodeIndex
* pIdxBehind
)
2434 ASSERT( pIdxBehind
, "kein Index" );
2435 *pIdxBehind
= *this;
2436 SwNode
*pNd
= GetNodes().FindPrvNxtFrmNode( *pIdxBehind
, EndOfSectionNode() );
2441 SwLayoutFrm
*pUpper( 0L );
2442 SwNode2Layout
aNode2Layout( *pNd
, GetIndex() );
2443 while( 0 != (pUpper
= aNode2Layout
.UpperFrm( pFrm
, *this )) )
2445 SwTabFrm
* pNew
= MakeFrm();
2446 pNew
->Paste( pUpper
, pFrm
);
2447 // --> OD 2005-12-01 #i27138#
2448 // notify accessibility paragraphs objects about changed
2449 // CONTENT_FLOWS_FROM/_TO relation.
2450 // Relation CONTENT_FLOWS_FROM for next paragraph will change
2451 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2453 ViewShell
* pViewShell( pNew
->GetShell() );
2454 if ( pViewShell
&& pViewShell
->GetLayout() &&
2455 pViewShell
->GetLayout()->IsAnyShellAccessible() )
2457 pViewShell
->InvalidateAccessibleParaFlowRelation(
2458 dynamic_cast<SwTxtFrm
*>(pNew
->FindNextCnt( true )),
2459 dynamic_cast<SwTxtFrm
*>(pNew
->FindPrevCnt( true )) );
2463 ((SwTabFrm
*)pNew
)->RegistFlys();
2467 void SwTableNode::DelFrms()
2469 //Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows
2470 //nehmen sie mit in's Grab.
2471 //Die TabFrms haengen am FrmFmt des SwTable.
2472 //Sie muessen etwas umstaendlich zerstort werden, damit die Master
2473 //die Follows mit in's Grab nehmen.
2475 SwClientIter
aIter( *(pTable
->GetFrmFmt()) );
2476 SwClient
*pLast
= aIter
.GoStart();
2479 BOOL bAgain
= FALSE
;
2480 if ( pLast
->IsA( TYPE(SwFrm
) ) )
2482 SwTabFrm
*pFrm
= (SwTabFrm
*)pLast
;
2483 if ( !pFrm
->IsFollow() )
2485 while ( pFrm
->HasFollow() )
2486 pFrm
->JoinAndDelFollows();
2487 // --> OD 2005-12-01 #i27138#
2488 // notify accessibility paragraphs objects about changed
2489 // CONTENT_FLOWS_FROM/_TO relation.
2490 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2491 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2493 ViewShell
* pViewShell( pFrm
->GetShell() );
2494 if ( pViewShell
&& pViewShell
->GetLayout() &&
2495 pViewShell
->GetLayout()->IsAnyShellAccessible() )
2497 pViewShell
->InvalidateAccessibleParaFlowRelation(
2498 dynamic_cast<SwTxtFrm
*>(pFrm
->FindNextCnt( true )),
2499 dynamic_cast<SwTxtFrm
*>(pFrm
->FindPrevCnt( true )) );
2508 pLast
= bAgain
? aIter
.GoStart() : aIter
++;
2513 void SwTableNode::SetNewTable( SwTable
* pNewTable
, BOOL bNewFrames
)
2520 SwNodeIndex
aIdx( *EndOfSectionNode());
2521 GetNodes().GoNext( &aIdx
);
2526 void SwDoc::GetTabCols( SwTabCols
&rFill
, const SwCursor
* pCrsr
,
2527 const SwCellFrm
* pBoxFrm
) const
2529 const SwTableBox
* pBox
= 0;
2534 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2535 pBox
= pBoxFrm
->GetTabBox();
2539 const SwCntntNode
* pCNd
= pCrsr
->GetCntntNode();
2544 const SwShellCrsr
*pShCrsr
= dynamic_cast<const SwShellCrsr
*>(pCrsr
);
2546 aPt
= pShCrsr
->GetPtPos();
2548 const SwFrm
* pTmpFrm
= pCNd
->GetFrm( &aPt
, 0, FALSE
);
2550 pTmpFrm
= pTmpFrm
->GetUpper();
2551 } while ( !pTmpFrm
->IsCellFrm() );
2553 pBoxFrm
= (SwCellFrm
*)pTmpFrm
;
2554 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2555 pBox
= pBoxFrm
->GetTabBox();
2557 else if( !pCrsr
&& !pBoxFrm
)
2559 ASSERT( !this, "einer von beiden muss angegeben werden!" );
2563 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2565 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2566 const ULONG nLeftMin
= (pTab
->Frm().*fnRect
->fnGetLeft
)() -
2567 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2568 const ULONG nRightMax
= (pTab
->Frm().*fnRect
->fnGetRight
)() -
2569 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2571 rFill
.SetLeftMin ( nLeftMin
);
2572 rFill
.SetLeft ( (pTab
->Prt().*fnRect
->fnGetLeft
)() );
2573 rFill
.SetRight ( (pTab
->Prt().*fnRect
->fnGetRight
)());
2574 rFill
.SetRightMax( nRightMax
- nLeftMin
);
2576 pTab
->GetTable()->GetTabCols( rFill
, pBox
);
2580 // Here are some little helpers used in SwDoc::GetTabRows
2587 bool operator() ( long s1
, long s2
) const;
2590 bool FuzzyCompare::operator() ( long s1
, long s2
) const
2592 return ( s1
< s2
&& abs( s1
- s2
) > ROWFUZZY
);
2595 bool lcl_IsFrmInColumn( const SwCellFrm
& rFrm
, SwSelBoxes
& rBoxes
)
2597 for( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
2599 if ( rFrm
.GetTabBox() == rBoxes
[ i
] )
2607 // SwDoc::GetTabRows()
2610 void SwDoc::GetTabRows( SwTabCols
&rFill
, const SwCursor
* ,
2611 const SwCellFrm
* pBoxFrm
) const
2613 ASSERT( pBoxFrm
, "GetTabRows called without pBoxFrm" )
2615 // --> FME 2005-09-12 #121591# Make code robust:
2620 // --> FME 2005-01-06 #i39552# Collection of the boxes of the current
2621 // column has to be done at the beginning of this function, because
2622 // the table may be formatted in ::GetTblSel.
2623 SwDeletionChecker
aDelCheck( pBoxFrm
);
2626 const SwCntntFrm
* pCntnt
= ::GetCellCntnt( *pBoxFrm
);
2627 if ( pCntnt
&& pCntnt
->IsTxtFrm() )
2629 const SwPosition
aPos( *((SwTxtFrm
*)pCntnt
)->GetTxtNode() );
2630 const SwCursor
aTmpCrsr( aPos
, 0, false );
2631 ::GetTblSel( aTmpCrsr
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
2635 // --> FME 2005-09-12 #121591# Make code robust:
2636 if ( aDelCheck
.HasBeenDeleted() )
2638 ASSERT( false, "Current box has been deleted during GetTabRows()" )
2643 // --> FME 2005-09-12 #121591# Make code robust:
2644 const SwTabFrm
* pTab
= pBoxFrm
->FindTabFrm();
2645 ASSERT( pTab
, "GetTabRows called without a table" )
2650 const SwFrm
* pFrm
= pTab
->GetNextLayoutLeaf();
2652 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2654 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2655 const long nLeftMin
= ( bVert
?
2656 pTab
->GetPrtLeft() - pPage
->Frm().Left() :
2657 pTab
->GetPrtTop() - pPage
->Frm().Top() );
2658 const long nLeft
= bVert
? LONG_MAX
: 0;
2659 const long nRight
= (pTab
->Prt().*fnRect
->fnGetHeight
)();
2660 const long nRightMax
= bVert
? nRight
: LONG_MAX
;
2662 rFill
.SetLeftMin( nLeftMin
);
2663 rFill
.SetLeft( nLeft
);
2664 rFill
.SetRight( nRight
);
2665 rFill
.SetRightMax( nRightMax
);
2667 typedef std::map
< long, std::pair
< long, long >, FuzzyCompare
> BoundaryMap
;
2668 BoundaryMap aBoundaries
;
2669 BoundaryMap::iterator aIter
;
2670 std::pair
< long, long > aPair
;
2672 typedef std::map
< long, bool > HiddenMap
;
2674 HiddenMap::iterator aHiddenIter
;
2676 while ( pFrm
&& pTab
->IsAnLower( pFrm
) )
2678 if ( pFrm
->IsCellFrm() && pFrm
->FindTabFrm() == pTab
)
2680 // upper and lower borders of current cell frame:
2681 long nUpperBorder
= (pFrm
->Frm().*fnRect
->fnGetTop
)();
2682 long nLowerBorder
= (pFrm
->Frm().*fnRect
->fnGetBottom
)();
2684 // get boundaries for nUpperBorder:
2685 aIter
= aBoundaries
.find( nUpperBorder
);
2686 if ( aIter
== aBoundaries
.end() )
2688 aPair
.first
= nUpperBorder
; aPair
.second
= LONG_MAX
;
2689 aBoundaries
[ nUpperBorder
] = aPair
;
2692 // get boundaries for nLowerBorder:
2693 aIter
= aBoundaries
.find( nLowerBorder
);
2694 if ( aIter
== aBoundaries
.end() )
2696 aPair
.first
= nUpperBorder
; aPair
.second
= LONG_MAX
;
2700 nLowerBorder
= (*aIter
).first
;
2701 long nNewLowerBorderUpperBoundary
= Max( (*aIter
).second
.first
, nUpperBorder
);
2702 aPair
.first
= nNewLowerBorderUpperBoundary
; aPair
.second
= LONG_MAX
;
2704 aBoundaries
[ nLowerBorder
] = aPair
;
2706 // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2707 long nTmpVal
= nUpperBorder
;
2708 for ( BYTE i
= 0; i
< 2; ++i
)
2710 aHiddenIter
= aHidden
.find( nTmpVal
);
2711 if ( aHiddenIter
== aHidden
.end() )
2712 aHidden
[ nTmpVal
] = !lcl_IsFrmInColumn( *((SwCellFrm
*)pFrm
), aBoxes
);
2715 if ( aHidden
[ nTmpVal
] &&
2716 lcl_IsFrmInColumn( *((SwCellFrm
*)pFrm
), aBoxes
) )
2717 aHidden
[ nTmpVal
] = false;
2719 nTmpVal
= nLowerBorder
;
2723 pFrm
= pFrm
->GetNextLayoutLeaf();
2726 // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2728 for ( aIter
= aBoundaries
.begin(); aIter
!= aBoundaries
.end(); ++aIter
)
2730 const long nTabTop
= (pTab
->*fnRect
->fnGetPrtTop
)();
2731 const long nKey
= (*fnRect
->fnYDiff
)( (*aIter
).first
, nTabTop
);
2732 const std::pair
< long, long > aTmpPair
= (*aIter
).second
;
2733 const long nFirst
= (*fnRect
->fnYDiff
)( aTmpPair
.first
, nTabTop
);
2734 const long nSecond
= aTmpPair
.second
;
2736 aHiddenIter
= aHidden
.find( (*aIter
).first
);
2737 const bool bHidden
= aHiddenIter
!= aHidden
.end() && (*aHiddenIter
).second
;
2738 rFill
.Insert( nKey
, nFirst
, nSecond
, bHidden
, nIdx
++ );
2741 // delete first and last entry
2742 ASSERT( rFill
.Count(), "Deleting from empty vector. Fasten your seatbelts!" )
2743 // --> FME 2006-01-19 #i60818# There may be only one entry in rFill. Make
2744 // code robust by checking count of rFill.
2745 if ( rFill
.Count() ) rFill
.Remove( 0, 1 );
2746 if ( rFill
.Count() ) rFill
.Remove( rFill
.Count() - 1 , 1 );
2748 rFill
.SetLastRowAllowedToChange( !pTab
->HasFollowFlowLine() );
2751 void SwDoc::SetTabCols( const SwTabCols
&rNew
, BOOL bCurRowOnly
,
2752 const SwCursor
* pCrsr
, const SwCellFrm
* pBoxFrm
)
2754 const SwTableBox
* pBox
= 0;
2759 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2760 pBox
= pBoxFrm
->GetTabBox();
2764 const SwCntntNode
* pCNd
= pCrsr
->GetCntntNode();
2769 const SwShellCrsr
*pShCrsr
= dynamic_cast<const SwShellCrsr
*>(pCrsr
);
2771 aPt
= pShCrsr
->GetPtPos();
2773 const SwFrm
* pTmpFrm
= pCNd
->GetFrm( &aPt
, 0, FALSE
);
2775 pTmpFrm
= pTmpFrm
->GetUpper();
2776 } while ( !pTmpFrm
->IsCellFrm() );
2778 pBoxFrm
= (SwCellFrm
*)pTmpFrm
;
2779 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2780 pBox
= pBoxFrm
->GetTabBox();
2782 else if( !pCrsr
&& !pBoxFrm
)
2784 ASSERT( !this, "einer von beiden muss angegeben werden!" );
2788 // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2789 // dann muss es jetzt auf absolute umgerechnet werden.
2790 SwTable
& rTab
= *pTab
->GetTable();
2791 const SwFmtFrmSize
& rTblFrmSz
= rTab
.GetFrmFmt()->GetFrmSize();
2793 // OD 06.08.2003 #i17174# - With fix for #i9040# the shadow size is taken
2794 // from the table width. Thus, add its left and right size to current table
2795 // printing area width in order to get the correct table size attribute.
2796 SwTwips nPrtWidth
= (pTab
->Prt().*fnRect
->fnGetWidth
)();
2798 SvxShadowItem
aShadow( rTab
.GetFrmFmt()->GetShadow() );
2799 nPrtWidth
+= aShadow
.CalcShadowSpace( SHADOW_LEFT
) +
2800 aShadow
.CalcShadowSpace( SHADOW_RIGHT
);
2802 if( nPrtWidth
!= rTblFrmSz
.GetWidth() )
2804 SwFmtFrmSize
aSz( rTblFrmSz
);
2805 aSz
.SetWidth( nPrtWidth
);
2806 rTab
.GetFrmFmt()->SetFmtAttr( aSz
);
2809 SwTabCols
aOld( rNew
.Count() );
2811 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2812 const ULONG nLeftMin
= (pTab
->Frm().*fnRect
->fnGetLeft
)() -
2813 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2814 const ULONG nRightMax
= (pTab
->Frm().*fnRect
->fnGetRight
)() -
2815 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2817 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2818 aOld
.SetLeftMin ( nLeftMin
);
2819 aOld
.SetLeft ( (pTab
->Prt().*fnRect
->fnGetLeft
)() );
2820 aOld
.SetRight ( (pTab
->Prt().*fnRect
->fnGetRight
)());
2821 aOld
.SetRightMax( nRightMax
- nLeftMin
);
2823 rTab
.GetTabCols( aOld
, pBox
);
2824 SetTabCols(rTab
, rNew
, aOld
, pBox
, bCurRowOnly
);
2827 void SwDoc::SetTabRows( const SwTabCols
&rNew
, BOOL bCurColOnly
, const SwCursor
*,
2828 const SwCellFrm
* pBoxFrm
)
2830 const SwTableBox
* pBox
;
2833 ASSERT( pBoxFrm
, "SetTabRows called without pBoxFrm" )
2835 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2836 pBox
= pBoxFrm
->GetTabBox();
2838 // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2839 // dann muss es jetzt auf absolute umgerechnet werden.
2841 SwTabCols
aOld( rNew
.Count() );
2843 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2844 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2846 aOld
.SetRight( (pTab
->Prt().*fnRect
->fnGetHeight
)() );
2850 nLeftMin
= pTab
->GetPrtLeft() - pPage
->Frm().Left();
2851 aOld
.SetLeft ( LONG_MAX
);
2852 aOld
.SetRightMax( aOld
.GetRight() );
2857 nLeftMin
= pTab
->GetPrtTop() - pPage
->Frm().Top();
2859 aOld
.SetRightMax( LONG_MAX
);
2861 aOld
.SetLeftMin ( nLeftMin
);
2863 GetTabRows( aOld
, 0, pBoxFrm
);
2865 StartUndo( UNDO_TABLE_ATTR
, NULL
);
2867 // check for differences between aOld and rNew:
2868 const USHORT nCount
= rNew
.Count();
2869 const SwTable
* pTable
= pTab
->GetTable();
2870 ASSERT( pTable
, "My colleague told me, this couldn't happen" );
2872 for ( USHORT i
= 0; i
<= nCount
; ++i
)
2874 const USHORT nIdxStt
= bVert
? nCount
- i
: i
- 1;
2875 const USHORT nIdxEnd
= bVert
? nCount
- i
- 1 : i
;
2877 const long nOldRowStart
= i
== 0 ? 0 : aOld
[ nIdxStt
];
2878 const long nOldRowEnd
= i
== nCount
? aOld
.GetRight() : aOld
[ nIdxEnd
];
2879 const long nOldRowHeight
= nOldRowEnd
- nOldRowStart
;
2881 const long nNewRowStart
= i
== 0 ? 0 : rNew
[ nIdxStt
];
2882 const long nNewRowEnd
= i
== nCount
? rNew
.GetRight() : rNew
[ nIdxEnd
];
2883 const long nNewRowHeight
= nNewRowEnd
- nNewRowStart
;
2885 const long nDiff
= nNewRowHeight
- nOldRowHeight
;
2886 if ( abs( nDiff
) >= ROWFUZZY
)
2888 // For the old table model pTxtFrm and pLine will be set for every box.
2889 // For the new table model pTxtFrm will be set if the box is not covered,
2890 // but the pLine will be set if the box is not an overlapping box
2891 // In the new table model the row height can be adjusted,
2892 // when both variables are set.
2893 SwTxtFrm
* pTxtFrm
= 0;
2894 const SwTableLine
* pLine
= 0;
2896 // Iterate over all SwCellFrms with Bottom = nOldPos
2897 const SwFrm
* pFrm
= pTab
->GetNextLayoutLeaf();
2898 while ( pFrm
&& pTab
->IsAnLower( pFrm
) )
2900 if ( pFrm
->IsCellFrm() && pFrm
->FindTabFrm() == pTab
)
2902 const long nLowerBorder
= (pFrm
->Frm().*fnRect
->fnGetBottom
)();
2903 const ULONG nTabTop
= (pTab
->*fnRect
->fnGetPrtTop
)();
2904 if ( abs( (*fnRect
->fnYInc
)( nTabTop
, nOldRowEnd
) - nLowerBorder
) <= ROWFUZZY
)
2906 if ( !bCurColOnly
|| pFrm
== pBoxFrm
)
2908 const SwFrm
* pCntnt
= ::GetCellCntnt( static_cast<const SwCellFrm
&>(*pFrm
) );
2910 if ( pCntnt
&& pCntnt
->IsTxtFrm() )
2912 pBox
= ((SwCellFrm
*)pFrm
)->GetTabBox();
2913 const long nRowSpan
= pBox
->getRowSpan();
2914 if( nRowSpan
> 0 ) // Not overlapped
2915 pTxtFrm
= (SwTxtFrm
*)pCntnt
;
2916 if( nRowSpan
< 2 ) // Not overlapping for row height
2917 pLine
= pBox
->GetUpper();
2918 if( pLine
&& pTxtFrm
) // always for old table model
2920 // The new row height must not to be calculated from a overlapping box
2921 SwFmtFrmSize
aNew( pLine
->GetFrmFmt()->GetFrmSize() );
2922 const long nNewSize
= (pFrm
->Frm().*fnRect
->fnGetHeight
)() + nDiff
;
2923 if( nNewSize
!= aNew
.GetHeight() )
2925 aNew
.SetHeight( nNewSize
);
2926 if ( ATT_VAR_SIZE
== aNew
.GetHeightSizeType() )
2927 aNew
.SetHeightSizeType( ATT_MIN_SIZE
);
2928 // This position must not be in an overlapped box
2929 const SwPosition
aPos( *((SwTxtFrm
*)pCntnt
)->GetTxtNode() );
2930 const SwCursor
aTmpCrsr( aPos
, 0, false );
2931 SetRowHeight( aTmpCrsr
, aNew
);
2932 // For the new table model we're done, for the old one
2933 // there might be another (sub)row to adjust...
2934 if( pTable
->IsNewModel() )
2943 pFrm
= pFrm
->GetNextLayoutLeaf();
2948 EndUndo( UNDO_TABLE_ATTR
, NULL
);
2950 ::ClearFEShellTabCols();
2953 /* -----------------18.07.98 11:45-------------------
2954 * Direktzugriff fuer UNO
2955 * --------------------------------------------------*/
2956 void SwDoc::SetTabCols(SwTable
& rTab
, const SwTabCols
&rNew
, const SwTabCols
&rOld
,
2957 const SwTableBox
*pStart
, BOOL bCurRowOnly
)
2962 AppendUndo( new SwUndoAttrTbl( *rTab
.GetTableNode(), TRUE
));
2964 rTab
.SetTabCols( rNew
, rOld
, pStart
, bCurRowOnly
);
2965 ::ClearFEShellTabCols();
2969 void SwDoc::SetRowsToRepeat( SwTable
&rTable
, USHORT nSet
)
2971 if( nSet
== rTable
.GetRowsToRepeat() )
2977 AppendUndo( new SwUndoTblHeadline( rTable
, rTable
.GetRowsToRepeat() , nSet
) );
2980 SwMsgPoolItem
aChg( RES_TBLHEADLINECHG
);
2981 rTable
.SetRowsToRepeat( nSet
);
2982 rTable
.GetFrmFmt()->Modify( &aChg
, &aChg
);
2989 // Splittet eine Tabelle in der Grund-Zeile, in der der Index steht.
2990 // Alle GrundZeilen dahinter wandern in eine neue Tabelle/-Node.
2991 // Ist das Flag bCalcNewSize auf TRUE, wird fuer beide neuen Tabellen
2992 // die neue Size aus dem Max der Boxen errechnet; vorrausgesetzt,
2993 // die Size ist "absolut" gesetzt (USHRT_MAX)
2995 void SwCollectTblLineBoxes::AddToUndoHistory( const SwCntntNode
& rNd
)
2998 pHst
->Add( rNd
.GetFmtColl(), rNd
.GetIndex(), ND_TEXTNODE
);
3001 void SwCollectTblLineBoxes::AddBox( const SwTableBox
& rBox
)
3003 aPosArr
.Insert( nWidth
, aPosArr
.Count() );
3004 SwTableBox
* p
= (SwTableBox
*)&rBox
;
3005 aBoxes
.Insert( p
, aBoxes
.Count() );
3006 nWidth
= nWidth
+ (USHORT
)rBox
.GetFrmFmt()->GetFrmSize().GetWidth();
3009 const SwTableBox
* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox
& rBox
)
3011 const SwTableBox
* pRet
= 0;
3014 if( aPosArr
.Count() )
3016 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3017 if( aPosArr
[ n
] == nWidth
)
3019 else if( aPosArr
[ n
] > nWidth
)
3026 if( n
>= aPosArr
.Count() )
3029 nWidth
= nWidth
+ (USHORT
)rBox
.GetFrmFmt()->GetFrmSize().GetWidth();
3035 BOOL
SwCollectTblLineBoxes::Resize( USHORT nOffset
, USHORT nOldWidth
)
3039 if( aPosArr
.Count() )
3041 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3042 if( aPosArr
[ n
] == nOffset
)
3044 else if( aPosArr
[ n
] > nOffset
)
3051 aPosArr
.Remove( 0, n
);
3052 aBoxes
.Remove( 0, n
);
3054 // dann die Positionen der neuen Size anpassen
3055 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3057 ULONG nSize
= nWidth
;
3058 nSize
*= ( aPosArr
[ n
] - nOffset
);
3060 aPosArr
[ n
] = USHORT( nSize
);
3063 return 0 != aPosArr
.Count();
3066 BOOL
lcl_Line_CollectBox( const SwTableLine
*& rpLine
, void* pPara
)
3068 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3069 if( pSplPara
->IsGetValues() )
3070 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, pPara
);
3072 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, pPara
);
3076 BOOL
lcl_Box_CollectBox( const SwTableBox
*& rpBox
, void* pPara
)
3078 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3079 USHORT nLen
= rpBox
->GetTabLines().Count();
3082 // dann mit der richtigen Line weitermachen
3083 if( pSplPara
->IsGetFromTop() )
3088 const SwTableLine
* pLn
= rpBox
->GetTabLines()[ nLen
];
3089 lcl_Line_CollectBox( pLn
, pPara
);
3092 pSplPara
->AddBox( *rpBox
);
3096 BOOL
lcl_BoxSetSplitBoxFmts( const SwTableBox
*& rpBox
, void* pPara
)
3098 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3099 USHORT nLen
= rpBox
->GetTabLines().Count();
3102 // dann mit der richtigen Line weitermachen
3103 if( pSplPara
->IsGetFromTop() )
3108 const SwTableLine
* pLn
= rpBox
->GetTabLines()[ nLen
];
3109 lcl_Line_CollectBox( pLn
, pPara
);
3113 const SwTableBox
* pSrcBox
= pSplPara
->GetBoxOfPos( *rpBox
);
3114 SwFrmFmt
* pFmt
= pSrcBox
->GetFrmFmt();
3115 SwTableBox
* pBox
= (SwTableBox
*)rpBox
;
3117 if( HEADLINE_BORDERCOPY
== pSplPara
->GetMode() )
3119 const SvxBoxItem
& rBoxItem
= pBox
->GetFrmFmt()->GetBox();
3120 if( !rBoxItem
.GetTop() )
3122 SvxBoxItem
aNew( rBoxItem
);
3123 aNew
.SetLine( pFmt
->GetBox().GetBottom(), BOX_LINE_TOP
);
3124 if( aNew
!= rBoxItem
)
3125 pBox
->ClaimFrmFmt()->SetFmtAttr( aNew
);
3130 USHORT __FAR_DATA aTableSplitBoxSetRange
[] = {
3131 RES_LR_SPACE
, RES_UL_SPACE
,
3132 RES_BACKGROUND
, RES_SHADOW
,
3133 RES_PROTECT
, RES_PROTECT
,
3134 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
3136 SfxItemSet
aTmpSet( pFmt
->GetDoc()->GetAttrPool(),
3137 aTableSplitBoxSetRange
);
3138 aTmpSet
.Put( pFmt
->GetAttrSet() );
3139 if( aTmpSet
.Count() )
3140 pBox
->ClaimFrmFmt()->SetFmtAttr( aTmpSet
);
3142 if( HEADLINE_BOXATRCOLLCOPY
== pSplPara
->GetMode() )
3144 SwNodeIndex
aIdx( *pSrcBox
->GetSttNd(), 1 );
3145 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
3147 pCNd
= aIdx
.GetNodes().GoNext( &aIdx
);
3148 aIdx
= *pBox
->GetSttNd();
3149 SwCntntNode
* pDNd
= aIdx
.GetNodes().GoNext( &aIdx
);
3151 // nur wenn der Node alleine in der Section steht
3152 if( 2 == pDNd
->EndOfSectionIndex() -
3153 pDNd
->StartOfSectionIndex() )
3155 pSplPara
->AddToUndoHistory( *pDNd
);
3156 pDNd
->ChgFmtColl( pCNd
->GetFmtColl() );
3160 // bedingte Vorlage beachten
3161 pBox
->GetSttNd()->CheckSectionCondColl();
3168 BOOL
SwDoc::SplitTable( const SwPosition
& rPos
, USHORT eHdlnMode
,
3171 SwNode
* pNd
= &rPos
.nNode
.GetNode();
3172 SwTableNode
* pTNd
= pNd
->FindTableNode();
3173 if( !pTNd
|| pNd
->IsTableNode() )
3176 if( pTNd
->GetTable().ISA( SwDDETable
))
3179 SwTable
& rTbl
= pTNd
->GetTable();
3180 rTbl
.SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
3182 SwTableFmlUpdate
aMsgHnt( &rTbl
);
3186 aMsgHnt
.pHistory
= &aHistory
;
3189 ULONG nSttIdx
= pNd
->FindTableBoxStartNode()->GetIndex();
3191 // Suche die Grund-Line dieser Box:
3192 SwTableBox
* pBox
= rTbl
.GetTblBox( nSttIdx
);
3195 SwTableLine
* pLine
= pBox
->GetUpper();
3196 while( pLine
->GetUpper() )
3197 pLine
= pLine
->GetUpper()->GetUpper();
3199 // in pLine steht jetzt die GrundLine.
3200 aMsgHnt
.nSplitLine
= rTbl
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
3203 String
sNewTblNm( GetUniqueTblName() );
3204 aMsgHnt
.DATA
.pNewTblNm
= &sNewTblNm
;
3205 aMsgHnt
.eFlags
= TBL_SPLITTBL
;
3206 UpdateTblFlds( &aMsgHnt
);
3209 //Lines fuer das Layout-Update heraussuchen.
3210 _FndBox
aFndBox( 0, 0 );
3211 aFndBox
.SetTableLines( rTbl
);
3212 aFndBox
.DelFrms( rTbl
);
3214 // TL_CHART2: need to inform chart of probably changed cell names
3215 //pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3217 SwTableNode
* pNew
= GetNodes().SplitTable( rPos
.nNode
, FALSE
, bCalcNewSize
);
3221 SwSaveRowSpan
* pSaveRowSp
= pNew
->GetTable().CleanUpTopRowSpan( rTbl
.GetTabLines().Count() );
3222 SwUndoSplitTbl
* pUndo
= 0;
3226 AppendUndo( pUndo
= new SwUndoSplitTbl( *pNew
, pSaveRowSp
, eHdlnMode
, bCalcNewSize
));
3227 if( aHistory
.Count() )
3228 pUndo
->SaveFormula( aHistory
);
3233 // setze die untere Border der vorherige Line,
3234 // an der aktuellen als obere
3235 case HEADLINE_BORDERCOPY
:
3237 SwCollectTblLineBoxes
aPara( FALSE
, eHdlnMode
);
3238 SwTableLine
* pLn
= rTbl
.GetTabLines()[
3239 rTbl
.GetTabLines().Count() - 1 ];
3240 pLn
->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, &aPara
);
3242 aPara
.SetValues( TRUE
);
3243 pLn
= pNew
->GetTable().GetTabLines()[ 0 ];
3244 pLn
->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, &aPara
);
3246 // Kopfzeile wiederholen abschalten
3247 pNew
->GetTable().SetRowsToRepeat( 0 );
3251 // setze die Attributierung der ersten Line an der neuen ersten
3252 case HEADLINE_BOXATTRCOPY
:
3253 case HEADLINE_BOXATRCOLLCOPY
:
3255 SwHistory
* pHst
= 0;
3256 if( HEADLINE_BOXATRCOLLCOPY
== eHdlnMode
&& pUndo
)
3257 pHst
= pUndo
->GetHistory();
3259 SwCollectTblLineBoxes
aPara( TRUE
, eHdlnMode
, pHst
);
3260 SwTableLine
* pLn
= rTbl
.GetTabLines()[ 0 ];
3261 pLn
->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, &aPara
);
3263 aPara
.SetValues( TRUE
);
3264 pLn
= pNew
->GetTable().GetTabLines()[ 0 ];
3265 pLn
->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, &aPara
);
3269 case HEADLINE_CNTNTCOPY
:
3270 rTbl
.CopyHeadlineIntoTable( *pNew
);
3272 pUndo
->SetTblNodeOffset( pNew
->GetIndex() );
3276 // Kopfzeile wiederholen abschalten
3277 pNew
->GetTable().SetRowsToRepeat( 0 );
3281 // und Frms einfuegen.
3282 SwNodeIndex
aNdIdx( *pNew
->EndOfSectionNode() );
3283 GetNodes().GoNext( &aNdIdx
); // zum naechsten ContentNode
3284 pNew
->MakeFrms( &aNdIdx
);
3286 //Zwischen die Tabellen wird ein Absatz geschoben
3287 GetNodes().MakeTxtNode( SwNodeIndex( *pNew
),
3288 GetTxtCollFromPool( RES_POOLCOLL_TEXT
) );
3292 aFndBox
.MakeFrms( rTbl
);
3294 // TL_CHART2: need to inform chart of probably changed cell names
3295 UpdateCharts( rTbl
.GetFrmFmt()->GetName() );
3297 SetFieldsDirty( true, NULL
, 0 );
3302 BOOL
lcl_ChgTblSize( SwTable
& rTbl
)
3304 // das Attribut darf nicht ueber das Modify an der
3305 // Tabelle gesetzt werden, denn sonst werden alle
3306 // Boxen wieder auf 0 zurueck gesetzt. Also locke das Format
3307 SwFrmFmt
* pFmt
= rTbl
.GetFrmFmt();
3308 SwFmtFrmSize
aTblMaxSz( pFmt
->GetFrmSize() );
3310 if( USHRT_MAX
== aTblMaxSz
.GetWidth() )
3313 BOOL bLocked
= pFmt
->IsModifyLocked();
3316 aTblMaxSz
.SetWidth( 0 );
3318 SwTableLines
& rLns
= rTbl
.GetTabLines();
3319 for( USHORT nLns
= 0; nLns
< rLns
.Count(); ++nLns
)
3321 SwTwips nMaxLnWidth
= 0;
3322 SwTableBoxes
& rBoxes
= rLns
[ nLns
]->GetTabBoxes();
3323 for( USHORT nBox
= 0; nBox
< rBoxes
.Count(); ++nBox
)
3324 nMaxLnWidth
+= rBoxes
[nBox
]->GetFrmFmt()->GetFrmSize().GetWidth();
3326 if( nMaxLnWidth
> aTblMaxSz
.GetWidth() )
3327 aTblMaxSz
.SetWidth( nMaxLnWidth
);
3329 pFmt
->SetFmtAttr( aTblMaxSz
);
3330 if( !bLocked
) // und gegebenenfalls Lock wieder freigeben
3331 pFmt
->UnlockModify();
3336 class _SplitTable_Para
3338 SvPtrarr aSrc
, aDest
;
3339 SwTableNode
* pNewTblNd
;
3343 _SplitTable_Para( SwTableNode
* pNew
, SwTable
& rOld
)
3344 : aSrc( 16, 16 ), aDest( 16, 16 ), pNewTblNd( pNew
), rOldTbl( rOld
)
3346 USHORT
SrcFmt_GetPos( void* pFmt
) const
3347 { return aSrc
.GetPos( pFmt
); }
3349 void DestFmt_Insert( void* pFmt
)
3350 { aDest
.Insert( pFmt
, aDest
.Count() ); }
3352 void SrcFmt_Insert( void* pFmt
)
3353 { aSrc
.Insert( pFmt
, aSrc
.Count() ); }
3355 SwFrmFmt
* DestFmt_Get( USHORT nPos
) const
3356 { return (SwFrmFmt
*)aDest
[ nPos
]; }
3358 void ChgBox( SwTableBox
* pBox
)
3360 rOldTbl
.GetTabSortBoxes().Remove( pBox
);
3361 pNewTblNd
->GetTable().GetTabSortBoxes().Insert( pBox
);
3366 BOOL
lcl_SplitTable_CpyBox( const SwTableBox
*& rpBox
, void* pPara
);
3368 BOOL
lcl_SplitTable_CpyLine( const SwTableLine
*& rpLine
, void* pPara
)
3370 SwTableLine
* pLn
= (SwTableLine
*)rpLine
;
3371 _SplitTable_Para
& rPara
= *(_SplitTable_Para
*)pPara
;
3373 SwFrmFmt
*pSrcFmt
= pLn
->GetFrmFmt();
3374 USHORT nPos
= rPara
.SrcFmt_GetPos( pSrcFmt
);
3375 if( USHRT_MAX
== nPos
)
3377 rPara
.DestFmt_Insert( pLn
->ClaimFrmFmt() );
3378 rPara
.SrcFmt_Insert( pSrcFmt
);
3381 pLn
->ChgFrmFmt( (SwTableLineFmt
*)rPara
.DestFmt_Get( nPos
) );
3383 pLn
->GetTabBoxes().ForEach( &lcl_SplitTable_CpyBox
, pPara
);
3387 BOOL
lcl_SplitTable_CpyBox( const SwTableBox
*& rpBox
, void* pPara
)
3389 SwTableBox
* pBox
= (SwTableBox
*)rpBox
;
3390 _SplitTable_Para
& rPara
= *(_SplitTable_Para
*)pPara
;
3392 SwFrmFmt
*pSrcFmt
= pBox
->GetFrmFmt();
3393 USHORT nPos
= rPara
.SrcFmt_GetPos( pSrcFmt
);
3394 if( USHRT_MAX
== nPos
)
3396 rPara
.DestFmt_Insert( pBox
->ClaimFrmFmt() );
3397 rPara
.SrcFmt_Insert( pSrcFmt
);
3400 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)rPara
.DestFmt_Get( nPos
) );
3402 if( pBox
->GetSttNd() )
3403 rPara
.ChgBox( pBox
);
3405 pBox
->GetTabLines().ForEach( &lcl_SplitTable_CpyLine
, pPara
);
3409 SwTableNode
* SwNodes::SplitTable( const SwNodeIndex
& rPos
, BOOL bAfter
,
3412 SwNode
* pNd
= &rPos
.GetNode();
3413 SwTableNode
* pTNd
= pNd
->FindTableNode();
3414 if( !pTNd
|| pNd
->IsTableNode() )
3417 ULONG nSttIdx
= pNd
->FindTableBoxStartNode()->GetIndex();
3419 // Suche die Grund-Line dieser Box:
3420 SwTable
& rTbl
= pTNd
->GetTable();
3421 SwTableBox
* pBox
= rTbl
.GetTblBox( nSttIdx
);
3425 SwTableLine
* pLine
= pBox
->GetUpper();
3426 while( pLine
->GetUpper() )
3427 pLine
= pLine
->GetUpper()->GetUpper();
3429 // in pLine steht jetzt die GrundLine.
3430 USHORT nLinePos
= rTbl
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
3431 if( USHRT_MAX
== nLinePos
||
3432 ( bAfter
? ++nLinePos
>= rTbl
.GetTabLines().Count() : !nLinePos
))
3433 return 0; // nicht gefunden oder letze Line !!
3435 // Suche jetzt die 1. Box der nachfolgenden Line
3436 SwTableLine
* pNextLine
= rTbl
.GetTabLines()[ nLinePos
];
3437 pBox
= pNextLine
->GetTabBoxes()[0];
3438 while( !pBox
->GetSttNd() )
3439 pBox
= pBox
->GetTabLines()[0]->GetTabBoxes()[0];
3441 // dann fuege mal einen End- und TabelleNode ins Nodes-Array ein.
3442 SwTableNode
* pNewTblNd
;
3444 SwEndNode
* pOldTblEndNd
= (SwEndNode
*)pTNd
->EndOfSectionNode()->GetEndNode();
3445 ASSERT( pOldTblEndNd
, "wo ist der EndNode?" )
3447 SwNodeIndex
aIdx( *pBox
->GetSttNd() );
3448 new SwEndNode( aIdx
, *pTNd
);
3449 pNewTblNd
= new SwTableNode( aIdx
);
3450 pNewTblNd
->GetTable().SetTableModel( rTbl
.IsNewModel() );
3452 pOldTblEndNd
->pStartOfSection
= pNewTblNd
;
3453 pNewTblNd
->pEndOfSection
= pOldTblEndNd
;
3455 SwNode
* pBoxNd
= aIdx
.GetNode().GetStartNode();
3457 ASSERT( pBoxNd
->IsStartNode(), "das muss ein StartNode sein!" );
3458 pBoxNd
->pStartOfSection
= pNewTblNd
;
3459 pBoxNd
= (*this)[ pBoxNd
->EndOfSectionIndex() + 1 ];
3460 } while( pBoxNd
!= pOldTblEndNd
);
3464 // die Lines ruebermoven...
3465 SwTable
& rNewTbl
= pNewTblNd
->GetTable();
3466 rNewTbl
.GetTabLines().Insert( &rTbl
.GetTabLines(), 0, nLinePos
);
3468 // von hinten (unten-rechts) nach vorn (oben-links) alle Boxen
3469 // beim chart data provider austragen (das modified event wird dann
3470 // in der aufrufenden Funktion getriggert.
3472 SwChartDataProvider
*pPCD
= rTbl
.GetFrmFmt()->getIDocumentChartDataProviderAccess()->GetChartDataProvider();
3475 for (USHORT k
= nLinePos
; k
< rTbl
.GetTabLines().Count(); ++k
)
3477 USHORT nLineIdx
= (rTbl
.GetTabLines().Count() - 1) - k
+ nLinePos
;
3478 USHORT nBoxCnt
= rTbl
.GetTabLines()[ nLineIdx
]->GetTabBoxes().Count();
3479 for (USHORT j
= 0; j
< nBoxCnt
; ++j
)
3481 USHORT nIdx
= nBoxCnt
- 1 - j
;
3482 pPCD
->DeleteBox( &rTbl
, *rTbl
.GetTabLines()[ nLineIdx
]->GetTabBoxes()[nIdx
] );
3488 USHORT nDeleted
= rTbl
.GetTabLines().Count() - nLinePos
;
3489 rTbl
.GetTabLines().Remove( nLinePos
, nDeleted
);
3491 // und die betr. Boxen verschieben. Dabei die Formate eindeutig
3492 // machen und die StartNodes korrigieren
3493 _SplitTable_Para
aPara( pNewTblNd
, rTbl
);
3494 rNewTbl
.GetTabLines().ForEach( &lcl_SplitTable_CpyLine
, &aPara
);
3495 rTbl
.CleanUpBottomRowSpan( nDeleted
);
3499 // Das Tabellen-FrmFormat kopieren
3500 SwFrmFmt
* pOldTblFmt
= rTbl
.GetFrmFmt();
3501 SwFrmFmt
* pNewTblFmt
= pOldTblFmt
->GetDoc()->MakeTblFrmFmt(
3502 pOldTblFmt
->GetDoc()->GetUniqueTblName(),
3503 pOldTblFmt
->GetDoc()->GetDfltFrmFmt() );
3505 *pNewTblFmt
= *pOldTblFmt
;
3506 pNewTblFmt
->Add( &pNewTblNd
->GetTable() );
3508 // neue Size errechnen ? (lcl_ChgTblSize nur das 2. aufrufen, wenn es
3509 // beim 1. schon geklappt hat; also absolute Groesse hat)
3510 if( bCalcNewSize
&& lcl_ChgTblSize( rTbl
) )
3511 lcl_ChgTblSize( pNewTblNd
->GetTable() );
3514 // TL_CHART2: need to inform chart of probably changed cell names
3515 rTbl
.UpdateCharts();
3517 return pNewTblNd
; // das wars
3520 // und die Umkehrung davon. rPos muss in der Tabelle stehen, die bestehen
3521 // bleibt. Das Flag besagt ob die aktuelle mit der davor oder dahinter
3522 // stehenden vereint wird.
3523 BOOL
SwDoc::MergeTable( const SwPosition
& rPos
, BOOL bWithPrev
, USHORT nMode
)
3525 SwTableNode
* pTblNd
= rPos
.nNode
.GetNode().FindTableNode(), *pDelTblNd
;
3529 SwNodes
& rNds
= GetNodes();
3531 pDelTblNd
= rNds
[ pTblNd
->GetIndex() - 1 ]->FindTableNode();
3533 pDelTblNd
= rNds
[ pTblNd
->EndOfSectionIndex() + 1 ]->GetTableNode();
3537 if( pTblNd
->GetTable().ISA( SwDDETable
) ||
3538 pDelTblNd
->GetTable().ISA( SwDDETable
))
3541 // MIB 9.7.97: HTML-Layout loeschen
3542 pTblNd
->GetTable().SetHTMLTableLayout( 0 );
3543 pDelTblNd
->GetTable().SetHTMLTableLayout( 0 );
3545 // beide Tabellen vorhanden, also kanns losgehen
3546 SwUndoMergeTbl
* pUndo
= 0;
3547 SwHistory
* pHistory
= 0;
3551 AppendUndo( pUndo
= new SwUndoMergeTbl( *pTblNd
, *pDelTblNd
,
3552 bWithPrev
, nMode
));
3553 pHistory
= new SwHistory
;
3556 // alle "Tabellenformeln" anpassen
3557 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
3558 aMsgHnt
.DATA
.pDelTbl
= &pDelTblNd
->GetTable();
3559 aMsgHnt
.eFlags
= TBL_MERGETBL
;
3560 aMsgHnt
.pHistory
= pHistory
;
3561 UpdateTblFlds( &aMsgHnt
);
3563 // das eigentliche Mergen
3564 SwNodeIndex
aIdx( bWithPrev
? *pTblNd
: *pDelTblNd
);
3565 BOOL bRet
= rNds
.MergeTable( aIdx
, !bWithPrev
, nMode
, pHistory
);
3569 if( pHistory
->Count() )
3570 pUndo
->SaveFormula( *pHistory
);
3576 SetFieldsDirty( true, NULL
, 0 );
3581 BOOL
SwNodes::MergeTable( const SwNodeIndex
& rPos
, BOOL bWithPrev
,
3582 USHORT nMode
, SwHistory
* )
3584 SwTableNode
* pDelTblNd
= rPos
.GetNode().GetTableNode();
3585 ASSERT( pDelTblNd
, "wo ist der TableNode geblieben?" );
3587 SwTableNode
* pTblNd
= (*this)[ rPos
.GetIndex() - 1]->FindTableNode();
3588 ASSERT( pTblNd
, "wo ist der TableNode geblieben?" );
3590 if( !pDelTblNd
|| !pTblNd
)
3593 pDelTblNd
->DelFrms();
3595 SwTable
& rDelTbl
= pDelTblNd
->GetTable();
3596 SwTable
& rTbl
= pTblNd
->GetTable();
3598 //Lines fuer das Layout-Update herausuchen.
3599 _FndBox
aFndBox( 0, 0 );
3600 aFndBox
.SetTableLines( rTbl
);
3601 aFndBox
.DelFrms( rTbl
);
3603 // TL_CHART2: since chart currently does not want to get informed about
3604 // additional rows/cols there is no need for a modified event in the
3605 // remaining first table. Also, if it is required it should be done
3606 // after the merging and not here...
3607 // pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3611 // tell the charts about the table to be deleted and have them use their own data
3612 GetDoc()->CreateChartInternalDataProviders( &rDelTbl
);
3614 // die Breite der TabellenFormate abgleichen:
3616 const SwFmtFrmSize
& rTblSz
= rTbl
.GetFrmFmt()->GetFrmSize();
3617 const SwFmtFrmSize
& rDelTblSz
= rDelTbl
.GetFrmFmt()->GetFrmSize();
3618 if( rTblSz
!= rDelTblSz
)
3620 // dann sollten die mal schleunigst korrigiert werden
3622 rDelTbl
.GetFrmFmt()->SetFmtAttr( rTblSz
);
3624 rTbl
.GetFrmFmt()->SetFmtAttr( rDelTblSz
);
3630 // dann mussen alle Attruibute der hinteren Tabelle auf die
3631 // vordere uebertragen werden, weil die hintere ueber das loeschen
3632 // des Node geloescht wird.
3633 rTbl
.SetRowsToRepeat( rDelTbl
.GetRowsToRepeat() );
3634 rTbl
.SetTblChgMode( rDelTbl
.GetTblChgMode() );
3636 rTbl
.GetFrmFmt()->LockModify();
3637 *rTbl
.GetFrmFmt() = *rDelTbl
.GetFrmFmt();
3638 // auch den Namen umsetzen!
3639 rTbl
.GetFrmFmt()->SetName( rDelTbl
.GetFrmFmt()->GetName() );
3640 rTbl
.GetFrmFmt()->UnlockModify();
3643 // die Lines und Boxen ruebermoven
3644 USHORT nOldSize
= rTbl
.GetTabLines().Count();
3645 rTbl
.GetTabLines().Insert( &rDelTbl
.GetTabLines(), nOldSize
);
3646 rDelTbl
.GetTabLines().Remove( 0, rDelTbl
.GetTabLines().Count() );
3648 rTbl
.GetTabSortBoxes().Insert( &rDelTbl
.GetTabSortBoxes() );
3649 rDelTbl
.GetTabSortBoxes().Remove( (USHORT
)0, rDelTbl
.GetTabSortBoxes().Count() );
3651 // die vordere Tabelle bleibt immer stehen, die hintere wird geloescht
3652 SwEndNode
* pTblEndNd
= pDelTblNd
->EndOfSectionNode();
3653 pTblNd
->pEndOfSection
= pTblEndNd
;
3655 SwNodeIndex
aIdx( *pDelTblNd
, 1 );
3657 SwNode
* pBoxNd
= aIdx
.GetNode().GetStartNode();
3659 ASSERT( pBoxNd
->IsStartNode(), "das muss ein StartNode sein!" );
3660 pBoxNd
->pStartOfSection
= pTblNd
;
3661 pBoxNd
= (*this)[ pBoxNd
->EndOfSectionIndex() + 1 ];
3662 } while( pBoxNd
!= pTblEndNd
);
3663 pBoxNd
->pStartOfSection
= pTblNd
;
3666 DelNodes( aIdx
, 2 );
3668 // jetzt an der 1. eingefuegten Line die bedingten Vorlagen umschubsen
3669 const SwTableLine
* pFirstLn
= rTbl
.GetTabLines()[ nOldSize
];
3672 // Header-Vorlagen in der Zeile setzen
3673 // und ggfs. in der History speichern fuers Undo!!!
3675 lcl_LineSetHeadCondColl( pFirstLn
, 0 );
3677 // und die Borders "aufrauemen"
3680 _SwGCLineBorder
aPara( rTbl
);
3681 aPara
.nLinePos
= --nOldSize
;
3682 pFirstLn
= rTbl
.GetTabLines()[ nOldSize
];
3683 lcl_GC_Line_Border( pFirstLn
, &aPara
);
3687 aFndBox
.MakeFrms( rTbl
);
3692 // -------------------------------------------------------------------
3695 // -- benutze die ForEach Methode vom PtrArray
3696 struct _SetAFmtTabPara
3698 SwTableAutoFmt
& rTblFmt
;
3699 SwUndoTblAutoFmt
* pUndo
;
3700 USHORT nEndBox
, nCurBox
;
3701 BYTE nAFmtLine
, nAFmtBox
;
3703 _SetAFmtTabPara( const SwTableAutoFmt
& rNew
)
3704 : rTblFmt( (SwTableAutoFmt
&)rNew
), pUndo( 0 ),
3705 nEndBox( 0 ), nCurBox( 0 ), nAFmtLine( 0 ), nAFmtBox( 0 )
3709 // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
3711 BOOL
lcl_SetAFmtBox( const _FndBox
*&, void *pPara
);
3712 BOOL
lcl_SetAFmtLine( const _FndLine
*&, void *pPara
);
3714 BOOL
lcl_SetAFmtLine( const _FndLine
*& rpLine
, void *pPara
)
3716 ((_FndLine
*&)rpLine
)->GetBoxes().ForEach( &lcl_SetAFmtBox
, pPara
);
3720 BOOL
lcl_SetAFmtBox( const _FndBox
*& rpBox
, void *pPara
)
3722 _SetAFmtTabPara
* pSetPara
= (_SetAFmtTabPara
*)pPara
;
3724 if( !rpBox
->GetUpper()->GetUpper() ) // Box auf 1. Ebene ?
3726 if( !pSetPara
->nCurBox
)
3727 pSetPara
->nAFmtBox
= 0;
3728 else if( pSetPara
->nCurBox
== pSetPara
->nEndBox
)
3729 pSetPara
->nAFmtBox
= 3;
3731 pSetPara
->nAFmtBox
= (BYTE
)(1 + ((pSetPara
->nCurBox
-1) & 1));
3734 if( rpBox
->GetBox()->GetSttNd() )
3736 SwTableBox
* pSetBox
= (SwTableBox
*)rpBox
->GetBox();
3737 SwDoc
* pDoc
= pSetBox
->GetFrmFmt()->GetDoc();
3738 // --> OD 2008-02-25 #refactorlists#
3739 // SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
3740 SfxItemSet
aCharSet( pDoc
->GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_LIST_END
-1 );
3742 SfxItemSet
aBoxSet( pDoc
->GetAttrPool(), aTableBoxSetRange
);
3743 BYTE nPos
= pSetPara
->nAFmtLine
* 4 + pSetPara
->nAFmtBox
;
3744 pSetPara
->rTblFmt
.UpdateToSet( nPos
, aCharSet
,
3745 SwTableAutoFmt::UPDATE_CHAR
, 0 );
3746 pSetPara
->rTblFmt
.UpdateToSet( nPos
, aBoxSet
,
3747 SwTableAutoFmt::UPDATE_BOX
,
3748 pDoc
->GetNumberFormatter( TRUE
) );
3749 if( aCharSet
.Count() )
3751 ULONG nSttNd
= pSetBox
->GetSttIdx()+1;
3752 ULONG nEndNd
= pSetBox
->GetSttNd()->EndOfSectionIndex();
3753 for( ; nSttNd
< nEndNd
; ++nSttNd
)
3755 SwCntntNode
* pNd
= pDoc
->GetNodes()[ nSttNd
]->GetCntntNode();
3757 pNd
->SetAttr( aCharSet
);
3761 if( aBoxSet
.Count() )
3763 if( pSetPara
->pUndo
&&
3764 SFX_ITEM_SET
== aBoxSet
.GetItemState( RES_BOXATR_FORMAT
))
3765 pSetPara
->pUndo
->SaveBoxCntnt( *pSetBox
);
3767 pSetBox
->ClaimFrmFmt()->SetFmtAttr( aBoxSet
);
3771 ((_FndBox
*&)rpBox
)->GetLines().ForEach( &lcl_SetAFmtLine
, pPara
);
3773 if( !rpBox
->GetUpper()->GetUpper() ) // eine BaseLine
3774 ++pSetPara
->nCurBox
;
3779 // AutoFormat fuer die Tabelle/TabellenSelection
3780 BOOL
SwDoc::SetTableAutoFmt( const SwSelBoxes
& rBoxes
, const SwTableAutoFmt
& rNew
)
3782 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
3783 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
3787 // suche alle Boxen / Lines
3788 _FndBox
aFndBox( 0, 0 );
3790 _FndPara
aPara( rBoxes
, &aFndBox
);
3791 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
3793 if( !aFndBox
.GetLines().Count() )
3796 pTblNd
->GetTable().SetHTMLTableLayout( 0 );
3798 _FndBox
* pFndBox
= &aFndBox
;
3799 while( 1 == pFndBox
->GetLines().Count() &&
3800 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
3801 pFndBox
= pFndBox
->GetLines()[0]->GetBoxes()[0];
3803 if( !pFndBox
->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
3804 pFndBox
= pFndBox
->GetUpper()->GetUpper();
3807 // Undo abschalten, Attribute werden sich vorher gemerkt
3808 SwUndoTblAutoFmt
* pUndo
= 0;
3812 AppendUndo( pUndo
= new SwUndoTblAutoFmt( *pTblNd
, rNew
) );
3816 _SetAFmtTabPara
aPara( rNew
);
3817 _FndLines
& rFLns
= pFndBox
->GetLines();
3820 for( USHORT n
= 0; n
< rFLns
.Count(); ++n
)
3824 // Upper auf 0 setzen (Base-Line simulieren!)
3825 _FndBox
* pSaveBox
= pLine
->GetUpper();
3826 pLine
->SetUpper( 0 );
3829 aPara
.nAFmtLine
= 0;
3830 else if( n
+1 == rFLns
.Count() )
3831 aPara
.nAFmtLine
= 3;
3833 aPara
.nAFmtLine
= (BYTE
)(1 + ((n
-1) & 1 ));
3837 aPara
.nEndBox
= pLine
->GetBoxes().Count()-1;
3838 aPara
.pUndo
= pUndo
;
3839 pLine
->GetBoxes().ForEach( &lcl_SetAFmtBox
, &aPara
);
3841 pLine
->SetUpper( pSaveBox
);
3848 SetFieldsDirty( true, NULL
, 0 );
3854 // Erfrage wie attributiert ist
3855 BOOL
SwDoc::GetTableAutoFmt( const SwSelBoxes
& rBoxes
, SwTableAutoFmt
& rGet
)
3857 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
3858 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
3862 // suche alle Boxen / Lines
3863 _FndBox
aFndBox( 0, 0 );
3865 _FndPara
aPara( rBoxes
, &aFndBox
);
3866 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
3868 if( !aFndBox
.GetLines().Count() )
3871 _FndBox
* pFndBox
= &aFndBox
;
3872 while( 1 == pFndBox
->GetLines().Count() &&
3873 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
3874 pFndBox
= pFndBox
->GetLines()[0]->GetBoxes()[0];
3876 if( !pFndBox
->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
3877 pFndBox
= pFndBox
->GetUpper()->GetUpper();
3879 _FndLines
& rFLns
= pFndBox
->GetLines();
3883 aLnArr
[1] = 1 < rFLns
.Count() ? 1 : 0;
3884 aLnArr
[2] = 2 < rFLns
.Count() ? 2 : aLnArr
[1];
3885 aLnArr
[3] = rFLns
.Count() - 1;
3887 for( BYTE nLine
= 0; nLine
< 4; ++nLine
)
3889 _FndLine
& rLine
= *rFLns
[ aLnArr
[ nLine
] ];
3893 aBoxArr
[1] = 1 < rLine
.GetBoxes().Count() ? 1 : 0;
3894 aBoxArr
[2] = 2 < rLine
.GetBoxes().Count() ? 2 : aBoxArr
[1];
3895 aBoxArr
[3] = rLine
.GetBoxes().Count() - 1;
3897 for( BYTE nBox
= 0; nBox
< 4; ++nBox
)
3899 SwTableBox
* pFBox
= rLine
.GetBoxes()[ aBoxArr
[ nBox
] ]->GetBox();
3900 // immer auf die 1. runterfallen
3901 while( !pFBox
->GetSttNd() )
3902 pFBox
= pFBox
->GetTabLines()[0]->GetTabBoxes()[0];
3904 BYTE nPos
= nLine
* 4 + nBox
;
3905 SwNodeIndex
aIdx( *pFBox
->GetSttNd(), 1 );
3906 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
3908 pCNd
= GetNodes().GoNext( &aIdx
);
3911 rGet
.UpdateFromSet( nPos
, pCNd
->GetSwAttrSet(),
3912 SwTableAutoFmt::UPDATE_CHAR
, 0 );
3913 rGet
.UpdateFromSet( nPos
, pFBox
->GetFrmFmt()->GetAttrSet(),
3914 SwTableAutoFmt::UPDATE_BOX
,
3915 GetNumberFormatter( TRUE
) );
3922 String
SwDoc::GetUniqueTblName() const
3924 ResId
aId( STR_TABLE_DEFNAME
, *pSwResMgr
);
3925 String
aName( aId
);
3926 xub_StrLen nNmLen
= aName
.Len();
3928 USHORT nNum
, nTmp
, nFlagSize
= ( pTblFrmFmtTbl
->Count() / 8 ) +2;
3931 BYTE
* pSetFlags
= new BYTE
[ nFlagSize
];
3932 memset( pSetFlags
, 0, nFlagSize
);
3934 for( n
= 0; n
< pTblFrmFmtTbl
->Count(); ++n
)
3936 const SwFrmFmt
* pFmt
= (*pTblFrmFmtTbl
)[ n
];
3937 if( !pFmt
->IsDefault() && IsUsed( *pFmt
) &&
3938 pFmt
->GetName().Match( aName
) == nNmLen
)
3940 // Nummer bestimmen und das Flag setzen
3941 nNum
= static_cast<USHORT
>(pFmt
->GetName().Copy( nNmLen
).ToInt32());
3942 if( nNum
-- && nNum
< pTblFrmFmtTbl
->Count() )
3943 pSetFlags
[ nNum
/ 8 ] |= (0x01 << ( nNum
& 0x07 ));
3947 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
3948 nNum
= pTblFrmFmtTbl
->Count();
3949 for( n
= 0; n
< nFlagSize
; ++n
)
3950 if( 0xff != ( nTmp
= pSetFlags
[ n
] ))
3952 // also die Nummer bestimmen
3959 delete [] pSetFlags
;
3960 return aName
+= String::CreateFromInt32( ++nNum
);
3963 SwTableFmt
* SwDoc::FindTblFmtByName( const String
& rName
, BOOL bAll
) const
3965 const SwFmt
* pRet
= 0;
3967 pRet
= FindFmtByName( (SvPtrarr
&)*pTblFrmFmtTbl
, rName
);
3970 // dann nur die, die im Doc gesetzt sind
3971 for( USHORT n
= 0; n
< pTblFrmFmtTbl
->Count(); ++n
)
3973 const SwFrmFmt
* pFmt
= (*pTblFrmFmtTbl
)[ n
];
3974 if( !pFmt
->IsDefault() && IsUsed( *pFmt
) &&
3975 pFmt
->GetName() == rName
)
3982 return (SwTableFmt
*)pRet
;
3985 BOOL
SwDoc::SetColRowWidthHeight( SwTableBox
& rAktBox
, USHORT eType
,
3986 SwTwips nAbsDiff
, SwTwips nRelDiff
)
3988 SwTableNode
* pTblNd
= (SwTableNode
*)rAktBox
.GetSttNd()->FindTableNode();
3991 if( nsTblChgWidthHeightType::WH_FLAG_INSDEL
& eType
&& pTblNd
->GetTable().ISA( SwDDETable
))
3994 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
3995 aMsgHnt
.eFlags
= TBL_BOXPTR
;
3996 UpdateTblFlds( &aMsgHnt
);
3999 switch( eType
& 0xff )
4001 case nsTblChgWidthHeightType::WH_COL_LEFT
:
4002 case nsTblChgWidthHeightType::WH_COL_RIGHT
:
4003 case nsTblChgWidthHeightType::WH_CELL_LEFT
:
4004 case nsTblChgWidthHeightType::WH_CELL_RIGHT
:
4006 bRet
= pTblNd
->GetTable().SetColWidth( rAktBox
,
4007 eType
, nAbsDiff
, nRelDiff
,
4008 DoesUndo() ? &pUndo
: 0 );
4011 case nsTblChgWidthHeightType::WH_ROW_TOP
:
4012 case nsTblChgWidthHeightType::WH_ROW_BOTTOM
:
4013 case nsTblChgWidthHeightType::WH_CELL_TOP
:
4014 case nsTblChgWidthHeightType::WH_CELL_BOTTOM
:
4015 bRet
= pTblNd
->GetTable().SetRowHeight( rAktBox
,
4016 eType
, nAbsDiff
, nRelDiff
,
4017 DoesUndo() ? &pUndo
: 0 );
4024 AppendUndo( pUndo
);
4025 DoUndo( TRUE
); // im SetColWidth kann es abgeschaltet werden!
4031 if( nsTblChgWidthHeightType::WH_FLAG_INSDEL
& eType
)
4032 SetFieldsDirty( true, NULL
, 0 );
4038 void SwDoc::ChkBoxNumFmt( SwTableBox
& rBox
, BOOL bCallUpdate
)
4040 //JP 09.07.97: Optimierung: wenn die Box schon sagt, das es Text
4041 // sein soll, dann bleibt das auch Text!
4042 const SfxPoolItem
* pNumFmtItem
= 0;
4043 if( SFX_ITEM_SET
== rBox
.GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT
,
4044 FALSE
, &pNumFmtItem
) && GetNumberFormatter()->IsTextFormat(
4045 ((SwTblBoxNumFormat
*)pNumFmtItem
)->GetValue() ))
4048 SwUndoTblNumFmt
* pUndo
= 0;
4050 BOOL bIsEmptyTxtNd
, bChgd
= TRUE
;
4053 if( rBox
.HasNumCntnt( fNumber
, nFmtIdx
, bIsEmptyTxtNd
) )
4055 if( !rBox
.IsNumberChanged() )
4061 StartUndo( UNDO_TABLE_AUTOFMT
, NULL
);
4062 pUndo
= new SwUndoTblNumFmt( rBox
);
4063 pUndo
->SetNumFmt( nFmtIdx
, fNumber
);
4066 SwTableBoxFmt
* pBoxFmt
= (SwTableBoxFmt
*)rBox
.GetFrmFmt();
4067 SfxItemSet
aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
4069 BOOL bSetNumFmt
= IsInsTblFormatNum(), bLockModify
= TRUE
;
4072 if( !IsInsTblChangeNumFormat() )
4078 ULONG nOldNumFmt
= ((SwTblBoxNumFormat
*)pNumFmtItem
)->
4080 SvNumberFormatter
* pNumFmtr
= GetNumberFormatter();
4082 short nFmtType
= pNumFmtr
->GetType( nFmtIdx
);
4083 if( nFmtType
== pNumFmtr
->GetType( nOldNumFmt
) ||
4084 NUMBERFORMAT_NUMBER
== nFmtType
)
4085 // eingstelltes und vorgegebenes NumFormat
4086 // stimmen ueberein -> altes Format beibehalten
4087 nFmtIdx
= nOldNumFmt
;
4089 // eingstelltes und vorgegebenes NumFormat
4090 // stimmen nicht ueberein -> als Text einfuegen
4091 bLockModify
= bSetNumFmt
= FALSE
;
4097 pBoxFmt
= (SwTableBoxFmt
*)rBox
.ClaimFrmFmt();
4099 aBoxSet
.Put( SwTblBoxValue( fNumber
));
4100 aBoxSet
.Put( SwTblBoxNumFormat( nFmtIdx
));
4104 // JP 28.04.98: Nur Formel zuruecksetzen reicht nicht.
4105 // Sorge dafuer, das der Text auch entsprechend
4108 if( !bSetNumFmt
&& !bIsEmptyTxtNd
&& pNumFmtItem
)
4110 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4111 // Sorge dafuer, das der Text auch entsprechend
4113 pBoxFmt
->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT
));
4116 if( bLockModify
) pBoxFmt
->LockModify();
4117 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
4118 if( bLockModify
) pBoxFmt
->UnlockModify();
4121 pBoxFmt
->SetFmtAttr( aBoxSet
);
4126 // es ist keine Zahl
4127 const SfxPoolItem
* pValueItem
= 0, *pFmtItem
= 0;
4128 SwTableBoxFmt
* pBoxFmt
= (SwTableBoxFmt
*)rBox
.GetFrmFmt();
4129 if( SFX_ITEM_SET
== pBoxFmt
->GetItemState( RES_BOXATR_FORMAT
,
4130 FALSE
, &pFmtItem
) ||
4131 SFX_ITEM_SET
== pBoxFmt
->GetItemState( RES_BOXATR_VALUE
,
4132 FALSE
, &pValueItem
))
4136 StartUndo( UNDO_TABLE_AUTOFMT
, NULL
);
4137 pUndo
= new SwUndoTblNumFmt( rBox
);
4140 pBoxFmt
= (SwTableBoxFmt
*)rBox
.ClaimFrmFmt();
4142 // alle Zahlenformate entfernen
4143 USHORT nWhich1
= RES_BOXATR_FORMULA
;
4144 if( !bIsEmptyTxtNd
)
4145 //JP 15.01.99: dieser Teil wurde doch schon oben abgeprueft!
4146 /* && pFmtItem && !GetNumberFormatter()->
4147 IsTextFormat( ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ) )*/
4149 nWhich1
= RES_BOXATR_FORMAT
;
4151 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4152 // Sorge dafuer, das der Text auch entsprechend
4154 pBoxFmt
->SetFmtAttr( *GetDfltAttr( nWhich1
));
4156 pBoxFmt
->ResetFmtAttr( nWhich1
, RES_BOXATR_VALUE
);
4166 pUndo
->SetBox( rBox
);
4167 AppendUndo( pUndo
);
4168 EndUndo( UNDO_END
, NULL
);
4171 const SwTableNode
* pTblNd
= rBox
.GetSttNd()->FindTableNode();
4174 SwTableFmlUpdate
aTblUpdate( &pTblNd
->GetTable() );
4175 UpdateTblFlds( &aTblUpdate
);
4177 // TL_CHART2: update charts (when cursor leaves cell and
4178 // automatic update is enabled)
4179 if (AUTOUPD_FIELD_AND_CHARTS
== getFieldUpdateFlags(true))
4180 pTblNd
->GetTable().UpdateCharts();
4186 void SwDoc::SetTblBoxFormulaAttrs( SwTableBox
& rBox
, const SfxItemSet
& rSet
)
4191 AppendUndo( new SwUndoTblNumFmt( rBox
, &rSet
) );
4194 SwFrmFmt
* pBoxFmt
= rBox
.ClaimFrmFmt();
4195 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMULA
))
4197 pBoxFmt
->LockModify();
4198 pBoxFmt
->ResetFmtAttr( RES_BOXATR_VALUE
);
4199 pBoxFmt
->UnlockModify();
4201 else if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_VALUE
))
4203 pBoxFmt
->LockModify();
4204 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMULA
);
4205 pBoxFmt
->UnlockModify();
4207 pBoxFmt
->SetFmtAttr( rSet
);
4211 void SwDoc::ClearLineNumAttrs( SwPosition
& rPos
)
4214 aPam
.Move(fnMoveBackward
);
4215 SwCntntNode
*pNode
= aPam
.GetCntntNode();
4218 if( pNode
->IsTxtNode() )
4220 SwTxtNode
* pTxtNode
= pNode
->GetTxtNode();
4221 if ( pTxtNode
&& pTxtNode
->IsNumbered() && pTxtNode
->GetTxt().Len()==0 )
4223 const SfxPoolItem
* pFmtItem
= 0;
4224 SfxItemSet
rSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
4225 RES_PARATR_BEGIN
, RES_PARATR_END
- 1,
4227 pTxtNode
->SwCntntNode::GetAttr( rSet
);
4228 if ( SFX_ITEM_SET
== rSet
.GetItemState( RES_PARATR_NUMRULE
, FALSE
, &pFmtItem
) )
4230 SwUndoDelNum
* pUndo
;
4234 AppendUndo( pUndo
= new SwUndoDelNum( aPam
) );
4238 SwRegHistory
aRegH( pUndo
? pUndo
->GetHistory() : 0 );
4239 aRegH
.RegisterInModify( pTxtNode
, *pTxtNode
);
4241 pUndo
->AddNode( *pTxtNode
, FALSE
);
4242 String aStyle
= String::CreateFromAscii("");
4243 SfxStringItem
* pNewItem
= (SfxStringItem
*)pFmtItem
->Clone();
4244 pNewItem
->SetValue( aStyle
);
4245 rSet
.Put( *pNewItem
);
4246 pTxtNode
->SetAttr( rSet
);
4253 void SwDoc::ClearBoxNumAttrs( const SwNodeIndex
& rNode
)
4255 SwStartNode
* pSttNd
;
4256 if( 0 != ( pSttNd
= GetNodes()[ rNode
]->
4257 FindSttNodeByType( SwTableBoxStartNode
)) &&
4258 2 == pSttNd
->EndOfSectionIndex() - pSttNd
->GetIndex() )
4260 SwTableBox
* pBox
= pSttNd
->FindTableNode()->GetTable().
4261 GetTblBox( pSttNd
->GetIndex() );
4263 const SfxPoolItem
* pFmtItem
= 0;
4264 const SfxItemSet
& rSet
= pBox
->GetFrmFmt()->GetAttrSet();
4265 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pFmtItem
) ||
4266 SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMULA
, FALSE
) ||
4267 SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_VALUE
, FALSE
))
4272 AppendUndo( new SwUndoTblNumFmt( *pBox
) );
4275 SwFrmFmt
* pBoxFmt
= pBox
->ClaimFrmFmt();
4277 //JP 01.09.97: TextFormate bleiben erhalten!
4278 USHORT nWhich1
= RES_BOXATR_FORMAT
;
4279 if( pFmtItem
&& GetNumberFormatter()->IsTextFormat(
4280 ((SwTblBoxNumFormat
*)pFmtItem
)->GetValue() ))
4281 nWhich1
= RES_BOXATR_FORMULA
;
4283 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4284 // Sorge dafuer, das der Text auch entsprechend
4286 pBoxFmt
->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT
));
4288 pBoxFmt
->ResetFmtAttr( nWhich1
, RES_BOXATR_VALUE
);
4294 // kopiert eine Tabelle aus dem selben oder einem anderen Doc in sich
4295 // selbst. Dabei wird eine neue Tabelle angelegt oder eine bestehende
4296 // mit dem Inhalt gefuellt; wobei entweder der Inhalt ab einer Box oder
4297 // in eine bestehende TblSelektion gefuellt wird.
4298 // Gerufen wird es von: edglss.cxx/fecopy.cxx
4300 BOOL
SwDoc::InsCopyOfTbl( SwPosition
& rInsPos
, const SwSelBoxes
& rBoxes
,
4301 const SwTable
* pCpyTbl
, BOOL bCpyName
, BOOL bCorrPos
)
4305 const SwTableNode
* pSrcTblNd
= pCpyTbl
4306 ? pCpyTbl
->GetTableNode()
4307 : rBoxes
[ 0 ]->GetSttNd()->FindTableNode();
4309 SwTableNode
* pInsTblNd
= GetNodes()[ rInsPos
.nNode
]->FindTableNode();
4311 if( !pCpyTbl
&& !pInsTblNd
)
4313 SwUndoCpyTbl
* pUndo
= 0;
4317 pUndo
= new SwUndoCpyTbl
;
4321 bRet
= pSrcTblNd
->GetTable().MakeCopy( this, rInsPos
, rBoxes
,
4329 pInsTblNd
= GetNodes()[ rInsPos
.nNode
.GetIndex() - 1 ]->FindTableNode();
4331 pUndo
->SetTableSttIdx( pInsTblNd
->GetIndex() );
4332 AppendUndo( pUndo
);
4339 RedlineMode_t eOld
= GetRedlineMode();
4341 SetRedlineMode( (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
|
4342 nsRedlineMode_t::REDLINE_SHOW_INSERT
|
4343 nsRedlineMode_t::REDLINE_SHOW_DELETE
));
4345 SwUndoTblCpyTbl
* pUndo
= 0;
4349 pUndo
= new SwUndoTblCpyTbl
;
4353 SwDoc
* pCpyDoc
= (SwDoc
*)pSrcTblNd
->GetDoc();
4354 SfxObjectShellRef
* pRefForDocSh
= 0;
4355 BOOL bDelCpyDoc
= pCpyDoc
== this;
4359 // kopiere die Tabelle erstmal in ein temp. Doc
4360 pCpyDoc
= new SwDoc
;
4362 pRefForDocSh
= new SfxObjectShellRef();
4363 pCpyDoc
->SetRefForDocShell( pRefForDocSh
);
4365 SwPosition
aPos( SwNodeIndex( pCpyDoc
->GetNodes().GetEndOfContent() ));
4366 if( !pSrcTblNd
->GetTable().MakeCopy( pCpyDoc
, aPos
, rBoxes
, TRUE
, TRUE
))
4368 delete pRefForDocSh
;
4369 if( pCpyDoc
->release() == 0 )
4379 aPos
.nNode
-= 1; // auf den EndNode der Tabelle
4380 pSrcTblNd
= aPos
.nNode
.GetNode().FindTableNode();
4382 pCpyDoc
->SetRefForDocShell( NULL
);
4385 const SwStartNode
* pSttNd
= rInsPos
.nNode
.GetNode().FindTableBoxStartNode();
4387 rInsPos
.nContent
.Assign( 0, 0 );
4389 // no complex into complex, but copy into or from new model is welcome
4390 if( ( !pSrcTblNd
->GetTable().IsTblComplex() || pInsTblNd
->GetTable().IsNewModel() )
4391 && ( bDelCpyDoc
|| rBoxes
.Count() ) )
4393 // dann die Tabelle "relativ" kopieren
4394 const SwSelBoxes
* pBoxes
;
4399 SwTableBox
* pBox
= pInsTblNd
->GetTable().GetTblBox(
4400 pSttNd
->GetIndex() );
4401 ASSERT( pBox
, "Box steht nicht in dieser Tabelle" );
4402 aBoxes
.Insert( pBox
);
4408 // kopiere die Tabelle in die selktierten Zellen.
4409 bRet
= pInsTblNd
->GetTable().InsTable( pSrcTblNd
->GetTable(),
4414 SwNodeIndex
aNdIdx( *pSttNd
, 1 );
4415 bRet
= pInsTblNd
->GetTable().InsTable( pSrcTblNd
->GetTable(),
4421 delete pRefForDocSh
;
4422 if( pCpyDoc
->release() == 0 )
4428 // falls die Tabelle nicht kopiert werden konnte, das Undo-Object
4430 if( !bRet
&& pUndo
->IsEmpty() )
4433 AppendUndo( pUndo
);
4439 rInsPos
.nNode
= *pSttNd
;
4440 rInsPos
.nContent
.Assign( GetNodes().GoNext( &rInsPos
.nNode
), 0 );
4442 SetRedlineMode( eOld
);
4448 SetFieldsDirty( true, NULL
, 0 );
4455 BOOL
SwDoc::_UnProtectTblCells( SwTable
& rTbl
)
4458 SwUndoAttrTbl
* pUndo
= DoesUndo() ? new SwUndoAttrTbl( *rTbl
.GetTableNode() )
4461 SwTableSortBoxes
& rSrtBox
= rTbl
.GetTabSortBoxes();
4462 for( USHORT i
= rSrtBox
.Count(); i
; )
4464 SwFrmFmt
*pBoxFmt
= rSrtBox
[ --i
]->GetFrmFmt();
4465 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4467 pBoxFmt
->ResetFmtAttr( RES_PROTECT
);
4477 AppendUndo( pUndo
);
4486 BOOL
SwDoc::UnProtectCells( const String
& rName
)
4489 SwTableFmt
* pFmt
= FindTblFmtByName( rName
);
4492 bChgd
= _UnProtectTblCells( *SwTable::FindTable( pFmt
) );
4500 BOOL
SwDoc::UnProtectCells( const SwSelBoxes
& rBoxes
)
4503 if( rBoxes
.Count() )
4505 SwUndoAttrTbl
* pUndo
= DoesUndo()
4506 ? new SwUndoAttrTbl( *rBoxes
[0]->GetSttNd()->FindTableNode() )
4509 SvPtrarr
aFmts( 16 ), aNewFmts( 16 );
4510 for( USHORT i
= rBoxes
.Count(); i
; )
4512 SwTableBox
* pBox
= rBoxes
[ --i
];
4513 SwFrmFmt
* pBoxFmt
= pBox
->GetFrmFmt();
4514 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4516 USHORT nFnd
= aFmts
.GetPos( pBoxFmt
);
4517 if( USHRT_MAX
!= nFnd
)
4518 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)aNewFmts
[ nFnd
] );
4521 aFmts
.Insert( pBoxFmt
, aFmts
.Count() );
4522 pBoxFmt
= pBox
->ClaimFrmFmt();
4523 pBoxFmt
->ResetFmtAttr( RES_PROTECT
);
4524 aNewFmts
.Insert( pBoxFmt
, aNewFmts
.Count() );
4535 AppendUndo( pUndo
);
4544 BOOL
SwDoc::UnProtectTbls( const SwPaM
& rPam
)
4546 StartUndo(UNDO_EMPTY
, NULL
);
4548 BOOL bChgd
= FALSE
, bHasSel
= rPam
.HasMark() ||
4549 rPam
.GetNext() != (SwPaM
*)&rPam
;
4550 SwFrmFmts
& rFmts
= *GetTblFrmFmts();
4552 const SwTableNode
* pTblNd
;
4553 for( USHORT n
= rFmts
.Count(); n
; )
4554 if( 0 != (pTbl
= SwTable::FindTable( rFmts
[ --n
] )) &&
4555 0 != (pTblNd
= pTbl
->GetTableNode() ) &&
4556 pTblNd
->GetNodes().IsDocNodes() )
4558 ULONG nTblIdx
= pTblNd
->GetIndex();
4560 // dann ueberpruefe ob Tabelle in der Selection liegt
4564 SwPaM
* pTmp
= (SwPaM
*)&rPam
;
4566 const SwPosition
*pStt
= pTmp
->Start(),
4567 *pEnd
= pTmp
->End();
4568 bFound
= pStt
->nNode
.GetIndex() < nTblIdx
&&
4569 nTblIdx
< pEnd
->nNode
.GetIndex();
4571 } while( !bFound
&& &rPam
!= ( pTmp
= (SwPaM
*)pTmp
->GetNext() ) );
4573 continue; // weitersuchen
4576 // dann mal den Schutz aufheben
4577 bChgd
|= _UnProtectTblCells( *pTbl
);
4580 EndUndo(UNDO_EMPTY
, NULL
);
4587 BOOL
SwDoc::HasTblAnyProtection( const SwPosition
* pPos
,
4588 const String
* pTblName
,
4589 BOOL
* pFullTblProtection
)
4591 BOOL bHasProtection
= FALSE
;
4594 pTbl
= SwTable::FindTable( FindTblFmtByName( *pTblName
) );
4597 SwTableNode
* pTblNd
= pPos
->nNode
.GetNode().FindTableNode();
4599 pTbl
= &pTblNd
->GetTable();
4604 SwTableSortBoxes
& rSrtBox
= pTbl
->GetTabSortBoxes();
4605 for( USHORT i
= rSrtBox
.Count(); i
; )
4607 SwFrmFmt
*pBoxFmt
= rSrtBox
[ --i
]->GetFrmFmt();
4608 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4610 if( !bHasProtection
)
4612 bHasProtection
= TRUE
;
4613 if( !pFullTblProtection
)
4615 *pFullTblProtection
= TRUE
;
4618 else if( bHasProtection
&& pFullTblProtection
)
4620 *pFullTblProtection
= FALSE
;
4625 return bHasProtection
;
4628 #ifdef DEL_TABLE_REDLINES
4629 lcl_DelRedlines::lcl_DelRedlines( const SwTableNode
& rNd
,
4630 BOOL bCheckForOwnRedline
)
4631 : pDoc( (SwDoc
*)rNd
.GetNodes().GetDoc() )
4633 pDoc
->StartUndo(UNDO_EMPTY
, NULL
);
4634 const SwRedlineTbl
& rTbl
= pDoc
->GetRedlineTbl();
4635 if( !pDoc
->IsIgnoreRedline() && rTbl
.Count() )
4637 BOOL bDelete
= TRUE
;
4638 if( bCheckForOwnRedline
)
4640 sal_uInt16 nRedlPos
= pDoc
->GetRedlinePos( rNd
, USHRT_MAX
);
4641 sal_uInt32 nSttNd
= rNd
.GetIndex(),
4642 nEndNd
= rNd
.EndOfSectionIndex();
4644 for ( ; nRedlPos
< rTbl
.Count(); ++nRedlPos
)
4646 const SwRedline
* pRedline
= rTbl
[ nRedlPos
];
4647 const SwPosition
* pStt
= pRedline
->Start(),
4648 * pEnd
= pStt
== pRedline
->GetPoint()
4649 ? pRedline
->GetMark()
4650 : pRedline
->GetPoint();
4651 if( pStt
->nNode
<= nSttNd
)
4653 if( pEnd
->nNode
>= nEndNd
&&
4654 pRedline
->GetAuthor() == pDoc
->GetRedlineAuthor() )
4666 SwPaM
aPam(*rNd
.EndOfSectionNode(), rNd
);
4667 pDoc
->AcceptRedline( aPam
, true );