| /************************************************************** |
| * |
| * 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: */ |