| /************************************************************** |
| * |
| * 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 -*- */ |
| #include <hintids.hxx> |
| #include <tools/list.hxx> |
| #include <tools/cachestr.hxx> |
| #include <svtools/rtftoken.h> |
| #include <svl/itemiter.hxx> |
| #include <editeng/prntitem.hxx> |
| #include <editeng/opaqitem.hxx> |
| #include <editeng/protitem.hxx> |
| #include <editeng/ulspitem.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/frmdiritem.hxx> |
| #include <fmtfsize.hxx> |
| #include <fmtanchr.hxx> |
| #include <fmtpdsc.hxx> |
| #include <fmtsrnd.hxx> |
| #include <fmtclds.hxx> |
| #include <fmtcntnt.hxx> |
| #include <frmatr.hxx> |
| #include <doc.hxx> |
| #include <pam.hxx> |
| #include <ndtxt.hxx> |
| #include <shellio.hxx> |
| #include <swparrtf.hxx> |
| #include <grfatr.hxx> |
| #include <paratr.hxx> |
| #include <rtf.hxx> |
| #include <ndgrf.hxx> |
| #include <pagedesc.hxx> |
| #include <swtable.hxx> |
| #include <txtflcnt.hxx> |
| #include <fmtflcnt.hxx> |
| #include <fltini.hxx> |
| #include <unoframe.hxx> |
| #include <deque> |
| #include <map> |
| #include <utility> |
| #include <fmtwrapinfluenceonobjpos.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <fmtfollowtextflow.hxx> |
| #include "dcontact.hxx" |
| #include <drawdoc.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| #define ANCHOR(p) ((SwFmtAnchor*)p) |
| |
| // steht in shellio.hxx |
| extern SwCntntNode* GoNextNds( SwNodeIndex * pIdx, sal_Bool bChk ); |
| |
| SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* ) |
| |
| inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, sal_Bool bInP=sal_True) |
| { |
| return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP); |
| } |
| |
| SwFlySave::SwFlySave(const SwPaM& rPam, SfxItemSet& rSet) |
| : aFlySet(rSet), nSttNd(rPam.GetPoint()->nNode), nEndNd(nSttNd), nEndCnt(0), |
| nPageWidth(ATT_MIN_SIZE), nDropLines(0), nDropAnchor(0) |
| { |
| } |
| |
| int SwFlySave::IsEqualFly( const SwPaM& rPos, SfxItemSet& rSet ) |
| { |
| if( rSet.Count() != aFlySet.Count() || nDropAnchor ) |
| return sal_False; |
| |
| // nur TextNodes zusammenfassen |
| if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() ) |
| return sal_False; |
| |
| // teste auf gleiche / naechste Position |
| if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() ) |
| { |
| if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) ) |
| return sal_False; |
| } |
| else if( rPos.GetPoint()->nContent.GetIndex() ) |
| return sal_False; |
| else |
| { |
| SwNodeIndex aIdx( nEndNd ); |
| SwCntntNode *const pCNd = aIdx.GetNode().GetCntntNode(); |
| if( !GoNextNds( &aIdx, sal_True ) || |
| aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() || |
| ( pCNd && pCNd->Len() != nEndCnt )) |
| { |
| return sal_False; |
| } |
| } |
| |
| if( rSet.Count() ) |
| { |
| SfxItemIter aIter( rSet ); |
| const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem(); |
| while( sal_True ) |
| { |
| if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(), |
| sal_False, &pItem ) || |
| // Ankerattribute gesondert behandeln |
| ( RES_ANCHOR == pCurr->Which() |
| ? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() || |
| ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum()) |
| : *pItem != *pCurr )) |
| return sal_False; |
| |
| if( aIter.IsAtEnd() ) |
| break; |
| pCurr = aIter.NextItem(); |
| } |
| } |
| return sal_True; |
| } |
| |
| void SwFlySave::SetFlySize( const SwTableNode& rTblNd ) |
| { |
| // sollte der Fly kleiner als diese Tabelle sein, dann |
| // korrigiere diesen (nur bei abs. Angaben!) |
| SwTwips nWidth = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth(); |
| const SwFmtFrmSize& rSz = GetFrmSize( aFlySet ); |
| if( nWidth > rSz.GetWidth() ) |
| aFlySet.Put( SwFmtFrmSize( rSz.GetHeightSizeType(), nWidth, rSz.GetHeight() )); |
| } |
| |
| sal_Bool lcl_HasBreakAttrs( const SwCntntNode& rNd ) |
| { |
| sal_Bool bRet = sal_False; |
| const SfxItemSet& rSet = rNd.GetSwAttrSet(); |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, sal_True, &pItem ) && |
| SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() ) |
| bRet = sal_True; |
| else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, sal_True, &pItem )&& |
| 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() ) |
| bRet = sal_True; |
| return bRet; |
| } |
| |
| |
| void lcl_CpyBreakAttrs( SwCntntNode* pSrcNd, SwCntntNode* pDstNd, |
| SwNodeIndex* pNewIdx ) |
| { |
| const SfxItemSet* pSet; |
| if( pSrcNd && pDstNd && 0 != ( pSet = pSrcNd->GetpSwAttrSet() ) ) |
| { |
| const SfxPoolItem *pDescItem, *pBreakItem; |
| |
| if( SFX_ITEM_SET != pSet->GetItemState( RES_BREAK, |
| sal_False, &pBreakItem ) ) |
| pBreakItem = 0; |
| |
| if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC, |
| sal_False, &pDescItem ) ) |
| pDescItem = 0; |
| |
| if( pDescItem || pBreakItem ) |
| { |
| if( lcl_HasBreakAttrs( *pDstNd )) |
| { |
| SwPosition aPos( *pDstNd, SwIndex( pDstNd )); |
| aPos.nNode--; |
| pDstNd->GetDoc()->AppendTxtNode( aPos ); |
| if( pNewIdx ) |
| *pNewIdx = aPos.nNode; |
| |
| SwCntntNode* pOldNd = pDstNd; |
| pDstNd = aPos.nNode.GetNode().GetCntntNode(); |
| pDstNd->ChgFmtColl( pOldNd->GetFmtColl() ); |
| if( pDstNd->HasSwAttrSet() ) |
| { |
| SfxItemSet aSet( *pDstNd->GetpSwAttrSet() ); |
| aSet.ClearItem( RES_BREAK ); |
| aSet.ClearItem( RES_PAGEDESC ); |
| pDstNd->SetAttr( aSet ); |
| } |
| } |
| if( pBreakItem ) |
| { |
| pDstNd->SetAttr( *pBreakItem ); |
| pSrcNd->ResetAttr( RES_BREAK ); |
| } |
| if( pDescItem ) |
| { |
| pDstNd->SetAttr( *pDescItem ); |
| pSrcNd->ResetAttr( RES_PAGEDESC ); |
| } |
| } |
| } |
| } |
| |
| void SwRTFParser::SetFlysInDoc() |
| { |
| // !! von Oben abarbeiten, CntntPos ist kein Index ! |
| SwNodes & rNds = pDoc->GetNodes(); |
| typedef std::pair<SwFlyFrmFmt*, SwFmtAnchor> frameEntry; |
| typedef std::deque<frameEntry> rtfframesAtIndex; |
| typedef std::map<const SwNode*, rtfframesAtIndex> rtfFmtMap; |
| rtfFmtMap aPrevFmts; |
| |
| SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME ); |
| for( sal_uInt16 n = 0; n < aFlyArr.Count(); ++n ) |
| { |
| SwFlySave* pFlySave = aFlyArr[ n ]; |
| |
| ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(), |
| "Content vom Fly steht in einem Fly" ); |
| ASSERT( pFlySave->nSttNd.GetIndex() <= pFlySave->nEndNd.GetIndex(), |
| "Fly hat falschen Bereich" ); |
| |
| |
| |
| //JP 21.09.98: wenn ein DropCap ist, dann Text im Node belassen, am |
| // Absatz das Absatz Attribut setzen. Ggfs noch die |
| // FontSize zuruecksetzen, damit das DropCap nicht zu |
| // gro? wird. |
| if( pFlySave->nDropAnchor ) |
| { |
| SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode(); |
| SwTxtNode* pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode(); |
| if( pSttNd && pEndNd && |
| pSttNd->GetIndex() + 1 == pEndNd->GetIndex() |
| && pSttNd->GetTxt().Len()>0 /* #i38227# leave drop caps with no content as fly frames */ ) |
| { |
| sal_uLong nPos = pSttNd->GetIndex(); |
| SwDoc * pDoc1 = pSttNd->GetDoc(); |
| |
| sal_Bool bJoined; |
| { |
| SwPaM aTmp( *pSttNd, pSttNd->GetTxt().Len(), *pEndNd, 0 ); |
| bJoined = pDoc1->DeleteAndJoin( aTmp ); |
| } |
| |
| SwTxtNode * pNd = (pDoc1->GetNodes()[nPos])->GetTxtNode(); |
| |
| if( bJoined && pNd != NULL) |
| { |
| SwFmtDrop aDropCap; |
| aDropCap.GetLines() = (sal_uInt8)pFlySave->nDropLines; |
| aDropCap.GetChars() = 1; |
| |
| SwIndex aIdx( pEndNd ); |
| pNd->RstTxtAttr( aIdx, 1, RES_CHRATR_FONTSIZE ); |
| pNd->SetAttr( aDropCap ); |
| } |
| delete pFlySave; |
| continue; |
| } |
| } |
| |
| // liegt Ende und Start vom Naechsten im gleichen Node, dann muss |
| // gesplittet werden |
| if (((static_cast<size_t>(n) + 1) < aFlyArr.Count()) && |
| pFlySave->nEndCnt && |
| pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd ) |
| { |
| SwCntntNode *const pCNd = pFlySave->nEndNd.GetNode().GetCntntNode(); |
| if( pCNd ) |
| { |
| SwPosition aPos( pFlySave->nEndNd, |
| SwIndex( pCNd, pFlySave->nEndCnt )); |
| pDoc->SplitNode( aPos, false ); |
| pFlySave->nEndNd--; |
| } |
| else |
| pFlySave->nEndCnt = 0; |
| } |
| |
| // verschiebe den Inhalt von diesem Anchor in den Auto-TextBereich |
| // und erzeuge dadurch den richtigen SwG-Rahmen |
| SwNodeRange aRg(pFlySave->nSttNd, 0, pFlySave->nEndNd, 0); |
| //Make a new section, unless there is no content at all |
| const bool bMakeEmptySection = aRg.aStart < aRg.aEnd || ((aRg.aStart == aRg.aEnd) && pFlySave->nEndCnt); |
| |
| { |
| // Nur TextNodes koennen in Tabellen stehen !! |
| const SwNode* pNd = &pFlySave->nSttNd.GetNode(); |
| if( pNd->IsNoTxtNode() ) |
| { |
| // die Size muss noch korrigiert werden! |
| nAktPageDesc = 0; // Standart PageDesc |
| if( SFX_ITEM_SET != pFlySave->aFlySet.GetItemState( |
| RES_FRM_SIZE, sal_False ) ) |
| _SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart, |
| pFlySave->aFlySet ); |
| if( 0 != ( pNd = pNd->FindTableNode() ) ) |
| pFlySave->SetFlySize( *(SwTableNode*)pNd ); |
| } |
| else |
| { |
| // Take care for table nodes |
| pNd = pNd->GetNodes()[ pNd->GetIndex() - 2 ]->GetTableNode(); |
| if( pNd ) // if the table starts immediately before aRg -> expand aRg |
| aRg.aStart = *pNd; |
| |
| if( bMakeEmptySection ) |
| { |
| pNd = &aRg.aEnd.GetNode(); |
| sal_uLong nSectEnd = pNd->EndOfSectionIndex()+1; |
| |
| if (!pNd->IsTableNode() && 0 !=(pNd = pNd->FindTableNode()) |
| && (pNd->GetIndex() >= aRg.aStart.GetNode().GetIndex()) ) |
| { |
| const SwNode* pTblBxNd; |
| |
| // Ende der Tabelle ist hinter dieser Box ?? |
| if( pNd->EndOfSectionIndex() == nSectEnd ) |
| aRg.aEnd = nSectEnd+1; |
| // is the end in the first box of the table, then |
| // move before the table (Bug 67663) |
| // but the range must not become emtpy, i.e. aStart==aEnd |
| // because otherwise we will get a crash (126506) later on |
| else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode(). |
| FindTableBoxStartNode()) && |
| pTblBxNd->GetIndex() - 1 == pNd->GetIndex() && |
| &aRg.aStart.GetNode() != pNd ) |
| aRg.aEnd = *pNd; |
| else |
| { |
| // Tabelle ist noch groesser, also splitte sie hier. |
| rNds.SplitTable( aRg.aEnd, sal_True ); |
| aRg.aEnd = pNd->EndOfSectionIndex() + 1; |
| } |
| } |
| } |
| } |
| } |
| |
| // vorm verschieben muss sich der Index auf die alte Position |
| // gemerkt werden, der Index wird mit verschoben !!! |
| |
| SwNodeIndex aTmpIdx( rNds.GetEndOfAutotext() ); |
| SwStartNode* pSttNd = bMakeEmptySection |
| ? rNds.MakeEmptySection( aTmpIdx, SwFlyStartNode ) |
| : rNds.MakeTextSection( aTmpIdx, SwFlyStartNode, |
| (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); |
| |
| // das ist die Verankerungs-Position (fuers Layout!) |
| pFlySave->nSttNd = aRg.aStart.GetIndex()-1; |
| if( bMakeEmptySection ) |
| { |
| // check: the move does not clear the surrounded section. If all |
| // nodes moved away, then create a new TxtNode |
| { |
| // i76403: an empty selection is not a good idea |
| if( aRg.aStart == aRg.aEnd && aRg.aStart.GetNode().GetTxtNode() ) |
| aRg.aEnd++; |
| SwNodeIndex aPrev( aRg.aStart, -1 ); |
| if( aPrev.GetNode().IsStartNode() && |
| aPrev.GetNode().EndOfSectionNode() == &aRg.aEnd.GetNode()) |
| { |
| // create new txtnode, because the section does never be empty |
| pDoc->GetNodes().MakeTxtNode( aRg.aEnd, |
| (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); |
| aRg.aEnd--; |
| } |
| } |
| aTmpIdx = *pSttNd->EndOfSectionNode(); |
| pDoc->MoveNodeRange( aRg, aTmpIdx, |
| IDocumentContentOperations::DOC_MOVEDEFAULT ); |
| } |
| |
| // patch from cmc for #i52542# |
| if (pSttNd->GetIndex() + 1 == pSttNd->EndOfSectionIndex()) |
| { |
| ASSERT(!this, "nothing in this frame, not legal"); |
| delete pFlySave; |
| continue; |
| } |
| |
| pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd )); |
| |
| CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd, |
| pFlySave->nPageWidth ); |
| |
| // THIS >>>>> |
| // if the section only contains one Node and this has a |
| // border or background, then put it to the frame |
| // Not in our own RTF-Format! |
| // <<<<< DOES NOT MAKE SENSE TO ME (flr) |
| // #102781#. Added support for transparent frames. |
| if( pSttNd->GetIndex() + 1 != pSttNd->EndOfSectionIndex() && |
| !bSwPageDesc ) |
| { |
| SwCntntNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetCntntNode(); |
| SfxItemSet aTmpSet( pDoc->GetAttrPool(), |
| RES_BACKGROUND, RES_BOX ); |
| const SvxBrushItem* pBackgroundBrush = (const SvxBrushItem*)pFlySave->aFlySet.GetItem(RES_BACKGROUND, sal_False); |
| if( pSrcNd && pSrcNd->HasSwAttrSet() ) |
| aTmpSet.Put( *pSrcNd->GetpSwAttrSet() ); |
| if (pBackgroundBrush) |
| { |
| aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND); |
| } |
| else |
| { |
| pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, sal_False); |
| if (pBackgroundBrush) |
| { |
| Color& rBackgroundColor = const_cast<SvxBrushItem*>(pBackgroundBrush)->GetColor(); |
| rBackgroundColor.SetTransparency(0xFE); |
| } |
| else |
| { |
| Color aColor = Color(0xff, 0xff, 0xff); |
| aColor.SetTransparency( 0xFE); |
| SvxBrushItem aBrush(aColor, RES_BACKGROUND); |
| aTmpSet.Put(aBrush, RES_BACKGROUND); |
| } |
| } |
| // #117914# Topic 6. |
| pFlySave->aFlySet.Put( aTmpSet ); |
| if( pSrcNd && pSrcNd->HasSwAttrSet() ) |
| { |
| pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX ); |
| } |
| } |
| |
| SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent ); |
| pFmt->SetFmtAttr( pFlySave->aFlySet ); |
| const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); |
| if (FLY_AS_CHAR != rAnchor.GetAnchorId()) |
| { |
| // korrigiere noch den Absatz, ist immer der vorhergehende ! |
| // JP 20.09.95: wenn es diesen gibt! (DocAnfang!) |
| |
| //JP 02.08.99: that is wrong. The anchor is ever the NEXT! |
| //JP 05.08.99: there are an Bug in the ExportFilter which will |
| // be fixed in the Version 517 - by SWG-Export |
| // the fly will be after the paragraph - but in RTF |
| // the flys will be before the paragraph. |
| if( !bSwPageDesc || 5430 < GetVersionNo() ) |
| pFlySave->nSttNd++; |
| |
| // if( !pFlySave->nSttNd.GetNode().IsCntntNode() ) |
| { |
| // Seitenumbrueche in den Bodybereich verschieben! |
| SwCntntNode* pSrcNd = aRg.aStart.GetNode().GetCntntNode(); |
| SwCntntNode* pDstNd = pFlySave->nSttNd.GetNode().GetCntntNode(); |
| if( !pDstNd ) |
| pDstNd = pDoc->GetNodes().GoNext( &pFlySave->nSttNd ); |
| |
| ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nSttNd ); |
| } |
| |
| const SwNodeIndex aSttNd(*pSttNd); |
| SwNodeIndex aEndNd(*pSttNd->EndOfSectionNode()); |
| aEndNd--; |
| |
| SwPosition aPos( pFlySave->nSttNd ); |
| SwFmtAnchor aAnchor(rAnchor); |
| aAnchor.SetAnchor(&aPos); |
| |
| const SwNode *pCurrentAnchor = &(pFlySave->nSttNd.GetNode()); |
| aPrevFmts[pCurrentAnchor].push_back(frameEntry(pFmt, aAnchor)); |
| |
| while (aEndNd > aSttNd) |
| { |
| typedef rtfframesAtIndex::iterator myIter; |
| rtfframesAtIndex &rDeque = aPrevFmts[&(aEndNd.GetNode())]; |
| myIter aEnd = rDeque.end(); |
| for (myIter aIter = rDeque.begin(); aIter != aEnd; ++aIter) |
| { |
| aIter->second.SetAnchor(&aPos); |
| // --> OD 2004-06-30 #i27767# - push on front to keep order |
| // of objects for the correct object positioning |
| //aPrevFmts[pCurrentAnchor].push_back(*aIter); |
| aPrevFmts[pCurrentAnchor].push_front(*aIter); |
| } |
| rDeque.clear(); |
| aEndNd--; |
| } |
| } |
| |
| // --> OD, FLR 2006-02-16 #131205# |
| // Create draw contact object, which also creates a <SdrObject> instance, |
| // in order to set the order number. |
| // The order number is assumed to be the order of the text flow. |
| SwFlyDrawContact* pContact = |
| new SwFlyDrawContact( pFmt, |
| pFmt->GetDoc()->GetOrCreateDrawModel() ); |
| pContact->GetMaster()->SetOrdNum( n ); |
| // <-- |
| |
| delete pFlySave; |
| } |
| |
| typedef rtfFmtMap::reverse_iterator myriter; |
| myriter aEnd = aPrevFmts.rend(); |
| for(myriter aIter = aPrevFmts.rbegin(); aIter != aEnd; ++aIter) |
| { |
| rtfframesAtIndex &rDeque = aIter->second; |
| typedef rtfframesAtIndex::iterator myIter; |
| myIter aQEnd = rDeque.end(); |
| for (myIter aQIter = rDeque.begin(); aQIter != aQEnd; ++aQIter) |
| { |
| frameEntry &rEntry = *aQIter; |
| SwFlyFrmFmt *pFrm = rEntry.first; |
| SwFmtAnchor &rAnchor = rEntry.second; |
| pFrm->SetFmtAttr(rAnchor); |
| } |
| } |
| |
| aFlyArr.Remove(0, aFlyArr.Count()); |
| } |
| |
| // clips the text box to the min or max position if it is outside our min or max boundary |
| long SwRTFParser::GetSafePos(long nPos) |
| { |
| if(nPos > SHRT_MAX) |
| nPos = SHRT_MAX; |
| else if(nPos < SHRT_MIN) |
| nPos = SHRT_MIN; |
| |
| return nPos; |
| } |
| |
| void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet ) |
| { |
| // ein Set fuer die FrmFmt-Attribute |
| SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); |
| if( !IsNewDoc() ) |
| Reader::ResetFrmFmtAttrs( aSet ); |
| |
| // der Fly beginnt immer in einem neuen Absatz |
| if( pPam->GetPoint()->nContent.GetIndex() ) |
| InsertPara(); |
| |
| // RTF-Defaults setzen: |
| // --> OD 2004-06-24 #i27767# |
| SwFmtAnchor aAnchor( FLY_AT_PARA ); |
| |
| SwFmtHoriOrient aHori( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME ); |
| SwFmtVertOrient aVert( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ); |
| // <-- |
| SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR ); |
| |
| sal_uInt16 nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0; |
| SvUShorts aColumns; |
| |
| sal_Bool bChkDropCap = 0 == pSet; |
| sal_uInt16 nDropCapLines = 0, nDropCapAnchor = 0; |
| int nNumOpenBrakets = GetOpenBrakets(); |
| |
| if( !pSet ) |
| { |
| pSet = &aSet; |
| } |
| else |
| { |
| // die Werte aus dem uebergebenen! |
| aAnchor = (SwFmtAnchor&)pSet->Get( RES_ANCHOR ); |
| aHori = (SwFmtHoriOrient&)pSet->Get( RES_HORI_ORIENT ); |
| aVert = (SwFmtVertOrient&)pSet->Get( RES_VERT_ORIENT ); |
| } |
| |
| // dann sammel mal alle Attribute zusammen |
| int bWeiter = sal_True; |
| int nAppliedProps=0; |
| do { |
| sal_uInt16 nVal = sal_uInt16(nTokenValue); |
| /* |
| #i5263# |
| Assume that a property genuinely contributes towards creating a frame, |
| and if turns out to be a non contributing one reduce the count. |
| */ |
| ++nAppliedProps; |
| switch( nToken ) |
| { |
| case RTF_ABSW: |
| { |
| SwFmtFrmSize aSz( ATT_MIN_SIZE, nTokenValue, 0 ); |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True, |
| &pItem )) |
| { |
| aSz.SetHeightSizeType( ((SwFmtFrmSize*)pItem)->GetHeightSizeType() ); |
| aSz.SetHeight( ((SwFmtFrmSize*)pItem)->GetHeight() ); |
| } |
| if( MINFLY > nTokenValue ) nTokenValue = MINFLY; |
| aSet.Put( aSz ); |
| } |
| break; |
| case RTF_ABSH: |
| { |
| SwFmtFrmSize aSz( ATT_MIN_SIZE, 0, MINFLY ); |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True, |
| &pItem )) |
| { |
| aSz.SetWidth( ((SwFmtFrmSize*)pItem)->GetWidth() ); |
| } |
| |
| if( 0 > nTokenValue ) |
| { |
| nTokenValue = -nTokenValue; |
| aSz.SetHeightSizeType( ATT_FIX_SIZE ); |
| } |
| if( MINFLY > nTokenValue ) nTokenValue = MINFLY; |
| aSz.SetHeight( nTokenValue ); |
| aSet.Put( aSz ); |
| } |
| break; |
| |
| case RTF_NOWRAP: |
| { |
| pSet->Put( SwFmtSurround( SURROUND_NONE )); |
| } |
| break; |
| case RTF_DXFRTEXT: |
| { |
| SvxULSpaceItem aUL( RES_UL_SPACE ); |
| SvxLRSpaceItem aLR( RES_LR_SPACE ); |
| aUL.SetUpper( nVal ); aUL.SetLower( nVal ); |
| aLR.SetLeft( nVal ); aLR.SetRight( nVal ); |
| pSet->Put( aUL ); |
| pSet->Put( aLR ); |
| } |
| break; |
| |
| case RTF_DFRMTXTX: |
| { |
| SvxLRSpaceItem aLR( RES_LR_SPACE ); |
| aLR.SetLeft( nVal ); aLR.SetRight( nVal ); |
| pSet->Put( aLR ); |
| } |
| break; |
| case RTF_DFRMTXTY: |
| { |
| SvxULSpaceItem aUL( RES_UL_SPACE ); |
| aUL.SetUpper( nVal ); aUL.SetLower( nVal ); |
| pSet->Put( aUL ); |
| } |
| break; |
| |
| case RTF_POSNEGX: |
| case RTF_POSX: aHori.SetHoriOrient( text::HoriOrientation::NONE ); |
| aHori.SetPos( GetSafePos((long)nTokenValue) ); |
| break; |
| case RTF_POSXC: aHori.SetHoriOrient( text::HoriOrientation::CENTER ); break; |
| case RTF_POSXI: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); |
| aHori.SetPosToggle( sal_True ); |
| break; |
| case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); |
| aHori.SetPosToggle( sal_True ); |
| break; |
| case RTF_POSXL: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); break; |
| case RTF_POSXR: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); break; |
| |
| case RTF_POSNEGY: |
| case RTF_POSY: aVert.SetVertOrient( text::VertOrientation::NONE ); |
| aVert.SetPos( GetSafePos((long)nTokenValue) ); |
| break; |
| case RTF_POSYT: aVert.SetVertOrient( text::VertOrientation::TOP ); break; |
| case RTF_POSYB: aVert.SetVertOrient( text::VertOrientation::BOTTOM ); break; |
| case RTF_POSYC: aVert.SetVertOrient( text::VertOrientation::CENTER ); break; |
| |
| case RTF_PHMRG: aHori.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break; |
| case RTF_PVMRG: aVert.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break; |
| case RTF_PHPG: aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME ); break; |
| case RTF_PVPG: aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );break; |
| case RTF_PHCOL: aHori.SetRelationOrient( text::RelOrientation::FRAME ); break; |
| case RTF_PVPARA: aVert.SetRelationOrient( text::RelOrientation::FRAME ); break; |
| |
| case RTF_POSYIL: |
| break; |
| case RTF_ABSLOCK: |
| /* |
| #i5263# |
| Not sufficient to make a frame at least word won't do it with just |
| an abslock |
| */ |
| --nAppliedProps; |
| break; |
| case RTF_FRMTXLRTB: |
| aFrmDir.SetValue( FRMDIR_HORI_LEFT_TOP ); |
| break; |
| case RTF_FRMTXTBRL: |
| aFrmDir.SetValue( FRMDIR_HORI_RIGHT_TOP ); |
| break; |
| case RTF_FRMTXLRTBV: |
| aFrmDir.SetValue( FRMDIR_VERT_TOP_LEFT ); |
| break; |
| case RTF_FRMTXTBRLV: |
| aFrmDir.SetValue( FRMDIR_VERT_TOP_RIGHT ); |
| break; |
| |
| case RTF_DROPCAPLI: // Dropcaps !! |
| if( bChkDropCap ) |
| { |
| nDropCapLines = sal_uInt16( nTokenValue ); |
| if( !nDropCapAnchor ) |
| nDropCapAnchor = 1; |
| } |
| break; |
| case RTF_DROPCAPT: |
| if( bChkDropCap ) |
| { |
| nDropCapAnchor = sal_uInt16( nTokenValue ); |
| if( !nDropCapLines ) |
| nDropCapLines = 3; |
| } |
| break; |
| |
| |
| // fuer die "alten" Writer - haben die Spaltigkeit falsch heraus- |
| // geschrieben |
| case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break; |
| case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break; |
| case RTF_COLNO: |
| nAktCol = sal_uInt16( nTokenValue ); |
| if( RTF_COLW == GetNextToken() ) |
| { |
| sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0; |
| if( RTF_COLSR == GetNextToken() ) |
| nSpace = sal_uInt16( nTokenValue ); |
| else |
| SkipToken( -1 ); // wieder zurueck |
| |
| if( --nAktCol == ( aColumns.Count() / 2 ) ) |
| { |
| aColumns.Insert( nWidth + nSpace, aColumns.Count() ); |
| aColumns.Insert( nSpace, aColumns.Count() ); |
| } |
| } |
| break; |
| |
| case '{': |
| { |
| short nSkip = 0; |
| if( RTF_IGNOREFLAG != ( nToken = GetNextToken() )) |
| { |
| if( RTF_SHADINGDEF == (nToken & ~0xff) ) |
| { |
| ReadBackgroundAttr( nToken, aSet ); |
| GetNextToken(); // Klammer ueberlesen |
| } |
| else |
| nSkip = -1; |
| } |
| else if( RTF_APOCTL == |
| ((nToken = GetNextToken() ) & ~(0xff | RTF_SWGDEFS)) ) |
| { |
| bReadSwFly = true; // alles kommt in den akt. Fly |
| SvxLRSpaceItem aLR( RES_LR_SPACE ); |
| SvxULSpaceItem aUL( RES_UL_SPACE ); |
| nCols = USHRT_MAX; // neu aufsetzen |
| nColSpace = USHRT_MAX; |
| do { |
| nVal = sal_uInt16(nTokenValue); |
| switch( nToken ) |
| { |
| // Swg-Frame-Tokens |
| case RTF_FLYPRINT: |
| { |
| pSet->Put( SvxPrintItem( RES_PRINT, sal_False )); |
| } |
| break; |
| case RTF_FLYOPAQUE: |
| { |
| pSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_False )); |
| } |
| break; |
| |
| case RTF_FLYPRTCTD: |
| { |
| RTFProtect aP( (sal_uInt8)nTokenValue ); |
| SvxProtectItem aProtectItem( RES_PROTECT ); |
| aProtectItem.SetCntntProtect( aP.GetCntnt() ); |
| aProtectItem.SetSizeProtect( aP.GetSize() ); |
| aProtectItem.SetPosProtect( aP.GetPos() ); |
| pSet->Put( aProtectItem ); |
| } |
| break; |
| |
| case RTF_FLYMAINCNT: |
| { |
| RTFSurround aMC( (sal_uInt8)nTokenValue ); |
| SwFmtSurround aSurr( (SwSurround)aMC.GetOrder()); |
| if( aMC.GetGoldCut() ) |
| aSurr.SetSurround( SURROUND_IDEAL ); |
| pSet->Put( aSurr ); |
| } |
| break; |
| case RTF_FLYVERT: |
| { |
| RTFVertOrient aVO( nVal ); |
| aVert.SetVertOrient( aVO.GetOrient() ); |
| aVert.SetRelationOrient( aVO.GetRelation() ); |
| } |
| break; |
| case RTF_FLYHORZ: |
| { |
| RTFHoriOrient aHO( nVal ); |
| aHori.SetHoriOrient( aHO.GetOrient() ); |
| aHori.SetRelationOrient( aHO.GetRelation() ); |
| } |
| break; |
| case RTF_FLYOUTLEFT: aLR.SetLeft( nVal ); break; |
| case RTF_FLYOUTRIGHT: aLR.SetRight( nVal ); break; |
| case RTF_FLYOUTUPPER: aUL.SetUpper( nVal ); break; |
| case RTF_FLYOUTLOWER: aUL.SetLower( nVal ); break; |
| case RTF_FLYANCHOR: |
| switch( GetNextToken() ) |
| { |
| case RTF_FLY_PAGE: |
| aAnchor.SetType( FLY_AT_PAGE ); |
| aAnchor.SetPageNum( sal_uInt16(nTokenValue)); |
| aAnchor.SetAnchor( 0 ); |
| break; |
| |
| case RTF_FLY_CNTNT: |
| { |
| SwNodeIndex aIdx( pPam->GetPoint()->nNode ); |
| pDoc->GetNodes().GoPrevious( &aIdx ); |
| SwPosition aPos( aIdx ); |
| aAnchor.SetType( FLY_AT_PARA ); |
| aAnchor.SetAnchor( &aPos ); |
| } |
| break; |
| |
| // JP 26.09.94: die Bindung an die Spalte gibt es nicht mehr !! |
| // case RTF_FLY_COLUMN: |
| } |
| break; |
| case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break; |
| case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break; |
| case RTF_COLNO: |
| nAktCol = sal_uInt16( nTokenValue ); |
| if( RTF_COLW == GetNextToken() ) |
| { |
| sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0; |
| if( RTF_COLSR == GetNextToken() ) |
| nSpace = sal_uInt16( nTokenValue ); |
| else |
| SkipToken( -1 ); // wieder zurueck |
| |
| if( --nAktCol == ( aColumns.Count() / 2 ) ) |
| { |
| aColumns.Insert( nWidth + nSpace, aColumns.Count() ); |
| aColumns.Insert( nSpace, aColumns.Count() ); |
| } |
| } |
| break; |
| |
| case '{': |
| if( RTF_BRDBOX == ( nToken = GetNextToken() ) ) |
| ReadBorderAttr( nToken, aSet ); |
| else if( RTF_SHADINGDEF == (nToken & ~0xff ) ) |
| ReadBackgroundAttr( nToken, aSet ); |
| else if( RTF_IGNOREFLAG == nToken ) |
| { |
| int bSkipGrp = sal_True; |
| switch( nToken = GetNextToken() ) |
| { |
| case RTF_SHADOW: |
| case RTF_BRDBOX: |
| ReadAttr( SkipToken( -2 ), &aSet ); |
| bSkipGrp = sal_False; |
| break; |
| |
| case RTF_BRDRT: |
| case RTF_BRDRB: |
| case RTF_BRDRR: |
| case RTF_BRDRL: |
| bSkipGrp = sal_False; |
| ReadBorderAttr( SkipToken( -2 ), aSet ); |
| break; |
| } |
| |
| // keine weitere Klammer mehr ueberlesen!!! |
| if( !bSkipGrp ) |
| break; |
| |
| SkipGroup(); |
| } |
| else |
| SkipGroup(); |
| GetNextToken(); // Klammer ueberlesen |
| break; |
| } |
| } while( IsParserWorking() && |
| '}' != ( nToken = GetNextToken() )); |
| |
| if( aUL.GetUpper() || aUL.GetLower() ) |
| pSet->Put( aUL ); |
| if( aLR.GetLeft() || aLR.GetRight() ) |
| pSet->Put( aLR ); |
| } |
| else if( RTF_BRDBOX == nToken ) |
| ReadBorderAttr( nToken, aSet ); |
| else if( RTF_SHADOW == nToken ) |
| ReadAttr( SkipToken( -2 ), &aSet ); |
| else if( RTF_SHADINGDEF == (nToken & ~0xff ) ) |
| ReadBackgroundAttr( nToken, aSet ); |
| else if( RTF_UNKNOWNCONTROL == nToken ) |
| SkipGroup(); |
| else |
| nSkip = -2; |
| |
| if( nSkip ) |
| { |
| nToken = SkipToken( nSkip ); |
| bWeiter = sal_False; |
| } |
| } |
| break; |
| |
| default: |
| --nAppliedProps; //Not sufficient to make a frame |
| bWeiter = sal_False; |
| } |
| |
| if( bWeiter ) |
| nToken = GetNextToken(); |
| } while( bWeiter && IsParserWorking() ); |
| |
| pSet->Put( aAnchor ); |
| pSet->Put( aHori ); |
| pSet->Put( aVert ); |
| |
| // --> OD 2004-06-30 #i27767# - set wrapping style influence |
| // --> OD 2004-10-18 #i35017# - constant name has changed |
| pSet->Put( SwFmtWrapInfluenceOnObjPos( |
| text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE )); |
| // <-- |
| |
| SwFmtFollowTextFlow aFollowTextFlow( sal_False ); |
| pSet->Put( aFollowTextFlow ); |
| |
| if( !( aFrmDir == pSet->Get( RES_FRAMEDIR )) ) |
| pSet->Put( aFrmDir ); |
| |
| if( nCols && USHRT_MAX != nCols ) |
| { |
| SwFmtCol aCol; |
| if( USHRT_MAX == nColSpace ) |
| nColSpace = 720; |
| |
| sal_uLong nWidth = USHRT_MAX; |
| aCol.Init( nCols, nColSpace, sal_uInt16( nWidth ) ); |
| if( nCols == ( aColumns.Count() / 2 ) ) |
| { |
| for( sal_uInt16 n = 0, i = 0; n < aColumns.Count(); n += 2, ++i ) |
| { |
| SwColumn* pCol = aCol.GetColumns()[ i ]; |
| sal_uLong nTmp = aColumns[ n ]; |
| nTmp *= USHRT_MAX; |
| nTmp /= nWidth; |
| pCol->SetWishWidth( sal_uInt16(nTmp) ); |
| /* |
| JP 07.07.95: der Dialog kennt nur eine Breite fuer alle Spalten |
| darum hier nicht weiter beachten |
| nTmp = aColumns[ n+1 ]; |
| if( nTmp ) |
| pCol->SetRight( sal_uInt16(nTmp) ); |
| else |
| pCol->SetRight( 0 ); |
| pCol->SetLeft( 0 ); |
| */ |
| } |
| } |
| pSet->Put( aCol ); |
| } |
| |
| if( pSet != &aSet ) // wurde der Set uebergeben, dann wars das |
| return ; |
| |
| // ein neues FlyFormat anlegen oder das alte benutzen ? |
| // (teste ob es die selben Attribute besitzt!) |
| SwFlySave* pFlySave = 0; |
| sal_uInt16 nFlyArrCnt = aFlyArr.Count(); |
| /* |
| #i5263# |
| There were not enough frame properties found to actually justify creating |
| an absolutely positioned frame. |
| */ |
| if (nAppliedProps) |
| { |
| if( !nFlyArrCnt || |
| !( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet )) |
| { |
| pFlySave = new SwFlySave( *pPam, aSet ); |
| Size aPgSize; |
| GetPageSize( aPgSize ); |
| pFlySave->nPageWidth = aPgSize.Width(); |
| |
| if( nDropCapAnchor ) |
| { |
| pFlySave->nDropAnchor = nDropCapAnchor; |
| pFlySave->nDropLines = nDropCapLines; |
| } |
| if (nFlyArrCnt >0){ |
| SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1]; |
| if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex()) |
| { |
| pFlySavePrev->nEndNd=pFlySave->nSttNd; |
| } |
| } |
| aFlyArr.Insert( pFlySave, nFlyArrCnt++ ); |
| // --> OD 2008-12-22 #i83368# - reset |
| mbReadCellWhileReadSwFly = false; |
| // <-- |
| } |
| } |
| |
| SetPardTokenRead( sal_False ); |
| const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode(); |
| |
| while( !IsPardTokenRead() && IsParserWorking() ) |
| { |
| if( RTF_PARD == nToken || nNumOpenBrakets > GetOpenBrakets() ) |
| break; |
| |
| NextToken( nToken ); |
| |
| if( !IsPardTokenRead() ) |
| { |
| // #102781#. Added support for transparent frames. |
| if (nToken == RTF_CBPAT && nFlyArrCnt > 0) |
| { |
| sal_uInt16 _index=sal_uInt16(nTokenValue); |
| const Color& rColor = GetColor(_index); |
| SvxBrushItem aBrush(rColor, RES_BACKGROUND); |
| SwFlySave* pFS = aFlyArr[nFlyArrCnt-1]; |
| pFS->aFlySet.Put(aBrush, RES_BACKGROUND); |
| } |
| |
| nToken = GetNextToken(); |
| |
| // BUG 22036: kommt zwischen Fly-Attributen ein unbekanntes, |
| // dann erzeuge nie 2 FlyFrames, sondern fasse |
| // beide zusammen !!! |
| while( RTF_APOCTL == ( nToken & ~(0xff | RTF_SWGDEFS) )) |
| { |
| if( RTF_FLY_INPARA == nToken ) |
| break; |
| |
| if( RTF_IGNOREFLAG == SkipToken( -1 ) ) |
| { |
| if( '{' == SkipToken( -1 ) ) |
| nToken = '{'; |
| else |
| SkipToken( 2 ); |
| } |
| else |
| SkipToken( 1 ); |
| |
| ReadFly( nToken, pFlySave ? &pFlySave->aFlySet : 0); |
| nToken = GetNextToken(); |
| } |
| } |
| } |
| |
| /* |
| #i5263# |
| There were enough frame properties found to actually justify creating |
| an absolutely positioned frame. |
| */ |
| if (!nAppliedProps) |
| { |
| bReadSwFly = false; |
| SkipToken( -1 ); |
| return; |
| } |
| |
| if( pTblNd && !pPam->GetPoint()->nContent.GetIndex() && |
| pTblNd->EndOfSectionIndex() + 1 == |
| pPam->GetPoint()->nNode.GetIndex() ) |
| { |
| // nicht mehr in der Tabelle, sondern dahinter ? |
| // Dann aber wieder zurueck in die Tabelle |
| pPam->Move( fnMoveBackward ); |
| } |
| else |
| pTblNd = 0; |
| |
| // wurde garnichts eingefuegt? |
| if( !pTblNd && |
| pPam->GetPoint()->nNode == pFlySave->nSttNd && |
| !pPam->GetPoint()->nContent.GetIndex() ) |
| { |
| // // dann erzeuge mindestens einen leeren TextNode |
| // pDoc->AppendTxtNode(*pPam); |
| // dann zerstoere den FlySave wieder. |
| aFlyArr.DeleteAndDestroy( --nFlyArrCnt ); |
| |
| } |
| else |
| { |
| sal_Bool bMovePaM = 0 != pTblNd; |
| |
| pFlySave->nEndNd = pPam->GetPoint()->nNode; |
| pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex(); |
| |
| if( bMovePaM ) |
| pPam->Move( fnMoveForward ); |
| |
| pTblNd = pFlySave->nSttNd.GetNode().FindTableNode(); |
| if( pTblNd && !pFlySave->nEndCnt && |
| pTblNd == pFlySave->nEndNd.GetNode().FindTableNode() ) |
| { |
| // dann teste mal, ob das \pard nicht zu spaet kam und |
| // eigentlich in die vorherige Zelle gehoert |
| const SwStartNode* pSttBoxNd = pFlySave->nSttNd.GetNode(). |
| FindTableBoxStartNode(), |
| * pEndBoxNd = pFlySave->nEndNd.GetNode(). |
| FindTableBoxStartNode(); |
| if( pSttBoxNd && pEndBoxNd && |
| bMovePaM ? ( pSttBoxNd == pEndBoxNd ) |
| : ( pSttBoxNd->EndOfSectionIndex() + 1 == |
| pEndBoxNd->GetIndex() && |
| pEndBoxNd->GetIndex() + 1 == |
| pFlySave->nEndNd.GetIndex() )) |
| { |
| // dann gehoert das Ende in die vorherige Box! |
| SwPosition aPos( *pPam->GetPoint() ); |
| pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode(); |
| pPam->Move( fnMoveBackward, fnGoNode ); |
| |
| DelLastNode(); |
| |
| pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode(); |
| pPam->Move( fnMoveBackward, fnGoNode ); |
| |
| pFlySave->nEndNd = pPam->GetPoint()->nNode; |
| pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex(); |
| |
| *pPam->GetPoint() = aPos; |
| } |
| } |
| else if( !bReadSwFly && !pFlySave->nEndCnt && |
| pFlySave->nSttNd.GetIndex() + 1 == pFlySave->nEndNd.GetIndex() && |
| pFlySave->nSttNd.GetNode().IsTxtNode() ) |
| { |
| |
| SwTxtNode* pTxtNd = pFlySave->nSttNd.GetNode().GetTxtNode(); |
| SwTxtFlyCnt* pFlyCnt = 0; |
| if( 1 == pTxtNd->GetTxt().Len() && |
| 0 != (pFlyCnt = static_cast<SwTxtFlyCnt*>( |
| pTxtNd->GetTxtAttrForCharAt(0, RES_TXTATR_FLYCNT))) && |
| pFlyCnt->GetFlyCnt().GetFrmFmt() ) |
| { |
| // then move the content into the surrounded fly |
| SwFrmFmt* pFlyFmt = pFlyCnt->GetFlyCnt().GetFrmFmt(); |
| const SwNodeIndex* pFlySNd = pFlyFmt->GetCntnt().GetCntntIdx(); |
| SwNodeRange aRg( *pFlySNd, 1, |
| *pFlySNd->GetNode().EndOfSectionNode(), 0 ); |
| |
| // merge the itemsets |
| SwFmtFrmSize aSz1( (SwFmtFrmSize&)pFlyFmt->GetAttrSet(). |
| Get( RES_FRM_SIZE )); |
| SwFmtFrmSize aSz2( (SwFmtFrmSize&)pFlySave->aFlySet. |
| Get( RES_FRM_SIZE )); |
| // if |
| if( !aRg.aStart.GetNode().IsNoTxtNode() || |
| !aSz1.GetHeight() || !aSz1.GetWidth() || |
| !aSz2.GetHeight() || !aSz2.GetWidth() || |
| ( aSz1.GetHeight() == aSz2.GetHeight() && |
| aSz1.GetWidth() == aSz2.GetWidth() ) ) |
| { |
| SfxItemSet aDiffs( pFlyFmt->GetAttrSet() ); |
| aDiffs.ClearItem( RES_ANCHOR ); |
| aDiffs.ClearItem( RES_FRM_SIZE ); |
| aDiffs.ClearItem( RES_CNTNT ); |
| aDiffs.Differentiate( pFlySave->aFlySet ); |
| pFlySave->aFlySet.Put( aDiffs ); |
| |
| sal_Bool bSet = sal_False; |
| if( aSz1.GetHeight() && !aSz2.GetHeight() ) |
| { |
| bSet = sal_True; |
| aSz2.SetHeight( aSz1.GetHeight() ); |
| } |
| if( aSz1.GetWidth() && !aSz2.GetWidth() ) |
| { |
| bSet = sal_True; |
| aSz2.SetWidth( aSz1.GetWidth() ); |
| } |
| if( bSet ) |
| pFlySave->aFlySet.Put( aSz2 ); |
| |
| // move any PageBreak/Desc Attr to the next Para |
| { |
| SwCntntNode* pSrcNd = pFlySave->nSttNd.GetNode().GetCntntNode(); |
| SwCntntNode* pDstNd = pFlySave->nEndNd.GetNode().GetCntntNode(); |
| |
| ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nEndNd ); |
| } |
| |
| // create new txtnode, because the section does never be empty |
| pDoc->GetNodes().MakeTxtNode( aRg.aStart, |
| (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); |
| |
| SwNodeIndex aTmp( pFlySave->nSttNd, +1 ); |
| pDoc->MoveNodeRange( aRg, aTmp, |
| IDocumentContentOperations::DOC_MOVEDEFAULT ); |
| |
| // now delete the redundant txtnode |
| pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 ); |
| } |
| } |
| } |
| } |
| |
| bReadSwFly = false; |
| SkipToken( -1 ); |
| } |
| |
| |
| void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf, |
| const SvxRTFPictureType* pPicType ) |
| { |
| // kennzeichen fuer Swg-Dokumente: |
| // (dann ist das FlyFmt fuer die Grafik!) |
| SwGrfNode * pGrfNd; |
| // --> OD 2008-12-22 #i83368# |
| // Assure that graphic node is enclosed by fly frame node. |
| // if( bReadSwFly ) |
| if ( bReadSwFly && !mbReadCellWhileReadSwFly ) |
| // <-- |
| { |
| OSL_ENSURE(aFlyArr.Count(), |
| "SwRTFParser::InsPicture: fly array empty."); |
| if (aFlyArr.Count()) |
| { |
| // erzeuge nur einen normalen GrafikNode und ersetze diesen gegen |
| // den vorhandenen Textnode |
| SwNodeIndex& rIdx = pPam->GetPoint()->nNode; |
| pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx, |
| rGrfNm, aEmptyStr, // Name der Graphic !! |
| pGrf, |
| (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl() ); |
| |
| if( pGrfAttrSet ) |
| pGrfNd->SetAttr( *pGrfAttrSet ); |
| |
| SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ]; |
| pFlySave->nSttNd = rIdx.GetIndex() - 1; |
| |
| if( 1 < aFlyArr.Count() ) |
| { |
| pFlySave = aFlyArr[ aFlyArr.Count() - 2 ]; |
| if( pFlySave->nEndNd == rIdx ) |
| pFlySave->nEndNd = rIdx.GetIndex() - 1; |
| } |
| } |
| } |
| else |
| { |
| // wenn normale RTF-Grafik, dann steht diese im Textfluss ! |
| SwAttrSet aFlySet( pDoc->GetAttrPool(), RES_OPAQUE, /*RES_OPAQUE, |
| RES_VERT_ORIENT,*/ RES_ANCHOR ); |
| const SwPosition* pPos = pPam->GetPoint(); |
| |
| SwFmtAnchor aAnchor( FLY_AS_CHAR ); |
| aAnchor.SetAnchor( pPos ); |
| aFlySet.Put( aAnchor ); |
| aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP )); |
| |
| if (pDoc->IsInHeaderFooter(pPos->nNode)) |
| { |
| SvxOpaqueItem aOpaqueItem(RES_OPAQUE, sal_False); |
| SwFmtSurround aSurroundItem(SURROUND_THROUGHT); |
| aFlySet.Put(aOpaqueItem); |
| aFlySet.Put(aSurroundItem); |
| } |
| |
| SwFlyFrmFmt* pFlyFmt = pDoc->Insert( *pPam, |
| rGrfNm, aEmptyStr, // Name der Graphic !! |
| pGrf, |
| &aFlySet, // Attribute fuer den FlyFrm |
| pGrfAttrSet, NULL ); // Attribute fuer die Grafik |
| |
| pGrfNd = pDoc->GetNodes()[ pFlyFmt->GetCntnt().GetCntntIdx()-> |
| GetIndex()+1 ]->GetGrfNode(); |
| |
| _SetPictureSize( *pGrfNd, pPos->nNode, |
| (SfxItemSet&)pFlyFmt->GetAttrSet(), |
| pPicType ); |
| if( pPicType ) |
| { |
| PictPropertyNameValuePairs::const_iterator aIt = pPicType->aPropertyPairs.begin(); |
| PictPropertyNameValuePairs::const_iterator aEnd = pPicType->aPropertyPairs.end(); |
| while( aIt != aEnd) |
| { |
| if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzDescription") )) |
| { |
| SwXFrame::GetOrCreateSdrObject( pFlyFmt ); |
| pDoc->SetFlyFrmDescription( *(pFlyFmt), aIt->second ); |
| } |
| else if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzName") )) |
| { |
| SwXFrame::GetOrCreateSdrObject( pFlyFmt ); |
| pDoc->SetFlyFrmTitle( *(pFlyFmt), aIt->second ); |
| } |
| ++aIt; |
| } |
| } |
| |
| } |
| |
| if( pGrfAttrSet ) |
| DELETEZ( pGrfAttrSet ); |
| } |
| |
| void SwRTFParser::_SetPictureSize( const SwNoTxtNode& rNd, |
| const SwNodeIndex& rAnchor, |
| SfxItemSet& rSet, |
| const SvxRTFPictureType* pPicType ) |
| { |
| Size aSize( ((SwNoTxtNode&)rNd).GetTwipSize() ); |
| if( pPicType ) |
| { |
| if( rNd.IsGrfNode() ) |
| { |
| if( SvxRTFPictureType::WIN_METAFILE != pPicType->eStyle && |
| pPicType->nGoalWidth && pPicType->nGoalHeight ) |
| { |
| aSize.Width() = pPicType->nGoalWidth; |
| aSize.Height() =pPicType->nGoalHeight; |
| } |
| else if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle ) |
| { |
| // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !! |
| aSize.Width() = pPicType->nWidth * 20; |
| aSize.Height() = pPicType->nHeight * 20; |
| } |
| else |
| { |
| // von 100TH_MM nach TWIP umrechenen! |
| // #117879# when \picwgoal resp \pichgoal are present, then use them. |
| // The values of \picwgoal and \picwgoal are already given in twips. |
| aSize.Width() = (pPicType->nGoalWidth?pPicType->nGoalWidth:(pPicType->nWidth*144)/254); |
| aSize.Height() = (pPicType->nGoalHeight?pPicType->nGoalHeight:(pPicType->nHeight*144)/254); |
| } |
| ((SwGrfNode&)rNd).SetTwipSize( aSize ); |
| } |
| |
| if( 100 != pPicType->nScalX ) |
| aSize.Width() = (((long)pPicType->nScalX) * ( aSize.Width() - |
| ( pPicType->nCropL + pPicType->nCropR ))) / 100L; |
| |
| if( 100 != pPicType->nScalY ) |
| aSize.Height() = (((long)pPicType->nScalY) * ( aSize.Height() - |
| ( pPicType->nCropT + pPicType->nCropB ))) / 100L; |
| } |
| |
| //steht der Fly etwa in einer Tabelle ? |
| const SwNode* pAnchorNd = & rAnchor.GetNode(); |
| const SwTableNode* pTblNd = pAnchorNd->FindTableNode(); |
| if( pTblNd ) |
| { |
| // Box feststellen: |
| const SwTableBox* pBox = pTblNd->GetTable().GetTblBox( |
| pAnchorNd->StartOfSectionIndex() ); |
| if( pBox ) |
| { |
| long nBoxWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); |
| if( aSize.Width() > nBoxWidth ) |
| aSize.Width() = nBoxWidth; |
| } |
| } |
| |
| //JP 8.11.2001: bug 94450 - if no size exist, then the size is set by |
| // the swapin of the graphic. |
| SwGrfNode* pGrfNd; |
| if( !aSize.Width() && !aSize.Height() && |
| 0 != (pGrfNd = (SwGrfNode*)rNd.GetGrfNode() ) && pGrfNd->IsGrfLink() ) |
| pGrfNd->SetChgTwipSize( sal_True ); |
| |
| // min. Werte einhalten !! |
| if( aSize.Width() < MINFLY ) |
| aSize.Width() = MINFLY; |
| if( aSize.Height() < MINFLY) |
| aSize.Height() = MINFLY; |
| |
| if( pPicType ) |
| { |
| sal_Bool bChg = sal_False; |
| SwCropGrf aCrop; |
| |
| /* |
| JP 28.07.99: Bug 67800 - no crop by MAC_QUICKDRAW. At time i dont know why |
| it has been coded. But this has used for any |
| RTF-File, but i dont found them. |
| if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle ) |
| { |
| // evt. ein wenig Croppen ?? |
| // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !! |
| long nTmp = pPicType->nWidth * 20; |
| if( nTmp != aSize.Width() ) |
| { |
| // in der Breite (also rechts) croppen |
| aCrop.Right() = nTmp - aSize.Width(); |
| aSize.Width() = nTmp; |
| bChg = sal_True; |
| } |
| |
| nTmp = pPicType->nHeight * 20; |
| if( nTmp != aSize.Height() ) |
| { |
| // in der Hoehe (also unten) croppen |
| aCrop.Bottom() = nTmp - aSize.Height(); |
| aSize.Height() = nTmp; |
| bChg = sal_True; |
| } |
| } |
| */ |
| if( pPicType->nCropT ) |
| { |
| aCrop.SetTop( pPicType->nCropT ); |
| bChg = sal_True; |
| } |
| if( pPicType->nCropB ) |
| { |
| aCrop.SetBottom( pPicType->nCropB ); |
| bChg = sal_True; |
| } |
| if( pPicType->nCropL ) |
| { |
| aCrop.SetLeft( pPicType->nCropL ); |
| bChg = sal_True; |
| } |
| if( pPicType->nCropR ) |
| { |
| aCrop.SetRight( pPicType->nCropR ); |
| bChg = sal_True; |
| } |
| |
| if( bChg ) |
| { |
| // dann mal an die CropWerte an die GrafikSize anpassen. |
| ((SwNoTxtNode&)rNd).SetAttr( aCrop ); |
| } |
| } |
| rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() )); |
| } |
| |
| void SwRTFParser::GetPageSize( Size& rSize ) |
| { |
| ASSERT(!maSegments.empty(), "not possible"); |
| if (maSegments.empty()) |
| { |
| rSize.Width() = 12240 - 1800 - 1800; |
| rSize.Height() = 15840 - 1440 - 1440; |
| return; |
| } |
| |
| const rtfSection &rSect = maSegments.back(); |
| |
| rSize.Width() = rSect.maPageInfo.mnPgwsxn - rSect.maPageInfo.mnMarglsxn - rSect.maPageInfo.mnMargrsxn; |
| rSize.Height() = rSect.maPageInfo.mnPghsxn - rSect.maPageInfo.mnMargtsxn - rSect.maPageInfo.mnMargbsxn; |
| |
| long nCols = rSect.NoCols(); |
| if (1 < nCols) |
| { |
| rSize.Width() /= nCols; |
| rSize.Height() /= nCols; |
| } |
| } |
| |
| void SwRTFParser::ReadBitmapData() |
| { |
| Graphic aGrf; |
| SvxRTFPictureType aPicType; |
| if( ReadBmpData( aGrf, aPicType ) ) |
| InsPicture( aEmptyStr, &aGrf, &aPicType ); |
| } |
| |
| #ifdef READ_OLE_OBJECT |
| void SwRTFParser::ReadOLEData() |
| { |
| SvCacheStream aTmpFile( 0xA000 ); |
| Graphic aGrf; |
| SvxRTFPictureType aPicType, aOleType; |
| |
| int nToken, bValidOle = sal_True, bWeiter = sal_True; |
| int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !! |
| |
| String* pStr = 0; |
| String sObjClass, sObjName, sObjData; |
| |
| while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle ) |
| { |
| nToken = GetNextToken(); |
| sal_uInt16 nVal = sal_uInt16( nTokenValue ); |
| switch( nToken ) |
| { |
| case '}': --nOpenBrakets; pStr = 0; break; |
| case '{': |
| { |
| if( RTF_IGNOREFLAG != GetNextToken() ) |
| nToken = SkipToken( -1 ); |
| else if( RTF_UNKNOWNCONTROL != GetNextToken() ) |
| nToken = SkipToken( -2 ); |
| else |
| { |
| // gleich herausfiltern |
| ReadUnknownData(); |
| nToken = GetNextToken(); |
| if( '}' != nToken ) |
| eState = SVPAR_ERROR; |
| break; |
| } |
| ++nOpenBrakets; |
| } |
| break; |
| |
| case RTF_OBJECT: |
| case RTF_OBJEMB: // default ist embedded |
| case RTF_LINKSELF: // ?? |
| case RTF_OBJLOCK: // ?? |
| case RTF_OBJUPDATE: // ?? |
| case RTF_OBJTIME: // ?? |
| case RTF_OBJSETSIZE: |
| case RTF_OBJALIGN: |
| case RTF_OBJTRANSY: |
| case RTF_OBJATTPH: |
| break; |
| |
| case RTF_OBJLINK: // ?? welche Daten sind das ?? |
| case RTF_OBJAUTLINK: // ?? -""- ?? |
| case RTF_OBJSUB: |
| case RTF_OBJPUB: |
| case RTF_OBJICEMB: |
| case RTF_OBJOCX: |
| case RTF_OBJHTML: |
| case RTF_OBJALIAS: |
| case RTF_OBJSECT: |
| bValidOle = sal_False; // diese Typen koennen wir nicht |
| break; |
| |
| case RTF_OBJCLASS: |
| // Daten lesen |
| pStr = &sObjClass; |
| break; |
| |
| case RTF_OBJNAME: |
| // Daten lesen |
| pStr = &sObjName; |
| break; |
| |
| case RTF_OBJDATA: |
| pStr = &sObjData; |
| break; |
| |
| case RTF_RESULT: |
| { |
| // hier weitermachen, wenn das OLE-Object ungueltig ist |
| bWeiter = sal_False; |
| } |
| break; |
| case RTF_RSLTBMP: // diese sollten wir ignorieren |
| case RTF_RSLTMERGE: |
| case RTF_RSLTPICT: |
| case RTF_RSLTRTF: |
| case RTF_RSLTTXT: |
| break; |
| |
| case RTF_OBJW: aOleType.nWidth = nVal; break; |
| case RTF_OBJH: aOleType.nHeight = nVal; break; |
| case RTF_OBJCROPT: aOleType.nCropT = (short)nTokenValue; break; |
| case RTF_OBJCROPB: aOleType.nCropB = (short)nTokenValue; break; |
| case RTF_OBJCROPL: aOleType.nCropL = (short)nTokenValue; break; |
| case RTF_OBJCROPR: aOleType.nCropR = (short)nTokenValue; break; |
| case RTF_OBJSCALEX: aOleType.nScalX = nVal; break; |
| case RTF_OBJSCALEY: aOleType.nScalY = nVal; break; |
| |
| case RTF_TEXTTOKEN: |
| if( 1 < nOpenBrakets && pStr ) |
| { |
| if( pStr == &sObjData ) |
| { |
| xub_StrLen nHexLen = HexToBin( aToken ); |
| if( STRING_NOTFOUND != nHexLen ) |
| bValidOle = sal_False; |
| else |
| { |
| aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen ); |
| bValidOle = 0 == aTmpFile.GetError(); |
| } |
| } |
| else |
| *pStr += aToken; |
| } |
| break; |
| } |
| } |
| |
| if( bValidOle ) |
| { |
| bValidOle = sal_False; // erstmal |
| } |
| |
| if( !bWeiter ) // dann stehen wir noch im Result |
| { |
| // ist das Ole-Object Ok? |
| // -> dann solange SkipGroup rufen, bis zur letzten |
| // schliessenden Klammer |
| // ansonsten alle Token verarbeiten, bis zur letzten |
| // schliessenden Klammer |
| |
| bWeiter = sal_True; |
| while( nOpenBrakets && IsParserWorking() && bWeiter ) |
| { |
| switch( nToken = GetNextToken() ) |
| { |
| case '}': --nOpenBrakets; break; |
| case '{': ++nOpenBrakets; break; |
| } |
| if( nOpenBrakets && !bValidOle ) |
| NextToken( nToken ); |
| } |
| } |
| |
| if( !bValidOle && '}' != nToken ) |
| SkipGroup(); |
| |
| SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet |
| } |
| #endif |
| |
| /* vi:set tabstop=4 shiftwidth=4 expandtab: */ |