blob: 4b85cf1da011d47cf209ce0f508fcbf274a4616a [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
#ifdef WTC
#define private public
#endif
#include <hintids.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <svtools/rtftoken.h>
#include <fmtfsize.hxx>
#include <fmtpdsc.hxx>
#include <ndtxt.hxx>
#include <doc.hxx>
#include <pam.hxx>
#include <swparrtf.hxx>
#include <swtable.hxx>
#include <tblsel.hxx>
#include <swtblfmt.hxx>
#include <wrtswtbl.hxx>
#include <tblenum.hxx>
#include <frmatr.hxx>
#include <fmtrowsplt.hxx>
using namespace ::com::sun::star;
typedef SwTableBoxFmt* SwTableBoxFmtPtr;
SV_DECL_PTRARR( SwBoxFrmFmts, SwTableBoxFmtPtr, 25, 50 )
class SwShareBoxFmts;
extern void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* = 0,
sal_Bool = sal_True, const sal_Bool = sal_True, SwShareBoxFmts* = 0 );
struct Row
{
bool mbUseLeftRowPad, mbUseRightRowPad, mbUseTopRowPad, mbUseBottomRowPad;
long mnLeftRowPad, mnRightRowPad, mnTopRowPad, mnBottomRowPad;
sal_uInt16 mnBrdDist;
Row() :
mbUseLeftRowPad(false), mbUseRightRowPad(false),
mbUseTopRowPad(false), mbUseBottomRowPad(false),
mnLeftRowPad(0), mnRightRowPad(0), mnTopRowPad(0), mnBottomRowPad(0),
mnBrdDist(MIN_BORDER_DIST)
{}
};
static void SetRowBorder(SfxItemSet& rSet, const Row &rRow)
{
#if 1
SvxBoxItem aBox((const SvxBoxItem&)rSet.Get(RES_BOX, false));
aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist),
BOX_LINE_LEFT);
aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist),
BOX_LINE_RIGHT);
aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0),
BOX_LINE_TOP);
aBox.SetDistance( static_cast< sal_uInt16 >(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0),
BOX_LINE_BOTTOM);
rSet.Put(aBox);
#else
const SfxPoolItem* pItem;
if (SFX_ITEM_SET == rSet.GetItemState(RES_BOX, sal_False, &pItem))
{
SvxBoxItem aBox( *(SvxBoxItem*)pItem );
aBox.SetDistance(rRow.mbUseLeftRowPad ? rRow.mnLeftRowPad : rRow.mnBrdDist,
BOX_LINE_LEFT);
aBox.SetDistance(rRow.mbUseRightRowPad ? rRow.mnRightRowPad : rRow.mnBrdDist,
BOX_LINE_RIGHT);
aBox.SetDistance(rRow.mbUseTopRowPad ? rRow.mnTopRowPad : 0,
BOX_LINE_TOP);
aBox.SetDistance(rRow.mbUseBottomRowPad ? rRow.mnBottomRowPad : 0,
BOX_LINE_BOTTOM);
rSet.Put(aBox);
}
#endif
}
void rtfSections::PrependedInlineNode(const SwPosition &rPos,
const SwNode &rNode)
{
ASSERT(!mrReader.IsNewDoc() || !maSegments.empty(),
"should not be possible, must be at least one segment in a new document");
if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
maSegments.back().maStart = SwNodeIndex(rNode);
}
bool SwRTFParser::IsBorderToken(int nToken)
{
/*
i30222 i28983
Our ability to sense border tokens is broken rtftoken.h is
organised in a way that ignores some border tokens. ReadBorderAttr
still doesn't support the more exotic borders but at least this
won't cause the parser to prematuerely exit the table
*/
bool bResult = false;
bResult = (nToken >= RTF_BRDRDASHD && nToken <= RTF_BRDRTHTNMG) ||
(nToken >= RTF_BRDRTNTHSG && nToken <= RTF_BRDRWAVY);
return bResult;
}
void SwRTFParser::ReadTable( int nToken )
{
nInsTblRow = USHRT_MAX;
if (CantUseTables())
{
// alle Tabellen-Tokens ueberlesen
nToken = GetNextToken(); // RTF_TROWD ueberlesen
do {
if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) &&
RTF_UNKNOWNCONTROL != nToken )
{
SkipToken( -1 );
break;
}
nToken = GetNextToken();
} while( IsParserWorking() );
return ;
}
// verhinder Tabelle in Tabelle/Footnote
SwTwips nTblSz = 0;
int bReadNewCell = sal_False, bChkExistTbl = sal_False;
enum Limits {eMAXCELLS=64000};
SvBools aMergeBackup(aMergeBoxes);
// kein TROWD aber ein TabellenToken -> zwischen TROWD und Tab.Token
// waren andere Zeichen (siehe Bug 27445.rtf)
if( RTF_TROWD == nToken || !pTableNode )
{
if( RTF_TROWD == nToken )
nToken = GetNextToken(); // RTF_TROWD ueberlesen
// Flag for delete merged boxes
aMergeBoxes.clear();
aMergeBoxes.push_back( (sal_Bool)sal_False );
m_nCurrentBox = 0;
// wenn schon in einer Tabellen, dann splitte oder benutze
// die bisherigen Boxen weiter
bChkExistTbl = 0 != pPam->GetPoint()->nNode.GetNode().FindTableNode();
}
else
{
bReadNewCell = sal_True;
SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
SwTableLine* pLine = rLns[ rLns.Count()-1 ];
// very robust to avoid crashes like bug 127425 + crash reports 118743
if( pLine )
{
sal_uInt16 nTmpBox = m_nCurrentBox;
if( nTmpBox > pLine->GetTabBoxes().Count() )
nTmpBox = pLine->GetTabBoxes().Count();
for (sal_uInt16 n = nTmpBox; n; )
{
const SwTableBox *pTmp = pLine->GetTabBoxes()[ --n ];
if( pTmp )
{
const SwFrmFmt* pTmpFmt = pTmp->GetFrmFmt();
if( pTmpFmt )
nTblSz += pTmpFmt->GetFrmSize().GetWidth();
}
}
}
}
sal_Int16 eAdjust = text::HoriOrientation::LEFT; // default fuer Tabellen
SwTwips nLSpace = 0;
Row aRow;
bool bUseLeftCellPad = false, bUseRightCellPad = false,
bUseTopCellPad = false, bUseBottomCellPad = false;
long nLeftCellPad = 0, nRightCellPad = 0, nTopCellPad = 0,
nBottomCellPad = 0;
sal_Int16 eVerOrient = text::VertOrientation::NONE;
long nLineHeight = 0;
if (aMergeBoxes.empty()) // can this actually happen?
{
OSL_ASSERT(false);
aMergeBoxes.push_back(sal_False);
}
size_t nBoxCnt = aMergeBoxes.size()-1;
SwBoxFrmFmts aBoxFmts;
SwTableBoxFmt* pBoxFmt = pDoc->MakeTableBoxFmt();
SvxFrameDirection eDir = FRMDIR_HORI_LEFT_TOP;
bool bCantSplit = false;
int bWeiter = sal_True;
do {
switch( nToken )
{
case RTF_TRPADDFL:
aRow.mbUseLeftRowPad = (nTokenValue == 3) ? true : false;
break;
case RTF_TRPADDFT:
aRow.mbUseTopRowPad = (nTokenValue == 3) ? true : false;
break;
case RTF_TRPADDFR:
aRow.mbUseRightRowPad = (nTokenValue == 3) ? true : false;
break;
case RTF_TRPADDFB:
aRow.mbUseBottomRowPad = (nTokenValue == 3) ? true : false;
break;
case RTF_TRPADDL:
aRow.mnLeftRowPad = nTokenValue;
break;
case RTF_TRPADDT:
aRow.mnTopRowPad = nTokenValue;
break;
case RTF_TRPADDR:
aRow.mnRightRowPad = nTokenValue;
break;
case RTF_TRPADDB:
aRow.mnBottomRowPad = nTokenValue;
break;
case RTF_CLPADFL:
bUseLeftCellPad = (nTokenValue == 3) ? true : false;
break;
case RTF_CLPADFT:
bUseTopCellPad = (nTokenValue == 3) ? true : false;
break;
case RTF_CLPADFR:
bUseRightCellPad = (nTokenValue == 3) ? true : false;
break;
case RTF_CLPADFB:
bUseBottomCellPad = (nTokenValue == 3) ? true : false;
break;
case RTF_CLPADL:
nLeftCellPad = nTokenValue;
break;
case RTF_CLPADT:
nTopCellPad = nTokenValue;
break;
case RTF_CLPADR:
nRightCellPad = nTokenValue;
break;
case RTF_CLPADB:
nBottomCellPad = nTokenValue;
break;
case RTF_TRRH:
nLineHeight = nTokenValue;
break;
case RTF_CLMRG:
// would crash later on reading \cellx (#i112657#):
// the first cell cannot be merged with earlier ones.
if (nBoxCnt != 0)
{
aMergeBoxes.back() = sal_True;
}
break;
case RTF_CELLX:
if (!bTrowdRead && (aMergeBoxes.size() < (SAL_MAX_UINT16 - 1)))
{
SwTableBoxFmt* pFmt = pBoxFmt;
SwTwips nSize = nTokenValue - nTblSz;
if( aMergeBoxes.back() )
{
// neue Zellen lesen und noch keine Formate vorhanden,
// dann benutze das der vorhergebende
if( bReadNewCell && !aBoxFmts.Count() )
{
SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
SwTableLine* pLine = rLns[ rLns.Count()-1 ];
if (m_nCurrentBox != 0)
{
--m_nCurrentBox;
}
if (m_nCurrentBox < pLine->GetTabBoxes().Count())
{
pFmt = static_cast<SwTableBoxFmt*>(
pLine->GetTabBoxes()[m_nCurrentBox]->GetFrmFmt());
}
}
else
pFmt = aBoxFmts[ aBoxFmts.Count()-1 ];
// --> OD 2007-01-25 #i73790# - method renamed
pBoxFmt->ResetAllFmtAttr();
// <--
nSize += pFmt->GetFrmSize().GetWidth();
}
else
{
//
if (nSize<=2*aRow.mnBrdDist) {
aRow.mnRightRowPad=0;
aRow.mbUseRightRowPad=sal_True;
}
SetRowBorder((SfxItemSet&)pBoxFmt->GetAttrSet(), aRow);
aBoxFmts.Insert( pBoxFmt, aBoxFmts.Count() );
pBoxFmt = pDoc->MakeTableBoxFmt();
}
if( !nSize )
nSize = COL_DFLT_WIDTH;
pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nSize, 0 ));
nTblSz = nTokenValue;
aMergeBoxes.push_back( (sal_Bool)sal_False );
++nBoxCnt;
SvxBoxItem aBox(pFmt->GetBox());
if (bUseRightCellPad)
aBox.SetDistance( static_cast< sal_uInt16 >(nRightCellPad), BOX_LINE_RIGHT);
if (bUseBottomCellPad)
aBox.SetDistance( static_cast< sal_uInt16 >(nBottomCellPad), BOX_LINE_BOTTOM);
//Yes, these are the wrong way around, there appears to
//be a bug in word where these are swapped.
if (bUseLeftCellPad)
aBox.SetDistance( static_cast< sal_uInt16 >(nLeftCellPad), BOX_LINE_TOP);
if (bUseTopCellPad)
aBox.SetDistance( static_cast< sal_uInt16 >(nTopCellPad), BOX_LINE_LEFT);
/*#106415# The Cell Borders are now balanced on import to
improve the layout of tables.
*/
/*
if ( aBoxFmts.Count()>1)
{
SwTableBoxFmt* prevpFmt = aBoxFmts[ aBoxFmts.Count()-2 ];
SvxBoxItem prevaBox(prevpFmt->GetBox());
sal_uInt16 prevWidthRight=0;
sal_uInt16 currWidthLeft=0;
bool bDoubleLine=false;
const SvxBorderLine* brdrline ;
const Color* pPrevRightColor;
if(prevaBox.GetRight())
{
brdrline=prevaBox.GetRight();
prevWidthRight = brdrline->GetOutWidth();
pPrevRightColor = &brdrline->GetColor();
if(brdrline->GetInWidth())
bDoubleLine=true;
}
if(aBox.GetLeft())
{
brdrline=aBox.GetLeft();
currWidthLeft = brdrline->GetOutWidth();
if(brdrline->GetInWidth())
bDoubleLine=true;
}
if((currWidthLeft >0 || prevWidthRight >0) &&
!bDoubleLine)
{
sal_uInt16 newBorderWidth=(currWidthLeft+prevWidthRight)/2 ;
if(newBorderWidth /2 ==DEF_LINE_WIDTH_0 )
{
newBorderWidth =DEF_LINE_WIDTH_0;
}
else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_4-DEF_LINE_WIDTH_3))
{
newBorderWidth =DEF_LINE_WIDTH_4;
}
else if(newBorderWidth /2 >=(DEF_LINE_WIDTH_3-DEF_LINE_WIDTH_2))
{
newBorderWidth =DEF_LINE_WIDTH_3;
}
else if(newBorderWidth /2>=(DEF_LINE_WIDTH_2-DEF_LINE_WIDTH_1))
{
newBorderWidth =DEF_LINE_WIDTH_2;
}
else if(newBorderWidth /2>=(DEF_LINE_WIDTH_1 - DEF_LINE_WIDTH_0) )
{
newBorderWidth =DEF_LINE_WIDTH_1;
}
else
{
newBorderWidth =DEF_LINE_WIDTH_0;
}
const SvxBorderLine newbrdrline(pPrevRightColor, newBorderWidth,0,0);
aBox.SetLine(&newbrdrline,BOX_LINE_LEFT);
prevaBox.SetLine(&newbrdrline,BOX_LINE_RIGHT);
prevpFmt->SetAttr(prevaBox);
}
}
*/
pFmt->SetFmtAttr(aBox);
bUseLeftCellPad = false;
bUseRightCellPad = false;
bUseTopCellPad = false;
bUseBottomCellPad = false;
}
break;
case RTF_TRGAPH:
//$flr bug #117887#: RTF: wrong internal table cell margin imported (A13)
aRow.mnBrdDist = (nTokenValue>0?(sal_uInt16)nTokenValue:0); // filter out negative values of \trgaph
break;
case RTF_TRQL: eAdjust = text::HoriOrientation::LEFT; break;
case RTF_TRQR: eAdjust = text::HoriOrientation::RIGHT; break;
case RTF_TRQC: eAdjust = text::HoriOrientation::CENTER; break;
// mit text::VertOrientation::TOP kommt der Dialog nicht klar!
// Bug #65126#
case RTF_CLVERTALT: eVerOrient = text::VertOrientation::NONE; break;
case RTF_CLVERTALC: eVerOrient = text::VertOrientation::CENTER; break;
case RTF_CLVERTALB: eVerOrient = text::VertOrientation::BOTTOM; break;
case RTF_TRLEFT:
if( text::HoriOrientation::LEFT == eAdjust )
eAdjust = text::HoriOrientation::LEFT_AND_WIDTH;
nLSpace = nTokenValue;
nTblSz = nTokenValue;
break;
case RTF_TRHDR:
nRowsToRepeat++;
break;
case RTF_CLTXLRTB:
case RTF_CLTXTBRL:
case RTF_INTBL: // das wissen wir !
case RTF_CLMGF:
case RTF_CLVMGF:
case RTF_CLVMRG:
break;
case RTF_LTRROW:
eDir = FRMDIR_HORI_LEFT_TOP;
break;
case RTF_RTLROW:
eDir = FRMDIR_HORI_RIGHT_TOP;
break;
case RTF_TRBRDRB:
case RTF_TRBRDRH:
case RTF_TRBRDRL:
case RTF_TRBRDRR:
case RTF_TRBRDRT:
case RTF_TRBRDRV:
break;
case RTF_TRKEEP:
bCantSplit = true;
break;
default:
if( ( nToken & ~(0xff | RTF_TABLEDEF)) == RTF_SHADINGDEF )
{
if( aMergeBoxes.back() )
break;
ReadBackgroundAttr( nToken,
(SfxItemSet&)pBoxFmt->GetAttrSet(), sal_True );
}
else if( ( nToken & ~(0xff | RTF_TABLEDEF) ) == RTF_BRDRDEF ||
IsBorderToken(nToken))
{
if( aMergeBoxes.back() )
break;
SfxItemSet& rSet = (SfxItemSet&)pBoxFmt->GetAttrSet();
if(!IsBorderToken( nToken ))
ReadBorderAttr( nToken, rSet, sal_True );
else
NextToken( nToken );
}
else if( RTF_TABLEDEF != (nToken & ~(0xff | RTF_SWGDEFS)) )
{
if( RTF_UNKNOWNCONTROL == nToken )
NextToken( nToken );
else
bWeiter = sal_False;
}
break;
}
if( text::VertOrientation::NONE != eVerOrient )
{
if( !aMergeBoxes.back() )
pBoxFmt->SetFmtAttr( SwFmtVertOrient( 0, eVerOrient ));
eVerOrient = text::VertOrientation::NONE;
}
if( bWeiter )
nToken = GetNextToken();
} while( bWeiter && IsParserWorking() );
// das letzte temp. BoxFmt loeschen
delete pBoxFmt;
// It has been recognized as not single box
if ((m_nCurrentBox == nBoxCnt) || ( bReadNewCell && !pTableNode ))
{
aMergeBoxes = aMergeBackup;
SkipToken( -1 ); // go back to the last valid
return;
}
nTblSz -= nLSpace;
int bNewTbl = sal_True;
SwTableLine* pNewLine;
bTrowdRead=true;
// lege eine neue Tabelle an oder erweiter die aktuelle um eine neue Line
// oder Box !
SwNode* pNd;
if( bChkExistTbl )
{
// es ist eine Tabelle vorhanden, teste mal ob die weiter benutzt
// werden kann oder ob sie abgesplittet und neu gefuellt werden
// muss.
pTableNode = pPam->GetNode()->FindTableNode();
// Cursor kann nur in der letzten Line stehen
// das Attribut darf nicht ueber das Modify an der
// Tabelle gesetzt werden, denn sonst werden alle
// Boxen wieder auf 0 zurueck gesetzt !!!!!
SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
const SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
if( 1 == pLns->Count() )
{
if( eAdjust != rHoriz.GetHoriOrient() )
{
((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
eAdjust ) );
}
if( rTblSz.GetWidth() != nTblSz )
{
SwFmtFrmSize aSz( rTblSz );
aSz.SetWidth( nTblSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
}
if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
nLSpace != pFmt->GetLRSpace().GetLeft() )
{
SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
}
}
else if
(
1 < pLns->Count() &&
(
rTblSz.GetWidth() != nTblSz ||
rHoriz.GetHoriOrient() != eAdjust ||
(
text::HoriOrientation::LEFT_AND_WIDTH == eAdjust &&
nLSpace != pFmt->GetLRSpace().GetLeft()
) ||
pTableNode->GetTable().GetTabSortBoxes().Count() >= eMAXCELLS
)
)
{
// Tabelle ab der PaM-Position splitten
// die vorherige Line!
pNewLine = (*pLns)[ pLns->Count() - 2 ];
SwTableBox* pBox = pNewLine->GetTabBoxes()[ 0 ];
while( ( pLns = &pBox->GetTabLines() )->Count() )
pBox = (*pLns)[ 0 ]->GetTabBoxes()[ 0 ];
SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
pDoc->GetNodes().SplitTable( aTmpIdx, HEADLINE_NONE, sal_False );
pTableNode = pPam->GetNode()->FindTableNode();
pFmt = pTableNode->GetTable().GetFrmFmt();
SwFmtFrmSize aSz( rTblSz );
aSz.SetWidth( nTblSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put( SwFmtHoriOrient( 0,
eAdjust ) );
if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
{
SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
}
}
pLns = &pTableNode->GetTable().GetTabLines();
pNewLine = (*pLns)[ pLns->Count() - 1 ];
// jetzt die Boxen abgleichen
sal_uInt16 nBoxes = Min( pNewLine->GetTabBoxes().Count(), aBoxFmts.Count() );
sal_uInt16 n;
for( n = 0; n < nBoxes; ++n )
{
SwTableBox* pBox = pNewLine->GetTabBoxes()[ n ];
*pBox->GetFrmFmt() = *aBoxFmts[ n ];
delete aBoxFmts[ n ];
}
aBoxFmts.Remove( 0, n );
if( aBoxFmts.Count() ) // es muessen noch neue zugefuegt werden
{
m_nCurrentBox = n;
}
else // es mussen noch Boxen geloescht werden
{
// remove ContentIndex of other Bound
pPam->SetMark(); pPam->DeleteMark();
while( n < pNewLine->GetTabBoxes().Count() )
_DeleteBox( pTableNode->GetTable(),
pNewLine->GetTabBoxes()[ n ], 0, sal_False, sal_False );
}
pOldTblNd = pTableNode;
bNewTbl = sal_False;
}
else
{
if( !bReadNewCell && ( pNd = pDoc->GetNodes()[
pPam->GetPoint()->nNode.GetIndex()-1 ])->IsEndNode() )
{
pTableNode = pNd->StartOfSectionNode()->GetTableNode();
if( pTableNode )
{
// dann test mal ob wirklich nur eine neue Line eingefuegt
// werden soll!
SwTable &rTable = pTableNode->GetTable();
SwFrmFmt* pFmt = rTable.GetFrmFmt();
const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
const SwFmtHoriOrient& rHoriz = pFmt->GetHoriOrient();
if (
rTblSz.GetWidth() != nTblSz ||
rHoriz.GetHoriOrient() != eAdjust ||
rTable.GetTabSortBoxes().Count() >= eMAXCELLS
)
{
pTableNode = 0;
}
}
}
if( pTableNode && !bForceNewTable)
{
// das Attribut darf nicht ueber das Modify an der
// Tabelle gesetzt werden, denn sonst werden alle
// Boxen wieder auf 0 zurueck gesetzt !!!!!
SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
const SwFmtFrmSize& rTblSz = pFmt->GetFrmSize();
if( rTblSz.GetWidth() < nTblSz )
{
SwFmtFrmSize aSz( rTblSz );
aSz.SetWidth( nTblSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
}
SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
if( bReadNewCell )
pNewLine = rLns[ rLns.Count()-1 ];
else
{
pNewLine = new SwTableLine(
(SwTableLineFmt*)rLns[ rLns.Count()-1 ]->GetFrmFmt(),
aBoxFmts.Count(), 0 );
pNewLine->ClaimFrmFmt();
pNewLine->GetFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
rLns.C40_INSERT( SwTableLine, pNewLine, rLns.Count() );
}
bNewTbl = sal_False;
}
else
{
bForceNewTable = false;
const SwTable *pTable =
pDoc->InsertTable(
SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
*pPam->GetPoint(), 1, 1, eAdjust, 0, 0, sal_False, sal_False );
bContainsTablePara=true; //#117881#
pTableNode = pTable ? pTable->GetTableNode() : 0;
if (pTableNode)
{
maSegments.PrependedInlineNode(*pPam->GetPoint(),
*pTableNode);
}
else
{
SkipToken( -1 ); // zum Letzen gueltigen zurueck
return;
}
SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
pNewLine = rLns[ rLns.Count()-1 ];
SwFrmFmt* pFmt = pTableNode->GetTable().GetFrmFmt();
SwFmtFrmSize aSz( pFmt->GetFrmSize() );
aSz.SetWidth( nTblSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aSz );
((SfxItemSet&)pFmt->GetAttrSet()).Put(SvxFrameDirectionItem(eDir, RES_FRAMEDIR));
if( text::HoriOrientation::LEFT_AND_WIDTH == eAdjust && nLSpace )
{
SvxLRSpaceItem aL( RES_LR_SPACE ); aL.SetLeft( nLSpace );
((SfxItemSet&)pFmt->GetAttrSet()).Put( aL );
}
m_nCurrentBox = 0;
pOldTblNd = pTableNode;
}
}
if( nLineHeight )
{
SwFrmSize eSize;
if( 0 > nLineHeight )
eSize = ATT_FIX_SIZE, nLineHeight = -nLineHeight;
else
eSize = ATT_MIN_SIZE;
pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtFrmSize(eSize, 0, nLineHeight));
}
pNewLine->ClaimFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bCantSplit));
if( aBoxFmts.Count() )
{
// setze das default Style
SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
if( !pColl )
pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
sal_uInt16 nStt = 0;
if( bNewTbl )
{
SwTableBox* pBox = pNewLine->GetTabBoxes()[0];
pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
pBox->ForgetFrmFmt();
delete pBoxFmt;
pBox->RegisterToFormat( *aBoxFmts[0] );
SwTxtNode* pTNd = pDoc->GetNodes()[ pBox->GetSttIdx()+1 ]
->GetTxtNode();
ASSERT( pTNd, "wo ist der Textnode dieser Box?" );
pTNd->ChgFmtColl( pColl );
++nStt;
nRowsToRepeat=0;
}
for( ; nStt < aBoxFmts.Count(); ++nStt )
{
pDoc->GetNodes().InsBoxen( pTableNode, pNewLine,
aBoxFmts[ nStt ],
// Formate fuer den TextNode der Box
pColl, 0,
m_nCurrentBox + nStt, 1 );
}
}
if( bChkExistTbl )
{
m_nCurrentBox = 0;
}
maInsertedTables.InsertTable(*pTableNode, *pPam);
SwNodeIndex aOldIdx(pPam->GetPoint()->nNode);
SwNodeIdx aOldPos(aOldIdx);
SwPaM aRg(*pPam);
bool bFailure = true;
if (pNewLine)
{
SwTableBoxes &rBoxes = pNewLine->GetTabBoxes();
if (SwTableBox* pBox = ((m_nCurrentBox < rBoxes.Count())
? rBoxes[m_nCurrentBox] : 0))
{
if (const SwStartNode *pStart = pBox->GetSttNd())
{
if (const SwEndNode *pEnd = pStart->EndOfSectionNode())
{
pPam->GetPoint()->nNode = *pEnd;
pPam->Move( fnMoveBackward, fnGoCntnt );
bFailure = false;
}
}
}
}
ASSERT(!bFailure, "RTF Table failure");
if (bFailure)
{
SkipToken( -1 ); // zum Letzen gueltigen zurueck
return;
}
//It might be that there was content at this point which is not already in
//a table, but which is being followed by properties to place it into the
//table. e.g. #109199#. If this is the case then move the para/char
//properties inside the table, and move any content of that paragraph into
//the table
bool bInTable = aRg.GetPoint()->nNode.GetNode().FindTableNode();
if (!bInTable)
{
SwNodeIndex aNewIdx(pPam->GetPoint()->nNode);
SwNodeIdx aNewPos(aNewIdx);
if (aRg.GetPoint()->nContent.GetIndex())
{
//If there is content in this node then move it entirely inside the
//table
aRg.SetMark();
aRg.GetMark()->nContent.Assign(aRg.GetCntntNode(), 0);
pDoc->MoveRange(aRg, *pPam->GetPoint(),
IDocumentContentOperations::DOC_MOVEDEFAULT);
}
//Update the attribute stack entries to reflect that the properties
//which were intended to be inside the tablerow are now left outside
//the table after the row was placed before the current insertion point
SvxRTFItemStack& rAttrStk = GetAttrStack();
for (size_t n = 0; n < rAttrStk.size(); ++n)
{
SvxRTFItemStackType* pStk = rAttrStk[n];
pStk->MoveFullNode(aOldPos, aNewPos);
}
}
SkipToken( -1 ); // zum Letzen gueltigen zurueck
}
// in die naechste Box dieser Line (opt.: falls es nicht die letzte ist)
void SwRTFParser::GotoNextBox()
{
nInsTblRow = USHRT_MAX;
ASSERT( pTableNode, "Kein Tabellennode, dann auch keine Box" );
if (!pTableNode)
return;
SwTableLines& rLns = pTableNode->GetTable().GetTabLines();
SwTableLine* pLine = rLns[ rLns.Count()-1 ];
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
if (++m_nCurrentBox >= aMergeBoxes.size())
{
OSL_ENSURE(aMergeBoxes.size() < SAL_MAX_UINT16, "too many boxes?");
m_nCurrentBox = static_cast<sal_uInt16>(aMergeBoxes.size()-1);
}
if (!aMergeBoxes[ m_nCurrentBox ])
{
int bMove = sal_True;
if( pBox->GetSttIdx() > pPam->GetPoint()->nNode.GetIndex() )
{
sal_uInt16 nRealBox = 0;
for (sal_uInt16 nTmp = 0; nTmp < m_nCurrentBox; ++nTmp)
if( !aMergeBoxes[ nTmp ] )
++nRealBox;
if( nRealBox < rBoxes.Count() )
{
pPam->GetPoint()->nNode = *rBoxes[ nRealBox ]->GetSttNd()->EndOfSectionNode();
pPam->Move( fnMoveBackward, fnGoCntnt );
bMove = sal_False;
}
}
if (bMove &&
((static_cast<size_t>(m_nCurrentBox) + 1) == aMergeBoxes.size()))
// dann hinter die Tabelle
pPam->Move( fnMoveForward, fnGoNode );
}
else if (pPam->GetPoint()->nNode.GetNode().IsCntntNode())
// dann in die vorherige ans Ende
pPam->Move( fnMoveBackward, fnGoCntnt );
}
void SwRTFParser::NewTblLine()
{
nInsTblRow = USHRT_MAX;
// erweiter die aktuelle um eine neue Line
sal_Bool bMakeCopy = sal_False;
SwNode* pNd = pDoc->GetNodes()[ pPam->GetPoint()->nNode.GetIndex()-1 ];
if( !pNd->IsEndNode() ||
!(pNd = pNd->StartOfSectionNode())->IsTableNode() )
{
if( !pOldTblNd )
return ;
bMakeCopy = sal_True;
pNd = pOldTblNd;
}
pTableNode = (SwTableNode*)pNd;
SwTableLines* pLns = &pTableNode->GetTable().GetTabLines();
SwTableLine* pLine = (*pLns)[ pLns->Count()-1 ];
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
SwTableBox* pBox = rBoxes[ rBoxes.Count()-1 ];
if(nRowsToRepeat>0)
pTableNode->GetTable().SetRowsToRepeat( nRowsToRepeat );
if( !bMakeCopy &&
64000 < pTableNode->GetTable().GetTabSortBoxes().Count() )
{
bMakeCopy = sal_True; // spaetestens jetzt eine neue anfangen!
}
if( bMakeCopy )
{
// und die Selektion kopieren
SwSelBoxes aBoxes;
pTableNode->GetTable().SelLineFromBox( pBox, aBoxes );
pTableNode->GetTable().MakeCopy( pDoc, *pPam->GetPoint(),
aBoxes, sal_False );
sal_uLong nNd = pPam->GetPoint()->nNode.GetIndex()-1;
pTableNode = pDoc->GetNodes()[ nNd ]->FindTableNode();
pOldTblNd = pTableNode;
nRowsToRepeat=0;
pTableNode->GetTable().SetRowsToRepeat(nRowsToRepeat);
pLns = &pTableNode->GetTable().GetTabLines();
}
else
// pDoc->InsertRow( aBoxes );
pTableNode->GetTable().AppendRow( pDoc );
pBox = (*pLns)[ pLns->Count()-1 ]->GetTabBoxes()[0];
sal_uLong nOldPos = pPam->GetPoint()->nNode.GetIndex();
pPam->GetPoint()->nNode = *pBox->GetSttNd();
pPam->Move( fnMoveForward );
m_nCurrentBox = 0;
// alle Nodes in den Boxen auf die "default" Vorlage setzten
{
SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 );
if( !pColl )
pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
pPam->SetMark();
pLine = (*pLns)[ pLns->Count()-1 ];
pBox = pLine->GetTabBoxes()[ pLine->GetTabBoxes().Count() -1 ];
pPam->GetPoint()->nNode = *pBox->GetSttNd()->EndOfSectionNode();
pPam->Move( fnMoveBackward );
pDoc->SetTxtFmtColl( *pPam, pColl );
// Bug 73940 - remove ALL attributes (NumRules/Break/etc.)
{
SwNodeIndex aIdx( pPam->GetMark()->nNode );
SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
while( aIdx <= rEndIdx )
{
SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
if( pCNd && pCNd->HasSwAttrSet() )
pCNd->ResetAllAttr();
aIdx++;
}
}
pPam->Exchange();
pPam->DeleteMark();
}
// all attributes which will be displayed in new Box
SvxRTFItemStack& rAttrStk = GetAttrStack();
const SvxRTFItemStackType* pStk;
for( size_t n = 0; n < rAttrStk.size(); ++n )
if( ( pStk = rAttrStk[ n ])->GetSttNodeIdx() == sal_uLong(nOldPos) &&
!pStk->GetSttCnt() )
((SvxRTFItemStackType*)pStk)->SetStartPos( SwxPosition( pPam ) );
}
void SwRTFParser::CheckInsNewTblLine()
{
if( USHRT_MAX != nInsTblRow )
{
if( nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )
nInsTblRow = USHRT_MAX;
else if( !pTableNode ) // Tabelle nicht mehr vorhanden ?
NewTblLine(); // evt. Line copieren
}
}
/* vi:set tabstop=4 shiftwidth=4 expandtab: */