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
->Erase( 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 rTxtNode
.pStartOfSection
= pTblNd
;
1327 // remove PageBreaks/PageDesc/ColBreak
1328 const SwAttrSet
* pSet
= rTxtNode
.GetpSwAttrSet();
1331 // das entfernen der PageBreaks erst nach dem erzeugen der Tabelle
1332 // erfolgen, denn sonst stehen sie falsch in der History !!!
1333 // SwRegHistory aRegH( pTxtNd, *pTxtNd, pHistory );
1334 const SfxPoolItem
* pItem
;
1335 if( SFX_ITEM_SET
== pSet
->GetItemState( RES_BREAK
, FALSE
, &pItem
) )
1338 pTblFmt
->SetFmtAttr( *pItem
);
1339 rTxtNode
.ResetAttr( RES_BREAK
);
1340 pSet
= rTxtNode
.GetpSwAttrSet();
1343 if( pSet
&& SFX_ITEM_SET
== pSet
->GetItemState(
1344 RES_PAGEDESC
, FALSE
, &pItem
) &&
1345 ((SwFmtPageDesc
*)pItem
)->GetPageDesc() )
1348 pTblFmt
->SetFmtAttr( *pItem
);
1349 rTxtNode
.ResetAttr( RES_PAGEDESC
);
1356 // SwNodeIndex aSttIdx( *pTblNd, 1 );
1357 // SwNodeIndex aEndIdx( rlNodes.rbegin()->aEnd, -1 );
1358 std::vector
<std::vector
< SwNodeRange
> >::const_iterator aRowIter
= rTableNodes
.begin();
1359 for( nLines
= 0, nBoxes
= 0;
1360 aRowIter
!= rTableNodes
.end();
1361 ++aRowIter
, /*aSttIdx += 2, */nLines
++, nBoxes
= 0 )
1363 // SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
1364 // ASSERT( pTxtNd, "nur TextNodes in der Tabelle aufnehmen" );
1366 pLine
= new SwTableLine( pLineFmt
, 1, 0 );
1367 pTable
->GetTabLines().C40_INSERT( SwTableLine
, pLine
, nLines
);
1369 // SwStartNode* pSttNd;
1370 // SwPosition aCntPos( aSttIdx, SwIndex( pTxtNd ));
1372 std::vector
< SwNodeRange
>::const_iterator aCellIter
= aRowIter
->begin();
1373 // SvULongs aBkmkArr( 15, 15 );
1374 // _SaveCntntIdx( pDoc, aCellIter->aStart.GetIndex(), pTxtNd->GetTxt().Len(), aBkmkArr );
1375 // const sal_Unicode* pTxt = pTxtNd->GetTxt().GetBuffer();
1377 for( ; aCellIter
!= aRowIter
->end(); ++aCellIter
)
1379 // aCellIter->aStart aCellIter->aEnd
1380 // aCntPos.nContent = nChPos;
1381 // SwCntntNode* pNewNd = pTxtNd->SplitNode( aCntPos );
1384 // if( aBkmkArr.Count() )
1385 // _RestoreCntntIdx( aBkmkArr, *pNewNd, nChPos,
1388 const SwNodeIndex
aTmpIdx( aCellIter
->aStart
, 0 );
1390 SwNodeIndex
aCellEndIdx(aCellIter
->aEnd
);
1392 SwStartNode
* pSttNd
= new SwStartNode( aTmpIdx
, ND_STARTNODE
,
1393 SwTableBoxStartNode
);
1394 new SwEndNode( aCellEndIdx
, *pSttNd
);
1395 //set the start node on all node of the current cell
1396 SwNodeIndex aCellNodeIdx
= aCellIter
->aStart
;
1397 for(;aCellNodeIdx
<= aCellIter
->aEnd
; ++aCellNodeIdx
)
1399 aCellNodeIdx
.GetNode().pStartOfSection
= pSttNd
;
1400 //skip start/end node pairs
1401 if( aCellNodeIdx
.GetNode().IsStartNode() )
1402 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
->Insert( pDelPara
->cCh
, aCntIdx
);
1556 if( pDelPara
->pUndo
)
1557 pDelPara
->pUndo
->AddBoxPos( *pDoc
, nNdIdx
, aDelRg
.aEnd
.GetIndex(),
1558 aCntIdx
.GetIndex() );
1560 SvULongs
aBkmkArr( 4, 4 );
1561 xub_StrLen nOldTxtLen
= aCntIdx
.GetIndex();
1562 _SaveCntntIdx( pDoc
, nNdIdx
, pCurTxtNd
->GetTxt().Len(),
1565 pDelPara
->pLastNd
->JoinNext();
1567 if( aBkmkArr
.Count() )
1568 _RestoreCntntIdx( pDoc
, aBkmkArr
,
1569 pDelPara
->pLastNd
->GetIndex(),
1572 else if( pDelPara
->pUndo
)
1575 pDelPara
->pUndo
->AddBoxPos( *pDoc
, nNdIdx
, aDelRg
.aEnd
.GetIndex() );
1578 else if( pDelPara
->pUndo
)
1579 pDelPara
->pUndo
->AddBoxPos( *pDoc
, aDelRg
.aStart
.GetIndex(), aDelRg
.aEnd
.GetIndex() );
1581 pDelPara
->pLastNd
= aDelRg
.aEnd
.GetNode().GetTxtNode();
1583 //JP 03.04.97: die Ausrichtung der ZahlenFormatierung auf
1584 // keinen Fall uebernehmen
1585 if( pDelPara
->pLastNd
&& pDelPara
->pLastNd
->HasSwAttrSet() )
1586 pDelPara
->pLastNd
->ResetAttr( RES_PARATR_ADJUST
);
1592 BOOL
SwNodes::TableToText( const SwNodeRange
& rRange
, sal_Unicode cCh
,
1593 SwUndoTblToTxt
* pUndo
)
1595 // ist eine Tabelle selektiert ?
1596 SwTableNode
* pTblNd
;
1597 if( rRange
.aStart
.GetIndex() >= rRange
.aEnd
.GetIndex() ||
1598 0 == ( pTblNd
= (*this)[ rRange
.aStart
]->GetTableNode()) ||
1599 &rRange
.aEnd
.GetNode() != pTblNd
->EndOfSectionNode() )
1602 // stand die Tabelle ganz alleine in einer Section ?
1603 // dann ueber den Upper der Tabelle die Frames anlegen
1604 SwNode2Layout
* pNode2Layout
= 0;
1605 SwNodeIndex
aFrmIdx( rRange
.aStart
);
1606 SwNode
* pFrmNd
= FindPrvNxtFrmNode( aFrmIdx
, &rRange
.aEnd
.GetNode() );
1608 // dann sammel mal alle Uppers ein
1609 pNode2Layout
= new SwNode2Layout( *pTblNd
);
1611 // loesche schon mal die Frames
1614 // dann "loeschen" die Tabellen und fasse alle Lines/Boxen zusammen
1615 _DelTabPara
aDelPara( *this, cCh
, pUndo
);
1616 pTblNd
->pTable
->GetTabLines().ForEach( &lcl_DelLine
, &aDelPara
);
1618 // jetzt ist aus jeder TableLine ein TextNode mit dem entsprechenden
1619 // Trenner erzeugt worden. Es braucht nur noch die Table-Section
1620 // geloescht und fuer die neuen TextNode die Frames erzeugt werden.
1621 SwNodeRange
aDelRg( rRange
.aStart
, rRange
.aEnd
);
1623 // JP 14.01.97: hat die Tabelle PageDesc-/Break-Attribute? Dann in den
1624 // ersten TextNode uebernehmen
1626 // was ist mit UNDO???
1627 const SfxItemSet
& rTblSet
= pTblNd
->pTable
->GetFrmFmt()->GetAttrSet();
1628 const SfxPoolItem
*pBreak
, *pDesc
;
1629 if( SFX_ITEM_SET
!= rTblSet
.GetItemState( RES_PAGEDESC
, FALSE
, &pDesc
))
1631 if( SFX_ITEM_SET
!= rTblSet
.GetItemState( RES_BREAK
, FALSE
, &pBreak
))
1634 if( pBreak
|| pDesc
)
1636 SwNodeIndex
aIdx( *pTblNd
);
1637 SwCntntNode
* pCNd
= GoNext( &aIdx
);
1639 pCNd
->SetAttr( *pBreak
);
1641 pCNd
->SetAttr( *pDesc
);
1645 SectionUp( &aDelRg
); // loesche die Section und damit die Tabelle
1647 ULONG nStt
= aDelRg
.aStart
.GetIndex(), nEnd
= aDelRg
.aEnd
.GetIndex();
1650 pNode2Layout
->RestoreUpperFrms( *this,
1651 aDelRg
.aStart
.GetIndex(), aDelRg
.aEnd
.GetIndex() );
1652 delete pNode2Layout
;
1657 SwSectionNode
*pSNd
;
1658 while( aDelRg
.aStart
.GetIndex() < nEnd
)
1660 if( 0 != ( pCNd
= aDelRg
.aStart
.GetNode().GetCntntNode()))
1662 if( pFrmNd
->IsCntntNode() )
1663 ((SwCntntNode
*)pFrmNd
)->MakeFrms( *pCNd
);
1664 else if( pFrmNd
->IsTableNode() )
1665 ((SwTableNode
*)pFrmNd
)->MakeFrms( aDelRg
.aStart
);
1666 else if( pFrmNd
->IsSectionNode() )
1667 ((SwSectionNode
*)pFrmNd
)->MakeFrms( aDelRg
.aStart
);
1670 else if( 0 != ( pSNd
= aDelRg
.aStart
.GetNode().GetSectionNode()))
1672 if( !pSNd
->GetSection().IsHidden() && !pSNd
->IsCntntHidden() )
1674 pSNd
->MakeFrms( &aFrmIdx
, &aDelRg
.aEnd
);
1678 aDelRg
.aStart
= *pSNd
->EndOfSectionNode();
1684 // #i28006# Fly frames have to be restored even if the table was
1685 // #alone in the section
1686 const SwSpzFrmFmts
& rFlyArr
= *GetDoc()->GetSpzFrmFmts();
1687 const SwPosition
* pAPos
;
1688 for( USHORT n
= 0; n
< rFlyArr
.Count(); ++n
)
1690 SwFrmFmt
* pFmt
= (SwFrmFmt
*)rFlyArr
[n
];
1691 const SwFmtAnchor
& rAnchor
= pFmt
->GetAnchor();
1692 if( ( FLY_AT_CNTNT
== rAnchor
.GetAnchorId() ||
1693 FLY_AUTO_CNTNT
== rAnchor
.GetAnchorId() ) &&
1694 0 != ( pAPos
= rAnchor
.GetCntntAnchor() ) &&
1695 nStt
<= pAPos
->nNode
.GetIndex() &&
1696 pAPos
->nNode
.GetIndex() < nEnd
)
1704 // ----- einfuegen von Spalten/Zeilen ------------------------
1706 BOOL
SwDoc::InsertCol( const SwCursor
& rCursor
, USHORT nCnt
, BOOL bBehind
)
1708 if( !::CheckSplitCells( rCursor
, nCnt
+ 1, nsSwTblSearchType::TBLSEARCH_COL
) )
1711 // lasse ueber das Layout die Boxen suchen
1713 ::GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
1716 if( aBoxes
.Count() )
1717 bRet
= InsertCol( aBoxes
, nCnt
, bBehind
);
1721 BOOL
SwDoc::InsertCol( const SwSelBoxes
& rBoxes
, USHORT nCnt
, BOOL bBehind
)
1723 // uebers SwDoc fuer Undo !!
1724 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1725 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1729 SwTable
& rTbl
= pTblNd
->GetTable();
1730 if( rTbl
.ISA( SwDDETable
))
1733 #ifdef DEL_TABLE_REDLINES
1734 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
1737 SwTableSortBoxes
aTmpLst( 0, 5 );
1738 SwUndoTblNdsChg
* pUndo
= 0;
1742 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_INSCOL
, rBoxes
, *pTblNd
,
1743 0, 0, nCnt
, bBehind
, FALSE
);
1744 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
1747 SwTableFmlUpdate
aMsgHnt( &rTbl
);
1748 aMsgHnt
.eFlags
= TBL_BOXPTR
;
1749 UpdateTblFlds( &aMsgHnt
);
1751 BOOL bRet
= rTbl
.InsertCol( this, rBoxes
, nCnt
, bBehind
);
1755 ::ClearFEShellTabCols();
1756 SetFieldsDirty( true, NULL
, 0 );
1765 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
1766 AppendUndo( pUndo
);
1774 BOOL
SwDoc::InsertRow( const SwCursor
& rCursor
, USHORT nCnt
, BOOL bBehind
)
1776 // lasse ueber das Layout die Boxen suchen
1778 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_ROW
);
1781 if( aBoxes
.Count() )
1782 bRet
= InsertRow( aBoxes
, nCnt
, bBehind
);
1786 BOOL
SwDoc::InsertRow( const SwSelBoxes
& rBoxes
, USHORT nCnt
, BOOL bBehind
)
1788 // uebers SwDoc fuer Undo !!
1789 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1790 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1794 SwTable
& rTbl
= pTblNd
->GetTable();
1795 if( rTbl
.ISA( SwDDETable
))
1798 #ifdef DEL_TABLE_REDLINES
1799 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
1802 SwTableSortBoxes
aTmpLst( 0, 5 );
1803 SwUndoTblNdsChg
* pUndo
= 0;
1807 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_INSROW
,rBoxes
, *pTblNd
,
1808 0, 0, nCnt
, bBehind
, FALSE
);
1809 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
1812 SwTableFmlUpdate
aMsgHnt( &rTbl
);
1813 aMsgHnt
.eFlags
= TBL_BOXPTR
;
1814 UpdateTblFlds( &aMsgHnt
);
1816 BOOL bRet
= rTbl
.InsertRow( this, rBoxes
, nCnt
, bBehind
);
1820 ::ClearFEShellTabCols();
1821 SetFieldsDirty( true, NULL
, 0 );
1830 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
1831 AppendUndo( pUndo
);
1840 // ----- loeschen von Spalten/Zeilen ------------------------
1842 BOOL
SwDoc::DeleteRow( const SwCursor
& rCursor
)
1844 // lasse ueber das Layout die Boxen suchen
1846 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_ROW
);
1847 if( ::HasProtectedCells( aBoxes
))
1850 // die Crsr aus dem Loeschbereich entfernen.
1851 // Der Cursor steht danach:
1852 // - es folgt noch eine Zeile, in dieser
1853 // - vorher steht noch eine Zeile, in dieser
1854 // - sonst immer dahinter
1856 SwTableNode
* pTblNd
= rCursor
.GetNode()->FindTableNode();
1858 if( pTblNd
->GetTable().ISA( SwDDETable
))
1861 // suche alle Boxen / Lines
1862 _FndBox
aFndBox( 0, 0 );
1864 _FndPara
aPara( aBoxes
, &aFndBox
);
1865 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
1868 if( !aFndBox
.GetLines().Count() )
1871 SwEditShell
* pESh
= GetEditShell();
1875 // JP: eigentlich sollte man ueber alle Shells iterieren!!
1878 _FndBox
* pFndBox
= &aFndBox
;
1879 while( 1 == pFndBox
->GetLines().Count() &&
1880 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
1882 _FndBox
* pTmp
= pFndBox
->GetLines()[0]->GetBoxes()[0];
1883 if( pTmp
->GetBox()->GetSttNd() )
1884 break; // das ist sonst zu weit
1888 SwTableLine
* pDelLine
= pFndBox
->GetLines()[
1889 pFndBox
->GetLines().Count()-1 ]->GetLine();
1890 SwTableBox
* pDelBox
= pDelLine
->GetTabBoxes()[
1891 pDelLine
->GetTabBoxes().Count() - 1 ];
1892 while( !pDelBox
->GetSttNd() )
1894 SwTableLine
* pLn
= pDelBox
->GetTabLines()[
1895 pDelBox
->GetTabLines().Count()-1 ];
1896 pDelBox
= pLn
->GetTabBoxes()[ pLn
->GetTabBoxes().Count() - 1 ];
1898 SwTableBox
* pNextBox
= pDelLine
->FindNextBox( pTblNd
->GetTable(),
1901 pNextBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
1902 pNextBox
= pNextBox
->FindNextBox( pTblNd
->GetTable(), pNextBox
);
1904 if( !pNextBox
) // keine nachfolgende? dann die vorhergehende
1906 pDelLine
= pFndBox
->GetLines()[ 0 ]->GetLine();
1907 pDelBox
= pDelLine
->GetTabBoxes()[ 0 ];
1908 while( !pDelBox
->GetSttNd() )
1909 pDelBox
= pDelBox
->GetTabLines()[0]->GetTabBoxes()[0];
1910 pNextBox
= pDelLine
->FindPreviousBox( pTblNd
->GetTable(),
1913 pNextBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
1914 pNextBox
= pNextBox
->FindPreviousBox( pTblNd
->GetTable(), pNextBox
);
1918 if( pNextBox
) // dann den Cursor hier hinein
1919 nIdx
= pNextBox
->GetSttIdx() + 1;
1920 else // ansonsten hinter die Tabelle
1921 nIdx
= pTblNd
->EndOfSectionIndex() + 1;
1923 SwNodeIndex
aIdx( GetNodes(), nIdx
);
1924 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
1926 pCNd
= GetNodes().GoNext( &aIdx
);
1930 // die Cursor von der Shell oder den uebergebenen Cursor aendern?
1931 SwPaM
* pPam
= (SwPaM
*)&rCursor
;
1932 pPam
->GetPoint()->nNode
= aIdx
;
1933 pPam
->GetPoint()->nContent
.Assign( pCNd
, 0 );
1934 pPam
->SetMark(); // beide wollen etwas davon haben
1939 // dann loesche doch die Zeilen
1941 StartUndo(UNDO_ROW_DELETE
, NULL
);
1942 BOOL bResult
= DeleteRowCol( aBoxes
);
1943 EndUndo(UNDO_ROW_DELETE
, NULL
);
1948 BOOL
SwDoc::DeleteCol( const SwCursor
& rCursor
)
1950 // lasse ueber das Layout die Boxen suchen
1952 GetTblSel( rCursor
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
1953 if( ::HasProtectedCells( aBoxes
))
1956 // die Crsr muessen noch aus dem Loesch Bereich entfernt
1957 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
1958 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
1959 SwEditShell
* pESh
= GetEditShell();
1962 const SwNode
* pNd
= rCursor
.GetNode()->FindTableBoxStartNode();
1963 pESh
->ParkCrsr( SwNodeIndex( *pNd
) );
1966 // dann loesche doch die Spalten
1967 StartUndo(UNDO_COL_DELETE
, NULL
);
1968 BOOL bResult
= DeleteRowCol( aBoxes
, true );
1969 EndUndo(UNDO_COL_DELETE
, NULL
);
1974 BOOL
SwDoc::DeleteRowCol( const SwSelBoxes
& rBoxes
, bool bColumn
)
1976 if( ::HasProtectedCells( rBoxes
))
1979 // uebers SwDoc fuer Undo !!
1980 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
1981 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1985 if( pTblNd
->GetTable().ISA( SwDDETable
))
1988 ::ClearFEShellTabCols();
1989 SwSelBoxes aSelBoxes
;
1990 aSelBoxes
.Insert(rBoxes
.GetData(), rBoxes
.Count());
1991 SwTable
&rTable
= pTblNd
->GetTable();
1994 if( rTable
.IsNewModel() )
1997 rTable
.ExpandColumnSelection( aSelBoxes
, nMin
, nMax
);
1999 rTable
.FindSuperfluousRows( aSelBoxes
);
2002 #ifdef DEL_TABLE_REDLINES
2003 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
2006 // soll die gesamte Tabelle geloescht werden ??
2007 const ULONG nTmpIdx1
= pTblNd
->GetIndex();
2008 const ULONG nTmpIdx2
= aSelBoxes
[ aSelBoxes
.Count()-1 ]->GetSttNd()->
2009 EndOfSectionIndex()+1;
2010 if( pTblNd
->GetTable().GetTabSortBoxes().Count() == aSelBoxes
.Count() &&
2011 aSelBoxes
[0]->GetSttIdx()-1 == nTmpIdx1
&&
2012 nTmpIdx2
== pTblNd
->EndOfSectionIndex() )
2014 BOOL bNewTxtNd
= FALSE
;
2015 // steht diese auch noch alleine in einem FlyFrame ?
2016 SwNodeIndex
aIdx( *pTblNd
, -1 );
2017 const SwStartNode
* pSttNd
= aIdx
.GetNode().GetStartNode();
2020 const ULONG nTblEnd
= pTblNd
->EndOfSectionIndex() + 1;
2021 const ULONG nSectEnd
= pSttNd
->EndOfSectionIndex();
2022 if( nTblEnd
== nSectEnd
)
2024 if( SwFlyStartNode
== pSttNd
->GetStartNodeType() )
2026 SwFrmFmt
* pFmt
= pSttNd
->GetFlyFmt();
2029 // Ok, das ist das gesuchte FlyFormat
2030 DelLayoutFmt( pFmt
);
2034 // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2035 // TextNode ueberig lassen.
2036 // Undo koennen wir dann vergessen !!
2041 // kein Fly ?? also Kopf- oder Fusszeile: dann immer einen
2042 // TextNode ueberig lassen.
2047 SwPaM
aPaM( *pTblNd
->EndOfSectionNode(), aIdx
.GetNode() );
2051 const SwNodeIndex
aTmpIdx( *pTblNd
->EndOfSectionNode(), 1 );
2052 GetNodes().MakeTxtNode( aTmpIdx
,
2053 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
) );
2056 // save the cursors (UNO and otherwise)
2057 SwPaM
aSavePaM( SwNodeIndex( *pTblNd
->EndOfSectionNode() ) );
2058 if( ! aSavePaM
.Move( fnMoveForward
, fnGoNode
) )
2060 *aSavePaM
.GetMark() = SwPosition( *pTblNd
);
2061 aSavePaM
.Move( fnMoveBackward
, fnGoNode
);
2063 ::PaMCorrAbs( SwNodeIndex( *pTblNd
),
2064 SwNodeIndex( *pTblNd
->EndOfSectionNode() ),
2065 *aSavePaM
.GetMark() );
2067 // harte SeitenUmbrueche am nachfolgenden Node verschieben
2068 BOOL bSavePageBreak
= FALSE
, bSavePageDesc
= FALSE
;
2069 ULONG nNextNd
= pTblNd
->EndOfSectionIndex()+1;
2070 SwCntntNode
* pNextNd
= GetNodes()[ nNextNd
]->GetCntntNode();
2073 //JP 24.08.98: will man wirklich den PageDesc/Break vom
2074 // nachfolgen Absatz ueberbuegeln?
2075 // const SwAttrSet& rAttrSet = pNextNd->GetSwAttrSet();
2076 // if( SFX_ITEM_SET != rAttrSet.GetItemState( RES_PAGEDESC ) &&
2077 // SFX_ITEM_SET != rAttrSet.GetItemState( RES_BREAK ))
2079 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2080 const SfxPoolItem
*pItem
;
2081 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_PAGEDESC
,
2084 pNextNd
->SetAttr( *pItem
);
2085 bSavePageDesc
= TRUE
;
2088 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_BREAK
,
2091 pNextNd
->SetAttr( *pItem
);
2092 bSavePageBreak
= TRUE
;
2096 SwUndoDelete
* pUndo
= new SwUndoDelete( aPaM
);
2098 pUndo
->SetTblDelLastNd();
2099 pUndo
->SetPgBrkFlags( bSavePageBreak
, bSavePageDesc
);
2100 pUndo
->SetTableName(pTblNd
->GetTable().GetFrmFmt()->GetName());
2101 AppendUndo( pUndo
);
2107 const SwNodeIndex
aTmpIdx( *pTblNd
->EndOfSectionNode(), 1 );
2108 GetNodes().MakeTxtNode( aTmpIdx
,
2109 GetTxtCollFromPool( RES_POOLCOLL_STANDARD
) );
2112 // save the cursors (UNO and otherwise)
2113 SwPaM
aSavePaM( SwNodeIndex( *pTblNd
->EndOfSectionNode() ) );
2114 if( ! aSavePaM
.Move( fnMoveForward
, fnGoNode
) )
2116 *aSavePaM
.GetMark() = SwPosition( *pTblNd
);
2117 aSavePaM
.Move( fnMoveBackward
, fnGoNode
);
2119 ::PaMCorrAbs( SwNodeIndex( *pTblNd
),
2120 SwNodeIndex( *pTblNd
->EndOfSectionNode() ),
2121 *aSavePaM
.GetMark() );
2123 // harte SeitenUmbrueche am nachfolgenden Node verschieben
2124 SwCntntNode
* pNextNd
= GetNodes()[ pTblNd
->EndOfSectionIndex()+1 ]->GetCntntNode();
2127 SwFrmFmt
* pTableFmt
= pTblNd
->GetTable().GetFrmFmt();
2128 const SfxPoolItem
*pItem
;
2129 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_PAGEDESC
,
2131 pNextNd
->SetAttr( *pItem
);
2133 if( SFX_ITEM_SET
== pTableFmt
->GetItemState( RES_BREAK
,
2135 pNextNd
->SetAttr( *pItem
);
2139 DeleteSection( pTblNd
);
2142 SetFieldsDirty( true, NULL
, 0 );
2146 SwUndoTblNdsChg
* pUndo
= 0;
2150 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_DELBOX
, aSelBoxes
, *pTblNd
,
2151 nMin
, nMax
, 0, FALSE
, FALSE
);
2154 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
2155 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2156 UpdateTblFlds( &aMsgHnt
);
2158 if( rTable
.IsNewModel() )
2161 rTable
.PrepareDeleteCol( nMin
, nMax
);
2162 rTable
.FindSuperfluousRows( aSelBoxes
);
2164 pUndo
->ReNewBoxes( aSelBoxes
);
2166 const BOOL bRet
= rTable
.DeleteSel( this, aSelBoxes
, 0, pUndo
, TRUE
, TRUE
);
2170 SetFieldsDirty( true, NULL
, 0 );
2179 AppendUndo( pUndo
);
2189 // ---------- teilen / zusammenfassen von Boxen in der Tabelle --------
2191 BOOL
SwDoc::SplitTbl( const SwSelBoxes
& rBoxes
, sal_Bool bVert
, USHORT nCnt
,
2192 sal_Bool bSameHeight
)
2194 // uebers SwDoc fuer Undo !!
2195 ASSERT( rBoxes
.Count() && nCnt
, "keine gueltige Box-Liste" );
2196 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
2200 SwTable
& rTbl
= pTblNd
->GetTable();
2201 if( rTbl
.ISA( SwDDETable
))
2204 #ifdef DEL_TABLE_REDLINES
2205 lcl_DelRedlines
aDelRedl( *pTblNd
, TRUE
);
2209 SwTableSortBoxes
aTmpLst( 0, 5 );
2210 SwUndoTblNdsChg
* pUndo
= 0;
2211 BOOL bDoUndo
= DoesUndo();
2215 pUndo
= new SwUndoTblNdsChg( UNDO_TABLE_SPLIT
, rBoxes
, *pTblNd
, 0, 0,
2216 nCnt
, bVert
, bSameHeight
);
2218 aTmpLst
.Insert( &rTbl
.GetTabSortBoxes(), 0, rTbl
.GetTabSortBoxes().Count() );
2221 for( USHORT n
= 0; n
< rBoxes
.Count(); ++n
)
2223 const SwStartNode
* pSttNd
= rBoxes
[ n
]->GetSttNd();
2224 aNdsCnts
.Insert( pSttNd
->EndOfSectionIndex() -
2225 pSttNd
->GetIndex(), n
);
2230 SwTableFmlUpdate
aMsgHnt( &rTbl
);
2231 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2232 UpdateTblFlds( &aMsgHnt
);
2236 bRet
= rTbl
.SplitCol( this, rBoxes
, nCnt
);
2238 bRet
= rTbl
.SplitRow( this, rBoxes
, nCnt
, bSameHeight
);
2243 SetFieldsDirty( true, NULL
, 0 );
2253 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
);
2255 pUndo
->SaveNewBoxes( *pTblNd
, aTmpLst
, rBoxes
, aNdsCnts
);
2256 AppendUndo( pUndo
);
2266 USHORT
SwDoc::MergeTbl( SwPaM
& rPam
)
2268 // pruefe ob vom aktuellen Crsr der SPoint/Mark in einer Tabelle stehen
2269 SwTableNode
* pTblNd
= rPam
.GetNode()->FindTableNode();
2271 return TBLMERGE_NOSELECTION
;
2272 SwTable
& rTable
= pTblNd
->GetTable();
2273 if( rTable
.ISA(SwDDETable
) )
2274 return TBLMERGE_NOSELECTION
;
2275 USHORT nRet
= TBLMERGE_NOSELECTION
;
2276 if( !rTable
.IsNewModel() )
2278 nRet
=::CheckMergeSel( rPam
);
2279 if( TBLMERGE_OK
!= nRet
)
2281 nRet
= TBLMERGE_NOSELECTION
;
2284 // --> FME 2004-10-08 #i33394#
2285 StartUndo( UNDO_TABLE_MERGE
, NULL
);
2288 #ifdef DEL_TABLE_REDLINES
2289 if( !IsIgnoreRedline() && GetRedlineTbl().Count() )
2290 DeleteRedline( *pTblNd
, true, USHRT_MAX
);
2292 RedlineMode_t eOld
= GetRedlineMode();
2293 SetRedlineMode_intern((RedlineMode_t
)(eOld
| nsRedlineMode_t::REDLINE_IGNORE
));
2295 SwUndoTblMerge
* pUndo
= 0;
2297 pUndo
= new SwUndoTblMerge( rPam
);
2299 // lasse ueber das Layout die Boxen suchen
2302 SwTableBox
* pMergeBox
;
2304 if( !rTable
.PrepareMerge( rPam
, aBoxes
, aMerged
, &pMergeBox
, pUndo
) )
2305 { // no cells found to merge
2306 SetRedlineMode_intern( eOld
);
2310 if( UNDO_REDLINE
== GetUndoIds(NULL
, NULL
) )
2312 SwUndoRedline
* pU
= (SwUndoRedline
*)RemoveLastUndo( UNDO_REDLINE
);
2313 if( pU
->GetRedlSaveCount() )
2315 SwUndoIter
aUndoIter( &rPam
, UNDO_REDLINE
);
2316 pU
->Undo( aUndoIter
);
2324 // die PaMs muessen noch aus dem Loesch Bereich entfernt
2325 // werden. Setze sie immer hinter/auf die Tabelle; ueber die
2326 // Dokument-Position werden sie dann immer an die alte Position gesetzt.
2327 // Erstmal einen Index auf die Parkposition merken, denn nach GetMergeSel
2328 // komme ich nicht mehr dran.
2331 rPam
.GetPoint()->nNode
= *pMergeBox
->GetSttNd();
2332 rPam
.GetPoint()->nContent
.Assign( 0, 0 );
2336 SwPaM
* pTmp
= &rPam
;
2337 while( &rPam
!= ( pTmp
= (SwPaM
*)pTmp
->GetNext() ))
2338 for( int i
= 0; i
< 2; ++i
)
2339 pTmp
->GetBound( (BOOL
)i
) = *rPam
.GetPoint();
2342 // dann fuege sie zusammen
2343 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
2344 aMsgHnt
.eFlags
= TBL_BOXPTR
;
2345 UpdateTblFlds( &aMsgHnt
);
2347 if( pTblNd
->GetTable().Merge( this, aBoxes
, aMerged
, pMergeBox
, pUndo
))
2351 SetFieldsDirty( true, NULL
, 0 );
2353 AppendUndo( pUndo
);
2358 rPam
.GetPoint()->nNode
= *pMergeBox
->GetSttNd();
2361 ::ClearFEShellTabCols();
2362 SetRedlineMode_intern( eOld
);
2364 EndUndo( UNDO_TABLE_MERGE
, NULL
);
2370 // -------------------------------------------------------
2376 SwTableNode::SwTableNode( const SwNodeIndex
& rIdx
)
2377 : SwStartNode( rIdx
, ND_TABLENODE
)
2379 pTable
= new SwTable( 0 );
2382 SwTableNode::~SwTableNode()
2384 //don't forget to notify uno wrappers
2385 SwFrmFmt
* pTblFmt
= GetTable().GetFrmFmt();
2386 SwPtrMsgPoolItem
aMsgHint( RES_REMOVE_UNO_OBJECT
,
2388 pTblFmt
->Modify( &aMsgHint
, &aMsgHint
);
2393 SwTabFrm
*SwTableNode::MakeFrm()
2395 return new SwTabFrm( *pTable
);
2398 //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
2399 //Dokument. Die erzeugten Contentframes werden in das entsprechende
2401 void SwTableNode::MakeFrms(const SwNodeIndex
& rIdx
)
2403 if( !GetTable().GetFrmFmt()->GetDepends())//gibt es ueberhaupt Frames ??
2407 SwCntntNode
* pNode
= rIdx
.GetNode().GetCntntNode();
2409 ASSERT( pNode
, "Kein Contentnode oder Copy-Node und neuer Node identisch.");
2411 BOOL bBefore
= rIdx
< GetIndex();
2413 SwNode2Layout
aNode2Layout( *this, rIdx
.GetIndex() );
2415 while( 0 != (pFrm
= aNode2Layout
.NextFrm()) )
2417 pNew
= pNode
->MakeFrm();
2418 // wird ein Node vorher oder nachher mit Frames versehen
2420 // der neue liegt vor mir
2421 pNew
->Paste( pFrm
->GetUpper(), pFrm
);
2423 // der neue liegt hinter mir
2424 pNew
->Paste( pFrm
->GetUpper(), pFrm
->GetNext() );
2428 //Fuer jede Shell einen TblFrm anlegen und vor den entsprechenden
2431 void SwTableNode::MakeFrms( SwNodeIndex
* pIdxBehind
)
2433 ASSERT( pIdxBehind
, "kein Index" );
2434 *pIdxBehind
= *this;
2435 SwNode
*pNd
= GetNodes().FindPrvNxtFrmNode( *pIdxBehind
, EndOfSectionNode() );
2440 SwLayoutFrm
*pUpper( 0L );
2441 SwNode2Layout
aNode2Layout( *pNd
, GetIndex() );
2442 while( 0 != (pUpper
= aNode2Layout
.UpperFrm( pFrm
, *this )) )
2444 SwTabFrm
* pNew
= MakeFrm();
2445 pNew
->Paste( pUpper
, pFrm
);
2446 // --> OD 2005-12-01 #i27138#
2447 // notify accessibility paragraphs objects about changed
2448 // CONTENT_FLOWS_FROM/_TO relation.
2449 // Relation CONTENT_FLOWS_FROM for next paragraph will change
2450 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2452 ViewShell
* pViewShell( pNew
->GetShell() );
2453 if ( pViewShell
&& pViewShell
->GetLayout() &&
2454 pViewShell
->GetLayout()->IsAnyShellAccessible() )
2456 pViewShell
->InvalidateAccessibleParaFlowRelation(
2457 dynamic_cast<SwTxtFrm
*>(pNew
->FindNextCnt( true )),
2458 dynamic_cast<SwTxtFrm
*>(pNew
->FindPrevCnt( true )) );
2462 ((SwTabFrm
*)pNew
)->RegistFlys();
2466 void SwTableNode::DelFrms()
2468 //Erstmal die TabFrms ausschneiden und deleten, die Columns und Rows
2469 //nehmen sie mit in's Grab.
2470 //Die TabFrms haengen am FrmFmt des SwTable.
2471 //Sie muessen etwas umstaendlich zerstort werden, damit die Master
2472 //die Follows mit in's Grab nehmen.
2474 SwClientIter
aIter( *(pTable
->GetFrmFmt()) );
2475 SwClient
*pLast
= aIter
.GoStart();
2478 BOOL bAgain
= FALSE
;
2479 if ( pLast
->IsA( TYPE(SwFrm
) ) )
2481 SwTabFrm
*pFrm
= (SwTabFrm
*)pLast
;
2482 if ( !pFrm
->IsFollow() )
2484 while ( pFrm
->HasFollow() )
2485 pFrm
->JoinAndDelFollows();
2486 // --> OD 2005-12-01 #i27138#
2487 // notify accessibility paragraphs objects about changed
2488 // CONTENT_FLOWS_FROM/_TO relation.
2489 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2490 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2492 ViewShell
* pViewShell( pFrm
->GetShell() );
2493 if ( pViewShell
&& pViewShell
->GetLayout() &&
2494 pViewShell
->GetLayout()->IsAnyShellAccessible() )
2496 pViewShell
->InvalidateAccessibleParaFlowRelation(
2497 dynamic_cast<SwTxtFrm
*>(pFrm
->FindNextCnt( true )),
2498 dynamic_cast<SwTxtFrm
*>(pFrm
->FindPrevCnt( true )) );
2507 pLast
= bAgain
? aIter
.GoStart() : aIter
++;
2512 void SwTableNode::SetNewTable( SwTable
* pNewTable
, BOOL bNewFrames
)
2519 SwNodeIndex
aIdx( *EndOfSectionNode());
2520 GetNodes().GoNext( &aIdx
);
2525 void SwDoc::GetTabCols( SwTabCols
&rFill
, const SwCursor
* pCrsr
,
2526 const SwCellFrm
* pBoxFrm
) const
2528 const SwTableBox
* pBox
= 0;
2533 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2534 pBox
= pBoxFrm
->GetTabBox();
2538 const SwCntntNode
* pCNd
= pCrsr
->GetCntntNode();
2543 const SwShellCrsr
*pShCrsr
= dynamic_cast<const SwShellCrsr
*>(pCrsr
);
2545 aPt
= pShCrsr
->GetPtPos();
2547 const SwFrm
* pTmpFrm
= pCNd
->GetFrm( &aPt
, 0, FALSE
);
2549 pTmpFrm
= pTmpFrm
->GetUpper();
2550 } while ( !pTmpFrm
->IsCellFrm() );
2552 pBoxFrm
= (SwCellFrm
*)pTmpFrm
;
2553 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2554 pBox
= pBoxFrm
->GetTabBox();
2556 else if( !pCrsr
&& !pBoxFrm
)
2558 ASSERT( !this, "einer von beiden muss angegeben werden!" );
2562 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2564 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2565 const ULONG nLeftMin
= (pTab
->Frm().*fnRect
->fnGetLeft
)() -
2566 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2567 const ULONG nRightMax
= (pTab
->Frm().*fnRect
->fnGetRight
)() -
2568 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2570 rFill
.SetLeftMin ( nLeftMin
);
2571 rFill
.SetLeft ( (pTab
->Prt().*fnRect
->fnGetLeft
)() );
2572 rFill
.SetRight ( (pTab
->Prt().*fnRect
->fnGetRight
)());
2573 rFill
.SetRightMax( nRightMax
- nLeftMin
);
2575 pTab
->GetTable()->GetTabCols( rFill
, pBox
);
2579 // Here are some little helpers used in SwDoc::GetTabRows
2586 bool operator() ( long s1
, long s2
) const;
2589 bool FuzzyCompare::operator() ( long s1
, long s2
) const
2591 return ( s1
< s2
&& abs( s1
- s2
) > ROWFUZZY
);
2594 bool lcl_IsFrmInColumn( const SwCellFrm
& rFrm
, SwSelBoxes
& rBoxes
)
2596 for( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
2598 if ( rFrm
.GetTabBox() == rBoxes
[ i
] )
2606 // SwDoc::GetTabRows()
2609 void SwDoc::GetTabRows( SwTabCols
&rFill
, const SwCursor
* ,
2610 const SwCellFrm
* pBoxFrm
) const
2612 ASSERT( pBoxFrm
, "GetTabRows called without pBoxFrm" )
2614 // --> FME 2005-09-12 #121591# Make code robust:
2619 // --> FME 2005-01-06 #i39552# Collection of the boxes of the current
2620 // column has to be done at the beginning of this function, because
2621 // the table may be formatted in ::GetTblSel.
2622 SwDeletionChecker
aDelCheck( pBoxFrm
);
2625 const SwCntntFrm
* pCntnt
= ::GetCellCntnt( *pBoxFrm
);
2626 if ( pCntnt
&& pCntnt
->IsTxtFrm() )
2628 const SwPosition
aPos( *((SwTxtFrm
*)pCntnt
)->GetTxtNode() );
2629 const SwCursor
aTmpCrsr( aPos
, 0, false );
2630 ::GetTblSel( aTmpCrsr
, aBoxes
, nsSwTblSearchType::TBLSEARCH_COL
);
2634 // --> FME 2005-09-12 #121591# Make code robust:
2635 if ( aDelCheck
.HasBeenDeleted() )
2637 ASSERT( false, "Current box has been deleted during GetTabRows()" )
2642 // --> FME 2005-09-12 #121591# Make code robust:
2643 const SwTabFrm
* pTab
= pBoxFrm
->FindTabFrm();
2644 ASSERT( pTab
, "GetTabRows called without a table" )
2649 const SwFrm
* pFrm
= pTab
->GetNextLayoutLeaf();
2651 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2653 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2654 const long nLeftMin
= ( bVert
?
2655 pTab
->GetPrtLeft() - pPage
->Frm().Left() :
2656 pTab
->GetPrtTop() - pPage
->Frm().Top() );
2657 const long nLeft
= bVert
? LONG_MAX
: 0;
2658 const long nRight
= (pTab
->Prt().*fnRect
->fnGetHeight
)();
2659 const long nRightMax
= bVert
? nRight
: LONG_MAX
;
2661 rFill
.SetLeftMin( nLeftMin
);
2662 rFill
.SetLeft( nLeft
);
2663 rFill
.SetRight( nRight
);
2664 rFill
.SetRightMax( nRightMax
);
2666 typedef std::map
< long, std::pair
< long, long >, FuzzyCompare
> BoundaryMap
;
2667 BoundaryMap aBoundaries
;
2668 BoundaryMap::iterator aIter
;
2669 std::pair
< long, long > aPair
;
2671 typedef std::map
< long, bool > HiddenMap
;
2673 HiddenMap::iterator aHiddenIter
;
2675 while ( pFrm
&& pTab
->IsAnLower( pFrm
) )
2677 if ( pFrm
->IsCellFrm() && pFrm
->FindTabFrm() == pTab
)
2679 // upper and lower borders of current cell frame:
2680 long nUpperBorder
= (pFrm
->Frm().*fnRect
->fnGetTop
)();
2681 long nLowerBorder
= (pFrm
->Frm().*fnRect
->fnGetBottom
)();
2683 // get boundaries for nUpperBorder:
2684 aIter
= aBoundaries
.find( nUpperBorder
);
2685 if ( aIter
== aBoundaries
.end() )
2687 aPair
.first
= nUpperBorder
; aPair
.second
= LONG_MAX
;
2688 aBoundaries
[ nUpperBorder
] = aPair
;
2691 // get boundaries for nLowerBorder:
2692 aIter
= aBoundaries
.find( nLowerBorder
);
2693 if ( aIter
== aBoundaries
.end() )
2695 aPair
.first
= nUpperBorder
; aPair
.second
= LONG_MAX
;
2699 nLowerBorder
= (*aIter
).first
;
2700 long nNewLowerBorderUpperBoundary
= Max( (*aIter
).second
.first
, nUpperBorder
);
2701 aPair
.first
= nNewLowerBorderUpperBoundary
; aPair
.second
= LONG_MAX
;
2703 aBoundaries
[ nLowerBorder
] = aPair
;
2705 // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2706 long nTmpVal
= nUpperBorder
;
2707 for ( BYTE i
= 0; i
< 2; ++i
)
2709 aHiddenIter
= aHidden
.find( nTmpVal
);
2710 if ( aHiddenIter
== aHidden
.end() )
2711 aHidden
[ nTmpVal
] = !lcl_IsFrmInColumn( *((SwCellFrm
*)pFrm
), aBoxes
);
2714 if ( aHidden
[ nTmpVal
] &&
2715 lcl_IsFrmInColumn( *((SwCellFrm
*)pFrm
), aBoxes
) )
2716 aHidden
[ nTmpVal
] = false;
2718 nTmpVal
= nLowerBorder
;
2722 pFrm
= pFrm
->GetNextLayoutLeaf();
2725 // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2727 for ( aIter
= aBoundaries
.begin(); aIter
!= aBoundaries
.end(); ++aIter
)
2729 const long nTabTop
= (pTab
->*fnRect
->fnGetPrtTop
)();
2730 const long nKey
= (*fnRect
->fnYDiff
)( (*aIter
).first
, nTabTop
);
2731 const std::pair
< long, long > aTmpPair
= (*aIter
).second
;
2732 const long nFirst
= (*fnRect
->fnYDiff
)( aTmpPair
.first
, nTabTop
);
2733 const long nSecond
= aTmpPair
.second
;
2735 aHiddenIter
= aHidden
.find( (*aIter
).first
);
2736 const bool bHidden
= aHiddenIter
!= aHidden
.end() && (*aHiddenIter
).second
;
2737 rFill
.Insert( nKey
, nFirst
, nSecond
, bHidden
, nIdx
++ );
2740 // delete first and last entry
2741 ASSERT( rFill
.Count(), "Deleting from empty vector. Fasten your seatbelts!" )
2742 // --> FME 2006-01-19 #i60818# There may be only one entry in rFill. Make
2743 // code robust by checking count of rFill.
2744 if ( rFill
.Count() ) rFill
.Remove( 0, 1 );
2745 if ( rFill
.Count() ) rFill
.Remove( rFill
.Count() - 1 , 1 );
2747 rFill
.SetLastRowAllowedToChange( !pTab
->HasFollowFlowLine() );
2750 void SwDoc::SetTabCols( const SwTabCols
&rNew
, BOOL bCurRowOnly
,
2751 const SwCursor
* pCrsr
, const SwCellFrm
* pBoxFrm
)
2753 const SwTableBox
* pBox
= 0;
2758 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2759 pBox
= pBoxFrm
->GetTabBox();
2763 const SwCntntNode
* pCNd
= pCrsr
->GetCntntNode();
2768 const SwShellCrsr
*pShCrsr
= dynamic_cast<const SwShellCrsr
*>(pCrsr
);
2770 aPt
= pShCrsr
->GetPtPos();
2772 const SwFrm
* pTmpFrm
= pCNd
->GetFrm( &aPt
, 0, FALSE
);
2774 pTmpFrm
= pTmpFrm
->GetUpper();
2775 } while ( !pTmpFrm
->IsCellFrm() );
2777 pBoxFrm
= (SwCellFrm
*)pTmpFrm
;
2778 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2779 pBox
= pBoxFrm
->GetTabBox();
2781 else if( !pCrsr
&& !pBoxFrm
)
2783 ASSERT( !this, "einer von beiden muss angegeben werden!" );
2787 // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2788 // dann muss es jetzt auf absolute umgerechnet werden.
2789 SwTable
& rTab
= *pTab
->GetTable();
2790 const SwFmtFrmSize
& rTblFrmSz
= rTab
.GetFrmFmt()->GetFrmSize();
2792 // OD 06.08.2003 #i17174# - With fix for #i9040# the shadow size is taken
2793 // from the table width. Thus, add its left and right size to current table
2794 // printing area width in order to get the correct table size attribute.
2795 SwTwips nPrtWidth
= (pTab
->Prt().*fnRect
->fnGetWidth
)();
2797 SvxShadowItem
aShadow( rTab
.GetFrmFmt()->GetShadow() );
2798 nPrtWidth
+= aShadow
.CalcShadowSpace( SHADOW_LEFT
) +
2799 aShadow
.CalcShadowSpace( SHADOW_RIGHT
);
2801 if( nPrtWidth
!= rTblFrmSz
.GetWidth() )
2803 SwFmtFrmSize
aSz( rTblFrmSz
);
2804 aSz
.SetWidth( nPrtWidth
);
2805 rTab
.GetFrmFmt()->SetFmtAttr( aSz
);
2808 SwTabCols
aOld( rNew
.Count() );
2810 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2811 const ULONG nLeftMin
= (pTab
->Frm().*fnRect
->fnGetLeft
)() -
2812 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2813 const ULONG nRightMax
= (pTab
->Frm().*fnRect
->fnGetRight
)() -
2814 (pPage
->Frm().*fnRect
->fnGetLeft
)();
2816 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2817 aOld
.SetLeftMin ( nLeftMin
);
2818 aOld
.SetLeft ( (pTab
->Prt().*fnRect
->fnGetLeft
)() );
2819 aOld
.SetRight ( (pTab
->Prt().*fnRect
->fnGetRight
)());
2820 aOld
.SetRightMax( nRightMax
- nLeftMin
);
2822 rTab
.GetTabCols( aOld
, pBox
);
2823 SetTabCols(rTab
, rNew
, aOld
, pBox
, bCurRowOnly
);
2826 void SwDoc::SetTabRows( const SwTabCols
&rNew
, BOOL bCurColOnly
, const SwCursor
*,
2827 const SwCellFrm
* pBoxFrm
)
2829 const SwTableBox
* pBox
;
2832 ASSERT( pBoxFrm
, "SetTabRows called without pBoxFrm" )
2834 pTab
= ((SwFrm
*)pBoxFrm
)->ImplFindTabFrm();
2835 pBox
= pBoxFrm
->GetTabBox();
2837 // sollte die Tabelle noch auf relativen Werten (USHRT_MAX) stehen
2838 // dann muss es jetzt auf absolute umgerechnet werden.
2840 SwTabCols
aOld( rNew
.Count() );
2842 //Fix-Punkte setzen, LeftMin in Dokumentkoordinaten die anderen relativ.
2843 const SwPageFrm
* pPage
= pTab
->FindPageFrm();
2845 aOld
.SetRight( (pTab
->Prt().*fnRect
->fnGetHeight
)() );
2849 nLeftMin
= pTab
->GetPrtLeft() - pPage
->Frm().Left();
2850 aOld
.SetLeft ( LONG_MAX
);
2851 aOld
.SetRightMax( aOld
.GetRight() );
2856 nLeftMin
= pTab
->GetPrtTop() - pPage
->Frm().Top();
2858 aOld
.SetRightMax( LONG_MAX
);
2860 aOld
.SetLeftMin ( nLeftMin
);
2862 GetTabRows( aOld
, 0, pBoxFrm
);
2864 StartUndo( UNDO_TABLE_ATTR
, NULL
);
2866 // check for differences between aOld and rNew:
2867 const USHORT nCount
= rNew
.Count();
2868 const SwTable
* pTable
= pTab
->GetTable();
2869 ASSERT( pTable
, "My colleague told me, this couldn't happen" );
2871 for ( USHORT i
= 0; i
<= nCount
; ++i
)
2873 const USHORT nIdxStt
= bVert
? nCount
- i
: i
- 1;
2874 const USHORT nIdxEnd
= bVert
? nCount
- i
- 1 : i
;
2876 const long nOldRowStart
= i
== 0 ? 0 : aOld
[ nIdxStt
];
2877 const long nOldRowEnd
= i
== nCount
? aOld
.GetRight() : aOld
[ nIdxEnd
];
2878 const long nOldRowHeight
= nOldRowEnd
- nOldRowStart
;
2880 const long nNewRowStart
= i
== 0 ? 0 : rNew
[ nIdxStt
];
2881 const long nNewRowEnd
= i
== nCount
? rNew
.GetRight() : rNew
[ nIdxEnd
];
2882 const long nNewRowHeight
= nNewRowEnd
- nNewRowStart
;
2884 const long nDiff
= nNewRowHeight
- nOldRowHeight
;
2885 if ( abs( nDiff
) >= ROWFUZZY
)
2887 // For the old table model pTxtFrm and pLine will be set for every box.
2888 // For the new table model pTxtFrm will be set if the box is not covered,
2889 // but the pLine will be set if the box is not an overlapping box
2890 // In the new table model the row height can be adjusted,
2891 // when both variables are set.
2892 SwTxtFrm
* pTxtFrm
= 0;
2893 const SwTableLine
* pLine
= 0;
2895 // Iterate over all SwCellFrms with Bottom = nOldPos
2896 const SwFrm
* pFrm
= pTab
->GetNextLayoutLeaf();
2897 while ( pFrm
&& pTab
->IsAnLower( pFrm
) )
2899 if ( pFrm
->IsCellFrm() && pFrm
->FindTabFrm() == pTab
)
2901 const long nLowerBorder
= (pFrm
->Frm().*fnRect
->fnGetBottom
)();
2902 const ULONG nTabTop
= (pTab
->*fnRect
->fnGetPrtTop
)();
2903 if ( abs( (*fnRect
->fnYInc
)( nTabTop
, nOldRowEnd
) - nLowerBorder
) <= ROWFUZZY
)
2905 if ( !bCurColOnly
|| pFrm
== pBoxFrm
)
2907 const SwFrm
* pCntnt
= ::GetCellCntnt( static_cast<const SwCellFrm
&>(*pFrm
) );
2909 if ( pCntnt
&& pCntnt
->IsTxtFrm() )
2911 pBox
= ((SwCellFrm
*)pFrm
)->GetTabBox();
2912 const long nRowSpan
= pBox
->getRowSpan();
2913 if( nRowSpan
> 0 ) // Not overlapped
2914 pTxtFrm
= (SwTxtFrm
*)pCntnt
;
2915 if( nRowSpan
< 2 ) // Not overlapping for row height
2916 pLine
= pBox
->GetUpper();
2917 if( pLine
&& pTxtFrm
) // always for old table model
2919 // The new row height must not to be calculated from a overlapping box
2920 SwFmtFrmSize
aNew( pLine
->GetFrmFmt()->GetFrmSize() );
2921 const long nNewSize
= (pFrm
->Frm().*fnRect
->fnGetHeight
)() + nDiff
;
2922 if( nNewSize
!= aNew
.GetHeight() )
2924 aNew
.SetHeight( nNewSize
);
2925 if ( ATT_VAR_SIZE
== aNew
.GetHeightSizeType() )
2926 aNew
.SetHeightSizeType( ATT_MIN_SIZE
);
2927 // This position must not be in an overlapped box
2928 const SwPosition
aPos( *((SwTxtFrm
*)pCntnt
)->GetTxtNode() );
2929 const SwCursor
aTmpCrsr( aPos
, 0, false );
2930 SetRowHeight( aTmpCrsr
, aNew
);
2931 // For the new table model we're done, for the old one
2932 // there might be another (sub)row to adjust...
2933 if( pTable
->IsNewModel() )
2942 pFrm
= pFrm
->GetNextLayoutLeaf();
2947 EndUndo( UNDO_TABLE_ATTR
, NULL
);
2949 ::ClearFEShellTabCols();
2952 /* -----------------18.07.98 11:45-------------------
2953 * Direktzugriff fuer UNO
2954 * --------------------------------------------------*/
2955 void SwDoc::SetTabCols(SwTable
& rTab
, const SwTabCols
&rNew
, const SwTabCols
&rOld
,
2956 const SwTableBox
*pStart
, BOOL bCurRowOnly
)
2961 AppendUndo( new SwUndoAttrTbl( *rTab
.GetTableNode(), TRUE
));
2963 rTab
.SetTabCols( rNew
, rOld
, pStart
, bCurRowOnly
);
2964 ::ClearFEShellTabCols();
2968 void SwDoc::SetRowsToRepeat( SwTable
&rTable
, USHORT nSet
)
2970 if( nSet
== rTable
.GetRowsToRepeat() )
2976 AppendUndo( new SwUndoTblHeadline( rTable
, rTable
.GetRowsToRepeat() , nSet
) );
2979 SwMsgPoolItem
aChg( RES_TBLHEADLINECHG
);
2980 rTable
.SetRowsToRepeat( nSet
);
2981 rTable
.GetFrmFmt()->Modify( &aChg
, &aChg
);
2988 // Splittet eine Tabelle in der Grund-Zeile, in der der Index steht.
2989 // Alle GrundZeilen dahinter wandern in eine neue Tabelle/-Node.
2990 // Ist das Flag bCalcNewSize auf TRUE, wird fuer beide neuen Tabellen
2991 // die neue Size aus dem Max der Boxen errechnet; vorrausgesetzt,
2992 // die Size ist "absolut" gesetzt (USHRT_MAX)
2994 void SwCollectTblLineBoxes::AddToUndoHistory( const SwCntntNode
& rNd
)
2997 pHst
->Add( rNd
.GetFmtColl(), rNd
.GetIndex(), ND_TEXTNODE
);
3000 void SwCollectTblLineBoxes::AddBox( const SwTableBox
& rBox
)
3002 aPosArr
.Insert( nWidth
, aPosArr
.Count() );
3003 SwTableBox
* p
= (SwTableBox
*)&rBox
;
3004 aBoxes
.Insert( p
, aBoxes
.Count() );
3005 nWidth
= nWidth
+ (USHORT
)rBox
.GetFrmFmt()->GetFrmSize().GetWidth();
3008 const SwTableBox
* SwCollectTblLineBoxes::GetBoxOfPos( const SwTableBox
& rBox
)
3010 const SwTableBox
* pRet
= 0;
3013 if( aPosArr
.Count() )
3015 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3016 if( aPosArr
[ n
] == nWidth
)
3018 else if( aPosArr
[ n
] > nWidth
)
3025 if( n
>= aPosArr
.Count() )
3028 nWidth
= nWidth
+ (USHORT
)rBox
.GetFrmFmt()->GetFrmSize().GetWidth();
3034 BOOL
SwCollectTblLineBoxes::Resize( USHORT nOffset
, USHORT nOldWidth
)
3038 if( aPosArr
.Count() )
3040 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3041 if( aPosArr
[ n
] == nOffset
)
3043 else if( aPosArr
[ n
] > nOffset
)
3050 aPosArr
.Remove( 0, n
);
3051 aBoxes
.Remove( 0, n
);
3053 // dann die Positionen der neuen Size anpassen
3054 for( n
= 0; n
< aPosArr
.Count(); ++n
)
3056 ULONG nSize
= nWidth
;
3057 nSize
*= ( aPosArr
[ n
] - nOffset
);
3059 aPosArr
[ n
] = USHORT( nSize
);
3062 return 0 != aPosArr
.Count();
3065 BOOL
lcl_Line_CollectBox( const SwTableLine
*& rpLine
, void* pPara
)
3067 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3068 if( pSplPara
->IsGetValues() )
3069 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, pPara
);
3071 ((SwTableLine
*)rpLine
)->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, pPara
);
3075 BOOL
lcl_Box_CollectBox( const SwTableBox
*& rpBox
, void* pPara
)
3077 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3078 USHORT nLen
= rpBox
->GetTabLines().Count();
3081 // dann mit der richtigen Line weitermachen
3082 if( pSplPara
->IsGetFromTop() )
3087 const SwTableLine
* pLn
= rpBox
->GetTabLines()[ nLen
];
3088 lcl_Line_CollectBox( pLn
, pPara
);
3091 pSplPara
->AddBox( *rpBox
);
3095 BOOL
lcl_BoxSetSplitBoxFmts( const SwTableBox
*& rpBox
, void* pPara
)
3097 SwCollectTblLineBoxes
* pSplPara
= (SwCollectTblLineBoxes
*)pPara
;
3098 USHORT nLen
= rpBox
->GetTabLines().Count();
3101 // dann mit der richtigen Line weitermachen
3102 if( pSplPara
->IsGetFromTop() )
3107 const SwTableLine
* pLn
= rpBox
->GetTabLines()[ nLen
];
3108 lcl_Line_CollectBox( pLn
, pPara
);
3112 const SwTableBox
* pSrcBox
= pSplPara
->GetBoxOfPos( *rpBox
);
3113 SwFrmFmt
* pFmt
= pSrcBox
->GetFrmFmt();
3114 SwTableBox
* pBox
= (SwTableBox
*)rpBox
;
3116 if( HEADLINE_BORDERCOPY
== pSplPara
->GetMode() )
3118 const SvxBoxItem
& rBoxItem
= pBox
->GetFrmFmt()->GetBox();
3119 if( !rBoxItem
.GetTop() )
3121 SvxBoxItem
aNew( rBoxItem
);
3122 aNew
.SetLine( pFmt
->GetBox().GetBottom(), BOX_LINE_TOP
);
3123 if( aNew
!= rBoxItem
)
3124 pBox
->ClaimFrmFmt()->SetFmtAttr( aNew
);
3129 USHORT __FAR_DATA aTableSplitBoxSetRange
[] = {
3130 RES_LR_SPACE
, RES_UL_SPACE
,
3131 RES_BACKGROUND
, RES_SHADOW
,
3132 RES_PROTECT
, RES_PROTECT
,
3133 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
3135 SfxItemSet
aTmpSet( pFmt
->GetDoc()->GetAttrPool(),
3136 aTableSplitBoxSetRange
);
3137 aTmpSet
.Put( pFmt
->GetAttrSet() );
3138 if( aTmpSet
.Count() )
3139 pBox
->ClaimFrmFmt()->SetFmtAttr( aTmpSet
);
3141 if( HEADLINE_BOXATRCOLLCOPY
== pSplPara
->GetMode() )
3143 SwNodeIndex
aIdx( *pSrcBox
->GetSttNd(), 1 );
3144 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
3146 pCNd
= aIdx
.GetNodes().GoNext( &aIdx
);
3147 aIdx
= *pBox
->GetSttNd();
3148 SwCntntNode
* pDNd
= aIdx
.GetNodes().GoNext( &aIdx
);
3150 // nur wenn der Node alleine in der Section steht
3151 if( 2 == pDNd
->EndOfSectionIndex() -
3152 pDNd
->StartOfSectionIndex() )
3154 pSplPara
->AddToUndoHistory( *pDNd
);
3155 pDNd
->ChgFmtColl( pCNd
->GetFmtColl() );
3159 // bedingte Vorlage beachten
3160 pBox
->GetSttNd()->CheckSectionCondColl();
3167 BOOL
SwDoc::SplitTable( const SwPosition
& rPos
, USHORT eHdlnMode
,
3170 SwNode
* pNd
= &rPos
.nNode
.GetNode();
3171 SwTableNode
* pTNd
= pNd
->FindTableNode();
3172 if( !pTNd
|| pNd
->IsTableNode() )
3175 if( pTNd
->GetTable().ISA( SwDDETable
))
3178 SwTable
& rTbl
= pTNd
->GetTable();
3179 rTbl
.SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
3181 SwTableFmlUpdate
aMsgHnt( &rTbl
);
3185 aMsgHnt
.pHistory
= &aHistory
;
3188 ULONG nSttIdx
= pNd
->FindTableBoxStartNode()->GetIndex();
3190 // Suche die Grund-Line dieser Box:
3191 SwTableBox
* pBox
= rTbl
.GetTblBox( nSttIdx
);
3194 SwTableLine
* pLine
= pBox
->GetUpper();
3195 while( pLine
->GetUpper() )
3196 pLine
= pLine
->GetUpper()->GetUpper();
3198 // in pLine steht jetzt die GrundLine.
3199 aMsgHnt
.nSplitLine
= rTbl
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
3202 String
sNewTblNm( GetUniqueTblName() );
3203 aMsgHnt
.DATA
.pNewTblNm
= &sNewTblNm
;
3204 aMsgHnt
.eFlags
= TBL_SPLITTBL
;
3205 UpdateTblFlds( &aMsgHnt
);
3208 //Lines fuer das Layout-Update heraussuchen.
3209 _FndBox
aFndBox( 0, 0 );
3210 aFndBox
.SetTableLines( rTbl
);
3211 aFndBox
.DelFrms( rTbl
);
3213 // TL_CHART2: need to inform chart of probably changed cell names
3214 //pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3216 SwTableNode
* pNew
= GetNodes().SplitTable( rPos
.nNode
, FALSE
, bCalcNewSize
);
3220 SwSaveRowSpan
* pSaveRowSp
= pNew
->GetTable().CleanUpTopRowSpan( rTbl
.GetTabLines().Count() );
3221 SwUndoSplitTbl
* pUndo
= 0;
3225 AppendUndo( pUndo
= new SwUndoSplitTbl( *pNew
, pSaveRowSp
, eHdlnMode
, bCalcNewSize
));
3226 if( aHistory
.Count() )
3227 pUndo
->SaveFormula( aHistory
);
3232 // setze die untere Border der vorherige Line,
3233 // an der aktuellen als obere
3234 case HEADLINE_BORDERCOPY
:
3236 SwCollectTblLineBoxes
aPara( FALSE
, eHdlnMode
);
3237 SwTableLine
* pLn
= rTbl
.GetTabLines()[
3238 rTbl
.GetTabLines().Count() - 1 ];
3239 pLn
->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, &aPara
);
3241 aPara
.SetValues( TRUE
);
3242 pLn
= pNew
->GetTable().GetTabLines()[ 0 ];
3243 pLn
->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, &aPara
);
3245 // Kopfzeile wiederholen abschalten
3246 pNew
->GetTable().SetRowsToRepeat( 0 );
3250 // setze die Attributierung der ersten Line an der neuen ersten
3251 case HEADLINE_BOXATTRCOPY
:
3252 case HEADLINE_BOXATRCOLLCOPY
:
3254 SwHistory
* pHst
= 0;
3255 if( HEADLINE_BOXATRCOLLCOPY
== eHdlnMode
&& pUndo
)
3256 pHst
= pUndo
->GetHistory();
3258 SwCollectTblLineBoxes
aPara( TRUE
, eHdlnMode
, pHst
);
3259 SwTableLine
* pLn
= rTbl
.GetTabLines()[ 0 ];
3260 pLn
->GetTabBoxes().ForEach( &lcl_Box_CollectBox
, &aPara
);
3262 aPara
.SetValues( TRUE
);
3263 pLn
= pNew
->GetTable().GetTabLines()[ 0 ];
3264 pLn
->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts
, &aPara
);
3268 case HEADLINE_CNTNTCOPY
:
3269 rTbl
.CopyHeadlineIntoTable( *pNew
);
3271 pUndo
->SetTblNodeOffset( pNew
->GetIndex() );
3275 // Kopfzeile wiederholen abschalten
3276 pNew
->GetTable().SetRowsToRepeat( 0 );
3280 // und Frms einfuegen.
3281 SwNodeIndex
aNdIdx( *pNew
->EndOfSectionNode() );
3282 GetNodes().GoNext( &aNdIdx
); // zum naechsten ContentNode
3283 pNew
->MakeFrms( &aNdIdx
);
3285 //Zwischen die Tabellen wird ein Absatz geschoben
3286 GetNodes().MakeTxtNode( SwNodeIndex( *pNew
),
3287 GetTxtCollFromPool( RES_POOLCOLL_TEXT
) );
3291 aFndBox
.MakeFrms( rTbl
);
3293 // TL_CHART2: need to inform chart of probably changed cell names
3294 UpdateCharts( rTbl
.GetFrmFmt()->GetName() );
3296 SetFieldsDirty( true, NULL
, 0 );
3301 BOOL
lcl_ChgTblSize( SwTable
& rTbl
)
3303 // das Attribut darf nicht ueber das Modify an der
3304 // Tabelle gesetzt werden, denn sonst werden alle
3305 // Boxen wieder auf 0 zurueck gesetzt. Also locke das Format
3306 SwFrmFmt
* pFmt
= rTbl
.GetFrmFmt();
3307 SwFmtFrmSize
aTblMaxSz( pFmt
->GetFrmSize() );
3309 if( USHRT_MAX
== aTblMaxSz
.GetWidth() )
3312 BOOL bLocked
= pFmt
->IsModifyLocked();
3315 aTblMaxSz
.SetWidth( 0 );
3317 SwTableLines
& rLns
= rTbl
.GetTabLines();
3318 for( USHORT nLns
= 0; nLns
< rLns
.Count(); ++nLns
)
3320 SwTwips nMaxLnWidth
= 0;
3321 SwTableBoxes
& rBoxes
= rLns
[ nLns
]->GetTabBoxes();
3322 for( USHORT nBox
= 0; nBox
< rBoxes
.Count(); ++nBox
)
3323 nMaxLnWidth
+= rBoxes
[nBox
]->GetFrmFmt()->GetFrmSize().GetWidth();
3325 if( nMaxLnWidth
> aTblMaxSz
.GetWidth() )
3326 aTblMaxSz
.SetWidth( nMaxLnWidth
);
3328 pFmt
->SetFmtAttr( aTblMaxSz
);
3329 if( !bLocked
) // und gegebenenfalls Lock wieder freigeben
3330 pFmt
->UnlockModify();
3335 class _SplitTable_Para
3337 SvPtrarr aSrc
, aDest
;
3338 SwTableNode
* pNewTblNd
;
3342 _SplitTable_Para( SwTableNode
* pNew
, SwTable
& rOld
)
3343 : aSrc( 16, 16 ), aDest( 16, 16 ), pNewTblNd( pNew
), rOldTbl( rOld
)
3345 USHORT
SrcFmt_GetPos( void* pFmt
) const
3346 { return aSrc
.GetPos( pFmt
); }
3348 void DestFmt_Insert( void* pFmt
)
3349 { aDest
.Insert( pFmt
, aDest
.Count() ); }
3351 void SrcFmt_Insert( void* pFmt
)
3352 { aSrc
.Insert( pFmt
, aSrc
.Count() ); }
3354 SwFrmFmt
* DestFmt_Get( USHORT nPos
) const
3355 { return (SwFrmFmt
*)aDest
[ nPos
]; }
3357 void ChgBox( SwTableBox
* pBox
)
3359 rOldTbl
.GetTabSortBoxes().Remove( pBox
);
3360 pNewTblNd
->GetTable().GetTabSortBoxes().Insert( pBox
);
3365 BOOL
lcl_SplitTable_CpyBox( const SwTableBox
*& rpBox
, void* pPara
);
3367 BOOL
lcl_SplitTable_CpyLine( const SwTableLine
*& rpLine
, void* pPara
)
3369 SwTableLine
* pLn
= (SwTableLine
*)rpLine
;
3370 _SplitTable_Para
& rPara
= *(_SplitTable_Para
*)pPara
;
3372 SwFrmFmt
*pSrcFmt
= pLn
->GetFrmFmt();
3373 USHORT nPos
= rPara
.SrcFmt_GetPos( pSrcFmt
);
3374 if( USHRT_MAX
== nPos
)
3376 rPara
.DestFmt_Insert( pLn
->ClaimFrmFmt() );
3377 rPara
.SrcFmt_Insert( pSrcFmt
);
3380 pLn
->ChgFrmFmt( (SwTableLineFmt
*)rPara
.DestFmt_Get( nPos
) );
3382 pLn
->GetTabBoxes().ForEach( &lcl_SplitTable_CpyBox
, pPara
);
3386 BOOL
lcl_SplitTable_CpyBox( const SwTableBox
*& rpBox
, void* pPara
)
3388 SwTableBox
* pBox
= (SwTableBox
*)rpBox
;
3389 _SplitTable_Para
& rPara
= *(_SplitTable_Para
*)pPara
;
3391 SwFrmFmt
*pSrcFmt
= pBox
->GetFrmFmt();
3392 USHORT nPos
= rPara
.SrcFmt_GetPos( pSrcFmt
);
3393 if( USHRT_MAX
== nPos
)
3395 rPara
.DestFmt_Insert( pBox
->ClaimFrmFmt() );
3396 rPara
.SrcFmt_Insert( pSrcFmt
);
3399 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)rPara
.DestFmt_Get( nPos
) );
3401 if( pBox
->GetSttNd() )
3402 rPara
.ChgBox( pBox
);
3404 pBox
->GetTabLines().ForEach( &lcl_SplitTable_CpyLine
, pPara
);
3408 SwTableNode
* SwNodes::SplitTable( const SwNodeIndex
& rPos
, BOOL bAfter
,
3411 SwNode
* pNd
= &rPos
.GetNode();
3412 SwTableNode
* pTNd
= pNd
->FindTableNode();
3413 if( !pTNd
|| pNd
->IsTableNode() )
3416 ULONG nSttIdx
= pNd
->FindTableBoxStartNode()->GetIndex();
3418 // Suche die Grund-Line dieser Box:
3419 SwTable
& rTbl
= pTNd
->GetTable();
3420 SwTableBox
* pBox
= rTbl
.GetTblBox( nSttIdx
);
3424 SwTableLine
* pLine
= pBox
->GetUpper();
3425 while( pLine
->GetUpper() )
3426 pLine
= pLine
->GetUpper()->GetUpper();
3428 // in pLine steht jetzt die GrundLine.
3429 USHORT nLinePos
= rTbl
.GetTabLines().C40_GETPOS( SwTableLine
, pLine
);
3430 if( USHRT_MAX
== nLinePos
||
3431 ( bAfter
? ++nLinePos
>= rTbl
.GetTabLines().Count() : !nLinePos
))
3432 return 0; // nicht gefunden oder letze Line !!
3434 // Suche jetzt die 1. Box der nachfolgenden Line
3435 SwTableLine
* pNextLine
= rTbl
.GetTabLines()[ nLinePos
];
3436 pBox
= pNextLine
->GetTabBoxes()[0];
3437 while( !pBox
->GetSttNd() )
3438 pBox
= pBox
->GetTabLines()[0]->GetTabBoxes()[0];
3440 // dann fuege mal einen End- und TabelleNode ins Nodes-Array ein.
3441 SwTableNode
* pNewTblNd
;
3443 SwEndNode
* pOldTblEndNd
= (SwEndNode
*)pTNd
->EndOfSectionNode()->GetEndNode();
3444 ASSERT( pOldTblEndNd
, "wo ist der EndNode?" )
3446 SwNodeIndex
aIdx( *pBox
->GetSttNd() );
3447 new SwEndNode( aIdx
, *pTNd
);
3448 pNewTblNd
= new SwTableNode( aIdx
);
3449 pNewTblNd
->GetTable().SetTableModel( rTbl
.IsNewModel() );
3451 pOldTblEndNd
->pStartOfSection
= pNewTblNd
;
3452 pNewTblNd
->pEndOfSection
= pOldTblEndNd
;
3454 SwNode
* pBoxNd
= aIdx
.GetNode().GetStartNode();
3456 ASSERT( pBoxNd
->IsStartNode(), "das muss ein StartNode sein!" );
3457 pBoxNd
->pStartOfSection
= pNewTblNd
;
3458 pBoxNd
= (*this)[ pBoxNd
->EndOfSectionIndex() + 1 ];
3459 } while( pBoxNd
!= pOldTblEndNd
);
3463 // die Lines ruebermoven...
3464 SwTable
& rNewTbl
= pNewTblNd
->GetTable();
3465 rNewTbl
.GetTabLines().Insert( &rTbl
.GetTabLines(), 0, nLinePos
);
3467 // von hinten (unten-rechts) nach vorn (oben-links) alle Boxen
3468 // beim chart data provider austragen (das modified event wird dann
3469 // in der aufrufenden Funktion getriggert.
3471 SwChartDataProvider
*pPCD
= rTbl
.GetFrmFmt()->getIDocumentChartDataProviderAccess()->GetChartDataProvider();
3474 for (USHORT k
= nLinePos
; k
< rTbl
.GetTabLines().Count(); ++k
)
3476 USHORT nLineIdx
= (rTbl
.GetTabLines().Count() - 1) - k
+ nLinePos
;
3477 USHORT nBoxCnt
= rTbl
.GetTabLines()[ nLineIdx
]->GetTabBoxes().Count();
3478 for (USHORT j
= 0; j
< nBoxCnt
; ++j
)
3480 USHORT nIdx
= nBoxCnt
- 1 - j
;
3481 pPCD
->DeleteBox( &rTbl
, *rTbl
.GetTabLines()[ nLineIdx
]->GetTabBoxes()[nIdx
] );
3487 USHORT nDeleted
= rTbl
.GetTabLines().Count() - nLinePos
;
3488 rTbl
.GetTabLines().Remove( nLinePos
, nDeleted
);
3490 // und die betr. Boxen verschieben. Dabei die Formate eindeutig
3491 // machen und die StartNodes korrigieren
3492 _SplitTable_Para
aPara( pNewTblNd
, rTbl
);
3493 rNewTbl
.GetTabLines().ForEach( &lcl_SplitTable_CpyLine
, &aPara
);
3494 rTbl
.CleanUpBottomRowSpan( nDeleted
);
3498 // Das Tabellen-FrmFormat kopieren
3499 SwFrmFmt
* pOldTblFmt
= rTbl
.GetFrmFmt();
3500 SwFrmFmt
* pNewTblFmt
= pOldTblFmt
->GetDoc()->MakeTblFrmFmt(
3501 pOldTblFmt
->GetDoc()->GetUniqueTblName(),
3502 pOldTblFmt
->GetDoc()->GetDfltFrmFmt() );
3504 *pNewTblFmt
= *pOldTblFmt
;
3505 pNewTblFmt
->Add( &pNewTblNd
->GetTable() );
3507 // neue Size errechnen ? (lcl_ChgTblSize nur das 2. aufrufen, wenn es
3508 // beim 1. schon geklappt hat; also absolute Groesse hat)
3509 if( bCalcNewSize
&& lcl_ChgTblSize( rTbl
) )
3510 lcl_ChgTblSize( pNewTblNd
->GetTable() );
3513 // TL_CHART2: need to inform chart of probably changed cell names
3514 rTbl
.UpdateCharts();
3516 return pNewTblNd
; // das wars
3519 // und die Umkehrung davon. rPos muss in der Tabelle stehen, die bestehen
3520 // bleibt. Das Flag besagt ob die aktuelle mit der davor oder dahinter
3521 // stehenden vereint wird.
3522 BOOL
SwDoc::MergeTable( const SwPosition
& rPos
, BOOL bWithPrev
, USHORT nMode
)
3524 SwTableNode
* pTblNd
= rPos
.nNode
.GetNode().FindTableNode(), *pDelTblNd
;
3528 SwNodes
& rNds
= GetNodes();
3530 pDelTblNd
= rNds
[ pTblNd
->GetIndex() - 1 ]->FindTableNode();
3532 pDelTblNd
= rNds
[ pTblNd
->EndOfSectionIndex() + 1 ]->GetTableNode();
3536 if( pTblNd
->GetTable().ISA( SwDDETable
) ||
3537 pDelTblNd
->GetTable().ISA( SwDDETable
))
3540 // MIB 9.7.97: HTML-Layout loeschen
3541 pTblNd
->GetTable().SetHTMLTableLayout( 0 );
3542 pDelTblNd
->GetTable().SetHTMLTableLayout( 0 );
3544 // beide Tabellen vorhanden, also kanns losgehen
3545 SwUndoMergeTbl
* pUndo
= 0;
3546 SwHistory
* pHistory
= 0;
3550 AppendUndo( pUndo
= new SwUndoMergeTbl( *pTblNd
, *pDelTblNd
,
3551 bWithPrev
, nMode
));
3552 pHistory
= new SwHistory
;
3555 // alle "Tabellenformeln" anpassen
3556 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
3557 aMsgHnt
.DATA
.pDelTbl
= &pDelTblNd
->GetTable();
3558 aMsgHnt
.eFlags
= TBL_MERGETBL
;
3559 aMsgHnt
.pHistory
= pHistory
;
3560 UpdateTblFlds( &aMsgHnt
);
3562 // das eigentliche Mergen
3563 SwNodeIndex
aIdx( bWithPrev
? *pTblNd
: *pDelTblNd
);
3564 BOOL bRet
= rNds
.MergeTable( aIdx
, !bWithPrev
, nMode
, pHistory
);
3568 if( pHistory
->Count() )
3569 pUndo
->SaveFormula( *pHistory
);
3575 SetFieldsDirty( true, NULL
, 0 );
3580 BOOL
SwNodes::MergeTable( const SwNodeIndex
& rPos
, BOOL bWithPrev
,
3581 USHORT nMode
, SwHistory
* )
3583 SwTableNode
* pDelTblNd
= rPos
.GetNode().GetTableNode();
3584 ASSERT( pDelTblNd
, "wo ist der TableNode geblieben?" );
3586 SwTableNode
* pTblNd
= (*this)[ rPos
.GetIndex() - 1]->FindTableNode();
3587 ASSERT( pTblNd
, "wo ist der TableNode geblieben?" );
3589 if( !pDelTblNd
|| !pTblNd
)
3592 pDelTblNd
->DelFrms();
3594 SwTable
& rDelTbl
= pDelTblNd
->GetTable();
3595 SwTable
& rTbl
= pTblNd
->GetTable();
3597 //Lines fuer das Layout-Update herausuchen.
3598 _FndBox
aFndBox( 0, 0 );
3599 aFndBox
.SetTableLines( rTbl
);
3600 aFndBox
.DelFrms( rTbl
);
3602 // TL_CHART2: since chart currently does not want to get informed about
3603 // additional rows/cols there is no need for a modified event in the
3604 // remaining first table. Also, if it is required it should be done
3605 // after the merging and not here...
3606 // pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
3610 // tell the charts about the table to be deleted and have them use their own data
3611 GetDoc()->CreateChartInternalDataProviders( &rDelTbl
);
3613 // die Breite der TabellenFormate abgleichen:
3615 const SwFmtFrmSize
& rTblSz
= rTbl
.GetFrmFmt()->GetFrmSize();
3616 const SwFmtFrmSize
& rDelTblSz
= rDelTbl
.GetFrmFmt()->GetFrmSize();
3617 if( rTblSz
!= rDelTblSz
)
3619 // dann sollten die mal schleunigst korrigiert werden
3621 rDelTbl
.GetFrmFmt()->SetFmtAttr( rTblSz
);
3623 rTbl
.GetFrmFmt()->SetFmtAttr( rDelTblSz
);
3629 // dann mussen alle Attruibute der hinteren Tabelle auf die
3630 // vordere uebertragen werden, weil die hintere ueber das loeschen
3631 // des Node geloescht wird.
3632 rTbl
.SetRowsToRepeat( rDelTbl
.GetRowsToRepeat() );
3633 rTbl
.SetTblChgMode( rDelTbl
.GetTblChgMode() );
3635 rTbl
.GetFrmFmt()->LockModify();
3636 *rTbl
.GetFrmFmt() = *rDelTbl
.GetFrmFmt();
3637 // auch den Namen umsetzen!
3638 rTbl
.GetFrmFmt()->SetName( rDelTbl
.GetFrmFmt()->GetName() );
3639 rTbl
.GetFrmFmt()->UnlockModify();
3642 // die Lines und Boxen ruebermoven
3643 USHORT nOldSize
= rTbl
.GetTabLines().Count();
3644 rTbl
.GetTabLines().Insert( &rDelTbl
.GetTabLines(), nOldSize
);
3645 rDelTbl
.GetTabLines().Remove( 0, rDelTbl
.GetTabLines().Count() );
3647 rTbl
.GetTabSortBoxes().Insert( &rDelTbl
.GetTabSortBoxes() );
3648 rDelTbl
.GetTabSortBoxes().Remove( (USHORT
)0, rDelTbl
.GetTabSortBoxes().Count() );
3650 // die vordere Tabelle bleibt immer stehen, die hintere wird geloescht
3651 SwEndNode
* pTblEndNd
= pDelTblNd
->EndOfSectionNode();
3652 pTblNd
->pEndOfSection
= pTblEndNd
;
3654 SwNodeIndex
aIdx( *pDelTblNd
, 1 );
3656 SwNode
* pBoxNd
= aIdx
.GetNode().GetStartNode();
3658 ASSERT( pBoxNd
->IsStartNode(), "das muss ein StartNode sein!" );
3659 pBoxNd
->pStartOfSection
= pTblNd
;
3660 pBoxNd
= (*this)[ pBoxNd
->EndOfSectionIndex() + 1 ];
3661 } while( pBoxNd
!= pTblEndNd
);
3662 pBoxNd
->pStartOfSection
= pTblNd
;
3665 DelNodes( aIdx
, 2 );
3667 // jetzt an der 1. eingefuegten Line die bedingten Vorlagen umschubsen
3668 const SwTableLine
* pFirstLn
= rTbl
.GetTabLines()[ nOldSize
];
3671 // Header-Vorlagen in der Zeile setzen
3672 // und ggfs. in der History speichern fuers Undo!!!
3674 lcl_LineSetHeadCondColl( pFirstLn
, 0 );
3676 // und die Borders "aufrauemen"
3679 _SwGCLineBorder
aPara( rTbl
);
3680 aPara
.nLinePos
= --nOldSize
;
3681 pFirstLn
= rTbl
.GetTabLines()[ nOldSize
];
3682 lcl_GC_Line_Border( pFirstLn
, &aPara
);
3686 aFndBox
.MakeFrms( rTbl
);
3691 // -------------------------------------------------------------------
3694 // -- benutze die ForEach Methode vom PtrArray
3695 struct _SetAFmtTabPara
3697 SwTableAutoFmt
& rTblFmt
;
3698 SwUndoTblAutoFmt
* pUndo
;
3699 USHORT nEndBox
, nCurBox
;
3700 BYTE nAFmtLine
, nAFmtBox
;
3702 _SetAFmtTabPara( const SwTableAutoFmt
& rNew
)
3703 : rTblFmt( (SwTableAutoFmt
&)rNew
), pUndo( 0 ),
3704 nEndBox( 0 ), nCurBox( 0 ), nAFmtLine( 0 ), nAFmtBox( 0 )
3708 // forward deklarieren damit sich die Lines und Boxen rekursiv aufrufen
3710 BOOL
lcl_SetAFmtBox( const _FndBox
*&, void *pPara
);
3711 BOOL
lcl_SetAFmtLine( const _FndLine
*&, void *pPara
);
3713 BOOL
lcl_SetAFmtLine( const _FndLine
*& rpLine
, void *pPara
)
3715 ((_FndLine
*&)rpLine
)->GetBoxes().ForEach( &lcl_SetAFmtBox
, pPara
);
3719 BOOL
lcl_SetAFmtBox( const _FndBox
*& rpBox
, void *pPara
)
3721 _SetAFmtTabPara
* pSetPara
= (_SetAFmtTabPara
*)pPara
;
3723 if( !rpBox
->GetUpper()->GetUpper() ) // Box auf 1. Ebene ?
3725 if( !pSetPara
->nCurBox
)
3726 pSetPara
->nAFmtBox
= 0;
3727 else if( pSetPara
->nCurBox
== pSetPara
->nEndBox
)
3728 pSetPara
->nAFmtBox
= 3;
3730 pSetPara
->nAFmtBox
= (BYTE
)(1 + ((pSetPara
->nCurBox
-1) & 1));
3733 if( rpBox
->GetBox()->GetSttNd() )
3735 SwTableBox
* pSetBox
= (SwTableBox
*)rpBox
->GetBox();
3736 SwDoc
* pDoc
= pSetBox
->GetFrmFmt()->GetDoc();
3737 // --> OD 2008-02-25 #refactorlists#
3738 // SfxItemSet aCharSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END-1 );
3739 SfxItemSet
aCharSet( pDoc
->GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_LIST_END
-1 );
3741 SfxItemSet
aBoxSet( pDoc
->GetAttrPool(), aTableBoxSetRange
);
3742 BYTE nPos
= pSetPara
->nAFmtLine
* 4 + pSetPara
->nAFmtBox
;
3743 pSetPara
->rTblFmt
.UpdateToSet( nPos
, aCharSet
,
3744 SwTableAutoFmt::UPDATE_CHAR
, 0 );
3745 pSetPara
->rTblFmt
.UpdateToSet( nPos
, aBoxSet
,
3746 SwTableAutoFmt::UPDATE_BOX
,
3747 pDoc
->GetNumberFormatter( TRUE
) );
3748 if( aCharSet
.Count() )
3750 ULONG nSttNd
= pSetBox
->GetSttIdx()+1;
3751 ULONG nEndNd
= pSetBox
->GetSttNd()->EndOfSectionIndex();
3752 for( ; nSttNd
< nEndNd
; ++nSttNd
)
3754 SwCntntNode
* pNd
= pDoc
->GetNodes()[ nSttNd
]->GetCntntNode();
3756 pNd
->SetAttr( aCharSet
);
3760 if( aBoxSet
.Count() )
3762 if( pSetPara
->pUndo
&&
3763 SFX_ITEM_SET
== aBoxSet
.GetItemState( RES_BOXATR_FORMAT
))
3764 pSetPara
->pUndo
->SaveBoxCntnt( *pSetBox
);
3766 pSetBox
->ClaimFrmFmt()->SetFmtAttr( aBoxSet
);
3770 ((_FndBox
*&)rpBox
)->GetLines().ForEach( &lcl_SetAFmtLine
, pPara
);
3772 if( !rpBox
->GetUpper()->GetUpper() ) // eine BaseLine
3773 ++pSetPara
->nCurBox
;
3778 // AutoFormat fuer die Tabelle/TabellenSelection
3779 BOOL
SwDoc::SetTableAutoFmt( const SwSelBoxes
& rBoxes
, const SwTableAutoFmt
& rNew
)
3781 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
3782 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
3786 // suche alle Boxen / Lines
3787 _FndBox
aFndBox( 0, 0 );
3789 _FndPara
aPara( rBoxes
, &aFndBox
);
3790 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
3792 if( !aFndBox
.GetLines().Count() )
3795 pTblNd
->GetTable().SetHTMLTableLayout( 0 );
3797 _FndBox
* pFndBox
= &aFndBox
;
3798 while( 1 == pFndBox
->GetLines().Count() &&
3799 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
3800 pFndBox
= pFndBox
->GetLines()[0]->GetBoxes()[0];
3802 if( !pFndBox
->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
3803 pFndBox
= pFndBox
->GetUpper()->GetUpper();
3806 // Undo abschalten, Attribute werden sich vorher gemerkt
3807 SwUndoTblAutoFmt
* pUndo
= 0;
3811 AppendUndo( pUndo
= new SwUndoTblAutoFmt( *pTblNd
, rNew
) );
3815 _SetAFmtTabPara
aPara( rNew
);
3816 _FndLines
& rFLns
= pFndBox
->GetLines();
3819 for( USHORT n
= 0; n
< rFLns
.Count(); ++n
)
3823 // Upper auf 0 setzen (Base-Line simulieren!)
3824 _FndBox
* pSaveBox
= pLine
->GetUpper();
3825 pLine
->SetUpper( 0 );
3828 aPara
.nAFmtLine
= 0;
3829 else if( n
+1 == rFLns
.Count() )
3830 aPara
.nAFmtLine
= 3;
3832 aPara
.nAFmtLine
= (BYTE
)(1 + ((n
-1) & 1 ));
3836 aPara
.nEndBox
= pLine
->GetBoxes().Count()-1;
3837 aPara
.pUndo
= pUndo
;
3838 pLine
->GetBoxes().ForEach( &lcl_SetAFmtBox
, &aPara
);
3840 pLine
->SetUpper( pSaveBox
);
3847 SetFieldsDirty( true, NULL
, 0 );
3853 // Erfrage wie attributiert ist
3854 BOOL
SwDoc::GetTableAutoFmt( const SwSelBoxes
& rBoxes
, SwTableAutoFmt
& rGet
)
3856 ASSERT( rBoxes
.Count(), "keine gueltige Box-Liste" );
3857 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
3861 // suche alle Boxen / Lines
3862 _FndBox
aFndBox( 0, 0 );
3864 _FndPara
aPara( rBoxes
, &aFndBox
);
3865 pTblNd
->GetTable().GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
3867 if( !aFndBox
.GetLines().Count() )
3870 _FndBox
* pFndBox
= &aFndBox
;
3871 while( 1 == pFndBox
->GetLines().Count() &&
3872 1 == pFndBox
->GetLines()[0]->GetBoxes().Count() )
3873 pFndBox
= pFndBox
->GetLines()[0]->GetBoxes()[0];
3875 if( !pFndBox
->GetLines().Count() ) // eine zu weit? (nur 1 sel.Box)
3876 pFndBox
= pFndBox
->GetUpper()->GetUpper();
3878 _FndLines
& rFLns
= pFndBox
->GetLines();
3882 aLnArr
[1] = 1 < rFLns
.Count() ? 1 : 0;
3883 aLnArr
[2] = 2 < rFLns
.Count() ? 2 : aLnArr
[1];
3884 aLnArr
[3] = rFLns
.Count() - 1;
3886 for( BYTE nLine
= 0; nLine
< 4; ++nLine
)
3888 _FndLine
& rLine
= *rFLns
[ aLnArr
[ nLine
] ];
3892 aBoxArr
[1] = 1 < rLine
.GetBoxes().Count() ? 1 : 0;
3893 aBoxArr
[2] = 2 < rLine
.GetBoxes().Count() ? 2 : aBoxArr
[1];
3894 aBoxArr
[3] = rLine
.GetBoxes().Count() - 1;
3896 for( BYTE nBox
= 0; nBox
< 4; ++nBox
)
3898 SwTableBox
* pFBox
= rLine
.GetBoxes()[ aBoxArr
[ nBox
] ]->GetBox();
3899 // immer auf die 1. runterfallen
3900 while( !pFBox
->GetSttNd() )
3901 pFBox
= pFBox
->GetTabLines()[0]->GetTabBoxes()[0];
3903 BYTE nPos
= nLine
* 4 + nBox
;
3904 SwNodeIndex
aIdx( *pFBox
->GetSttNd(), 1 );
3905 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
3907 pCNd
= GetNodes().GoNext( &aIdx
);
3910 rGet
.UpdateFromSet( nPos
, pCNd
->GetSwAttrSet(),
3911 SwTableAutoFmt::UPDATE_CHAR
, 0 );
3912 rGet
.UpdateFromSet( nPos
, pFBox
->GetFrmFmt()->GetAttrSet(),
3913 SwTableAutoFmt::UPDATE_BOX
,
3914 GetNumberFormatter( TRUE
) );
3921 String
SwDoc::GetUniqueTblName() const
3923 ResId
aId( STR_TABLE_DEFNAME
, *pSwResMgr
);
3924 String
aName( aId
);
3925 xub_StrLen nNmLen
= aName
.Len();
3927 USHORT nNum
, nTmp
, nFlagSize
= ( pTblFrmFmtTbl
->Count() / 8 ) +2;
3930 BYTE
* pSetFlags
= new BYTE
[ nFlagSize
];
3931 memset( pSetFlags
, 0, nFlagSize
);
3933 for( n
= 0; n
< pTblFrmFmtTbl
->Count(); ++n
)
3935 const SwFrmFmt
* pFmt
= (*pTblFrmFmtTbl
)[ n
];
3936 if( !pFmt
->IsDefault() && IsUsed( *pFmt
) &&
3937 pFmt
->GetName().Match( aName
) == nNmLen
)
3939 // Nummer bestimmen und das Flag setzen
3940 nNum
= static_cast<USHORT
>(pFmt
->GetName().Copy( nNmLen
).ToInt32());
3941 if( nNum
-- && nNum
< pTblFrmFmtTbl
->Count() )
3942 pSetFlags
[ nNum
/ 8 ] |= (0x01 << ( nNum
& 0x07 ));
3946 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
3947 nNum
= pTblFrmFmtTbl
->Count();
3948 for( n
= 0; n
< nFlagSize
; ++n
)
3949 if( 0xff != ( nTmp
= pSetFlags
[ n
] ))
3951 // also die Nummer bestimmen
3958 delete [] pSetFlags
;
3959 return aName
+= String::CreateFromInt32( ++nNum
);
3962 SwTableFmt
* SwDoc::FindTblFmtByName( const String
& rName
, BOOL bAll
) const
3964 const SwFmt
* pRet
= 0;
3966 pRet
= FindFmtByName( (SvPtrarr
&)*pTblFrmFmtTbl
, rName
);
3969 // dann nur die, die im Doc gesetzt sind
3970 for( USHORT n
= 0; n
< pTblFrmFmtTbl
->Count(); ++n
)
3972 const SwFrmFmt
* pFmt
= (*pTblFrmFmtTbl
)[ n
];
3973 if( !pFmt
->IsDefault() && IsUsed( *pFmt
) &&
3974 pFmt
->GetName() == rName
)
3981 return (SwTableFmt
*)pRet
;
3984 BOOL
SwDoc::SetColRowWidthHeight( SwTableBox
& rAktBox
, USHORT eType
,
3985 SwTwips nAbsDiff
, SwTwips nRelDiff
)
3987 SwTableNode
* pTblNd
= (SwTableNode
*)rAktBox
.GetSttNd()->FindTableNode();
3990 if( nsTblChgWidthHeightType::WH_FLAG_INSDEL
& eType
&& pTblNd
->GetTable().ISA( SwDDETable
))
3993 SwTableFmlUpdate
aMsgHnt( &pTblNd
->GetTable() );
3994 aMsgHnt
.eFlags
= TBL_BOXPTR
;
3995 UpdateTblFlds( &aMsgHnt
);
3998 switch( eType
& 0xff )
4000 case nsTblChgWidthHeightType::WH_COL_LEFT
:
4001 case nsTblChgWidthHeightType::WH_COL_RIGHT
:
4002 case nsTblChgWidthHeightType::WH_CELL_LEFT
:
4003 case nsTblChgWidthHeightType::WH_CELL_RIGHT
:
4005 bRet
= pTblNd
->GetTable().SetColWidth( rAktBox
,
4006 eType
, nAbsDiff
, nRelDiff
,
4007 DoesUndo() ? &pUndo
: 0 );
4010 case nsTblChgWidthHeightType::WH_ROW_TOP
:
4011 case nsTblChgWidthHeightType::WH_ROW_BOTTOM
:
4012 case nsTblChgWidthHeightType::WH_CELL_TOP
:
4013 case nsTblChgWidthHeightType::WH_CELL_BOTTOM
:
4014 bRet
= pTblNd
->GetTable().SetRowHeight( rAktBox
,
4015 eType
, nAbsDiff
, nRelDiff
,
4016 DoesUndo() ? &pUndo
: 0 );
4023 AppendUndo( pUndo
);
4024 DoUndo( TRUE
); // im SetColWidth kann es abgeschaltet werden!
4030 if( nsTblChgWidthHeightType::WH_FLAG_INSDEL
& eType
)
4031 SetFieldsDirty( true, NULL
, 0 );
4037 void SwDoc::ChkBoxNumFmt( SwTableBox
& rBox
, BOOL bCallUpdate
)
4039 //JP 09.07.97: Optimierung: wenn die Box schon sagt, das es Text
4040 // sein soll, dann bleibt das auch Text!
4041 const SfxPoolItem
* pNumFmtItem
= 0;
4042 if( SFX_ITEM_SET
== rBox
.GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT
,
4043 FALSE
, &pNumFmtItem
) && GetNumberFormatter()->IsTextFormat(
4044 ((SwTblBoxNumFormat
*)pNumFmtItem
)->GetValue() ))
4047 SwUndoTblNumFmt
* pUndo
= 0;
4049 BOOL bIsEmptyTxtNd
, bChgd
= TRUE
;
4052 if( rBox
.HasNumCntnt( fNumber
, nFmtIdx
, bIsEmptyTxtNd
) )
4054 if( !rBox
.IsNumberChanged() )
4060 StartUndo( UNDO_TABLE_AUTOFMT
, NULL
);
4061 pUndo
= new SwUndoTblNumFmt( rBox
);
4062 pUndo
->SetNumFmt( nFmtIdx
, fNumber
);
4065 SwTableBoxFmt
* pBoxFmt
= (SwTableBoxFmt
*)rBox
.GetFrmFmt();
4066 SfxItemSet
aBoxSet( GetAttrPool(), RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
4068 BOOL bSetNumFmt
= IsInsTblFormatNum(), bLockModify
= TRUE
;
4071 if( !IsInsTblChangeNumFormat() )
4077 ULONG nOldNumFmt
= ((SwTblBoxNumFormat
*)pNumFmtItem
)->
4079 SvNumberFormatter
* pNumFmtr
= GetNumberFormatter();
4081 short nFmtType
= pNumFmtr
->GetType( nFmtIdx
);
4082 if( nFmtType
== pNumFmtr
->GetType( nOldNumFmt
) ||
4083 NUMBERFORMAT_NUMBER
== nFmtType
)
4084 // eingstelltes und vorgegebenes NumFormat
4085 // stimmen ueberein -> altes Format beibehalten
4086 nFmtIdx
= nOldNumFmt
;
4088 // eingstelltes und vorgegebenes NumFormat
4089 // stimmen nicht ueberein -> als Text einfuegen
4090 bLockModify
= bSetNumFmt
= FALSE
;
4096 pBoxFmt
= (SwTableBoxFmt
*)rBox
.ClaimFrmFmt();
4098 aBoxSet
.Put( SwTblBoxValue( fNumber
));
4099 aBoxSet
.Put( SwTblBoxNumFormat( nFmtIdx
));
4103 // JP 28.04.98: Nur Formel zuruecksetzen reicht nicht.
4104 // Sorge dafuer, das der Text auch entsprechend
4107 if( !bSetNumFmt
&& !bIsEmptyTxtNd
&& pNumFmtItem
)
4109 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4110 // Sorge dafuer, das der Text auch entsprechend
4112 pBoxFmt
->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT
));
4115 if( bLockModify
) pBoxFmt
->LockModify();
4116 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
4117 if( bLockModify
) pBoxFmt
->UnlockModify();
4120 pBoxFmt
->SetFmtAttr( aBoxSet
);
4125 // es ist keine Zahl
4126 const SfxPoolItem
* pValueItem
= 0, *pFmtItem
= 0;
4127 SwTableBoxFmt
* pBoxFmt
= (SwTableBoxFmt
*)rBox
.GetFrmFmt();
4128 if( SFX_ITEM_SET
== pBoxFmt
->GetItemState( RES_BOXATR_FORMAT
,
4129 FALSE
, &pFmtItem
) ||
4130 SFX_ITEM_SET
== pBoxFmt
->GetItemState( RES_BOXATR_VALUE
,
4131 FALSE
, &pValueItem
))
4135 StartUndo( UNDO_TABLE_AUTOFMT
, NULL
);
4136 pUndo
= new SwUndoTblNumFmt( rBox
);
4139 pBoxFmt
= (SwTableBoxFmt
*)rBox
.ClaimFrmFmt();
4141 // alle Zahlenformate entfernen
4142 USHORT nWhich1
= RES_BOXATR_FORMULA
;
4143 if( !bIsEmptyTxtNd
)
4144 //JP 15.01.99: dieser Teil wurde doch schon oben abgeprueft!
4145 /* && pFmtItem && !GetNumberFormatter()->
4146 IsTextFormat( ((SwTblBoxNumFormat*)pFmtItem)->GetValue() ) )*/
4148 nWhich1
= RES_BOXATR_FORMAT
;
4150 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4151 // Sorge dafuer, das der Text auch entsprechend
4153 pBoxFmt
->SetFmtAttr( *GetDfltAttr( nWhich1
));
4155 pBoxFmt
->ResetFmtAttr( nWhich1
, RES_BOXATR_VALUE
);
4165 pUndo
->SetBox( rBox
);
4166 AppendUndo( pUndo
);
4167 EndUndo( UNDO_END
, NULL
);
4170 const SwTableNode
* pTblNd
= rBox
.GetSttNd()->FindTableNode();
4173 SwTableFmlUpdate
aTblUpdate( &pTblNd
->GetTable() );
4174 UpdateTblFlds( &aTblUpdate
);
4176 // TL_CHART2: update charts (when cursor leaves cell and
4177 // automatic update is enabled)
4178 if (AUTOUPD_FIELD_AND_CHARTS
== getFieldUpdateFlags(true))
4179 pTblNd
->GetTable().UpdateCharts();
4185 void SwDoc::SetTblBoxFormulaAttrs( SwTableBox
& rBox
, const SfxItemSet
& rSet
)
4190 AppendUndo( new SwUndoTblNumFmt( rBox
, &rSet
) );
4193 SwFrmFmt
* pBoxFmt
= rBox
.ClaimFrmFmt();
4194 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMULA
))
4196 pBoxFmt
->LockModify();
4197 pBoxFmt
->ResetFmtAttr( RES_BOXATR_VALUE
);
4198 pBoxFmt
->UnlockModify();
4200 else if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_VALUE
))
4202 pBoxFmt
->LockModify();
4203 pBoxFmt
->ResetFmtAttr( RES_BOXATR_FORMULA
);
4204 pBoxFmt
->UnlockModify();
4206 pBoxFmt
->SetFmtAttr( rSet
);
4210 void SwDoc::ClearLineNumAttrs( SwPosition
& rPos
)
4213 aPam
.Move(fnMoveBackward
);
4214 SwCntntNode
*pNode
= aPam
.GetCntntNode();
4217 if( pNode
->IsTxtNode() )
4219 SwTxtNode
* pTxtNode
= pNode
->GetTxtNode();
4220 if ( pTxtNode
&& pTxtNode
->IsNumbered() && pTxtNode
->GetTxt().Len()==0 )
4222 const SfxPoolItem
* pFmtItem
= 0;
4223 SfxItemSet
rSet( const_cast<SwAttrPool
&>(pTxtNode
->GetDoc()->GetAttrPool()),
4224 RES_PARATR_BEGIN
, RES_PARATR_END
- 1,
4226 pTxtNode
->SwCntntNode::GetAttr( rSet
);
4227 if ( SFX_ITEM_SET
== rSet
.GetItemState( RES_PARATR_NUMRULE
, FALSE
, &pFmtItem
) )
4229 SwUndoDelNum
* pUndo
;
4233 AppendUndo( pUndo
= new SwUndoDelNum( aPam
) );
4237 SwRegHistory
aRegH( pUndo
? pUndo
->GetHistory() : 0 );
4238 aRegH
.RegisterInModify( pTxtNode
, *pTxtNode
);
4240 pUndo
->AddNode( *pTxtNode
, FALSE
);
4241 String aStyle
= String::CreateFromAscii("");
4242 SfxStringItem
* pNewItem
= (SfxStringItem
*)pFmtItem
->Clone();
4243 pNewItem
->SetValue( aStyle
);
4244 rSet
.Put( *pNewItem
);
4245 pTxtNode
->SetAttr( rSet
);
4252 void SwDoc::ClearBoxNumAttrs( const SwNodeIndex
& rNode
)
4254 SwStartNode
* pSttNd
;
4255 if( 0 != ( pSttNd
= GetNodes()[ rNode
]->
4256 FindSttNodeByType( SwTableBoxStartNode
)) &&
4257 2 == pSttNd
->EndOfSectionIndex() - pSttNd
->GetIndex() )
4259 SwTableBox
* pBox
= pSttNd
->FindTableNode()->GetTable().
4260 GetTblBox( pSttNd
->GetIndex() );
4262 const SfxPoolItem
* pFmtItem
= 0;
4263 const SfxItemSet
& rSet
= pBox
->GetFrmFmt()->GetAttrSet();
4264 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMAT
, FALSE
, &pFmtItem
) ||
4265 SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMULA
, FALSE
) ||
4266 SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_VALUE
, FALSE
))
4271 AppendUndo( new SwUndoTblNumFmt( *pBox
) );
4274 SwFrmFmt
* pBoxFmt
= pBox
->ClaimFrmFmt();
4276 //JP 01.09.97: TextFormate bleiben erhalten!
4277 USHORT nWhich1
= RES_BOXATR_FORMAT
;
4278 if( pFmtItem
&& GetNumberFormatter()->IsTextFormat(
4279 ((SwTblBoxNumFormat
*)pFmtItem
)->GetValue() ))
4280 nWhich1
= RES_BOXATR_FORMULA
;
4282 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
4283 // Sorge dafuer, das der Text auch entsprechend
4285 pBoxFmt
->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT
));
4287 pBoxFmt
->ResetFmtAttr( nWhich1
, RES_BOXATR_VALUE
);
4293 // kopiert eine Tabelle aus dem selben oder einem anderen Doc in sich
4294 // selbst. Dabei wird eine neue Tabelle angelegt oder eine bestehende
4295 // mit dem Inhalt gefuellt; wobei entweder der Inhalt ab einer Box oder
4296 // in eine bestehende TblSelektion gefuellt wird.
4297 // Gerufen wird es von: edglss.cxx/fecopy.cxx
4299 BOOL
SwDoc::InsCopyOfTbl( SwPosition
& rInsPos
, const SwSelBoxes
& rBoxes
,
4300 const SwTable
* pCpyTbl
, BOOL bCpyName
, BOOL bCorrPos
)
4304 const SwTableNode
* pSrcTblNd
= pCpyTbl
4305 ? pCpyTbl
->GetTableNode()
4306 : rBoxes
[ 0 ]->GetSttNd()->FindTableNode();
4308 SwTableNode
* pInsTblNd
= GetNodes()[ rInsPos
.nNode
]->FindTableNode();
4310 if( !pCpyTbl
&& !pInsTblNd
)
4312 SwUndoCpyTbl
* pUndo
= 0;
4316 pUndo
= new SwUndoCpyTbl
;
4320 bRet
= pSrcTblNd
->GetTable().MakeCopy( this, rInsPos
, rBoxes
,
4328 pInsTblNd
= GetNodes()[ rInsPos
.nNode
.GetIndex() - 1 ]->FindTableNode();
4330 pUndo
->SetTableSttIdx( pInsTblNd
->GetIndex() );
4331 AppendUndo( pUndo
);
4338 RedlineMode_t eOld
= GetRedlineMode();
4340 SetRedlineMode( (RedlineMode_t
)(nsRedlineMode_t::REDLINE_ON
|
4341 nsRedlineMode_t::REDLINE_SHOW_INSERT
|
4342 nsRedlineMode_t::REDLINE_SHOW_DELETE
));
4344 SwUndoTblCpyTbl
* pUndo
= 0;
4348 pUndo
= new SwUndoTblCpyTbl
;
4352 SwDoc
* pCpyDoc
= (SwDoc
*)pSrcTblNd
->GetDoc();
4353 SfxObjectShellRef
* pRefForDocSh
= 0;
4354 BOOL bDelCpyDoc
= pCpyDoc
== this;
4358 // kopiere die Tabelle erstmal in ein temp. Doc
4359 pCpyDoc
= new SwDoc
;
4361 pRefForDocSh
= new SfxObjectShellRef();
4362 pCpyDoc
->SetRefForDocShell( pRefForDocSh
);
4364 SwPosition
aPos( SwNodeIndex( pCpyDoc
->GetNodes().GetEndOfContent() ));
4365 if( !pSrcTblNd
->GetTable().MakeCopy( pCpyDoc
, aPos
, rBoxes
, TRUE
, TRUE
))
4367 delete pRefForDocSh
;
4368 if( pCpyDoc
->release() == 0 )
4378 aPos
.nNode
-= 1; // auf den EndNode der Tabelle
4379 pSrcTblNd
= aPos
.nNode
.GetNode().FindTableNode();
4381 pCpyDoc
->SetRefForDocShell( NULL
);
4384 const SwStartNode
* pSttNd
= rInsPos
.nNode
.GetNode().FindTableBoxStartNode();
4386 rInsPos
.nContent
.Assign( 0, 0 );
4388 // no complex into complex, but copy into or from new model is welcome
4389 if( ( !pSrcTblNd
->GetTable().IsTblComplex() || pInsTblNd
->GetTable().IsNewModel() )
4390 && ( bDelCpyDoc
|| rBoxes
.Count() ) )
4392 // dann die Tabelle "relativ" kopieren
4393 const SwSelBoxes
* pBoxes
;
4398 SwTableBox
* pBox
= pInsTblNd
->GetTable().GetTblBox(
4399 pSttNd
->GetIndex() );
4400 ASSERT( pBox
, "Box steht nicht in dieser Tabelle" );
4401 aBoxes
.Insert( pBox
);
4407 // kopiere die Tabelle in die selktierten Zellen.
4408 bRet
= pInsTblNd
->GetTable().InsTable( pSrcTblNd
->GetTable(),
4413 SwNodeIndex
aNdIdx( *pSttNd
, 1 );
4414 bRet
= pInsTblNd
->GetTable().InsTable( pSrcTblNd
->GetTable(),
4420 delete pRefForDocSh
;
4421 if( pCpyDoc
->release() == 0 )
4427 // falls die Tabelle nicht kopiert werden konnte, das Undo-Object
4429 if( !bRet
&& pUndo
->IsEmpty() )
4432 AppendUndo( pUndo
);
4438 rInsPos
.nNode
= *pSttNd
;
4439 rInsPos
.nContent
.Assign( GetNodes().GoNext( &rInsPos
.nNode
), 0 );
4441 SetRedlineMode( eOld
);
4447 SetFieldsDirty( true, NULL
, 0 );
4454 BOOL
SwDoc::_UnProtectTblCells( SwTable
& rTbl
)
4457 SwUndoAttrTbl
* pUndo
= DoesUndo() ? new SwUndoAttrTbl( *rTbl
.GetTableNode() )
4460 SwTableSortBoxes
& rSrtBox
= rTbl
.GetTabSortBoxes();
4461 for( USHORT i
= rSrtBox
.Count(); i
; )
4463 SwFrmFmt
*pBoxFmt
= rSrtBox
[ --i
]->GetFrmFmt();
4464 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4466 pBoxFmt
->ResetFmtAttr( RES_PROTECT
);
4476 AppendUndo( pUndo
);
4485 BOOL
SwDoc::UnProtectCells( const String
& rName
)
4488 SwTableFmt
* pFmt
= FindTblFmtByName( rName
);
4491 bChgd
= _UnProtectTblCells( *SwTable::FindTable( pFmt
) );
4499 BOOL
SwDoc::UnProtectCells( const SwSelBoxes
& rBoxes
)
4502 if( rBoxes
.Count() )
4504 SwUndoAttrTbl
* pUndo
= DoesUndo()
4505 ? new SwUndoAttrTbl( *rBoxes
[0]->GetSttNd()->FindTableNode() )
4508 SvPtrarr
aFmts( 16 ), aNewFmts( 16 );
4509 for( USHORT i
= rBoxes
.Count(); i
; )
4511 SwTableBox
* pBox
= rBoxes
[ --i
];
4512 SwFrmFmt
* pBoxFmt
= pBox
->GetFrmFmt();
4513 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4515 USHORT nFnd
= aFmts
.GetPos( pBoxFmt
);
4516 if( USHRT_MAX
!= nFnd
)
4517 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)aNewFmts
[ nFnd
] );
4520 aFmts
.Insert( pBoxFmt
, aFmts
.Count() );
4521 pBoxFmt
= pBox
->ClaimFrmFmt();
4522 pBoxFmt
->ResetFmtAttr( RES_PROTECT
);
4523 aNewFmts
.Insert( pBoxFmt
, aNewFmts
.Count() );
4534 AppendUndo( pUndo
);
4543 BOOL
SwDoc::UnProtectTbls( const SwPaM
& rPam
)
4545 StartUndo(UNDO_EMPTY
, NULL
);
4547 BOOL bChgd
= FALSE
, bHasSel
= rPam
.HasMark() ||
4548 rPam
.GetNext() != (SwPaM
*)&rPam
;
4549 SwFrmFmts
& rFmts
= *GetTblFrmFmts();
4551 const SwTableNode
* pTblNd
;
4552 for( USHORT n
= rFmts
.Count(); n
; )
4553 if( 0 != (pTbl
= SwTable::FindTable( rFmts
[ --n
] )) &&
4554 0 != (pTblNd
= pTbl
->GetTableNode() ) &&
4555 pTblNd
->GetNodes().IsDocNodes() )
4557 ULONG nTblIdx
= pTblNd
->GetIndex();
4559 // dann ueberpruefe ob Tabelle in der Selection liegt
4563 SwPaM
* pTmp
= (SwPaM
*)&rPam
;
4565 const SwPosition
*pStt
= pTmp
->Start(),
4566 *pEnd
= pTmp
->End();
4567 bFound
= pStt
->nNode
.GetIndex() < nTblIdx
&&
4568 nTblIdx
< pEnd
->nNode
.GetIndex();
4570 } while( !bFound
&& &rPam
!= ( pTmp
= (SwPaM
*)pTmp
->GetNext() ) );
4572 continue; // weitersuchen
4575 // dann mal den Schutz aufheben
4576 bChgd
|= _UnProtectTblCells( *pTbl
);
4579 EndUndo(UNDO_EMPTY
, NULL
);
4586 BOOL
SwDoc::HasTblAnyProtection( const SwPosition
* pPos
,
4587 const String
* pTblName
,
4588 BOOL
* pFullTblProtection
)
4590 BOOL bHasProtection
= FALSE
;
4593 pTbl
= SwTable::FindTable( FindTblFmtByName( *pTblName
) );
4596 SwTableNode
* pTblNd
= pPos
->nNode
.GetNode().FindTableNode();
4598 pTbl
= &pTblNd
->GetTable();
4603 SwTableSortBoxes
& rSrtBox
= pTbl
->GetTabSortBoxes();
4604 for( USHORT i
= rSrtBox
.Count(); i
; )
4606 SwFrmFmt
*pBoxFmt
= rSrtBox
[ --i
]->GetFrmFmt();
4607 if( pBoxFmt
->GetProtect().IsCntntProtected() )
4609 if( !bHasProtection
)
4611 bHasProtection
= TRUE
;
4612 if( !pFullTblProtection
)
4614 *pFullTblProtection
= TRUE
;
4617 else if( bHasProtection
&& pFullTblProtection
)
4619 *pFullTblProtection
= FALSE
;
4624 return bHasProtection
;
4627 #ifdef DEL_TABLE_REDLINES
4628 lcl_DelRedlines::lcl_DelRedlines( const SwTableNode
& rNd
,
4629 BOOL bCheckForOwnRedline
)
4630 : pDoc( (SwDoc
*)rNd
.GetNodes().GetDoc() )
4632 pDoc
->StartUndo(UNDO_EMPTY
, NULL
);
4633 const SwRedlineTbl
& rTbl
= pDoc
->GetRedlineTbl();
4634 if( !pDoc
->IsIgnoreRedline() && rTbl
.Count() )
4636 BOOL bDelete
= TRUE
;
4637 if( bCheckForOwnRedline
)
4639 sal_uInt16 nRedlPos
= pDoc
->GetRedlinePos( rNd
, USHRT_MAX
);
4640 sal_uInt32 nSttNd
= rNd
.GetIndex(),
4641 nEndNd
= rNd
.EndOfSectionIndex();
4643 for ( ; nRedlPos
< rTbl
.Count(); ++nRedlPos
)
4645 const SwRedline
* pRedline
= rTbl
[ nRedlPos
];
4646 const SwPosition
* pStt
= pRedline
->Start(),
4647 * pEnd
= pStt
== pRedline
->GetPoint()
4648 ? pRedline
->GetMark()
4649 : pRedline
->GetPoint();
4650 if( pStt
->nNode
<= nSttNd
)
4652 if( pEnd
->nNode
>= nEndNd
&&
4653 pRedline
->GetAuthor() == pDoc
->GetRedlineAuthor() )
4665 SwPaM
aPam(*rNd
.EndOfSectionNode(), rNd
);
4666 pDoc
->AcceptRedline( aPam
, true );