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: rtftbl.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"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #define private public
38 #include <hintids.hxx>
39 #include <svx/lrspitem.hxx>
40 #include <svx/boxitem.hxx>
41 #include <svx/frmdiritem.hxx>
42 #include <svtools/rtftoken.h>
43 #include <fmtfsize.hxx>
44 #include <fmtpdsc.hxx>
48 #include <swparrtf.hxx>
49 #include <swtable.hxx>
51 #include <swtblfmt.hxx>
52 #include <wrtswtbl.hxx>
53 #include <tblenum.hxx>
55 #include <fmtrowsplt.hxx>
57 using namespace ::com::sun::star
;
59 typedef SwTableBoxFmt
* SwTableBoxFmtPtr
;
60 SV_DECL_PTRARR( SwBoxFrmFmts
, SwTableBoxFmtPtr
, 25, 50 )
63 extern void _DeleteBox( SwTable
& rTbl
, SwTableBox
* pBox
, SwUndo
* = 0,
64 BOOL
= TRUE
, const BOOL
= TRUE
, SwShareBoxFmts
* = 0 );
68 bool mbUseLeftRowPad
, mbUseRightRowPad
, mbUseTopRowPad
, mbUseBottomRowPad
;
69 long mnLeftRowPad
, mnRightRowPad
, mnTopRowPad
, mnBottomRowPad
;
72 mbUseLeftRowPad(false), mbUseRightRowPad(false),
73 mbUseTopRowPad(false), mbUseBottomRowPad(false),
74 mnLeftRowPad(0), mnRightRowPad(0), mnTopRowPad(0), mnBottomRowPad(0),
75 mnBrdDist(MIN_BORDER_DIST
)
79 static void SetRowBorder(SfxItemSet
& rSet
, const Row
&rRow
)
82 SvxBoxItem
aBox((const SvxBoxItem
&)rSet
.Get(RES_BOX
, false));
83 aBox
.SetDistance( static_cast< USHORT
>(rRow
.mbUseLeftRowPad
? rRow
.mnLeftRowPad
: rRow
.mnBrdDist
),
86 aBox
.SetDistance( static_cast< USHORT
>(rRow
.mbUseRightRowPad
? rRow
.mnRightRowPad
: rRow
.mnBrdDist
),
89 aBox
.SetDistance( static_cast< USHORT
>(rRow
.mbUseTopRowPad
? rRow
.mnTopRowPad
: 0),
92 aBox
.SetDistance( static_cast< USHORT
>(rRow
.mbUseBottomRowPad
? rRow
.mnBottomRowPad
: 0),
97 const SfxPoolItem
* pItem
;
98 if (SFX_ITEM_SET
== rSet
.GetItemState(RES_BOX
, FALSE
, &pItem
))
100 SvxBoxItem
aBox( *(SvxBoxItem
*)pItem
);
101 aBox
.SetDistance(rRow
.mbUseLeftRowPad
? rRow
.mnLeftRowPad
: rRow
.mnBrdDist
,
104 aBox
.SetDistance(rRow
.mbUseRightRowPad
? rRow
.mnRightRowPad
: rRow
.mnBrdDist
,
107 aBox
.SetDistance(rRow
.mbUseTopRowPad
? rRow
.mnTopRowPad
: 0,
110 aBox
.SetDistance(rRow
.mbUseBottomRowPad
? rRow
.mnBottomRowPad
: 0,
118 void rtfSections::PrependedInlineNode(const SwPosition
&rPos
,
121 ASSERT(!mrReader
.IsNewDoc() || !maSegments
.empty(),
122 "should not be possible, must be at least one segment in a new document");
123 if ((!maSegments
.empty()) && (maSegments
.back().maStart
== rPos
.nNode
))
124 maSegments
.back().maStart
= SwNodeIndex(rNode
);
127 bool SwRTFParser::IsBorderToken(int nToken
)
131 Our ability to sense border tokens is broken rtftoken.h is
132 organised in a way that ignores some border tokens. ReadBorderAttr
133 still doesn't support the more exotic borders but at least this
134 won't cause the parser to prematuerely exit the table
136 bool bResult
= false;
138 bResult
= (nToken
>= RTF_BRDRDASHD
&& nToken
<= RTF_BRDRTHTNMG
) ||
139 (nToken
>= RTF_BRDRTNTHSG
&& nToken
<= RTF_BRDRWAVY
);
144 void SwRTFParser::ReadTable( int nToken
)
146 nInsTblRow
= USHRT_MAX
;
150 // alle Tabellen-Tokens ueberlesen
151 nToken
= GetNextToken(); // RTF_TROWD ueberlesen
153 if( RTF_TABLEDEF
!= (nToken
& ~(0xff | RTF_SWGDEFS
)) &&
154 RTF_UNKNOWNCONTROL
!= nToken
)
159 nToken
= GetNextToken();
160 } while( IsParserWorking() );
164 // verhinder Tabelle in Tabelle/Footnote
166 int bReadNewCell
= FALSE
, bChkExistTbl
= FALSE
;
169 enum Limits
{eMAXCELLS
=64000};
171 SvBools aMergeBackup
;
172 int nCount
= aMergeBoxes
.Count();
173 for (USHORT i
= 0; i
< nCount
; ++i
)
174 aMergeBackup
.Insert(aMergeBoxes
[i
], i
);
176 // kein TROWD aber ein TabellenToken -> zwischen TROWD und Tab.Token
177 // waren andere Zeichen (siehe Bug 27445.rtf)
178 if( RTF_TROWD
== nToken
|| !pTableNode
)
180 if( RTF_TROWD
== nToken
)
181 nToken
= GetNextToken(); // RTF_TROWD ueberlesen
183 // Flags fuer die gemergten Boxen loeschen
184 aMergeBoxes
.Remove( 0, aMergeBoxes
.Count() );
185 aMergeBoxes
.Insert( (BOOL
)FALSE
, USHORT(0) );
188 // wenn schon in einer Tabellen, dann splitte oder benutze
189 // die bisherigen Boxen weiter
190 bChkExistTbl
= 0 != pDoc
->GetNodes()[ pPam
->GetPoint()->nNode
]->FindTableNode();
195 SwTableLines
& rLns
= pTableNode
->GetTable().GetTabLines();
196 SwTableLine
* pLine
= rLns
[ rLns
.Count()-1 ];
197 // very robust to avoid crashes like bug 127425 + crash reports 118743
200 USHORT nTmpBox
= nAktBox
;
201 if( nTmpBox
> pLine
->GetTabBoxes().Count() )
202 nTmpBox
= pLine
->GetTabBoxes().Count();
204 for( USHORT n
= nTmpBox
; n
; )
206 const SwTableBox
*pTmp
= pLine
->GetTabBoxes()[ --n
];
209 const SwFrmFmt
* pTmpFmt
= pTmp
->GetFrmFmt();
211 nTblSz
+= pTmpFmt
->GetFrmSize().GetWidth();
218 sal_Int16 eAdjust
= text::HoriOrientation::LEFT
; // default fuer Tabellen
222 bool bUseLeftCellPad
= false, bUseRightCellPad
= false,
223 bUseTopCellPad
= false, bUseBottomCellPad
= false;
224 long nLeftCellPad
= 0, nRightCellPad
= 0, nTopCellPad
= 0,
227 sal_Int16 eVerOrient
= text::VertOrientation::NONE
;
228 long nLineHeight
= 0;
229 USHORT nBoxCnt
= aMergeBoxes
.Count()-1;
230 SwBoxFrmFmts aBoxFmts
;
231 SwTableBoxFmt
* pBoxFmt
= pDoc
->MakeTableBoxFmt();
232 SvxFrameDirection eDir
= FRMDIR_HORI_LEFT_TOP
;
233 bool bCantSplit
= false;
240 aRow
.mbUseLeftRowPad
= (nTokenValue
== 3) ? true : false;
243 aRow
.mbUseTopRowPad
= (nTokenValue
== 3) ? true : false;
246 aRow
.mbUseRightRowPad
= (nTokenValue
== 3) ? true : false;
249 aRow
.mbUseBottomRowPad
= (nTokenValue
== 3) ? true : false;
252 aRow
.mnLeftRowPad
= nTokenValue
;
255 aRow
.mnTopRowPad
= nTokenValue
;
258 aRow
.mnRightRowPad
= nTokenValue
;
261 aRow
.mnBottomRowPad
= nTokenValue
;
265 bUseLeftCellPad
= (nTokenValue
== 3) ? true : false;
268 bUseTopCellPad
= (nTokenValue
== 3) ? true : false;
271 bUseRightCellPad
= (nTokenValue
== 3) ? true : false;
274 bUseBottomCellPad
= (nTokenValue
== 3) ? true : false;
277 nLeftCellPad
= nTokenValue
;
280 nTopCellPad
= nTokenValue
;
283 nRightCellPad
= nTokenValue
;
286 nBottomCellPad
= nTokenValue
;
290 nLineHeight
= nTokenValue
;
294 aMergeBoxes
[ nBoxCnt
] = TRUE
;
299 SwTableBoxFmt
* pFmt
= pBoxFmt
;
300 SwTwips nSize
= nTokenValue
- nTblSz
;
301 if( aMergeBoxes
[ nBoxCnt
] )
303 // neue Zellen lesen und noch keine Formate vorhanden,
304 // dann benutze das der vorhergebende
305 if( bReadNewCell
&& !aBoxFmts
.Count() )
307 SwTableLines
& rLns
= pTableNode
->GetTable().GetTabLines();
308 SwTableLine
* pLine
= rLns
[ rLns
.Count()-1 ];
311 pFmt
= (SwTableBoxFmt
*)pLine
->GetTabBoxes()[ nAktBox
]->GetFrmFmt();
314 pFmt
= aBoxFmts
[ aBoxFmts
.Count()-1 ];
316 // --> OD 2007-01-25 #i73790# - method renamed
317 pBoxFmt
->ResetAllFmtAttr();
319 nSize
+= pFmt
->GetFrmSize().GetWidth();
324 if (nSize
<=2*aRow
.mnBrdDist
) {
325 aRow
.mnRightRowPad
=0;
326 aRow
.mbUseRightRowPad
=TRUE
;
328 SetRowBorder((SfxItemSet
&)pBoxFmt
->GetAttrSet(), aRow
);
329 aBoxFmts
.Insert( pBoxFmt
, aBoxFmts
.Count() );
330 pBoxFmt
= pDoc
->MakeTableBoxFmt();
334 nSize
= COL_DFLT_WIDTH
;
335 pFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nSize
, 0 ));
336 nTblSz
= nTokenValue
;
337 aMergeBoxes
.Insert( (BOOL
)FALSE
, ++nBoxCnt
);
339 SvxBoxItem
aBox(pFmt
->GetBox());
341 if (bUseRightCellPad
)
342 aBox
.SetDistance( static_cast< USHORT
>(nRightCellPad
), BOX_LINE_RIGHT
);
343 if (bUseBottomCellPad
)
344 aBox
.SetDistance( static_cast< USHORT
>(nBottomCellPad
), BOX_LINE_BOTTOM
);
346 //Yes, these are the wrong way around, there appears to
347 //be a bug in word where these are swapped.
349 aBox
.SetDistance( static_cast< USHORT
>(nLeftCellPad
), BOX_LINE_TOP
);
351 aBox
.SetDistance( static_cast< USHORT
>(nTopCellPad
), BOX_LINE_LEFT
);
354 /*#106415# The Cell Borders are now balanced on import to
355 improve the layout of tables.
358 if ( aBoxFmts.Count()>1)
361 SwTableBoxFmt* prevpFmt = aBoxFmts[ aBoxFmts.Count()-2 ];
362 SvxBoxItem prevaBox(prevpFmt->GetBox());
363 USHORT prevWidthRight=0;
364 USHORT currWidthLeft=0;
365 bool bDoubleLine=false;
366 const SvxBorderLine* brdrline ;
367 const Color* pPrevRightColor;
368 if(prevaBox.GetRight())
370 brdrline=prevaBox.GetRight();
371 prevWidthRight = brdrline->GetOutWidth();
372 pPrevRightColor = &brdrline->GetColor();
373 if(brdrline->GetInWidth())
378 brdrline=aBox.GetLeft();
379 currWidthLeft = brdrline->GetOutWidth();
380 if(brdrline->GetInWidth())
384 if((currWidthLeft >0 || prevWidthRight >0) &&
387 USHORT newBorderWidth=(currWidthLeft+prevWidthRight)/2 ;
388 if(newBorderWidth /2 ==DEF_LINE_WIDTH_0 )
390 newBorderWidth =DEF_LINE_WIDTH_0;
392 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_4-DEF_LINE_WIDTH_3))
394 newBorderWidth =DEF_LINE_WIDTH_4;
396 else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_3-DEF_LINE_WIDTH_2))
398 newBorderWidth =DEF_LINE_WIDTH_3;
400 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_2-DEF_LINE_WIDTH_1))
402 newBorderWidth =DEF_LINE_WIDTH_2;
404 else if(newBorderWidth /2>=(DEF_LINE_WIDTH_1 - DEF_LINE_WIDTH_0) )
406 newBorderWidth =DEF_LINE_WIDTH_1;
410 newBorderWidth =DEF_LINE_WIDTH_0;
412 const SvxBorderLine newbrdrline(pPrevRightColor, newBorderWidth,0,0);
413 aBox.SetLine(&newbrdrline,BOX_LINE_LEFT);
414 prevaBox.SetLine(&newbrdrline,BOX_LINE_RIGHT);
415 prevpFmt->SetAttr(prevaBox);
421 pFmt
->SetFmtAttr(aBox
);
423 bUseLeftCellPad
= false;
424 bUseRightCellPad
= false;
425 bUseTopCellPad
= false;
426 bUseBottomCellPad
= false;
431 //$flr bug #117887#: RTF: wrong internal table cell margin imported (A13)
432 aRow
.mnBrdDist
= (nTokenValue
>0?(USHORT
)nTokenValue
:0); // filter out negative values of \trgaph
435 case RTF_TRQL
: eAdjust
= text::HoriOrientation::LEFT
; break;
436 case RTF_TRQR
: eAdjust
= text::HoriOrientation::RIGHT
; break;
437 case RTF_TRQC
: eAdjust
= text::HoriOrientation::CENTER
; break;
439 // mit text::VertOrientation::TOP kommt der Dialog nicht klar!
441 case RTF_CLVERTALT
: eVerOrient
= text::VertOrientation::NONE
; break;
443 case RTF_CLVERTALC
: eVerOrient
= text::VertOrientation::CENTER
; break;
444 case RTF_CLVERTALB
: eVerOrient
= text::VertOrientation::BOTTOM
; break;
447 if( text::HoriOrientation::LEFT
== eAdjust
)
448 eAdjust
= text::HoriOrientation::LEFT_AND_WIDTH
;
449 nLSpace
= nTokenValue
;
450 nTblSz
= nTokenValue
;
459 case RTF_INTBL
: // das wissen wir !
465 eDir
= FRMDIR_HORI_LEFT_TOP
;
468 eDir
= FRMDIR_HORI_RIGHT_TOP
;
482 if( ( nToken
& ~(0xff | RTF_TABLEDEF
)) == RTF_SHADINGDEF
)
484 if( aMergeBoxes
[ nBoxCnt
] )
486 ReadBackgroundAttr( nToken
,
487 (SfxItemSet
&)pBoxFmt
->GetAttrSet(), TRUE
);
489 else if( ( nToken
& ~(0xff | RTF_TABLEDEF
) ) == RTF_BRDRDEF
||
490 IsBorderToken(nToken
))
492 if( aMergeBoxes
[ nBoxCnt
] )
495 SfxItemSet
& rSet
= (SfxItemSet
&)pBoxFmt
->GetAttrSet();
496 if(!IsBorderToken( nToken
))
497 ReadBorderAttr( nToken
, rSet
, TRUE
);
501 else if( RTF_TABLEDEF
!= (nToken
& ~(0xff | RTF_SWGDEFS
)) )
503 if( RTF_UNKNOWNCONTROL
== nToken
)
511 if( text::VertOrientation::NONE
!= eVerOrient
)
513 if( !aMergeBoxes
[ nBoxCnt
] )
514 pBoxFmt
->SetFmtAttr( SwFmtVertOrient( 0, eVerOrient
));
515 eVerOrient
= text::VertOrientation::NONE
;
518 nToken
= GetNextToken();
519 } while( bWeiter
&& IsParserWorking() );
521 // das letzte temp. BoxFmt loeschen
524 // es wurde keine einzige Box erkannt
525 if( nAktBox
== nBoxCnt
|| ( bReadNewCell
&& !pTableNode
))
527 int nC
= aMergeBackup
.Count();
528 for (USHORT i
= 0; i
< nC
; ++i
)
529 aMergeBoxes
.Insert(aMergeBackup
[i
], i
);
530 SkipToken( -1 ); // zum Letzen gueltigen zurueck
537 SwTableLine
* pNewLine
;
540 // lege eine neue Tabelle an oder erweiter die aktuelle um eine neue Line
546 // es ist eine Tabelle vorhanden, teste mal ob die weiter benutzt
547 // werden kann oder ob sie abgesplittet und neu gefuellt werden
549 pTableNode
= pPam
->GetNode()->FindTableNode();
551 // Cursor kann nur in der letzten Line stehen
553 // das Attribut darf nicht ueber das Modify an der
554 // Tabelle gesetzt werden, denn sonst werden alle
555 // Boxen wieder auf 0 zurueck gesetzt !!!!!
556 SwFrmFmt
* pFmt
= pTableNode
->GetTable().GetFrmFmt();
557 const SwFmtFrmSize
& rTblSz
= pFmt
->GetFrmSize();
558 const SwFmtHoriOrient
& rHoriz
= pFmt
->GetHoriOrient();
560 const SwTableLines
* pLns
= &pTableNode
->GetTable().GetTabLines();
562 if( 1 == pLns
->Count() )
564 if( eAdjust
!= rHoriz
.GetHoriOrient() )
566 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( SwFmtHoriOrient( 0,
569 if( rTblSz
.GetWidth() != nTblSz
)
571 SwFmtFrmSize
aSz( rTblSz
);
572 aSz
.SetWidth( nTblSz
);
573 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aSz
);
576 if( text::HoriOrientation::LEFT_AND_WIDTH
== eAdjust
&&
577 nLSpace
!= pFmt
->GetLRSpace().GetLeft() )
579 SvxLRSpaceItem
aL( RES_LR_SPACE
); aL
.SetLeft( nLSpace
);
580 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aL
);
587 rTblSz
.GetWidth() != nTblSz
||
588 rHoriz
.GetHoriOrient() != eAdjust
||
590 text::HoriOrientation::LEFT_AND_WIDTH
== eAdjust
&&
591 nLSpace
!= pFmt
->GetLRSpace().GetLeft()
593 pTableNode
->GetTable().GetTabSortBoxes().Count() >= eMAXCELLS
597 // Tabelle ab der PaM-Position splitten
598 // die vorherige Line!
599 pNewLine
= (*pLns
)[ pLns
->Count() - 2 ];
600 SwTableBox
* pBox
= pNewLine
->GetTabBoxes()[ 0 ];
601 while( ( pLns
= &pBox
->GetTabLines() )->Count() )
602 pBox
= (*pLns
)[ 0 ]->GetTabBoxes()[ 0 ];
604 SwNodeIndex
aTmpIdx( *pBox
->GetSttNd() );
605 pDoc
->GetNodes().SplitTable( aTmpIdx
, HEADLINE_NONE
, FALSE
);
606 pTableNode
= pPam
->GetNode()->FindTableNode();
607 pFmt
= pTableNode
->GetTable().GetFrmFmt();
609 SwFmtFrmSize
aSz( rTblSz
);
610 aSz
.SetWidth( nTblSz
);
611 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aSz
);
612 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( SwFmtHoriOrient( 0,
614 if( text::HoriOrientation::LEFT_AND_WIDTH
== eAdjust
&& nLSpace
)
616 SvxLRSpaceItem
aL( RES_LR_SPACE
); aL
.SetLeft( nLSpace
);
617 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aL
);
621 pLns
= &pTableNode
->GetTable().GetTabLines();
622 pNewLine
= (*pLns
)[ pLns
->Count() - 1 ];
624 // jetzt die Boxen abgleichen
625 USHORT nBoxes
= Min( pNewLine
->GetTabBoxes().Count(), aBoxFmts
.Count() );
628 for( n
= 0; n
< nBoxes
; ++n
)
630 SwTableBox
* pBox
= pNewLine
->GetTabBoxes()[ n
];
631 *pBox
->GetFrmFmt() = *aBoxFmts
[ n
];
632 delete aBoxFmts
[ n
];
634 aBoxFmts
.Remove( 0, n
);
636 if( aBoxFmts
.Count() ) // es muessen noch neue zugefuegt werden
638 else // es mussen noch Boxen geloescht werden
640 // remove ContentIndex of other Bound
641 pPam
->SetMark(); pPam
->DeleteMark();
642 while( n
< pNewLine
->GetTabBoxes().Count() )
643 _DeleteBox( pTableNode
->GetTable(),
644 pNewLine
->GetTabBoxes()[ n
], 0, FALSE
, FALSE
);
647 pOldTblNd
= pTableNode
;
651 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
653 aTblFmts
.Insert( p
, aTblFmts
.Count() );
658 if( !bReadNewCell
&& ( pNd
= pDoc
->GetNodes()[
659 pPam
->GetPoint()->nNode
.GetIndex()-1 ])->IsEndNode() )
661 pTableNode
= pNd
->StartOfSectionNode()->GetTableNode();
664 // dann test mal ob wirklich nur eine neue Line eingefuegt
666 SwTable
&rTable
= pTableNode
->GetTable();
667 SwFrmFmt
* pFmt
= rTable
.GetFrmFmt();
668 const SwFmtFrmSize
& rTblSz
= pFmt
->GetFrmSize();
669 const SwFmtHoriOrient
& rHoriz
= pFmt
->GetHoriOrient();
671 rTblSz
.GetWidth() != nTblSz
||
672 rHoriz
.GetHoriOrient() != eAdjust
||
673 rTable
.GetTabSortBoxes().Count() >= eMAXCELLS
681 if( pTableNode
&& !bForceNewTable
)
684 // das Attribut darf nicht ueber das Modify an der
685 // Tabelle gesetzt werden, denn sonst werden alle
686 // Boxen wieder auf 0 zurueck gesetzt !!!!!
687 SwFrmFmt
* pFmt
= pTableNode
->GetTable().GetFrmFmt();
688 const SwFmtFrmSize
& rTblSz
= pFmt
->GetFrmSize();
689 if( rTblSz
.GetWidth() < nTblSz
)
691 SwFmtFrmSize
aSz( rTblSz
);
692 aSz
.SetWidth( nTblSz
);
693 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aSz
);
696 SwTableLines
& rLns
= pTableNode
->GetTable().GetTabLines();
699 pNewLine
= rLns
[ rLns
.Count()-1 ];
702 pNewLine
= new SwTableLine(
703 (SwTableLineFmt
*)rLns
[ rLns
.Count()-1 ]->GetFrmFmt(),
704 aBoxFmts
.Count(), 0 );
705 pNewLine
->ClaimFrmFmt();
706 pNewLine
->GetFrmFmt()->ResetFmtAttr( RES_FRM_SIZE
);
707 rLns
.C40_INSERT( SwTableLine
, pNewLine
, rLns
.Count() );
713 bForceNewTable
= false;
714 const SwTable
*pTable
=
716 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER
, 0 ),
717 *pPam
->GetPoint(), 1, 1, eAdjust
, 0, 0, FALSE
, FALSE
);
718 bContainsTablePara
=true; //#117881#
719 pTableNode
= pTable
? pTable
->GetTableNode() : 0;
723 maSegments
.PrependedInlineNode(*pPam
->GetPoint(),
728 SkipToken( -1 ); // zum Letzen gueltigen zurueck
732 SwTableLines
& rLns
= pTableNode
->GetTable().GetTabLines();
733 pNewLine
= rLns
[ rLns
.Count()-1 ];
735 SwFrmFmt
* pFmt
= pTableNode
->GetTable().GetFrmFmt();
736 SwFmtFrmSize
aSz( pFmt
->GetFrmSize() );
737 aSz
.SetWidth( nTblSz
);
738 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aSz
);
739 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put(SvxFrameDirectionItem(eDir
, RES_FRAMEDIR
));
741 if( text::HoriOrientation::LEFT_AND_WIDTH
== eAdjust
&& nLSpace
)
743 SvxLRSpaceItem
aL( RES_LR_SPACE
); aL
.SetLeft( nLSpace
);
744 ((SfxItemSet
&)pFmt
->GetAttrSet()).Put( aL
);
748 pOldTblNd
= pTableNode
;
751 // JP 13.08.98: TabellenUmrandungen optimieren - Bug 53525
753 aTblFmts
.Insert( p
, aTblFmts
.Count() );
761 if( 0 > nLineHeight
)
762 eSize
= ATT_FIX_SIZE
, nLineHeight
= -nLineHeight
;
764 eSize
= ATT_MIN_SIZE
;
765 pNewLine
->ClaimFrmFmt()->SetFmtAttr(SwFmtFrmSize(eSize
, 0, nLineHeight
));
768 pNewLine
->ClaimFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bCantSplit
));
770 if( aBoxFmts
.Count() )
772 // setze das default Style
773 SwTxtFmtColl
* pColl
= aTxtCollTbl
.Get( 0 );
775 pColl
= pDoc
->GetTxtCollFromPool( RES_POOLCOLL_STANDARD
, false );
780 SwTableBox
* pBox
= pNewLine
->GetTabBoxes()[0];
781 pBoxFmt
= (SwTableBoxFmt
*)pBox
->GetFrmFmt();
782 pBoxFmt
->Remove( pBox
);
784 aBoxFmts
[0]->Add( pBox
);
785 SwTxtNode
* pTNd
= pDoc
->GetNodes()[ pBox
->GetSttIdx()+1 ]
787 ASSERT( pTNd
, "wo ist der Textnode dieser Box?" );
788 pTNd
->ChgFmtColl( pColl
);
793 for( ; nStt
< aBoxFmts
.Count(); ++nStt
)
795 pDoc
->GetNodes().InsBoxen( pTableNode
, pNewLine
,
797 // Formate fuer den TextNode der Box
806 maInsertedTables
.InsertTable(*pTableNode
, *pPam
);
808 SwNodeIndex
aOldIdx(pPam
->GetPoint()->nNode
);
809 SwNodeIdx
aOldPos(aOldIdx
);
812 bool bFailure
= true;
815 SwTableBoxes
&rBoxes
= pNewLine
->GetTabBoxes();
816 if (SwTableBox
* pBox
= (nAktBox
< rBoxes
.Count() ? rBoxes
[nAktBox
] : 0))
818 if (const SwStartNode
*pStart
= pBox
->GetSttNd())
820 if (const SwEndNode
*pEnd
= pStart
->EndOfSectionNode())
822 pPam
->GetPoint()->nNode
= *pEnd
;
823 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
830 ASSERT(!bFailure
, "RTF Table failure");
833 SkipToken( -1 ); // zum Letzen gueltigen zurueck
837 //It might be that there was content at this point which is not already in
838 //a table, but which is being followed by properties to place it into the
839 //table. e.g. #109199#. If this is the case then move the para/char
840 //properties inside the table, and move any content of that paragraph into
842 bool bInTable
= aRg
.GetPoint()->nNode
.GetNode().FindTableNode();
845 SwNodeIndex
aNewIdx(pPam
->GetPoint()->nNode
);
846 SwNodeIdx
aNewPos(aNewIdx
);
848 if (aRg
.GetPoint()->nContent
.GetIndex())
850 //If there is content in this node then move it entirely inside the
853 aRg
.GetMark()->nContent
.Assign(aRg
.GetCntntNode(), 0);
854 pDoc
->MoveRange(aRg
, *pPam
->GetPoint(),
855 IDocumentContentOperations::DOC_MOVEDEFAULT
);
858 //Update the attribute stack entries to reflect that the properties
859 //which were intended to be inside the tablerow are now left outside
860 //the table after the row was placed before the current insertion point
861 SvxRTFItemStack
& rAttrStk
= GetAttrStack();
862 for (USHORT n
= 0; n
< rAttrStk
.Count(); ++n
)
864 SvxRTFItemStackType
* pStk
= rAttrStk
[n
];
865 pStk
->MoveFullNode(aOldPos
, aNewPos
);
868 SkipToken( -1 ); // zum Letzen gueltigen zurueck
871 // in die naechste Box dieser Line (opt.: falls es nicht die letzte ist)
872 void SwRTFParser::GotoNextBox()
874 nInsTblRow
= USHRT_MAX
;
876 ASSERT( pTableNode
, "Kein Tabellennode, dann auch keine Box" );
881 SwTableLines
& rLns
= pTableNode
->GetTable().GetTabLines();
882 SwTableLine
* pLine
= rLns
[ rLns
.Count()-1 ];
883 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
884 SwTableBox
* pBox
= rBoxes
[ rBoxes
.Count()-1 ];
886 if( ++nAktBox
>= aMergeBoxes
.Count() )
887 nAktBox
= aMergeBoxes
.Count()-1;
889 if( !aMergeBoxes
[ nAktBox
] )
892 if( pBox
->GetSttIdx() > pPam
->GetPoint()->nNode
.GetIndex() )
895 for( USHORT nTmp
= 0; nTmp
< nAktBox
; ++nTmp
)
896 if( !aMergeBoxes
[ nTmp
] )
899 if( nRealBox
< rBoxes
.Count() )
901 pPam
->GetPoint()->nNode
= *rBoxes
[ nRealBox
]->GetSttNd()->EndOfSectionNode();
902 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
907 if( bMove
&& nAktBox
+ 1 == aMergeBoxes
.Count() )
908 // dann hinter die Tabelle
909 pPam
->Move( fnMoveForward
, fnGoNode
);
911 else if( !pDoc
->GetNodes()[ pPam
->GetPoint()->nNode
]->IsCntntNode() )
912 // dann in die vorherige ans Ende
913 pPam
->Move( fnMoveBackward
, fnGoCntnt
);
917 void SwRTFParser::NewTblLine()
919 nInsTblRow
= USHRT_MAX
;
921 // erweiter die aktuelle um eine neue Line
922 BOOL bMakeCopy
= FALSE
;
923 SwNode
* pNd
= pDoc
->GetNodes()[ pPam
->GetPoint()->nNode
.GetIndex()-1 ];
924 if( !pNd
->IsEndNode() ||
925 !(pNd
= pNd
->StartOfSectionNode())->IsTableNode() )
933 pTableNode
= (SwTableNode
*)pNd
;
935 SwTableLines
* pLns
= &pTableNode
->GetTable().GetTabLines();
936 SwTableLine
* pLine
= (*pLns
)[ pLns
->Count()-1 ];
937 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
938 SwTableBox
* pBox
= rBoxes
[ rBoxes
.Count()-1 ];
941 pTableNode
->GetTable().SetRowsToRepeat( nRowsToRepeat
);
944 64000 < pTableNode
->GetTable().GetTabSortBoxes().Count() )
946 bMakeCopy
= TRUE
; // spaetestens jetzt eine neue anfangen!
951 // und die Selektion kopieren
953 pTableNode
->GetTable().SelLineFromBox( pBox
, aBoxes
);
954 pTableNode
->GetTable().MakeCopy( pDoc
, *pPam
->GetPoint(),
956 ULONG nNd
= pPam
->GetPoint()->nNode
.GetIndex()-1;
957 pTableNode
= pDoc
->GetNodes()[ nNd
]->FindTableNode();
958 pOldTblNd
= pTableNode
;
961 pTableNode
->GetTable().SetRowsToRepeat(nRowsToRepeat
);
962 pLns
= &pTableNode
->GetTable().GetTabLines();
965 // pDoc->InsertRow( aBoxes );
966 pTableNode
->GetTable().AppendRow( pDoc
);
968 pBox
= (*pLns
)[ pLns
->Count()-1 ]->GetTabBoxes()[0];
970 ULONG nOldPos
= pPam
->GetPoint()->nNode
.GetIndex();
971 pPam
->GetPoint()->nNode
= *pBox
->GetSttNd();
972 pPam
->Move( fnMoveForward
);
975 // alle Nodes in den Boxen auf die "default" Vorlage setzten
977 SwTxtFmtColl
* pColl
= aTxtCollTbl
.Get( 0 );
979 pColl
= pDoc
->GetTxtCollFromPool( RES_POOLCOLL_STANDARD
, false );
982 pLine
= (*pLns
)[ pLns
->Count()-1 ];
983 pBox
= pLine
->GetTabBoxes()[ pLine
->GetTabBoxes().Count() -1 ];
984 pPam
->GetPoint()->nNode
= *pBox
->GetSttNd()->EndOfSectionNode();
985 pPam
->Move( fnMoveBackward
);
986 pDoc
->SetTxtFmtColl( *pPam
, pColl
);
987 // Bug 73940 - remove ALL attributes (NumRules/Break/etc.)
989 SwNodeIndex
aIdx( pPam
->GetMark()->nNode
);
990 SwNodeIndex
& rEndIdx
= pPam
->GetPoint()->nNode
;
991 while( aIdx
<= rEndIdx
)
993 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
994 if( pCNd
&& pCNd
->HasSwAttrSet() )
995 pCNd
->ResetAllAttr();
1003 // alle Attribute, die schon auf den nachfolgen zeigen auf die neue
1005 SvxRTFItemStack
& rAttrStk
= GetAttrStack();
1006 const SvxRTFItemStackType
* pStk
;
1007 for( USHORT n
= 0; n
< rAttrStk
.Count(); ++n
)
1008 if( ( pStk
= rAttrStk
[ n
])->GetSttNodeIdx() == ULONG(nOldPos
) &&
1009 !pStk
->GetSttCnt() )
1010 ((SvxRTFItemStackType
*)pStk
)->SetStartPos( SwxPosition( pPam
) );
1013 void SwRTFParser::CheckInsNewTblLine()
1015 if( USHRT_MAX
!= nInsTblRow
)
1017 if( nInsTblRow
> GetOpenBrakets() || IsPardTokenRead() )
1018 nInsTblRow
= USHRT_MAX
;
1019 else if( !pTableNode
) // Tabelle nicht mehr vorhanden ?
1020 NewTblLine(); // evt. Line copieren
1024 /* vi:set tabstop=4 shiftwidth=4 expandtab: */