? AllIDid ? mypatch.2 ? output ? mypatch ? sortof Index: rtffly.cxx =================================================================== RCS file: /cvs/sw/sw/source/filter/rtf/rtffly.cxx,v retrieving revision 1.13 diff -u -r1.13 rtffly.cxx --- rtffly.cxx 13 Jan 2004 16:49:58 -0000 1.13 +++ rtffly.cxx 2 Feb 2004 10:56:17 -0000 @@ -2,9 +2,9 @@ * * $RCSfile: rtffly.cxx,v $ * - * $Revision: 1.13 $ + * $Revision: 1.12.120.4 $ * - * last change: $Author: obo $ $Date: 2004/01/13 16:49:58 $ + * last change: $Author: cmc $ $Date: 2004/01/23 15:10:30 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -172,15 +172,15 @@ #ifndef _FLTINI_HXX #include #endif -#ifndef __SGI_STL_DEQUE -#include +#ifndef _TBLSEL_HXX +#include #endif -#ifndef __SGI_STL_MAP +#include + +#include #include -#endif -#ifndef __SGI_STL_UTILITY #include -#endif +#include #define ANCHOR(p) ((SwFmtAnchor*)p) @@ -190,13 +190,194 @@ SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* ) inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, BOOL bInP=TRUE) -{ - return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP); + { return (const SwFmtFrmSize&)rSet.Get( RES_FRM_SIZE,bInP); } + + +rtfFrame::rtfFrame(const SwPaM &rPaM) + : mnSttNd(rPaM.GetPoint()->nNode), mnEndNd(mnSttNd), + mnSttCnt(rPaM.GetPoint()->nContent.GetIndex()), mnEndCnt(mnSttCnt) +{ +} + +void rtfFrame::setend(const SwPaM &rPaM, const APOProperties &rApoProps) +{ + maApoProps = rApoProps; + mnEndNd = rPaM.GetPoint()->nNode; + mnEndCnt = rPaM.GetPoint()->nContent.GetIndex(); +} + +void rtfFrame::ConvertToItemSet(SfxItemSet &rSet) const +{ + /* + A positive number indicates the minimum height of the frame and a negative + number indicates the exact height of the frame. + */ + SwTwips nHeight = maApoProps.absh; + SwFrmSize eSize = maApoProps.absh < 0 ? ATT_FIX_SIZE : ATT_MIN_SIZE; + if (eSize == ATT_FIX_SIZE) + nHeight = -nHeight; + + /* + A value of zero indicates that the height of the frame adjusts to the + contents of the frame. This is the default for frames where no height is + given. + */ + if (nHeight < MINFLY) + nHeight = MINFLY; + rSet.Put(SwFmtFrmSize(eSize, maApoProps.absw, nHeight)); + + SwRelationOrient eHoriRel; + switch (maApoProps.eHoriRel) + { + case phmrg: + //Use the margin as the horizontal reference frame. + eHoriRel = REL_PG_PRTAREA; + break; + case phpg: + //Use the page as the horizontal reference frame. + eHoriRel = REL_PG_FRAME; + break; + //Use the column as the horizontal reference frame, This is the + //default if no horizontal reference frame is given. + case phcol: + default: + eHoriRel = PRTAREA; + break; + } + + SwHoriOrient eHoriOri; + switch (maApoProps.eHoriOri) + { + case posxnone: + eHoriOri = HORI_NONE; + break; + case posxc: + //Centers the frame horizontally within the reference frame. + eHoriOri = HORI_CENTER; + break; + case posxi: + //Positions the paragraph horizontally inside the reference frame. + eHoriOri = HORI_LEFT; + break; + case posxo: + //Positions the paragraph horizontally outside the reference frame. + eHoriOri = HORI_RIGHT; + break; + case posxr: + //Positions the paragraph to the right within the reference frame. + eHoriOri = HORI_RIGHT; + break; + case posxl: + default: + //Positions the paragraph to the left within the reference frame. + //This is the default if no horizontal positioning information is + //given. + eHoriOri = HORI_LEFT; + break; + } + + using namespace sw::util; + rSet.Put(SwFmtHoriOrient(MakeSafePositioningValue(maApoProps.posx), + eHoriOri, eHoriRel)); + + SwRelationOrient eVertRel; + switch (maApoProps.eVertRel) + { + case pvmrg: + default: + //Positions the reference frame vertically relative to the margin. + //This is the default if no vertical frame positioning information + //is given. + eVertRel = REL_PG_PRTAREA; + break; + case pvpg: + //Positions the reference frame vertically relative to the page. + eVertRel = REL_PG_FRAME; + break; + case pvpara: + //Positions the reference frame vertically relative to the top left + //corner of the next unframed paragraph in the RTF stream. + eVertRel = PRTAREA; + break; + } + + SwVertOrient eVertOri; + switch (maApoProps.eVertOri) + { + case posynone: + eVertOri = VERT_NONE; + break; + case posyil: + //Positions the paragraph vertically to be in-line. + eVertOri = VERT_NONE; /*???*/ + break; + case posyt: + //Positions the paragraph at the top of the reference frame. + eVertOri = VERT_TOP; + break; + case posyc: + //Centers the paragraph vertically within the reference frame. + eVertOri = VERT_CENTER; + break; + case posyb: + //Positions the paragraph at the bottom of the reference frame. + eVertOri = VERT_BOTTOM; + break ; + case posyin: + //Positions the paragraph vertically inside the reference frame. + eVertOri = VERT_TOP; + break; + case posyout: + //Positions the paragraph vertically outside the reference frame. + eVertOri = VERT_BOTTOM; + break; + } + + rSet.Put(SwFmtVertOrient(MakeSafePositioningValue(maApoProps.posy), + eVertOri, eVertRel)); + + //Prevents text from flowing around the positioned object. + if (maApoProps.nowrap) + rSet.Put(SwFmtSurround(SURROUND_NONE)); + + //horizontal distance in twips from text on both sides of the frame. + rSet.Put(SvxLRSpaceItem(maApoProps.dfrmtxtx, maApoProps.dfrmtxtx)); + //vertical distance in twips from text on both sides of the frame. + rSet.Put(SvxULSpaceItem(maApoProps.dfrmtxty, maApoProps.dfrmtxty)); + + SvxFrameDirection eDir; + switch (maApoProps.eFlow) + { + case frmtxlrtb: + default: + //Frame box flows from left to right and top to bottom (default). + eDir = FRMDIR_HORI_LEFT_TOP; + break; + case frmtxtbrl: + //Frame box flows right to left and top to bottom. + eDir = FRMDIR_HORI_RIGHT_TOP; + break; + case frmtxbtlr: + //Frame box flows left to right and bottom to top. + eDir = FRMDIR_HORI_LEFT_TOP; /*???*/ + break; + case frmtxlrtbv: + //Frame box flows left to right and top to bottom, vertical. + eDir = FRMDIR_VERT_TOP_LEFT; + break; + case frmtxtbrlv: + //Frame box flows top to bottom and right to left, vertical. + eDir = FRMDIR_VERT_TOP_RIGHT; + break; + } + rSet.Put(SvxFrameDirectionItem(eDir)); } -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) +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 ) { } @@ -328,19 +509,142 @@ } } -void SwRTFParser::SetFlysInDoc() +void rtfFrameManager::MakeFlyFrames(const SwRTFParser &rReader) const { - // !! von Oben abarbeiten, CntntPos ist kein Index ! - SwNodes & rNds = pDoc->GetNodes(); - typedef std::pair frameEntry; - typedef std::deque rtfframesAtIndex; - typedef std::map rtfFmtMap; - rtfFmtMap aPrevFmts; + bool bHack = false; + bHack = bHack; + if (bHack) + return; + + //No paragraphs in document at all + mycIter aEnd = maFrames.end(); + mycIter aIter = maFrames.begin(); + if (aIter == aEnd) + return; + + APOProperties aNone; //Default Ctor for APO is "No apo properties" - SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME ); - for( USHORT n = 0; n < aFlyArr.Count(); ++n ) + SwPosition aAnchorPos(*rReader.pPam->GetPoint()); + for (; aIter != aEnd; ++aIter) + { + //Find the first not apo paragraph to make as the default anchor + //location, if no others will be found + if (aIter->maApoProps == aNone) + { + aAnchorPos = SwPosition(aIter->mnSttNd); + break; + } + } + + SwFrmFmt* pParent = rReader.pDoc->GetFrmFmtFromPool(RES_POOLFRM_FRAME); + std::stack aToRemove; + for (aIter = maFrames.begin(); aIter != aEnd; ++aIter) + { + if (aIter->maApoProps == aNone) + continue; + + //Find the next non apo paragraph to use an an anchor if one exists + for (mycIter aNext = aIter+1; aNext != aEnd; ++aNext) + { + if (aNext->maApoProps == aNone && aNext->mnSttNd.GetNode().IsTxtNode()) + { + aAnchorPos = SwPosition(aNext->mnSttNd); + break; + } + } + + //Nothing here to make into a frame, i.e. final txtnode was deleted + if (!aIter->mnSttNd.GetNode().IsTxtNode()) + continue; + + SwPaM aSelection(aIter->mnSttNd, aIter->mnSttCnt, aIter->mnEndNd, + aIter->mnEndCnt); + + SfxItemSet aSet(rReader.pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END-1); + if (!rReader.IsNewDoc()) + Reader::ResetFrmFmtAttrs(aSet); + + aIter->ConvertToItemSet(aSet); + +#if 0 + SwCntntNode *pStartNd = aSelection.GetCntntNode(); //Point + SwCntntFrm *pStart = pStartNd->GetFrm(); + SwCntntNode *pMarkNd = aSelection.GetCntntNode(false); //Mark + SwCntntFrm *pMark = pMarkNd->GetFrm(); + + SwSelBoxes aBoxes; + GetTblSel(pStart, pMark, aBoxes); + + + SwFlyFrmFmt* pFmt = rReader.pDoc->MakeFlyAndMove(aSelection, aSet, + &aBoxes, pParent); + +#else +#if 0 + SwTableCursor aTest(*aSelection.GetPoint()); + const SwSelBoxes &rBoxes = aTest.GetBoxes(); + + SwFlyFrmFmt* pFmt = rReader.pDoc->MakeFlyAndMove(aSelection, aSet, + &rBoxes, pParent); +#else + const SwTableSortBoxes *pBoxes = 0; + if (SwTableNode* pTblNd = aSelection.GetNode()->FindTableNode()) + { + pTblNd->DelFrms(); + SwNodeIndex aIdx(*pTblNd->EndOfSectionNode(), 1); + pTblNd->MakeFrms(&aIdx ); + + pBoxes = &(pTblNd->GetTable().GetTabSortBoxes()); + } + SwFlyFrmFmt* pFmt = rReader.pDoc->MakeFlyAndMove(aSelection, aSet, + (const SwSelBoxes*)pBoxes, pParent); +#endif +#endif + ASSERT(pFmt, "inserting a frame failed!"); + if (!pFmt) + continue; + + SwFmtAnchor aAnchor(FLY_AUTO_CNTNT); + aAnchor.SetAnchor(&aAnchorPos); + pFmt->SetAttr(aAnchor); + aToRemove.push(aIter->mnSttNd); + + if (aIter->maApoProps.absw == 0) + { + SfxItemSet aFlySet(pFmt->GetAttrSet()); + SwFmtFrmSize aSize((const SwFmtFrmSize&)(aFlySet.Get(RES_FRM_SIZE))); + aFlySet.ClearItem(RES_FRM_SIZE); + + Size aPgSize; + rReader.GetPageSize(aPgSize); + + CalculateFlySize(aFlySet, aAnchorPos.nNode, aPgSize.Width()); + + SwFmtFrmSize aNewSize((const SwFmtFrmSize&)(aFlySet.Get(RES_FRM_SIZE))); + aSize.SetWidth(aNewSize.GetWidth()); + pFmt->SetAttr(aSize); + } + } + + bHack = bHack; + if (bHack) + return; + + while (!aToRemove.empty()) + { + SwPaM aPaM(aToRemove.top()); + rReader.pDoc->DelFullPara(aPaM); + aToRemove.pop(); + } +} + +void SwRTFParser::SetFlysInDoc() +{ + SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool(RES_POOLFRM_FRAME); + for (USHORT n = 0; n < aFlyArr.Count(); ++n) { - SwFlySave* pFlySave = aFlyArr[ n ]; + SwFlySave* pFlySave = aFlyArr[n]; ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(), "Content vom Fly steht in einem Fly" ); @@ -351,19 +655,19 @@ // Absatz das Absatz Attribut setzen. Ggfs noch die // FontSize zuruecksetzen, damit das DropCap nicht zu // groá wird. - if( pFlySave->nDropAnchor ) + if (pFlySave->nDropAnchor) { SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode(), * pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode(); - if( pSttNd && pEndNd && - pSttNd->GetIndex() + 1 == pEndNd->GetIndex() ) + if (pSttNd && pEndNd && + pSttNd->GetIndex() + 1 == pEndNd->GetIndex()) { - BOOL bJoined; + bool bJoined; { SwPaM aTmp( *pEndNd, 0, *pSttNd, pSttNd->GetTxt().Len() ); bJoined = pDoc->DeleteAndJoin( aTmp ); } - if( bJoined ) + if (bJoined) { SwFmtDrop aDropCap; aDropCap.GetLines() = (BYTE)pFlySave->nDropLines; @@ -378,219 +682,147 @@ continue; } - // liegt Ende und Start vom Naechsten im gleichen Node, dann muss - // gesplittet werden - if( n + 1 < aFlyArr.Count() && pFlySave->nEndCnt && - pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd ) - { - SwCntntNode* pCNd = rNds[ pFlySave->nEndNd ]->GetCntntNode(); - if( pCNd ) - { - SwPosition aPos( pFlySave->nEndNd, - SwIndex( pCNd, pFlySave->nEndCnt )); - pDoc->SplitNode( aPos ); - 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 - 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, FALSE ) ) - _SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart, - pFlySave->aFlySet ); - if( 0 != ( pNd = pNd->FindTableNode() ) ) - pFlySave->SetFlySize( *(SwTableNode*)pNd ); - } - else - { - // TabelleNodes beachten - pNd = pNd->FindTableNode(); - if( pNd ) // am Anfang eine Tabelle, -> Bereich auf TabStart - aRg.aStart = *pNd; - - if( bMakeEmptySection ) - { - pNd = &aRg.aEnd.GetNode(); - ULONG nSectEnd = pNd->EndOfSectionIndex()+1; - - if (!pNd->IsTableNode() && (pNd = pNd->FindTableNode())) - { - 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) - else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode(). - FindTableBoxStartNode()) && - pTblBxNd->GetIndex() - 1 == pNd->GetIndex()) - aRg.aEnd = *pNd; - else - { - // Tabelle ist noch groesser, also splitte sie hier. - rNds.SplitTable( aRg.aEnd, 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 - { - 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->Move( aRg, aTmpIdx ); - } - - pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd )); - - CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd, - pFlySave->nPageWidth ); + SwPosition aPos(pFlySave->nSttNd); + SwFmtAnchor aAnchor((const SwFmtAnchor&)pFlySave->aFlySet.Get(RES_ANCHOR)); + aAnchor.SetAnchor(&aPos); + pFlySave->aFlySet.Put(aAnchor); - // if the section only contains one Node and this has a - // border or backgorund, then put it to the frame - // Not in our own RTF-Format! - if( pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() && - !bSwPageDesc ) - { - SwTxtNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ] - ->GetTxtNode(); - if( pSrcNd && pSrcNd->GetpSwAttrSet() ) - { - SfxItemSet aTmpSet( pDoc->GetAttrPool(), - RES_BACKGROUND, RES_BOX ); - aTmpSet.Put( *pSrcNd->GetpSwAttrSet() ); - if( aTmpSet.Count() ) - { - pFlySave->aFlySet.Put( aTmpSet ); - pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX ); - } - } - } - - SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent ); - pFmt->SetAttr( pFlySave->aFlySet ); - const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); - if( FLY_IN_CNTNT != 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); - aPrevFmts[pCurrentAnchor].push_back(*aIter); - } - rDeque.clear(); - aEndNd--; - } - } - 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) + SwFlyFrmFmt* pFmt = 0; { - frameEntry &rEntry = *aQIter; - SwFlyFrmFmt *pFrm = rEntry.first; - SwFmtAnchor &rAnchor = rEntry.second; - pFrm->SetAttr(rAnchor); + SwPaM aRegion(pFlySave->nSttNd, 0, pFlySave->nEndNd, pFlySave->nEndCnt); + pFmt = pDoc->MakeFlyAndMove(aRegion, pFlySave->aFlySet, 0, pParent); } - } + ASSERT(pFmt, "Format missing"); + if (pFmt) + { + SwAttrSet aFlySet(pFmt->GetAttrSet()); + CalculateFlySize(aFlySet, pFlySave->nSttNd, pFlySave->nPageWidth ); + pFmt->SetAttr(aFlySet); + } + delete pFlySave; + } aFlyArr.Remove(0, aFlyArr.Count()); } -// clips the text box to the min or max position if it is outside our min or max boundry -long SwRTFParser::GetSafePos(long nPos) +bool APOProperties::HandleToken(int nToken, long nTokenValue) { - if(nPos > SHRT_MAX) - nPos = SHRT_MAX; - else if(nPos < SHRT_MIN) - nPos = SHRT_MIN; - - return nPos; + bool bHandled = true; + switch (nToken) + { + case RTF_ABSW: + absw = nTokenValue; + break; + case RTF_ABSH: + absh = nTokenValue; + break; + case RTF_PHMRG: + eHoriRel = phmrg; + break; + case RTF_PHPG: + eHoriRel = phpg; + break; + case RTF_PHCOL: + eHoriRel = phcol; + break; + case RTF_POSX: + case RTF_POSNEGX: + eHoriOri = posxnone; + posx = nTokenValue; + break; + case RTF_POSXC: + eHoriOri = posxc; + break; + case RTF_POSXI: + eHoriOri = posxi; + break; + case RTF_POSXO: + eHoriOri = posxo; + break; + case RTF_POSXR: + eHoriOri = posxr; + case RTF_POSXL: + eHoriOri = posxl; + break; + case RTF_PVMRG: + eVertRel = pvmrg; + break; + case RTF_PVPG: + eVertRel = pvpg; + break; + case RTF_PVPARA: + eVertRel = pvpara; + break; + case RTF_POSY: + case RTF_POSNEGY: + posy = nTokenValue; + break; + case RTF_POSYIL: + eVertOri = posyil; + break; + case RTF_POSYT: + eVertOri = posyt; + break; + case RTF_POSYC: + eVertOri = posyc; + break; + case RTF_POSYB: + eVertOri = posyb; + break; + case RTF_POSYIN: + eVertOri = posyin; + break; + case RTF_POSYOUT: + eVertOri = posyout; + break; + case RTF_ABSLOCK: + abslock = nTokenValue ? true : false; + break; + case RTF_NOWRAP: + nowrap = true; + break; + case RTF_DXFRTEXT: + dfrmtxtx = dfrmtxty = nTokenValue; + break; + case RTF_DFRMTXTX: + dfrmtxtx = nTokenValue; + break; + case RTF_DFRMTXTY: + dfrmtxty = nTokenValue; + break; + case RTF_DROPCAPLI: + dropcapli = nTokenValue; + break; + case RTF_DROPCAPT: + dropcapt = static_cast(nTokenValue); + break; + case RTF_ABSNOOVRLP: + absnoovrlp = nTokenValue ? true : false; + break; + case RTF_FRMTXLRTB: + eFlow = frmtxlrtb; + break; + case RTF_FRMTXTBRL: + eFlow = frmtxtbrl; + break; + case RTF_FRMTXBTLR: + eFlow = frmtxbtlr; + break; + case RTF_FRMTXLRTBV: + eFlow = frmtxlrtbv; + break; + case RTF_FRMTXTBRLV: + eFlow = frmtxtbrlv; + break; + default: + bHandled = false; + break; + } + return bHandled; } +#if 0 + void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet ) { // ein Set fuer die FrmFmt-Attribute @@ -605,7 +837,7 @@ // RTF-Defaults setzen: SwFmtAnchor aAnchor(FLY_PAGE); - SwFmtHoriOrient aHori( 0, HORI_LEFT, /*FRAME*/REL_PG_PRTAREA ); + SwFmtHoriOrient aHori( 0, HORI_LEFT, REL_PG_PRTAREA ); SwFmtVertOrient aVert( 0, VERT_TOP, REL_PG_PRTAREA ); SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP ); @@ -707,7 +939,7 @@ case RTF_POSNEGX: case RTF_POSX: aHori.SetHoriOrient( HORI_NONE ); - aHori.SetPos( GetSafePos((long)nTokenValue) ); + aHori.SetPos(MakeSafePositioningValue(nTokenValue)); break; case RTF_POSXC: aHori.SetHoriOrient( HORI_CENTER ); break; case RTF_POSXI: aHori.SetHoriOrient( HORI_LEFT ); @@ -721,7 +953,7 @@ case RTF_POSNEGY: case RTF_POSY: aVert.SetVertOrient( VERT_NONE ); - aVert.SetPos( GetSafePos((long)nTokenValue) ); + aVert.SetPos(MakeSafePositioningValue(nTokenValue)); break; case RTF_POSYT: aVert.SetVertOrient( VERT_TOP ); break; case RTF_POSYB: aVert.SetVertOrient( VERT_BOTTOM ); break; @@ -987,18 +1219,6 @@ nToken = GetNextToken(); } while( bWeiter && IsParserWorking() ); -#if 0 - if( !bReadSwFly && ( FRAME == aVert.GetRelationOrient() || - //JP 21.07.99: for Bug 67630 - it read into Header od Footer, set - // never the anchor to Page. Because it is then only - // on the first used page . - ( FLY_PAGE == aAnchor.GetAnchorId() && - pPam->GetPoint()->nNode < pDoc->GetNodes().GetEndOfExtras() && - ( pPam->GetNode()->FindHeaderStartNode() || - pPam->GetNode()->FindFooterStartNode() )) )) - aAnchor.SetType( FLY_AT_CNTNT ); -#endif - pSet->Put( aAnchor ); pSet->Put( aHori ); pSet->Put( aVert ); @@ -1023,16 +1243,6 @@ nTmp *= USHRT_MAX; nTmp /= nWidth; pCol->SetWishWidth( USHORT(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( USHORT(nTmp) ); - else - pCol->SetRight( 0 ); - pCol->SetLeft( 0 ); -*/ } } pSet->Put( aCol ); @@ -1043,8 +1253,9 @@ // ein neues FlyFormat anlegen oder das alte benutzen ? // (teste ob es die selben Attribute besitzt!) - SwFlySave* pFlySave; USHORT nFlyArrCnt = aFlyArr.Count(); + SwFlySave* pFlySavePrev = nFlyArrCnt ? aFlyArr[nFlyArrCnt-1] : 0; + SwFlySave* pFlySave = pFlySavePrev; /* #i5263# There were not enough frame properties found to actually justify creating @@ -1052,222 +1263,35 @@ */ if (nAppliedProps) { - if( !nFlyArrCnt || - !( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet )) + if (!pFlySavePrev || !pFlySavePrev->IsEqualFly(*pPam, aSet)) { - pFlySave = new SwFlySave( *pPam, aSet ); + pFlySave = new SwFlySave(*pPam, aSet); Size aPgSize; GetPageSize( aPgSize ); pFlySave->nPageWidth = aPgSize.Width(); - - if( nDropCapAnchor ) + if(nDropCapAnchor) { pFlySave->nDropAnchor = nDropCapAnchor; pFlySave->nDropLines = nDropCapLines; } - if (nFlyArrCnt >0){ - SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1]; + if (pFlySavePrev) + { if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex()) - { pFlySavePrev->nEndNd=pFlySave->nSttNd; - } } - aFlyArr.Insert( pFlySave, nFlyArrCnt++ ); + aFlyArr.Insert(pFlySave, nFlyArrCnt++); } } - SetPardTokenRead( FALSE ); - const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode(); - - while( !IsPardTokenRead() && IsParserWorking() ) - { - if( RTF_PARD == nToken || nOpenBrakets > GetOpenBrakets() ) - break; - - NextToken( nToken ); - - if( !IsPardTokenRead() ) - { - 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) + if (pFlySave) { - bReadSwFly = FALSE; - SkipToken( -1 ); - return; + pFlySave->nEndNd = pPam->GetPoint()->nNode; + pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex(); } - - 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 - { - FASTBOOL 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; - if( 1 == pTxtNd->GetTxt().Len() && - 0 != ( pFlyCnt = (SwTxtFlyCnt*)pTxtNd->GetTxtAttr( - 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 ); - - BOOL bSet = FALSE; - if( aSz1.GetHeight() && !aSz2.GetHeight() ) - { - bSet = TRUE; - aSz2.SetHeight( aSz1.GetHeight() ); - } - if( aSz1.GetWidth() && !aSz2.GetWidth() ) - { - bSet = 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->Move( aRg, aTmp ); - - // now delete the redundant txtnode - pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 ); - } - } - } - } - - bReadSwFly = FALSE; - SkipToken( -1 ); + bReadSwFly = false; + SkipToken(-1); } - +#endif void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf, const SvxRTFPictureType* pPicType ) @@ -1473,7 +1497,7 @@ rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() )); } -void SwRTFParser::GetPageSize( Size& rSize ) +void SwRTFParser::GetPageSize(Size& rSize) const { ASSERT(!maSegments.empty(), "not possible"); if (maSegments.empty()) Index: rtftbl.cxx =================================================================== RCS file: /cvs/sw/sw/source/filter/rtf/rtftbl.cxx,v retrieving revision 1.21 diff -u -r1.21 rtftbl.cxx --- rtftbl.cxx 13 Jan 2004 16:50:52 -0000 1.21 +++ rtftbl.cxx 2 Feb 2004 10:56:17 -0000 @@ -2,9 +2,9 @@ * * $RCSfile: rtftbl.cxx,v $ * - * $Revision: 1.21 $ + * $Revision: 1.19.30.2 $ * - * last change: $Author: obo $ $Date: 2004/01/13 16:50:52 $ + * last change: $Author: cmc $ $Date: 2004/01/22 17:17:32 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -857,8 +857,11 @@ { if (const SwEndNode *pEnd = pStart->EndOfSectionNode()) { + SwNodeIndex aOld(pPam->GetPoint()->nNode); pPam->GetPoint()->nNode = *pEnd; pPam->Move( fnMoveBackward, fnGoCntnt ); + SwNodeIndex aNew(pPam->GetPoint()->nNode); + maFrameManager.MoveStart(aOld, aNew); bFailure = false; } } Index: swparrtf.cxx =================================================================== RCS file: /cvs/sw/sw/source/filter/rtf/swparrtf.cxx,v retrieving revision 1.35 diff -u -r1.35 swparrtf.cxx --- swparrtf.cxx 13 Jan 2004 16:51:23 -0000 1.35 +++ swparrtf.cxx 2 Feb 2004 10:56:17 -0000 @@ -2,9 +2,9 @@ * * $RCSfile: swparrtf.cxx,v $ * - * $Revision: 1.35 $ + * $Revision: 1.34.14.2 $ * - * last change: $Author: obo $ $Date: 2004/01/13 16:51:23 $ + * last change: $Author: cmc $ $Date: 2004/01/22 17:17:44 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -250,11 +250,8 @@ #include #endif -#ifndef SW_MS_MSFILTER_HXX -#include -#endif #ifndef WW_WWSTYLES_HXX -#include "../inc/wwstyles.hxx" +# include #endif // einige Hilfs-Funktionen // char @@ -323,12 +320,71 @@ SetReadDocInfo( TRUE ); // diese sollen zusaetzlich ueber \pard zurueck gesetzt werden - USHORT temp; - temp = RES_TXTATR_CHARFMT; AddPlainAttr( temp ); - temp = RES_PAGEDESC; AddPardAttr( temp ); - temp = RES_BREAK; AddPardAttr( temp ); - temp = RES_PARATR_NUMRULE; AddPardAttr( temp ); - temp = FN_PARAM_NUM_LEVEL; AddPardAttr( temp ); + AddPlainAttr(RES_TXTATR_CHARFMT); + AddPardAttr(RES_PAGEDESC); + AddPardAttr(RES_BREAK); + AddPardAttr(RES_PARATR_NUMRULE); + AddPardAttr(FN_PARAM_NUM_LEVEL); + + maFrameManager.StartPara(*pPam); +} + +//The defaults according to the RTF 1.6 Specification with a little obvious +//extrapolation from section "Positioned Objects and Frames" +APOProperties::APOProperties() + : absh(0), absw(0), eHoriRel(phcol), posx(0), eHoriOri(posxl), + eVertRel(pvmrg), posy(0), eVertOri(posynone), abslock(false), nowrap(false), + dfrmtxtx(0), dfrmtxty(0), overlay(false), dropcapli(0), dropcapt(none), + absnoovrlp(false), eFlow(frmtxlrtb) +{ +} + +bool APOProperties::operator==(const APOProperties& rOther) const +{ + return + ( + absw == rOther.absw && + absh == rOther.absh && + eHoriRel == rOther.eHoriRel && + posx == rOther.posx && + eHoriOri == rOther.eHoriOri && + eVertRel == rOther.eVertRel && + posy == rOther.posy && + eVertOri == rOther.eVertOri && + abslock == rOther.abslock && + nowrap == rOther.nowrap && + dfrmtxtx == rOther.dfrmtxtx && + dfrmtxty == rOther.dfrmtxty && + overlay == rOther.overlay && + dropcapli == rOther.dropcapli && + dropcapt == rOther.dropcapt && + absnoovrlp == rOther.absnoovrlp && + eFlow == rOther.eFlow + ); +} + +void SwRTFParser::EnterEnvironment() +{ + maFrameManager.EnterEnvironment(); +} + +void SwRTFParser::LeaveEnvironment() +{ + maFrameManager.LeaveEnvironment(); +} + +void SwRTFParser::ResetPard() +{ + maFrameManager.ResetCurrentEnvironment(); +} + +void SwRTFParser::InsertText() +{ + bContainsPara = false; + // dann fuege den String ein, ohne das Attribute am Ende + // aufgespannt werden. + CheckInsNewTblLine(); + pDoc->Insert( *pPam, aToken ); } // Aufruf des Parsers @@ -574,6 +630,8 @@ else if( GetDocInfo() ) // evt. eingelesen DocInfo setzen pDoc->SetInfo( *GetDocInfo() ); + + maFrameManager.MakeFlyFrames(*this); } delete pSttNdIdx, pSttNdIdx = 0; delete pRegionEndIdx, pRegionEndIdx = 0; @@ -1309,7 +1367,9 @@ // Tabelle nicht mehr vorhanden ? if (USHRT_MAX != nInsTblRow && !pTableNode) NewTblLine(); // evt. Line copieren + maFrameManager.EndPara(*pPam); GotoNextBox(); + maFrameManager.StartPara(*pPam); } break; @@ -1468,57 +1528,135 @@ // RTF_SUBENTRYINDEX default: - switch( nToken & ~(0xff | RTF_SWGDEFS) ) - { - case RTF_DOCFMT: - ReadDocControls( nToken ); - break; - case RTF_SECTFMT: - ReadSectControls( nToken ); - break; - case RTF_APOCTL: - ReadFly( nToken ); - break; - case RTF_BRDRDEF | RTF_TABLEDEF: - case RTF_SHADINGDEF | RTF_TABLEDEF: - case RTF_TABLEDEF: - ReadTable( nToken ); - break; - - case RTF_INFO: - ReadInfo(); - break; - - default: - if( USHRT_MAX != nInsTblRow && - (nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )) - nInsTblRow = USHRT_MAX; + { + /* Just to break this into its logical handlers we'll split the + * remainder of the tokens into seperate handlers */ + bool bHandled = maFrameManager.HandleToken(nToken, nTokenValue); + if (!bHandled) + { + //Legacy messy code + switch( nToken & ~(0xff | RTF_SWGDEFS) ) + { + case RTF_DOCFMT: + ReadDocControls( nToken ); + break; + case RTF_SECTFMT: + ReadSectControls( nToken ); + break; + case RTF_BRDRDEF | RTF_TABLEDEF: + case RTF_SHADINGDEF | RTF_TABLEDEF: + case RTF_TABLEDEF: + ReadTable( nToken ); + break; + + case RTF_INFO: + ReadInfo(); + break; + } + } - SvxRTFParser::NextToken( nToken ); - break; - } + if (!bHandled) + { + if( USHRT_MAX != nInsTblRow && + (nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )) + nInsTblRow = USHRT_MAX; + + SvxRTFParser::NextToken( nToken ); + } + } + break; } if( USHRT_MAX != nInsTblRow && (nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )) nInsTblRow = USHRT_MAX; } +void rtfFrameManager::EndPara(const SwPaM &rPaM) +{ + ASSERT(!maFrames.empty(), "called without any paragraphs"); + if (!maFrames.empty()) + { + if (maFrames.size() > 1) + { + //Consecutive paragraphs with the same frame + //formatting are considered part of the same frame. + myrIter aRIter = maFrames.rbegin(); + ++aRIter; + if (aRIter->maApoProps == CurrentAPO()) + maFrames.pop_back(); + } -void SwRTFParser::InsertText() + maFrames.back().setend(rPaM, CurrentAPO()); + } +} + +void rtfFrameManager::MoveStart(const SwNodeIndex &rOld, + const SwNodeIndex &rNew) { - bContainsPara = false; - // dann fuege den String ein, ohne das Attribute am Ende - // aufgespannt werden. - CheckInsNewTblLine(); - pDoc->Insert( *pPam, aToken ); + if (!maFrames.empty()) + { + if (maFrames.back().mnSttNd == rOld) + maFrames.back().mnSttNd = rNew; + } } +void rtfFrameManager::StartPara(const SwPaM &rPaM) +{ + maFrames.push_back(rtfFrame(rPaM)); +} + +APOProperties &rtfFrameManager::CurrentAPO() +{ + ASSERT(!maProps.empty(), "called without any paragraphs"); + //throw something + return maProps.top(); +} + +void rtfFrameManager::ResetCurrentEnvironment() +{ + ASSERT(!maFrames.empty(), "called without any paragraphs"); + CurrentAPO() = APOProperties(); +} + +bool rtfFrameManager::HandleToken(int nToken, long nTokenValue) +{ + return CurrentAPO().HandleToken(nToken, nTokenValue); +} + +void rtfFrameManager::EnterEnvironment() +{ + if (maProps.empty()) + maProps.push(APOProperties()); + else + maProps.push(maProps.top()); +} + +void rtfFrameManager::LeaveEnvironment() +{ + ASSERT(!maProps.empty(), "should not be empty"); + if (!maProps.empty()) + maProps.pop(); +} + +rtfFrameManager::rtfFrameManager() +{ + EnterEnvironment(); +} + +rtfFrameManager::~rtfFrameManager() +{ + ASSERT(maProps.size() == 1, "Expected only 1 environment at dtor, no problem though"); + while (!maProps.empty()) + maProps.pop(); +} void SwRTFParser::InsertPara() { bContainsPara = true; CheckInsNewTblLine(); + maFrameManager.EndPara(*pPam); pDoc->AppendTxtNode(*pPam->GetPoint()); + maFrameManager.StartPara(*pPam); // setze das default Style if( !bStyleTabValid ) @@ -1531,8 +1669,6 @@ ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() ); } - - void SwRTFParser::MovePos( int bForward ) { Index: swparrtf.hxx =================================================================== RCS file: /cvs/sw/sw/source/filter/rtf/swparrtf.hxx,v retrieving revision 1.15 diff -u -r1.15 swparrtf.hxx --- swparrtf.hxx 13 Jan 2004 16:51:53 -0000 1.15 +++ swparrtf.hxx 2 Feb 2004 10:56:18 -0000 @@ -2,9 +2,9 @@ * * $RCSfile: swparrtf.hxx,v $ * - * $Revision: 1.15 $ + * $Revision: 1.14.14.2 $ * - * last change: $Author: obo $ $Date: 2004/01/13 16:51:53 $ + * last change: $Author: cmc $ $Date: 2004/01/22 17:17:56 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -64,15 +64,10 @@ #ifndef _SWPARRTF_HXX #define _SWPARRTF_HXX -#ifndef __SGI_STL_MAP #include -#endif -#ifndef __SGI_STL_DEQUE #include -#endif -#ifndef __SGI_STL_VECTOR +#include #include -#endif #ifndef _SVSTDARR_HXX #define _SVSTDARR_BOOLS @@ -93,7 +88,7 @@ #endif #ifndef SW_MS_MSFILTER_HXX -#include "../inc/msfilter.hxx" +#include #endif extern void GetLineIndex(SvxBoxItem &rBox, short nLineThickness, short nSpace, BYTE nCol, short nIdx, @@ -273,6 +268,103 @@ bool IsLandScape() const { return maPageInfo.mbLndscpsxn; } }; +class TokenHandler +{ +public: + virtual bool HandleToken(int nToken, long nTokenValue) = 0; +}; + +enum horirel {phmrg, phpg, phcol}; +enum horiori {posxnone, posxc, posxi, posxo, posxr, posxl}; +enum vertrel {pvmrg, pvpg, pvpara}; +enum vertori {posynone, posyil, posyt, posyc, posyb, posyin, posyout}; +enum dropcap {none = 0, intext = 1, margin = 2}; +enum textflow {frmtxlrtb, frmtxtbrl, frmtxbtlr, frmtxlrtbv, frmtxtbrlv}; + +//See RTF Specification 1.6 Section "Positioned Objects and Frames" for details +class APOProperties : public TokenHandler +{ +public: + //Frame Size + long absw; + long absh; + //Horizontal Position + horirel eHoriRel; //phmrg, phpg, phcol + long posx; //posx, posnegx + horiori eHoriOri; //posxc, posxi, posxo, posxr, posxl + //Vertical Position + vertrel eVertRel; //pvmrg, pvpg, pvpara + long posy; //posy, posnegy + vertori eVertOri; //posyil, posyt, posyc, posyb, posyin, posyout + bool abslock; + //Text Wrapping + bool nowrap; + long dfrmtxtx; //dfrmtxtx, dxfrtext + long dfrmtxty; //dfrmtxty, dxfrtext + bool overlay; + //Drop Caps + long dropcapli; + dropcap dropcapt; + //Overlap + bool absnoovrlp; + //Text Flow + textflow eFlow; //frmtxlrtb, frmtxtbrl, frmtxbtlr, frmtxlrtbv, frmtxtbrlv + + APOProperties(); + bool HandleToken(int nToken, long nTokenValue); + bool operator==(const APOProperties& rOther) const; +}; + +class rtfFrame +{ +public: + APOProperties maApoProps; + SwNodeIndex mnSttNd, mnEndNd; + xub_StrLen mnSttCnt, mnEndCnt; + rtfFrame(const SwPaM &rPaM); + void setend(const SwPaM &rPaM, const APOProperties &rApoProperties); + void ConvertToItemSet(SfxItemSet &rSet) const; +}; + +/* + A lot of the current code in the filter sees a token of e.g. frame type and + loops through all the following tokens until it sees one it doesn't know and + considers that the end of all the frame positioning tokens. This is clearly + rubbish, as the spec clearly says "These control words can appear anywhere in + the body of the paragraph, not just at the beginning." Instead we should + gather this information inside the range in which it has an effect and make + our decisions when we leave that environment and know at that stage that we + have seen all the possible tokens that will affect our decision + + In other words the rtfFrameManager and related classes are right, nearly + everthing else is probably wrong :-(. But one step at a time +*/ +class rtfFrameManager : public TokenHandler +{ +private: + std::stack maProps; + std::deque maFrames; + typedef std::deque::const_iterator mycIter; + typedef std::deque::reverse_iterator myrIter; +public: + APOProperties &CurrentAPO(); + + void EnterEnvironment(); + void ResetCurrentEnvironment(); + void LeaveEnvironment(); + + void StartPara(const SwPaM &rPaM); + void MoveStart(const SwNodeIndex &rOld, const SwNodeIndex &rNew); + void EndPara(const SwPaM &rPaM); + + bool HandleToken(int nToken, long nTokenValue); + + void MakeFlyFrames(const SwRTFParser &rReader) const; + + rtfFrameManager(); + ~rtfFrameManager(); +}; + class rtfSections { private: @@ -323,11 +415,29 @@ */ sw::util::ParaStyleMapper maParaStyleMapper; sw::util::CharStyleMapper maCharStyleMapper; - - friend class rtfSections; + + /* + The default page settings + */ DocPageInformation maPageDefaults; + + /* + All the sections which are inserted into the document + */ + friend class rtfSections; rtfSections maSegments; + /* + All the frames (Absolutely Positioned Objects) which are inserted into the + document + */ + friend class rtfFrameManager; + rtfFrameManager maFrameManager; + virtual void EnterEnvironment(); + virtual void LeaveEnvironment(); + virtual void ResetPard(); + virtual void InsertPara(); + std::map maTables; SwRTFStyleTbl aTxtCollTbl; SwRTFCharStyleTbl aCharFmtTbl; @@ -368,7 +478,6 @@ */ bool CantUseTables() const { return mbReadNoTbl || mbIsFootnote; } - virtual void InsertPara(); virtual void InsertText(); virtual void MovePos( int bForward = TRUE ); virtual void SetEndPrevPara( SvxNodeIdx*& rpNodePos, xub_StrLen& rCntPos ); @@ -415,7 +524,7 @@ SfxItemSet& rSet, const SvxRTFPictureType* = 0 ); void SetFlysInDoc(); - void GetPageSize( Size& rSize ); // Groesse der PagePrintArea + void GetPageSize(Size& rSize) const; // Groesse der PagePrintArea // fuers Einlesen von Tabellen void GotoNextBox(); @@ -429,8 +538,6 @@ const SwNodeIndex& rEnd ); void SetNumLSpace( SwTxtNode& rNd, const SwNodeNum& rNum, const SwNumRule& rRule ); - long GetSafePos(long nPos); - protected: // wird fuer jedes Token gerufen, das in CallParser erkannt wird virtual void NextToken( int nToken ); @@ -452,7 +559,7 @@ void SetPageInformationAsDefault(const DocPageInformation &rInfo); void ReadSectControls( int nToken ); void DoHairyWriterPageDesc(int nToken); - void ReadFly( int nToken, SfxItemSet* pFillSet = 0 ); + bool ReadFly(int nToken); void ReadTable( int nToken ); void ReadPageDescTbl();