diff options
Diffstat (limited to 'sw/source/filter/rtf/swparrtf.cxx')
-rw-r--r-- | sw/source/filter/rtf/swparrtf.cxx | 4462 |
1 files changed, 4462 insertions, 0 deletions
diff --git a/sw/source/filter/rtf/swparrtf.cxx b/sw/source/filter/rtf/swparrtf.cxx new file mode 100644 index 000000000000..5a5e7a65e0a7 --- /dev/null +++ b/sw/source/filter/rtf/swparrtf.cxx @@ -0,0 +1,4462 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 <stack> + +#include <tools/errinf.hxx> +#include <tools/stream.hxx> +#include <svl/itemiter.hxx> +#include <svtools/rtftoken.h> +#include <svl/intitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/lspcitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/escpitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/hyznitem.hxx> +#include <fmtpdsc.hxx> +#include <fmtfld.hxx> +#include <fmthdft.hxx> +#include <fmtcntnt.hxx> +#include <txtftn.hxx> +#include <fmtclds.hxx> +#include <fmtftn.hxx> +#include <fmtfsize.hxx> +#include <fmtflcnt.hxx> +#include <fmtanchr.hxx> +#include <frmatr.hxx> +#include <docstat.hxx> +#include <swtable.hxx> +#include <shellio.hxx> +#include <swtypes.hxx> +#include <ndtxt.hxx> +#include <doc.hxx> +#include <docary.hxx> +#include <pam.hxx> +#include <mdiexp.hxx> // ...Percent() +#include <swparrtf.hxx> +#include <charfmt.hxx> +#include <pagedesc.hxx> +#include <ftninfo.hxx> +#include <docufld.hxx> +#include <flddat.hxx> +#include <fltini.hxx> +#include <fchrfmt.hxx> +#include <paratr.hxx> +#include <section.hxx> +#include <fmtclbl.hxx> +#include <viewsh.hxx> +#include <shellres.hxx> +#include <hfspacingitem.hxx> +#include <tox.hxx> +#include <swerror.h> +#include <cmdid.h> +#include <statstr.hrc> // ResId fuer Statusleiste +#include <SwStyleNameMapper.hxx> +#include <tblsel.hxx> // SwSelBoxes + +#include <docsh.hxx> +#include <fmtlsplt.hxx> // SwLayoutSplit +#include <editeng/keepitem.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdorect.hxx> + + +#include <fmtsrnd.hxx> +#include <fmtfollowtextflow.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <editeng/opaqitem.hxx> +#include "svx/svdograf.hxx" +#include <svx/xflclit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/paperinf.hxx> + +#include <tools/stream.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/b2drange.hxx> +#include <vcl/salbtype.hxx> // FRound + +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> + + +using namespace ::com::sun::star; + + +// einige Hilfs-Funktionen +// char +inline const SvxFontHeightItem& GetSize(const SfxItemSet& rSet,BOOL bInP=TRUE) + { return (const SvxFontHeightItem&)rSet.Get( RES_CHRATR_FONTSIZE,bInP); } +inline const SvxLRSpaceItem& GetLRSpace(const SfxItemSet& rSet,BOOL bInP=TRUE) + { return (const SvxLRSpaceItem&)rSet.Get( RES_LR_SPACE,bInP); } + +/* */ + +extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportRTF() +{ + return new RtfReader(); +} + +// Aufruf fuer die allg. Reader-Schnittstelle +ULONG RtfReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String &) +{ + if( !pStrm ) + { + ASSERT( FALSE, "RTF-Read ohne Stream" ); + return ERR_SWG_READ_ERROR; + } + + //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne + // Kapitelnummer. Darum hier explizit abschalten + // weil das Default jetzt wieder auf AN ist. + if( !bInsertMode ) + { + Reader::SetNoOutlineNum( rDoc ); + + // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf. + Reader::ResetFrmFmts( rDoc ); + } + + ULONG nRet = 0; + SwDocShell *pDocShell(rDoc.GetDocShell()); + DBG_ASSERT(pDocShell, "no SwDocShell"); + uno::Reference<document::XDocumentProperties> xDocProps; + if (pDocShell) { + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + pDocShell->GetModel(), uno::UNO_QUERY_THROW); + xDocProps.set(xDPS->getDocumentProperties()); + } + + SvParserRef xParser = new SwRTFParser( &rDoc, xDocProps, + rPam, *pStrm, rBaseURL, !bInsertMode ); + SvParserState eState = xParser->CallParser(); + if( SVPAR_PENDING != eState && SVPAR_ACCEPTED != eState ) + { + String sErr( String::CreateFromInt32( xParser->GetLineNr() )); + sErr += ','; + sErr += String::CreateFromInt32( xParser->GetLinePos() ); + + nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr, + ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR ); + } + + + return nRet; +} + +SwRTFParser::SwRTFParser(SwDoc* pD, + uno::Reference<document::XDocumentProperties> i_xDocProps, + const SwPaM& rCrsr, SvStream& rIn, const String& rBaseURL, + int bReadNewDoc) : + SvxRTFParser(pD->GetAttrPool(), rIn, i_xDocProps, bReadNewDoc), + maParaStyleMapper(*pD), + maCharStyleMapper(*pD), + maSegments(*this), + maInsertedTables(*pD), + aMergeBoxes(0, 5), + aTblFmts(0, 10), + mpBookmarkStart(0), + mpRedlineStack(0), + pAuthorInfos(0), + pGrfAttrSet(0), + pTableNode(0), + pOldTblNd(0), + pSttNdIdx(0), + pRegionEndIdx(0), + pDoc(pD), + pRelNumRule(new SwRelNumRuleSpaces(*pD, static_cast< BOOL >(bReadNewDoc))), + pRedlineInsert(0), + pRedlineDelete(0), + sBaseURL( rBaseURL ), + nAktPageDesc(0), + nAktFirstPageDesc(0), + nAktBox(0), + nInsTblRow(USHRT_MAX), + nNewNumSectDef(USHRT_MAX), + nRowsToRepeat(0), + // --> OD 2008-12-22 #i83368# + mbReadCellWhileReadSwFly( false ), + // <-- + bTrowdRead(0), + nReadFlyDepth(0), + nZOrder(0) +{ + mbIsFootnote = mbReadNoTbl = bReadSwFly = bSwPageDesc = bStyleTabValid = + bInPgDscTbl = bNewNumList = false; + bFirstContinue = true; + bContainsPara = false; + bContainsTablePara = false; + bNestedField = false; + bForceNewTable = false; + + pPam = new SwPaM( *rCrsr.GetPoint() ); + SetInsPos( SwxPosition( pPam ) ); + SetChkStyleAttr( 0 != bReadNewDoc ); + SetCalcValue( FALSE ); + 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 ); +} + +// Aufruf des Parsers +SvParserState SwRTFParser::CallParser() +{ + mbReadNoTbl = false; + bFirstContinue = true; + + rInput.Seek(STREAM_SEEK_TO_BEGIN); + rInput.ResetError(); + + mpRedlineStack = new sw::util::RedlineStack(*pDoc); + + return SvxRTFParser::CallParser(); +} + +bool lcl_UsedPara(SwPaM &rPam) +{ + const SwCntntNode* pCNd; + const SfxItemSet* pSet; + if( rPam.GetPoint()->nContent.GetIndex() || + ( 0 != ( pCNd = rPam.GetCntntNode()) && + 0 != ( pSet = pCNd->GetpSwAttrSet()) && + ( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, FALSE ) || + SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, FALSE )))) + return true; + return false; +} + +void SwRTFParser::Continue( int nToken ) +{ + if( bFirstContinue ) + { + bFirstContinue = FALSE; + + if (IsNewDoc()) + { + // + // COMPATIBILITY FLAGS START + // + pDoc->set(IDocumentSettingAccess::PARA_SPACE_MAX, true); + pDoc->set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true); + pDoc->set(IDocumentSettingAccess::TAB_COMPAT, true); + pDoc->set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, true); + pDoc->set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true); + pDoc->set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true); + pDoc->set(IDocumentSettingAccess::ADD_EXT_LEADING, true); + pDoc->set(IDocumentSettingAccess::OLD_NUMBERING, false); + pDoc->set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false ); + pDoc->set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, false); + pDoc->set(IDocumentSettingAccess::OLD_LINE_SPACING, false); + pDoc->set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true); + pDoc->set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false); + pDoc->set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false); + pDoc->set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true); + pDoc->set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false); // --> FME 2005-08-11 #i53199# + // --> FME 2006-02-10 #131283# + pDoc->set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); + pDoc->set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true); + + // + // COMPATIBILITY FLAGS END + // + } + + // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt! + pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() ); + if( !IsNewDoc() ) // in ein Dokument einfuegen ? + { + const SwPosition* pPos = pPam->GetPoint(); + SwTxtNode* pSttNd = pPos->nNode.GetNode().GetTxtNode(); + + pDoc->SplitNode( *pPos, false ); + + *pSttNdIdx = pPos->nNode.GetIndex()-1; + pDoc->SplitNode( *pPos, false ); + + SwPaM aInsertionRangePam( *pPos ); + + pPam->Move( fnMoveBackward ); + + // #106634# split any redline over the insertion point + aInsertionRangePam.SetMark(); + *aInsertionRangePam.GetPoint() = *pPam->GetPoint(); + aInsertionRangePam.Move( fnMoveBackward ); + pDoc->SplitRedline( aInsertionRangePam ); + + pDoc->SetTxtFmtColl( *pPam, pDoc->GetTxtCollFromPool + ( RES_POOLCOLL_STANDARD, false )); + + // verhinder das einlesen von Tabellen in Fussnoten / Tabellen + ULONG nNd = pPos->nNode.GetIndex(); + mbReadNoTbl = 0 != pSttNd->FindTableNode() || + ( nNd < pDoc->GetNodes().GetEndOfInserts().GetIndex() && + pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd ); + } + + // Laufbalken anzeigen, aber nur bei synchronem Call + ULONG nCurrPos = rInput.Tell(); + rInput.Seek(STREAM_SEEK_TO_END); + rInput.ResetError(); + ::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(), pDoc->GetDocShell()); + rInput.Seek( nCurrPos ); + rInput.ResetError(); + } + + SvxRTFParser::Continue( nToken ); + + if( SVPAR_PENDING == GetStatus() ) + return ; // weiter gehts beim naechsten mal + + pRelNumRule->SetNumRelSpaces( *pDoc ); + + // den Start wieder korrigieren + if( !IsNewDoc() && pSttNdIdx->GetIndex() ) + { + //die Flys muessen zuerst zurecht gerueckt werden, denn sonst wird + // ein am 1. Absatz verankerter Fly falsch eingefuegt + if( SVPAR_ACCEPTED == eState ) + { + if( aFlyArr.Count() ) + SetFlysInDoc(); + pRelNumRule->SetOultineRelSpaces( *pSttNdIdx, pPam->GetPoint()->nNode ); + } + + SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode(); + SwNodeIndex aNxtIdx( *pSttNdIdx ); + if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx )) + { + xub_StrLen nStt = pTxtNode->GetTxt().Len(); + // wenn der Cursor noch in dem Node steht, dann setze in an das Ende + if( pPam->GetPoint()->nNode == aNxtIdx ) + { + pPam->GetPoint()->nNode = *pSttNdIdx; + pPam->GetPoint()->nContent.Assign( pTxtNode, nStt ); + } + +#ifdef DBG_UTIL +// !!! sollte nicht moeglich sein, oder ?? +ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( TRUE ).nNode.GetIndex(), + "Pam.Bound1 steht noch im Node" ); +ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( FALSE ).nNode.GetIndex(), + "Pam.Bound2 steht noch im Node" ); + +if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( TRUE ).nNode.GetIndex() ) +{ + xub_StrLen nCntPos = pPam->GetBound( TRUE ).nContent.GetIndex(); + pPam->GetBound( TRUE ).nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() + nCntPos ); +} +if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( FALSE ).nNode.GetIndex() ) +{ + xub_StrLen nCntPos = pPam->GetBound( FALSE ).nContent.GetIndex(); + pPam->GetBound( FALSE ).nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() + nCntPos ); +} +#endif + // Zeichen Attribute beibehalten! + SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode(); + if( pTxtNode->GetTxt().Len() ) + pDelNd->FmtToTxtAttr( pTxtNode ); + else + pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() ); + pTxtNode->JoinNext(); + } + } + + if( SVPAR_ACCEPTED == eState ) + { + // den letzen Bereich wieder zumachen + if( pRegionEndIdx ) + { + // JP 06.01.00: Task 71411 - the last section in WW are not a + // balanced Section. + if( !GetVersionNo() ) + { + SwSectionNode* pSectNd = pRegionEndIdx->GetNode(). + StartOfSectionNode()->GetSectionNode(); + if( pSectNd ) + pSectNd->GetSection().GetFmt()->SetFmtAttr( + SwFmtNoBalancedColumns( TRUE ) ); + } + + DelLastNode(); + pPam->GetPoint()->nNode = *pRegionEndIdx; + pPam->Move( fnMoveForward, fnGoNode ); + delete pRegionEndIdx, pRegionEndIdx = 0; + } + + sal_uInt16 nPageDescOffset = pDoc->GetPageDescCnt(); + maSegments.InsertSegments(IsNewDoc()); + UpdatePageDescs(*pDoc, nPageDescOffset); + //$flr folloing garbe collecting code has been moved from the previous procedure + // UpdatePageDescs to here in order to fix bug #117882# + rtfSections::myrDummyIter aDEnd = maSegments.maDummyPageNos.rend(); + for (rtfSections::myrDummyIter aI = maSegments.maDummyPageNos.rbegin(); aI != aDEnd; ++aI) + pDoc->DelPageDesc(*aI); + + if( aFlyArr.Count() ) + SetFlysInDoc(); + + // jetzt noch den letzten ueberfluessigen Absatz loeschen + SwPosition* pPos = pPam->GetPoint(); + if( !pPos->nContent.GetIndex() ) + { + SwTxtNode* pAktNd; + ULONG nNodeIdx = pPos->nNode.GetIndex(); + if( IsNewDoc() ) + { + SwNode* pTmp = pDoc->GetNodes()[ nNodeIdx -1 ]; + if( pTmp->IsCntntNode() && !pTmp->FindTableNode() ) + { + // --> FME 2006-02-15 #131200# Do not delete the paragraph + // if it has anchored objects: + bool bAnchoredObjs = false; + const SwSpzFrmFmts* pFrmFmts = pDoc->GetSpzFrmFmts(); + if ( pFrmFmts && pFrmFmts->Count() ) + { + for ( USHORT nI = pFrmFmts->Count(); nI; --nI ) + { + const SwFmtAnchor & rAnchor = (*pFrmFmts)[ nI - 1 ]->GetAnchor(); + if ((FLY_AT_PARA == rAnchor.GetAnchorId()) || + (FLY_AT_CHAR == rAnchor.GetAnchorId())) + { + const SwPosition * pObjPos = rAnchor.GetCntntAnchor(); + if ( pObjPos && nNodeIdx == pObjPos->nNode.GetIndex() ) + { + bAnchoredObjs = true; + break; + } + } + } + } + // <-- + + if ( !bAnchoredObjs ) + DelLastNode(); + } + } + else if (0 != (pAktNd = pDoc->GetNodes()[nNodeIdx]->GetTxtNode())) + { + if( pAktNd->CanJoinNext( &pPos->nNode )) + { + SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode(); + pPos->nContent.Assign( pNextNd, 0 ); + pPam->SetMark(); pPam->DeleteMark(); + pNextNd->JoinPrev(); + } + else if( !pAktNd->GetTxt().Len() && + pAktNd->StartOfSectionIndex()+2 < + pAktNd->EndOfSectionIndex() ) + { + pPos->nContent.Assign( 0, 0 ); + pPam->SetMark(); pPam->DeleteMark(); + pDoc->GetNodes().Delete( pPos->nNode, 1 ); + pPam->Move( fnMoveBackward ); + } + } + } + // nun noch das SplitNode vom Ende aufheben + else if( !IsNewDoc() ) + { + if( pPos->nContent.GetIndex() ) // dann gabs am Ende kein \par, + pPam->Move( fnMoveForward, fnGoNode ); // als zum naechsten Node + SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode(); + SwNodeIndex aPrvIdx( pPos->nNode ); + if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) && + *pSttNdIdx <= aPrvIdx ) + { + // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor + // usw. sind im pTxtNode angemeldet, so dass der bestehen + // bleiben MUSS. + + // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die + // Absatzattribute und die Vorlage uebernehmen! + SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode(); + pTxtNode->ChgFmtColl( pPrev->GetTxtColl() ); + pTxtNode->FmtToTxtAttr( pPrev ); + pTxtNode->ResetAllAttr(); + + if( pPrev->HasSwAttrSet() ) + pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() ); + + if( &pPam->GetBound(TRUE).nNode.GetNode() == pPrev ) + pPam->GetBound(TRUE).nContent.Assign( pTxtNode, 0 ); + if( &pPam->GetBound(FALSE).nNode.GetNode() == pPrev ) + pPam->GetBound(FALSE).nContent.Assign( pTxtNode, 0 ); + + pTxtNode->JoinPrev(); + } + } + } + delete pSttNdIdx, pSttNdIdx = 0; + delete pRegionEndIdx, pRegionEndIdx = 0; + RemoveUnusedNumRules(); + + pDoc->SetUpdateExpFldStat(true); + pDoc->SetInitDBFields(true); + + // Laufbalken bei asynchronen Call nicht einschalten !!! + ::EndProgress( pDoc->GetDocShell() ); +} + +bool rtfSections::SetCols(SwFrmFmt &rFmt, const rtfSection &rSection, + USHORT nNettoWidth) +{ + //sprmSCcolumns - Anzahl der Spalten - 1 + USHORT nCols = static_cast< USHORT >(rSection.NoCols()); + + if (nCols < 2) + return false; // keine oder bloedsinnige Spalten + + SwFmtCol aCol; // Erzeuge SwFmtCol + + //sprmSDxaColumns - Default-Abstand 1.25 cm + USHORT nColSpace = static_cast< USHORT >(rSection.StandardColSeperation()); + + aCol.Init( nCols, nColSpace, nNettoWidth ); + + // not SFEvenlySpaced + if (rSection.maPageInfo.maColumns.size()) + { + aCol._SetOrtho(false); + USHORT nWishWidth = 0, nHalfPrev = 0; + for(USHORT n=0, i=0; n < rSection.maPageInfo.maColumns.size() && i < nCols; n += 2, ++i ) + { + SwColumn* pCol = aCol.GetColumns()[ i ]; + pCol->SetLeft( nHalfPrev ); + USHORT nSp = static_cast< USHORT >(rSection.maPageInfo.maColumns[ n+1 ]); + nHalfPrev = nSp / 2; + pCol->SetRight( nSp - nHalfPrev ); + pCol->SetWishWidth( static_cast< USHORT >(rSection.maPageInfo.maColumns[ n ]) + + pCol->GetLeft() + pCol->GetRight()); + nWishWidth = nWishWidth + pCol->GetWishWidth(); + } + aCol.SetWishWidth( nWishWidth ); + } + + rFmt.SetFmtAttr(aCol); + return true; +} + +void rtfSections::SetPage(SwPageDesc &rInPageDesc, SwFrmFmt &rFmt, + const rtfSection &rSection, bool bIgnoreCols) +{ + // 1. Orientierung + rInPageDesc.SetLandscape(rSection.IsLandScape()); + + // 2. Papiergroesse + SwFmtFrmSize aSz(rFmt.GetFrmSize()); + aSz.SetWidth(rSection.GetPageWidth()); + aSz.SetHeight(rSection.GetPageHeight()); + rFmt.SetFmtAttr(aSz); + + rFmt.SetFmtAttr( + SvxLRSpaceItem(rSection.GetPageLeft(), rSection.GetPageRight(), 0, 0, RES_LR_SPACE)); + + if (!bIgnoreCols) + { + SetCols(rFmt, rSection, static_cast< USHORT >(rSection.GetPageWidth() - + rSection.GetPageLeft() - rSection.GetPageRight())); + } + + rFmt.SetFmtAttr(rSection.maPageInfo.maBox); +} + +bool HasHeader(const SwFrmFmt &rFmt) +{ + const SfxPoolItem *pHd; + if (SFX_ITEM_SET == rFmt.GetItemState(RES_HEADER, false, &pHd)) + return ((const SwFmtHeader *)(pHd))->IsActive(); + return false; +} + +bool HasFooter(const SwFrmFmt &rFmt) +{ + const SfxPoolItem *pFt; + if (SFX_ITEM_SET == rFmt.GetItemState(RES_FOOTER, false, &pFt)) + return ((const SwFmtFooter *)(pFt))->IsActive(); + return false; +} + +void rtfSections::GetPageULData(const rtfSection &rSection, bool bFirst, + rtfSections::wwULSpaceData& rData) +{ + short nWWUp = static_cast< short >(rSection.maPageInfo.mnMargtsxn); + short nWWLo = static_cast< short >(rSection.maPageInfo.mnMargbsxn); + short nWWHTop = static_cast< short >(rSection.maPageInfo.mnHeadery); + short nWWFBot = static_cast< short >(rSection.maPageInfo.mnFootery); + + if (bFirst) + { + if ( + rSection.mpTitlePage && HasHeader(rSection.mpTitlePage->GetMaster()) + ) + { + rData.bHasHeader = true; + } + } + else + { + if (rSection.mpPage && + ( + HasHeader(rSection.mpPage->GetMaster()) + || HasHeader(rSection.mpPage->GetLeft()) + ) + ) + { + rData.bHasHeader = true; + } + } + + if( rData.bHasHeader ) + { + rData.nSwUp = nWWHTop; // Header -> umrechnen, see ww8par6.cxx + + if ( nWWUp > 0 && nWWUp >= nWWHTop ) + rData.nSwHLo = nWWUp - nWWHTop; + else + rData.nSwHLo = 0; + + if (rData.nSwHLo < cMinHdFtHeight) + rData.nSwHLo = cMinHdFtHeight; + } + else // kein Header -> Up einfach uebernehmen + rData.nSwUp = Abs(nWWUp); + + if (bFirst) + { + if ( + rSection.mpTitlePage && + HasFooter(rSection.mpTitlePage->GetMaster()) + ) + { + rData.bHasFooter = true; + } + } + else + { + if (rSection.mpPage && + ( + HasFooter(rSection.mpPage->GetMaster()) + || HasFooter(rSection.mpPage->GetLeft()) + ) + ) + { + rData.bHasFooter = true; + } + } + + if( rData.bHasFooter ) + { + rData.nSwLo = nWWFBot; // Footer -> Umrechnen + if ( nWWLo > 0 && nWWLo >= nWWFBot ) + rData.nSwFUp = nWWLo - nWWFBot; + else + rData.nSwFUp = 0; + + if (rData.nSwFUp < cMinHdFtHeight) + rData.nSwFUp = cMinHdFtHeight; + } + else // kein Footer -> Lo einfach uebernehmen + rData.nSwLo = Abs(nWWLo); +} + +void rtfSections::SetPageULSpaceItems(SwFrmFmt &rFmt, + rtfSections::wwULSpaceData& rData) +{ + if (rData.bHasHeader) // ... und Header-Lower setzen + { + //Kopfzeilenhoehe minimal sezten + if (SwFrmFmt* pHdFmt = (SwFrmFmt*)rFmt.GetHeader().GetHeaderFmt()) + { + pHdFmt->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, 0, rData.nSwHLo)); + SvxULSpaceItem aHdUL(pHdFmt->GetULSpace()); + aHdUL.SetLower( rData.nSwHLo - cMinHdFtHeight ); + pHdFmt->SetFmtAttr(aHdUL); + pHdFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem( + RES_HEADER_FOOTER_EAT_SPACING, true)); + } + } + + if (rData.bHasFooter) // ... und Footer-Upper setzen + { + if (SwFrmFmt* pFtFmt = (SwFrmFmt*)rFmt.GetFooter().GetFooterFmt()) + { + pFtFmt->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, 0, rData.nSwFUp)); + SvxULSpaceItem aFtUL(pFtFmt->GetULSpace()); + aFtUL.SetUpper( rData.nSwFUp - cMinHdFtHeight ); + pFtFmt->SetFmtAttr(aFtUL); + pFtFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem( + RES_HEADER_FOOTER_EAT_SPACING, true)); + } + } + + SvxULSpaceItem aUL(rData.nSwUp, rData.nSwLo, RES_UL_SPACE ); // Page-UL setzen + rFmt.SetFmtAttr(aUL); +} + +void rtfSections::SetSegmentToPageDesc(const rtfSection &rSection, + bool bTitlePage, bool bIgnoreCols) +{ + SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage; + +// SetNumberingType(rSection, rPage); + + SwFrmFmt &rFmt = rPage.GetMaster(); +// mrReader.SetDocumentGrid(rFmt, rSection); + + wwULSpaceData aULData; + GetPageULData(rSection, bTitlePage, aULData); + SetPageULSpaceItems(rFmt, aULData); + + SetPage(rPage, rFmt, rSection, bIgnoreCols); + + UseOnPage ePage = rPage.ReadUseOn(); + if(ePage & nsUseOnPage::PD_ALL) + { + SwFrmFmt &rFmtLeft = rPage.GetLeft(); + SetPageULSpaceItems(rFmtLeft, aULData); + SetPage(rPage, rFmtLeft, rSection, bIgnoreCols); + } + +} + +void rtfSections::CopyFrom(const SwPageDesc &rFrom, SwPageDesc &rDest) +{ + UseOnPage ePage = rFrom.ReadUseOn(); + rDest.WriteUseOn(ePage); + + mrReader.pDoc->CopyHeader(rFrom.GetMaster(), rDest.GetMaster()); + SwFrmFmt &rDestFmt = rDest.GetMaster(); + rDestFmt.SetFmtAttr(rFrom.GetMaster().GetHeader()); + mrReader.pDoc->CopyHeader(rFrom.GetLeft(), rDest.GetLeft()); + mrReader.pDoc->CopyFooter(rFrom.GetMaster(), rDest.GetMaster()); + mrReader.pDoc->CopyFooter(rFrom.GetLeft(), rDest.GetLeft()); +} + +void rtfSections::MoveFrom(SwPageDesc &rFrom, SwPageDesc &rDest) +{ + UseOnPage ePage = rFrom.ReadUseOn(); + rDest.WriteUseOn(ePage); + + SwFrmFmt &rDestMaster = rDest.GetMaster(); + SwFrmFmt &rFromMaster = rFrom.GetMaster(); + rDestMaster.SetFmtAttr(rFromMaster.GetHeader()); + rDestMaster.SetFmtAttr(rFromMaster.GetFooter()); + //rFromMaster.SetAttr(SwFmtHeader()); //$flr uncommented due to bug fix #117882# + //rFromMaster.SetAttr(SwFmtFooter()); //$flr uncommented due to bug fix #117882# + + SwFrmFmt &rDestLeft = rDest.GetLeft(); + SwFrmFmt &rFromLeft = rFrom.GetLeft(); + rDestLeft.SetFmtAttr(rFromLeft.GetHeader()); + rDestLeft.SetFmtAttr(rFromLeft.GetFooter()); + //rFromLeft.SetAttr(SwFmtHeader()); //$flr uncommented due to bug fix #117882# + //rFromLeft.SetAttr(SwFmtFooter()); //$flr uncommented due to bug fix #117882# +} + +void rtfSections::SetHdFt(rtfSection &rSection) +{ + ASSERT(rSection.mpPage, "makes no sense to call without a main page"); + if (rSection.mpPage && rSection.maPageInfo.mpPageHdFt) + { + if (rSection.maPageInfo.mbPageHdFtUsed) + { + MoveFrom(*rSection.maPageInfo.mpPageHdFt, *rSection.mpPage); + rSection.maPageInfo.mbPageHdFtUsed = false; + rSection.maPageInfo.mpPageHdFt = rSection.mpPage; + } + else + CopyFrom(*rSection.maPageInfo.mpPageHdFt, *rSection.mpPage); + } + + if (rSection.mpTitlePage && rSection.maPageInfo.mpTitlePageHdFt) + { + if (rSection.maPageInfo.mbTitlePageHdFtUsed) + { + MoveFrom(*rSection.maPageInfo.mpTitlePageHdFt, + *rSection.mpTitlePage); + rSection.maPageInfo.mbTitlePageHdFtUsed = false; + rSection.maPageInfo.mpTitlePageHdFt = rSection.mpTitlePage; + } + else + { + CopyFrom(*rSection.maPageInfo.mpTitlePageHdFt, + *rSection.mpTitlePage); + } + } +} + +SwSectionFmt *rtfSections::InsertSection(SwPaM& rMyPaM, rtfSection &rSection) +{ + SwSectionData aSectionData(CONTENT_SECTION, + mrReader.pDoc->GetUniqueSectionName()); + + SfxItemSet aSet( mrReader.pDoc->GetAttrPool(), aFrmFmtSetRange ); + + sal_uInt8 nRTLPgn = maSegments.empty() ? 0 : maSegments.back().IsBiDi(); + aSet.Put(SvxFrameDirectionItem( + nRTLPgn ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR)); + + rSection.mpSection = + mrReader.pDoc->InsertSwSection( rMyPaM, aSectionData, 0, &aSet ); + ASSERT(rSection.mpSection, "section not inserted!"); + if (!rSection.mpSection) + return 0; + + SwPageDesc *pPage = 0; + mySegrIter aEnd = maSegments.rend(); + for (mySegrIter aIter = maSegments.rbegin(); aIter != aEnd; ++aIter) + { + pPage = aIter->mpPage; + if (pPage) + break; + } + + ASSERT(pPage, "no page outside this section!"); + + if (!pPage) + pPage = &mrReader.pDoc->_GetPageDesc(0); + + if (!pPage) + return 0; + + SwFrmFmt& rFmt = pPage->GetMaster(); + const SwFmtFrmSize& rSz = rFmt.GetFrmSize(); + const SvxLRSpaceItem& rLR = rFmt.GetLRSpace(); + SwTwips nWidth = rSz.GetWidth(); + long nLeft = rLR.GetTxtLeft(); + long nRight = rLR.GetRight(); + + SwSectionFmt *pFmt = rSection.mpSection->GetFmt(); + ASSERT(pFmt, "impossible"); + if (!pFmt) + return 0; + SetCols(*pFmt, rSection, (USHORT)(nWidth - nLeft - nRight) ); + + return pFmt; +} + +void rtfSections::InsertSegments(bool bNewDoc) +{ + sal_uInt16 nDesc(0); + mySegIter aEnd = maSegments.end(); + mySegIter aStart = maSegments.begin(); + for (mySegIter aIter = aStart; aIter != aEnd; ++aIter) + { + mySegIter aNext = aIter+1; + + bool bInsertSection = aIter != aStart ? aIter->IsContinous() : false; + + if (!bInsertSection) + { + /* + If a cont section follow this section then we won't be + creating a page desc with 2+ cols as we cannot host a one + col section in a 2+ col pagedesc and make it look like + word. But if the current section actually has columns then + we are forced to insert a section here as well as a page + descriptor. + */ + + /* + Note for the future: + If we want to import "protected sections" the here is + where we would also test for that and force a section + insertion if that was true. + */ + bool bIgnoreCols = false; + if (aNext != aEnd && aNext->IsContinous()) + { + bIgnoreCols = true; + if (aIter->NoCols() > 1) + bInsertSection = true; + } + + if (aIter->HasTitlePage()) + { + if (bNewDoc && aIter == aStart) + { + aIter->mpTitlePage = + mrReader.pDoc->GetPageDescFromPool(RES_POOLPAGE_FIRST); + } + else + { + USHORT nPos = mrReader.pDoc->MakePageDesc( + ViewShell::GetShellRes()->GetPageDescName(nDesc) + , 0, false); + aIter->mpTitlePage = &mrReader.pDoc->_GetPageDesc(nPos); + } + ASSERT(aIter->mpTitlePage, "no page!"); + if (!aIter->mpTitlePage) + continue; + + SetSegmentToPageDesc(*aIter, true, bIgnoreCols); + } + + if (!bNewDoc && aIter == aStart) + continue; + else if (bNewDoc && aIter == aStart) + { + aIter->mpPage = + mrReader.pDoc->GetPageDescFromPool(RES_POOLPAGE_STANDARD); + } + else + { + USHORT nPos = mrReader.pDoc->MakePageDesc( + ViewShell::GetShellRes()->GetPageDescName(nDesc, + false, aIter->HasTitlePage()), + aIter->mpTitlePage, false); + aIter->mpPage = &mrReader.pDoc->_GetPageDesc(nPos); + } + ASSERT(aIter->mpPage, "no page!"); + if (!aIter->mpPage) + continue; + + SetHdFt(*aIter); + + if (aIter->mpTitlePage) + SetSegmentToPageDesc(*aIter, true, bIgnoreCols); + SetSegmentToPageDesc(*aIter, false, bIgnoreCols); + + SwFmtPageDesc aPgDesc(aIter->HasTitlePage() ? + aIter->mpTitlePage : aIter->mpPage); + + if (aIter->mpTitlePage) + aIter->mpTitlePage->SetFollow(aIter->mpPage); + + if (aIter->PageRestartNo() || + ((aIter == aStart) && aIter->PageStartAt() != 1)) + aPgDesc.SetNumOffset( static_cast< USHORT >(aIter->PageStartAt()) ); + + /* + If its a table here, apply the pagebreak to the table + properties, otherwise we add it to the para at this + position + */ + if (aIter->maStart.GetNode().IsTableNode()) + { + SwTable& rTable = + aIter->maStart.GetNode().GetTableNode()->GetTable(); + SwFrmFmt* pApply = rTable.GetFrmFmt(); + ASSERT(pApply, "impossible"); + if (pApply) + pApply->SetFmtAttr(aPgDesc); + } + else + { + SwPosition aPamStart(aIter->maStart); + aPamStart.nContent.Assign( + aIter->maStart.GetNode().GetCntntNode(), 0); + SwPaM aPage(aPamStart); + + mrReader.pDoc->InsertPoolItem(aPage, aPgDesc, 0); + } + ++nDesc; + } + + SwTxtNode* pTxtNd = 0; + if (bInsertSection) + { + SwPaM aSectPaM(*mrReader.pPam); + SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode); + if (aNext != aEnd) + { + aAnchor = aNext->maStart; + aSectPaM.GetPoint()->nNode = aAnchor; + aSectPaM.GetPoint()->nContent.Assign( + aNext->maStart.GetNode().GetCntntNode(), 0); + aSectPaM.Move(fnMoveBackward); + } + + const SwPosition* pPos = aSectPaM.GetPoint(); + const SwTxtNode* pSttNd = + mrReader.pDoc->GetNodes()[ pPos->nNode ]->GetTxtNode(); + const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0; + if (pTableNd) + { + pTxtNd = + mrReader.pDoc->GetNodes().MakeTxtNode(aAnchor, + mrReader.pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT )); + + aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd); + aSectPaM.GetPoint()->nContent.Assign( + aSectPaM.GetCntntNode(), 0); + } + + aSectPaM.SetMark(); + + aSectPaM.GetPoint()->nNode = aIter->maStart; + aSectPaM.GetPoint()->nContent.Assign( + aSectPaM.GetCntntNode(), 0); + + SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter); + //The last section if continous is always unbalanced + if (aNext == aEnd && pRet) + pRet->SetFmtAttr(SwFmtNoBalancedColumns(true)); + } + + if (pTxtNd) + { + SwNodeIndex aIdx(*pTxtNd); + SwPosition aPos(aIdx); + SwPaM aTest(aPos); + mrReader.pDoc->DelFullPara(aTest); + pTxtNd = 0; + } + } +} + +namespace sw{ + namespace util{ + +InsertedTableClient::InsertedTableClient(SwTableNode & rNode) +{ + rNode.Add(this); +} + +SwTableNode * InsertedTableClient::GetTableNode() +{ + return dynamic_cast<SwTableNode *> (pRegisteredIn); +} + +InsertedTablesManager::InsertedTablesManager(const SwDoc &rDoc) + : mbHasRoot(rDoc.GetRootFrm()) +{ +} + +void InsertedTablesManager::DelAndMakeTblFrms() +{ + if (!mbHasRoot) + return; + TblMapIter aEnd = maTables.end(); + for (TblMapIter aIter = maTables.begin(); aIter != aEnd; ++aIter) + { + // exitiert schon ein Layout, dann muss an dieser Tabelle die BoxFrames + // neu erzeugt + SwTableNode *pTable = aIter->first->GetTableNode(); + ASSERT(pTable, "Why no expected table"); + if (pTable) + { + SwFrmFmt * pFrmFmt = pTable->GetTable().GetFrmFmt(); + + if (pFrmFmt != NULL) + { + SwNodeIndex *pIndex = aIter->second; + pTable->DelFrms(); + pTable->MakeFrms(pIndex); + } + } + } +} + +void InsertedTablesManager::InsertTable(SwTableNode &rTableNode, SwPaM &rPaM) +{ + if (!mbHasRoot) + return; + //Associate this tablenode with this after position, replace an //old + //node association if necessary + + InsertedTableClient * pClient = new InsertedTableClient(rTableNode); + + maTables.insert(TblMap::value_type(pClient, &(rPaM.GetPoint()->nNode))); +} +} +} + +SwRTFParser::~SwRTFParser() +{ + maInsertedTables.DelAndMakeTblFrms(); + mpRedlineStack->closeall(*pPam->GetPoint()); + delete mpRedlineStack; + + delete pSttNdIdx; + delete pRegionEndIdx; + delete pPam; + delete pRelNumRule; + + if (aFlyArr.Count()) + aFlyArr.DeleteAndDestroy( 0, aFlyArr.Count() ); + + if (pGrfAttrSet) + DELETEZ( pGrfAttrSet ); + + DELETEZ( pAuthorInfos ); +} + +//i19718 +void SwRTFParser::ReadShpRslt() +{ + int nToken; + while ('}' != (nToken = GetNextToken() ) && IsParserWorking()) + { + switch(nToken) + { + case RTF_PAR: + break; + default: + NextToken(nToken); + break; + } + } + SkipToken(-1); +} + +void SwRTFParser::ReadShpTxt(String& s) +{ + int nToken; + int level=1; + s.AppendAscii("{\\rtf"); + while (level>0 && IsParserWorking()) + { + nToken = GetNextToken(); + switch(nToken) + { + case RTF_SN: + case RTF_SV: + SkipGroup(); + break; + case RTF_TEXTTOKEN: + s.Append(aToken); + break; + case '{': + level++; + s.Append(String::CreateFromAscii("{")); + break; + case '}': + level--; + s.Append(String::CreateFromAscii("}")); + break; + default: + s.Append(aToken); + if (bTokenHasValue) { + s.Append(String::CreateFromInt64(nTokenValue)); + } + s.Append(String::CreateFromAscii(" ")); + break; + } + } + SkipToken(-1); +} + +/* + * #127429#. Very basic support for the "Buchhalternase". + */ +void SwRTFParser::ReadDrawingObject() +{ + int nToken; + int level; + level=1; + Rectangle aRect; + ::basegfx::B2DPolygon aPolygon; + ::basegfx::B2DPoint aPoint; + bool bPolygonActive(false); + + while (level>0 && IsParserWorking()) + { + nToken = GetNextToken(); + switch(nToken) + { + case '}': + level--; + break; + case '{': + level++; + break; + case RTF_DPX: + aRect.setX(nTokenValue); + break; + case RTF_DPXSIZE: + aRect.setWidth(nTokenValue); + break; + case RTF_DPY: + aRect.setY(nTokenValue); + break; + case RTF_DPYSIZE: + aRect.setHeight(nTokenValue); + break; + case RTF_DPPOLYCOUNT: + bPolygonActive = true; + break; + case RTF_DPPTX: + aPoint.setX(nTokenValue); + break; + case RTF_DPPTY: + aPoint.setY(nTokenValue); + + if(bPolygonActive) + { + aPolygon.append(aPoint); + } + + break; + default: + break; + } + } + SkipToken(-1); + /* + const Point aPointC1( 0, 0 ); + const Point aPointC2( 100, 200 ); + const Point aPointC3( 300, 400 ); + XPolygon aPolygonC(3); + aPolygonC[0] = aPointC1; + aPolygonC[1] = aPointC2; + aPolygonC[2] = aPointC3; + */ + if(bPolygonActive && aPolygon.count()) + { + SdrPathObj* pStroke = new SdrPathObj(OBJ_PLIN, ::basegfx::B2DPolyPolygon(aPolygon)); + SfxItemSet aFlySet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1); + SwFmtSurround aSur( SURROUND_PARALLEL ); + aSur.SetContour( false ); + aSur.SetOutside(true); + aFlySet.Put( aSur ); + SwFmtFollowTextFlow aFollowTextFlow( FALSE ); + aFlySet.Put( aFollowTextFlow ); + /* + sw::util::SetLayer aSetLayer(*pDoc); + aSetLayer.SendObjectToHeaven(*pStroke); + */ + SwFmtAnchor aAnchor( FLY_AT_PARA ); + aAnchor.SetAnchor( pPam->GetPoint() ); + aFlySet.Put( aAnchor ); + + /* + text::RelOrientation::FRAME, // Absatz inkl. Raender + text::RelOrientation::PRINT_AREA, // Absatz ohne Raender + text::RelOrientation::CHAR, // an einem Zeichen + text::RelOrientation::PAGE_LEFT, // im linken Seitenrand + text::RelOrientation::PAGE_RIGHT, // im rechten Seitenrand + text::RelOrientation::FRAME_LEFT, // im linken Absatzrand + text::RelOrientation::FRAME_RIGHT, // im rechten Absatzrand + text::RelOrientation::PAGE_FRAME, // Seite inkl. Raender, bei seitengeb. identisch mit text::RelOrientation::FRAME + text::RelOrientation::PAGE_PRINT_AREA, // Seite ohne Raender, bei seitengeb. identisch mit text::RelOrientation::PRTAREA + // OD 11.11.2003 #i22341# + text::RelOrientation::TEXT_LINE, // vertical relative to top of text line, only for to-character + // anchored objects. + + + text::HoriOrientation::NONE, //Der Wert in nYPos gibt die RelPos direkt an. + text::HoriOrientation::RIGHT, //Der Rest ist fuer automatische Ausrichtung. + text::HoriOrientation::CENTER, + text::HoriOrientation::LEFT, + text::HoriOrientation::INSIDE, + text::HoriOrientation::OUTSIDE, + text::HoriOrientation::FULL, //Spezialwert fuer Tabellen + text::HoriOrientation::LEFT_AND_WIDTH //Auch fuer Tabellen + */ + SwFmtHoriOrient aHori( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ); + aFlySet.Put( aHori ); + /* + text::VertOrientation::NONE, //Der Wert in nYPos gibt die RelPos direkt an. + text::VertOrientation::TOP, //Der Rest ist fuer automatische Ausrichtung. + text::VertOrientation::CENTER, + text::VertOrientation::BOTTOM, + text::VertOrientation::CHAR_TOP, //Ausrichtung _nur_ fuer Zeichengebundene Rahmen + text::VertOrientation::CHAR_CENTER, //wie der Name jew. sagt wird der RefPoint des Rahmens + text::VertOrientation::CHAR_BOTTOM, //entsprechend auf die Oberkante, Mitte oder Unterkante + text::VertOrientation::LINE_TOP, //der Zeile gesetzt. Der Rahmen richtet sich dann + text::VertOrientation::LINE_CENTER, //entsprechend aus. + text::VertOrientation::LINE_BOTTOM + */ + SwFmtVertOrient aVert( 0, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ); + aFlySet.Put( aVert ); + + pDoc->GetOrCreateDrawModel(); + SdrModel* pDrawModel = pDoc->GetDrawModel(); + SdrPage* pDrawPg = pDrawModel->GetPage(0); + pDrawPg->InsertObject(pStroke, 0); + + pStroke->SetSnapRect(aRect); + + /* SwFrmFmt* pRetFrmFmt = */pDoc->Insert(*pPam, *pStroke, &aFlySet, NULL); + } +} + +void SwRTFParser::InsertShpObject(SdrObject* pStroke, int _nZOrder) +{ + SfxItemSet aFlySet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1); + SwFmtSurround aSur( SURROUND_THROUGHT ); + aSur.SetContour( false ); + aSur.SetOutside(true); + aFlySet.Put( aSur ); + SwFmtFollowTextFlow aFollowTextFlow( FALSE ); + aFlySet.Put( aFollowTextFlow ); + + SwFmtAnchor aAnchor( FLY_AT_PARA ); + aAnchor.SetAnchor( pPam->GetPoint() ); + aFlySet.Put( aAnchor ); + + + SwFmtHoriOrient aHori( 0, text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ); + aFlySet.Put( aHori ); + + SwFmtVertOrient aVert( 0, text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ); + aFlySet.Put( aVert ); + + aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false)); + + pDoc->GetOrCreateDrawModel(); + SdrModel* pDrawModel = pDoc->GetDrawModel(); + SdrPage* pDrawPg = pDrawModel->GetPage(0); + pDrawPg->InsertObject(pStroke); + pDrawPg->SetObjectOrdNum(pStroke->GetOrdNum(), _nZOrder); + /* SwFrmFmt* pRetFrmFmt = */pDoc->Insert(*pPam, *pStroke, &aFlySet, NULL); +} + +::basegfx::B2DPoint rotate(const ::basegfx::B2DPoint& rStart, const ::basegfx::B2DPoint& rEnd) +{ + const ::basegfx::B2DVector aVector(rStart - rEnd); + return ::basegfx::B2DPoint(aVector.getY() + rEnd.getX(), -aVector.getX() + rEnd.getY()); +} + + +void SwRTFParser::ReadShapeObject() +{ + int nToken; + int level; + level=1; + ::basegfx::B2DPoint aPointLeftTop; + ::basegfx::B2DPoint aPointRightBottom; + String sn; + sal_Int32 shapeType=-1; + Graphic aGrf; + bool bGrfValid=false; + bool fFilled=true; + Color fillColor(255, 255, 255); + bool fLine=true; + int lineWidth=9525/360; + String shpTxt; + bool bshpTxt=false; + int txflTextFlow=0; + + + while (level>0 && IsParserWorking()) + { + nToken = GetNextToken(); + switch(nToken) + { + case '}': + level--; + break; + case '{': + level++; + break; + case RTF_SHPLEFT: + aPointLeftTop.setX(nTokenValue); + break; + case RTF_SHPTOP: + aPointLeftTop.setY(nTokenValue); + break; + case RTF_SHPBOTTOM: + aPointRightBottom.setY(nTokenValue); + break; + case RTF_SHPRIGHT: + aPointRightBottom.setX(nTokenValue); + break; + case RTF_SN: + nToken = GetNextToken(); + ASSERT(nToken==RTF_TEXTTOKEN, "expected name"); + sn=aToken; + break; + case RTF_SV: + nToken = GetNextToken(); + if (nToken==RTF_TEXTTOKEN) + { + if (sn.EqualsAscii("shapeType")) + { + shapeType=aToken.ToInt32(); + + } else if (sn.EqualsAscii("fFilled")) + { + fFilled=aToken.ToInt32(); + + } else if (sn.EqualsAscii("fLine")) + { + fLine=aToken.ToInt32(); + } else if (sn.EqualsAscii("lineWidth")) + { + lineWidth=aToken.ToInt32()/360; + + } else if (sn.EqualsAscii("fillColor")) + { + sal_uInt32 nColor=aToken.ToInt32(); + fillColor=Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) ); + }else if (sn.EqualsAscii("txflTextFlow")) + { + txflTextFlow=aToken.ToInt32(); + } + + } + break; + case RTF_PICT: + { + SvxRTFPictureType aPicType; + bGrfValid=ReadBmpData( aGrf, aPicType ); + } + break; + case RTF_SHPRSLT: + if (shapeType!=1 && shapeType!=20 && shapeType!=75) + { + ReadShpRslt(); + } + break; + case RTF_SHPTXT: + ReadShpTxt(shpTxt); + bshpTxt=true; + break; + + default: + break; + } + } + SkipToken(-1); + + switch(shapeType) + { + case 202: /* Text Box */ + case 1: /* Rectangle */ + { + ::basegfx::B2DRange aRange(aPointLeftTop); + aRange.expand(aPointRightBottom); + + if (txflTextFlow==2) { + const ::basegfx::B2DPoint a(rotate(aRange.getMinimum(), aRange.getCenter())); + const ::basegfx::B2DPoint b(rotate(aRange.getMaximum(), aRange.getCenter())); + + aRange.reset(); + aRange.expand(a); + aRange.expand(b); + } + + const Rectangle aRect(FRound(aRange.getMinX()), FRound(aRange.getMinY()), FRound(aRange.getMaxX()), FRound(aRange.getMaxY())); + SdrRectObj* pStroke = new SdrRectObj(aRect); + pStroke->SetSnapRect(aRect); + pDoc->GetOrCreateDrawModel(); // create model + InsertShpObject(pStroke, this->nZOrder++); + SfxItemSet aSet(pStroke->GetMergedItemSet()); + if (fFilled) + { + aSet.Put(XFillStyleItem(XFILL_SOLID)); + aSet.Put(XFillColorItem( String(), fillColor ) ); + } + else + { + aSet.Put(XFillStyleItem(XFILL_NONE)); + } + if (!fLine) { + aSet.Put(XLineStyleItem(XLINE_NONE)); + } else { + aSet.Put( XLineWidthItem( lineWidth/2 ) ); // lineWidth are in 1000th mm, seems that XLineWidthItem expects 1/2 the line width + } + + pStroke->SetMergedItemSet(aSet); + if (bshpTxt) { + SdrOutliner& rOutliner=pDoc->GetDrawModel()->GetDrawOutliner(pStroke); + rOutliner.Clear(); + ByteString bs(shpTxt, RTL_TEXTENCODING_ASCII_US); + SvMemoryStream aStream((sal_Char*)bs.GetBuffer(), bs.Len(), STREAM_READ); + rOutliner.Read(aStream, String::CreateFromAscii(""), EE_FORMAT_RTF); + OutlinerParaObject* pParaObject=rOutliner.CreateParaObject(); + pStroke->NbcSetOutlinerParaObject(pParaObject); + //delete pParaObject; + rOutliner.Clear(); + } + if (txflTextFlow==2) { + long nAngle = 90; + double a = nAngle*100*nPi180; + pStroke->Rotate(pStroke->GetCurrentBoundRect().Center(), nAngle*100, sin(a), cos(a) ); + + } + + } + break; + case 20: /* Line */ + { + ::basegfx::B2DPolygon aLine; + aLine.append(aPointLeftTop); + aLine.append(aPointRightBottom); + + SdrPathObj* pStroke = new SdrPathObj(OBJ_PLIN, ::basegfx::B2DPolyPolygon(aLine)); + //pStroke->SetSnapRect(aRect); + + InsertShpObject(pStroke, this->nZOrder++); + SfxItemSet aSet(pStroke->GetMergedItemSet()); + if (!fLine) { + aSet.Put(XLineStyleItem(XLINE_NONE)); + } else { + aSet.Put( XLineWidthItem( lineWidth/2 ) ); // lineWidth are in 1000th mm, seems that XLineWidthItem expects 1/2 the line width + } + + pStroke->SetMergedItemSet(aSet); + } + break; + case 75 : /* Picture */ + if (bGrfValid) { + ::basegfx::B2DRange aRange(aPointLeftTop); + aRange.expand(aPointRightBottom); + const Rectangle aRect(FRound(aRange.getMinX()), FRound(aRange.getMinY()), FRound(aRange.getMaxX()), FRound(aRange.getMaxY())); + + SdrRectObj* pStroke = new SdrGrafObj(aGrf); + pStroke->SetSnapRect(aRect); + + InsertShpObject(pStroke, this->nZOrder++); + } + } +} + +extern void sw3io_ConvertFromOldField( SwDoc& rDoc, USHORT& rWhich, + USHORT& rSubType, ULONG &rFmt, + USHORT nVersion ); + +USHORT SwRTFParser::ReadRevTbl() +{ + // rStr.Erase( 0 ); + int nNumOpenBrakets = 1, nToken; // die erste wurde schon vorher erkannt !! + USHORT nAuthorTableIndex = 0; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( nToken = GetNextToken() ) + { + case '}': --nNumOpenBrakets; break; + case '{': + { + if( RTF_IGNOREFLAG != GetNextToken() ) + nToken = SkipToken( -1 ); + else if( RTF_UNKNOWNCONTROL != GetNextToken() ) + nToken = SkipToken( -2 ); + else + { + ReadUnknownData(); + nToken = GetNextToken(); + if( '}' != nToken ) + eState = SVPAR_ERROR; + break; + } + ++nNumOpenBrakets; + } + break; + + case RTF_TEXTTOKEN: + aToken.EraseTrailingChars(';'); + + USHORT nSWId = pDoc->InsertRedlineAuthor(aToken); + // Store matchpair + if( !pAuthorInfos ) + pAuthorInfos = new sw::util::AuthorInfos; + sw::util::AuthorInfo* pAutorInfo = new sw::util::AuthorInfo( nAuthorTableIndex, nSWId ); + if( 0 == pAuthorInfos->Insert( pAutorInfo ) ) + delete pAutorInfo; + + aRevTbl.push_back(aToken); + nAuthorTableIndex++; + break; + } + } + SkipToken( -1 ); + return nAuthorTableIndex; +} + +// #117910# simulate words behaviour of \keepn in table rows +void fixKeepAndSplitAttributes(SwTableNode *pTableNode) +{ + ASSERT(pTableNode!=NULL, "no table node!"); + if (!pTableNode) return; + SwDoc *pDoc=pTableNode->GetDoc(); + if (pTableNode==NULL) return; + SwTable& rTable=pTableNode->GetTable(); + SwTableLines& rLns = rTable.GetTabLines(); + USHORT nLines=rLns.Count(); + if (nLines==0) return; + // get first paragaph in left down-most box + SwTableLine* pLastLine = rLns[ nLines-1 ]; + SwTableBox* pBox = pLastLine->GetTabBoxes()[ 0 ]; + ULONG iFirstParagraph=pBox->GetSttIdx()+1; + SwTxtNode *pTxtNode=(SwTxtNode *)pDoc->GetNodes()[iFirstParagraph]; + SwFrmFmt* pFmt=rTable.GetFrmFmt(); + + SwFmtLayoutSplit *pTableSplit=(SwFmtLayoutSplit *)pFmt->GetAttrSet().GetItem(RES_LAYOUT_SPLIT); + BOOL isTableKeep = pTableSplit!=NULL && !pTableSplit->GetValue(); + SvxFmtKeepItem *pTableKeep=(SvxFmtKeepItem *)pFmt->GetAttrSet().GetItem(RES_KEEP); + BOOL isTableKeepNext = pTableKeep!=NULL && pTableKeep->GetValue(); + SvxFmtKeepItem *pKeepNext = (SvxFmtKeepItem *)pTxtNode->GetSwAttrSet().GetItem(RES_KEEP); + + if (isTableKeepNext) + { + if (nLines>2 && !isTableKeep) + { // split + SwTableLine* pSplitLine = rLns[ nLines-2 ]; + SwTableBox* pSplitBox = pSplitLine->GetTabBoxes()[ 0 ]; + SwNodeIndex aSplitIdx( *pSplitBox->GetSttNd() ); + pDoc->SplitTable( SwPosition(aSplitIdx), HEADLINE_NONE, + !isTableKeep ); + SwTable& rSplitTable=aSplitIdx.GetNode().FindTableNode()->GetTable(); + aSplitIdx-=2; + pDoc->GetNodes().Delete(aSplitIdx); + pFmt=rSplitTable.GetFrmFmt(); + pFmt->ResetFmtAttr(RES_PAGEDESC); + } + // set keep=1(i.e. split=0) attribut + SwFmtLayoutSplit aSplit(0); + SwAttrSet aNewSet(pFmt->GetAttrSet()); + aNewSet.Put(aSplit); + pFmt->SetFmtAttr(aNewSet); + } + else // !isTableKeepNext + { + if (isTableKeep) + { + SwNodeIndex aTmpIdx( *pBox->GetSttNd() ); + pDoc->SplitTable( SwPosition(aTmpIdx), HEADLINE_NONE, FALSE ); + SwTable& rSplitTable=aTmpIdx.GetNode().FindTableNode()->GetTable(); + aTmpIdx-=2; + pDoc->GetNodes().Delete(aTmpIdx); + pFmt=rSplitTable.GetFrmFmt(); + pFmt->ResetFmtAttr(RES_PAGEDESC); + } + // set keep=0(i.e. split=1) attribut + SwFmtLayoutSplit aSplit(1); + SwAttrSet aNewSet(pFmt->GetAttrSet()); + aNewSet.Put(aSplit); + pFmt->SetFmtAttr(aNewSet); + } + // move keepnext attribtue from last paragraph to table + if (pKeepNext!=NULL) + { + SvxFmtKeepItem aNewKeepItem(pKeepNext->GetValue(), RES_KEEP); + SwAttrSet aNewSet(pFmt->GetAttrSet()); + aNewSet.Put(aNewKeepItem); + pFmt->SetFmtAttr(aNewSet); + } +} + +void SwRTFParser::NextToken( int nToken ) +{ + USHORT eDateFmt; + + switch( nToken ) + { + case RTF_FOOTNOTE: + //We can only insert a footnote if we're not inside a footnote. e.g. + //#i7713# + if (!mbIsFootnote) + { + ReadHeaderFooter( nToken ); + SkipToken( -1 ); // Klammer wieder zurueck + } + break; + case RTF_SWG_PRTDATA: + ReadPrtData(); + break; + case RTF_XE: + ReadXEField(); + break; + case RTF_FIELD: + ReadField(); + break; + case RTF_SHPRSLT: + ReadShpRslt(); + break; + case RTF_DO: + ReadDrawingObject(); + break; + case RTF_SHP: + ReadShapeObject(); + break; + case RTF_SHPPICT: + case RTF_PICT: + ReadBitmapData(); + break; +#ifdef READ_OLE_OBJECT + case RTF_OBJECT: + ReadOLEData(); + break; +#endif + case RTF_TROWD: ReadTable( nToken ); break; + case RTF_PGDSCTBL: + if( !IsNewDoc() ) + SkipPageDescTbl(); + else + ReadPageDescTbl(); + break; + case RTF_LISTTABLE: ReadListTable(); break; + case RTF_LISTOVERRIDETABLE: ReadListOverrideTable(); break; + + case RTF_LISTTEXT: + GetAttrSet().Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, 0 )); + SkipGroup(); + break; + + case RTF_PN: + if( bNewNumList ) + SkipGroup(); + else + { + bStyleTabValid = TRUE; + if (SwNumRule* pRule = ReadNumSecLevel( nToken )) + { + GetAttrSet().Put( SwNumRuleItem( pRule->GetName() )); + + if( SFX_ITEM_SET != GetAttrSet().GetItemState( FN_PARAM_NUM_LEVEL, FALSE )) + GetAttrSet().Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, 0 )); + } + } + break; + + + case RTF_BKMKSTART: + if(RTF_TEXTTOKEN == GetNextToken()) + mpBookmarkStart = new BookmarkPosition(*pPam); + else + SkipToken(-1); + + SkipGroup(); + break; + + case RTF_BKMKEND: + if(RTF_TEXTTOKEN == GetNextToken()) + { + const String& sBookmark = aToken; + KeyCode aEmptyKeyCode; + if (mpBookmarkStart) + { + BookmarkPosition aBookmarkEnd(*pPam); + SwPaM aBookmarkRegion( mpBookmarkStart->maMkNode, mpBookmarkStart->mnMkCntnt, + aBookmarkEnd.maMkNode, aBookmarkEnd.mnMkCntnt); + if (*mpBookmarkStart == aBookmarkEnd) + aBookmarkRegion.DeleteMark(); + pDoc->getIDocumentMarkAccess()->makeMark(aBookmarkRegion, sBookmark, IDocumentMarkAccess::BOOKMARK); + } + delete mpBookmarkStart, mpBookmarkStart = 0; + } + else + SkipToken(-1); + + SkipGroup(); + break; + + + case RTF_PNSECLVL:{ + if( bNewNumList) + SkipGroup(); + else + ReadNumSecLevel( nToken ); + break; + } + + case RTF_PNTEXT: + case RTF_NONSHPPICT: + SkipGroup(); + break; + + case RTF_DEFFORMAT: + case RTF_DEFTAB: + case RTF_DEFLANG: + // sind zwar Dok-Controls, werden aber manchmal auch vor der + // Font/Style/Color-Tabelle gesetzt! + SvxRTFParser::NextToken( nToken ); + break; + + case RTF_PAGE: + if (pTableNode==NULL) { //#117410#: A \page command within a table is ignored by Word. + if (lcl_UsedPara(*pPam)) + InsertPara(); + CheckInsNewTblLine(); + pDoc->InsertPoolItem(*pPam, + SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0); + } + break; + + case RTF_SECT: + ReadSectControls( nToken ); + break; + case RTF_CELL: + // --> OD 2008-12-22 #i83368# + mbReadCellWhileReadSwFly = bReadSwFly; + // <-- + if (CantUseTables()) + InsertPara(); + else + { + // Tabelle nicht mehr vorhanden ? + if (USHRT_MAX != nInsTblRow && !pTableNode) + NewTblLine(); // evt. Line copieren + GotoNextBox(); + } + break; + + case RTF_ROW: + bTrowdRead=false; + if (!CantUseTables()) + { + // aus der Line raus + nAktBox = 0; + pTableNode = 0; + // noch in der Tabelle drin? + SwNodeIndex& rIdx = pPam->GetPoint()->nNode; + const SwTableNode* pTblNd = rIdx.GetNode().FindTableNode(); + if( pTblNd ) + { + // search the end of this row + const SwStartNode* pBoxStt = + rIdx.GetNode().FindTableBoxStartNode(); + const SwTableBox* pBox = pTblNd->GetTable().GetTblBox( + pBoxStt->GetIndex() ); + const SwTableLine* pLn = pBox->GetUpper(); + pBox = pLn->GetTabBoxes()[ pLn->GetTabBoxes().Count() - 1 ]; + rIdx = *pBox->GetSttNd()->EndOfSectionNode(); + pPam->Move( fnMoveForward, fnGoNode ); + } + nInsTblRow = static_cast< USHORT >(GetOpenBrakets()); + SetPardTokenRead( FALSE ); + SwPaM aTmp(*pPam); + aTmp.Move( fnMoveBackward, fnGoNode ); + } + ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() ); + break; + + case RTF_INTBL: + if (!CantUseTables()) + { + if( !pTableNode ) // Tabelle nicht mehr vorhanden ? + { + if (RTF_TROWD != GetNextToken()) + NewTblLine(); // evt. Line copieren + SkipToken(-1); + } + else + { + // Crsr nicht mehr in der Tabelle ? + if( !pPam->GetNode()->FindTableNode() ) + { + // dann wieder in die letzte Box setzen + // (kann durch einlesen von Flys geschehen!) + pPam->GetPoint()->nNode = *pTableNode->EndOfSectionNode(); + pPam->Move( fnMoveBackward ); + } + } + } + break; + + case RTF_REVTBL: + ReadRevTbl(); + break; + + case RTF_REVISED: + pRedlineInsert = new SwFltRedline(nsRedlineType_t::REDLINE_INSERT, 0, DateTime(Date( 0 ), Time( 0 ))); + break; + + case RTF_DELETED: + pRedlineDelete = new SwFltRedline(nsRedlineType_t::REDLINE_DELETE, 0, DateTime(Date( 0 ), Time( 0 ))); + break; + + case RTF_REVAUTH: + { + sw::util::AuthorInfo aEntry( static_cast< USHORT >(nTokenValue) ); + USHORT nPos; + + if(pRedlineInsert) + { + if (pAuthorInfos && pAuthorInfos->Seek_Entry(&aEntry, &nPos)) + { + if (const sw::util::AuthorInfo* pAuthor = pAuthorInfos->GetObject(nPos)) + { + pRedlineInsert->nAutorNo = pAuthor->nOurId; + } + } + } + } + break; + + case RTF_REVAUTHDEL: + { + sw::util::AuthorInfo aEntry( static_cast< short >(nTokenValue) ); + USHORT nPos; + + if(pRedlineDelete) + { + if (pAuthorInfos && pAuthorInfos->Seek_Entry(&aEntry, &nPos)) + { + if (const sw::util::AuthorInfo* pAuthor = pAuthorInfos->GetObject(nPos)) + { + pRedlineDelete->nAutorNo = pAuthor->nOurId; + } + } + } + } + break; + + case RTF_REVDTTM: + if (pRedlineInsert != NULL) + pRedlineInsert->aStamp = sw::ms::DTTM2DateTime(nTokenValue); + + break; + + case RTF_REVDTTMDEL: + pRedlineDelete->aStamp = sw::ms::DTTM2DateTime(nTokenValue); + break; + + + case RTF_FLY_INPARA: + // \pard und plain ueberlesen ! + if( '}' != GetNextToken() && '}' != GetNextToken() ) + { + // Zeichengebundener Fly in Fly + ReadHeaderFooter( nToken ); + SetPardTokenRead( FALSE ); + } + break; + + case RTF_PGDSCNO: + if( IsNewDoc() && bSwPageDesc && + USHORT(nTokenValue) < pDoc->GetPageDescCnt() ) + { + const SwPageDesc* pPgDsc = + &const_cast<const SwDoc *>(pDoc) + ->GetPageDesc( USHORT(nTokenValue) ); + CheckInsNewTblLine(); + pDoc->InsertPoolItem(*pPam, SwFmtPageDesc( pPgDsc ), 0); + } + break; + + case RTF_COLUM: + pDoc->InsertPoolItem(*pPam, + SvxFmtBreakItem( SVX_BREAK_COLUMN_BEFORE, RES_BREAK ), 0); + break; + + case RTF_DXFRTEXT: // werden nur im Zusammenhang mit Flys ausgewertet + case RTF_DFRMTXTX: + case RTF_DFRMTXTY: + break; + + case RTF_CHDATE: eDateFmt = DF_SHORT; goto SETCHDATEFIELD; + case RTF_CHDATEA: eDateFmt = DF_SSYS; goto SETCHDATEFIELD; + case RTF_CHDATEL: eDateFmt = DF_LSYS; goto SETCHDATEFIELD; +SETCHDATEFIELD: + { + USHORT nSubType = DATEFLD, nWhich = RES_DATEFLD; + ULONG nFormat = eDateFmt; + sw3io_ConvertFromOldField( *pDoc, nWhich, nSubType, nFormat, 0x0110 ); + + SwDateTimeField aDateFld( (SwDateTimeFieldType*) + pDoc->GetSysFldType( RES_DATETIMEFLD ), DATEFLD, nFormat); + CheckInsNewTblLine(); + pDoc->InsertPoolItem(*pPam, SwFmtFld( aDateFld ), 0); + } + break; + + case RTF_CHTIME: + { + USHORT nSubType = TIMEFLD, nWhich = RES_TIMEFLD; + ULONG nFormat = TF_SSMM_24; + sw3io_ConvertFromOldField( *pDoc, nWhich, nSubType, nFormat, 0x0110 ); + SwDateTimeField aTimeFld( (SwDateTimeFieldType*) + pDoc->GetSysFldType( RES_DATETIMEFLD ), TIMEFLD, nFormat); + CheckInsNewTblLine(); + pDoc->InsertPoolItem(*pPam, SwFmtFld( aTimeFld ), 0); + } + break; + + case RTF_CHPGN: + { + SwPageNumberField aPageFld( (SwPageNumberFieldType*) + pDoc->GetSysFldType( RES_PAGENUMBERFLD ), + PG_RANDOM, SVX_NUM_ARABIC ); + CheckInsNewTblLine(); + pDoc->InsertPoolItem(*pPam, SwFmtFld(aPageFld), 0); + } + break; + + case RTF_CHFTN: + bFootnoteAutoNum = TRUE; + break; + + case RTF_NOFPAGES: + if( IsNewDoc() && nTokenValue && -1 != nTokenValue ) + ((SwDocStat&)pDoc->GetDocStat()).nPage = (USHORT)nTokenValue; + break; + + case RTF_NOFWORDS: + if( IsNewDoc() && nTokenValue && -1 != nTokenValue ) + ((SwDocStat&)pDoc->GetDocStat()).nWord = (USHORT)nTokenValue; + break; + case RTF_NOFCHARS: + if( IsNewDoc() && nTokenValue && -1 != nTokenValue ) + ((SwDocStat&)pDoc->GetDocStat()).nChar = (USHORT)nTokenValue; + break; + case RTF_LYTPRTMET: + if (IsNewDoc()) + pDoc->set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, false); + break; + case RTF_U: + { + CheckInsNewTblLine(); + if( nTokenValue ) + aToken = (sal_Unicode )nTokenValue; + pDoc->InsertString( *pPam, aToken ); + } + break; + + case RTF_USERPROPS: + ReadUserProperties(); // #i28758 For now we don't support user properties + break; + +// RTF_SUBENTRYINDEX + + default: + switch( nToken & ~(0xff | RTF_SWGDEFS) ) + { + case RTF_DOCFMT: + ReadDocControls( nToken ); + break; + case RTF_SECTFMT: + ReadSectControls( nToken ); + break; + case RTF_APOCTL: + if (nReadFlyDepth < 10) + { + nReadFlyDepth++; + ReadFly( nToken ); + nReadFlyDepth--; + } + 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; + + SvxRTFParser::NextToken( nToken ); + break; + } + } + if( USHRT_MAX != nInsTblRow && + (nInsTblRow > GetOpenBrakets() || IsPardTokenRead() )) + nInsTblRow = USHRT_MAX; +} + + + +void SwRTFParser::InsertText() +{ + bContainsPara = false; + // dann fuege den String ein, ohne das Attribute am Ende + // aufgespannt werden. + CheckInsNewTblLine(); + + if(pRedlineInsert) + mpRedlineStack->open(*pPam->GetPoint(), *pRedlineInsert); + if(pRedlineDelete) + mpRedlineStack->open(*pPam->GetPoint(), *pRedlineDelete); + + pDoc->InsertString( *pPam, aToken ); + + if(pRedlineDelete) + { + mpRedlineStack->close(*pPam->GetPoint(), pRedlineDelete->eType); + } + + if(pRedlineInsert) + { + mpRedlineStack->close(*pPam->GetPoint(), pRedlineInsert->eType); + } + + +} + + +void SwRTFParser::InsertPara() +{ + bContainsPara = true; + CheckInsNewTblLine(); + pDoc->AppendTxtNode(*pPam->GetPoint()); + + // setze das default Style + if( !bStyleTabValid ) + MakeStyleTab(); + + SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 ); + if( !pColl ) + pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + pDoc->SetTxtFmtColl( *pPam, pColl ); + + ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() ); +} + + + +void SwRTFParser::MovePos( int bForward ) +{ + if( bForward ) + pPam->Move( fnMoveForward ); + else + pPam->Move( fnMoveBackward ); +} + +int SwRTFParser::IsEndPara( SvxNodeIdx* pNd, xub_StrLen nCnt ) const +{ + SwCntntNode *pNode = pDoc->GetNodes()[pNd->GetIdx()]->GetCntntNode(); + return pNode && pNode->Len() == nCnt; +} + +bool SwRTFParser::UncompressableStackEntry(const SvxRTFItemStackType &rSet) + const +{ + /* + #i21961# + Seeing as CHARFMT sets all the properties of the charfmt itself, its not + good enough to just see it as a single property from the point of + compressing property sets. If bold and charfmt are in a child, and bold is + in the parent, removing bold from the child will not result in the same + thing, if the charfmt removes bold itself for example + */ + bool bRet = false; + if (rSet.GetAttrSet().Count()) + { + + if (SFX_ITEM_SET == + rSet.GetAttrSet().GetItemState(RES_TXTATR_CHARFMT, FALSE)) + { + bRet = true; + } + } + return bRet; +} + +void SwRTFParser::SetEndPrevPara( SvxNodeIdx*& rpNodePos, xub_StrLen& rCntPos ) +{ + SwNodeIndex aIdx( pPam->GetPoint()->nNode ); + SwCntntNode* pNode = pDoc->GetNodes().GoPrevious( &aIdx ); + if( !pNode ) + { + ASSERT( FALSE, "keinen vorherigen ContentNode gefunden" ); + } + + rpNodePos = new SwNodeIdx( aIdx ); + rCntPos = pNode->Len(); +} + +void SwRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) +{ + ULONG nSNd = rSet.GetSttNodeIdx(), nENd = rSet.GetEndNodeIdx(); + xub_StrLen nSCnt = rSet.GetSttCnt(), nECnt = rSet.GetEndCnt(); + + SwPaM aPam( *pPam->GetPoint() ); + +#ifdef DBG_UTIL + ASSERT( nSNd <= nENd, "Start groesser als Ende" ); + SwNode* pDebugNd = pDoc->GetNodes()[ nSNd ]; + ASSERT( pDebugNd->IsCntntNode(), "Start kein ContentNode" ); + pDebugNd = pDoc->GetNodes()[ nENd ]; + ASSERT( pDebugNd->IsCntntNode(), "Ende kein ContentNode" ); +#endif + + SwCntntNode* pCNd = pDoc->GetNodes()[ nSNd ]->GetCntntNode(); + aPam.GetPoint()->nNode = nSNd; + aPam.GetPoint()->nContent.Assign( pCNd, nSCnt ); + aPam.SetMark(); + if( nENd == nSNd ) + aPam.GetPoint()->nContent = nECnt; + else + { + aPam.GetPoint()->nNode = nENd; + pCNd = aPam.GetCntntNode(); + aPam.GetPoint()->nContent.Assign( pCNd, nECnt ); + } + + // setze ueber den Bereich das entsprechende Style + if( rSet.StyleNo() ) + { + // setze jetzt das Style + if( !bStyleTabValid ) + MakeStyleTab(); + SwTxtFmtColl* pColl = aTxtCollTbl.Get( rSet.StyleNo() ); + if( pColl ) + pDoc->SetTxtFmtColl( aPam, pColl, false ); + } + + const SfxPoolItem* pItem; + const SfxPoolItem* pCharFmt; + if (rSet.GetAttrSet().Count() ) + { + + // falls eine Zeichenvorlage im Set steht, deren Attribute + // aus dem Set loeschen. Sonst sind diese doppelt, was man ja + // nicht will. + if( SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( + RES_TXTATR_CHARFMT, FALSE, &pCharFmt ) && + ((SwFmtCharFmt*)pCharFmt)->GetCharFmt() ) + { + const String& rName = ((SwFmtCharFmt*)pCharFmt)->GetCharFmt()->GetName(); + SvxRTFStyleType* pStyle = GetStyleTbl().First(); + do { + if( pStyle->bIsCharFmt && pStyle->sName == rName ) + { + // alle Attribute, die schon vom Style definiert sind, aus dem + // akt. AttrSet entfernen + SfxItemSet &rAttrSet = rSet.GetAttrSet(), + &rStyleSet = pStyle->aAttrSet; + SfxItemIter aIter( rAttrSet ); + USHORT nWhich = aIter.GetCurItem()->Which(); + while( TRUE ) + { + const SfxPoolItem* pI; + if( SFX_ITEM_SET == rStyleSet.GetItemState( + nWhich, FALSE, &pI ) && *pI == *aIter.GetCurItem()) + rAttrSet.ClearItem( nWhich ); // loeschen + + if( aIter.IsAtEnd() ) + break; + nWhich = aIter.NextItem()->Which(); + } + break; + } + } while( 0 != (pStyle = GetStyleTbl().Next()) ); + + pDoc->InsertPoolItem(aPam, *pCharFmt, 0); + rSet.GetAttrSet().ClearItem(RES_TXTATR_CHARFMT); //test hack + } + if (rSet.GetAttrSet().Count()) + { + // dann setze ueber diesen Bereich die Attrbiute + SetSwgValues(rSet.GetAttrSet()); + pDoc->InsertItemSet(aPam, rSet.GetAttrSet(), + nsSetAttrMode::SETATTR_DONTCHGNUMRULE); + } + } + + if( SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( + FN_PARAM_NUM_LEVEL, FALSE, &pItem )) + { + // dann ueber den Bereich an den Nodes das NodeNum setzen + for( ULONG n = nSNd; n <= nENd; ++n ) + { + SwTxtNode* pTxtNd = pDoc->GetNodes()[ n ]->GetTxtNode(); + if( pTxtNd ) + { + pTxtNd->SetAttrListLevel((BYTE) ((SfxUInt16Item*)pItem)->GetValue()); + // Update vom LR-Space abschalten? + } + } + } + + if( SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( + RES_PARATR_NUMRULE, FALSE, &pItem )) + { + const SwNumRule* pRule = pDoc->FindNumRulePtr( + ((SwNumRuleItem*)pItem)->GetValue() ); + if( pRule && ( pRule->IsContinusNum() || !bNewNumList )) + { + // diese Rule hat keinen Level, also muss die Einrueckung + // erhalten bleiben! + // dann ueber den Bereich an den Nodes das Flag zuruecksetzen + for( ULONG n = nSNd; n <= nENd; ++n ) + { + SwTxtNode* pTxtNd = pDoc->GetNodes()[ n ]->GetTxtNode(); + if( pTxtNd ) + { + // Update vom LR-Space abschalten + pTxtNd->SetNumLSpace( FALSE ); + } + } + } + } + + bool bNoNum = true; + if ( + (SFX_ITEM_SET == rSet.GetAttrSet().GetItemState(RES_PARATR_NUMRULE)) + || (SFX_ITEM_SET == rSet.GetAttrSet().GetItemState(FN_PARAM_NUM_LEVEL)) + ) + { + bNoNum = false; + } + + if (bNoNum) + { + for( ULONG n = nSNd; n <= nENd; ++n ) + { + SwTxtNode* pTxtNd = pDoc->GetNodes()[ n ]->GetTxtNode(); + if( pTxtNd ) + { + pTxtNd->SetAttr( + *GetDfltAttr(RES_PARATR_NUMRULE)); + } + } + } +} + +DocPageInformation::DocPageInformation() + : maBox( RES_BOX ), + mnPaperw(12240), mnPaperh(15840), mnMargl(1800), mnMargr(1800), + mnMargt(1440), mnMargb(1440), mnGutter(0), mnPgnStart(1), mbFacingp(false), + mbLandscape(false), mbRTLdoc(false) +{ +} + +SectPageInformation::SectPageInformation(const DocPageInformation &rDoc) + : maBox(rDoc.maBox), mpTitlePageHdFt(0), mpPageHdFt(0), + mnPgwsxn(rDoc.mnPaperw), mnPghsxn(rDoc.mnPaperh), mnMarglsxn(rDoc.mnMargl), + mnMargrsxn(rDoc.mnMargr), mnMargtsxn(rDoc.mnMargt), + mnMargbsxn(rDoc.mnMargb), mnGutterxsn(rDoc.mnGutter), mnHeadery(720), + mnFootery(720), mnPgnStarts(rDoc.mnPgnStart), mnCols(1), mnColsx(720), + mnStextflow(rDoc.mbRTLdoc ? 3 : 0), mnBkc(2), mbLndscpsxn(rDoc.mbLandscape), + mbTitlepg(false), mbFacpgsxn(rDoc.mbFacingp), mbRTLsection(rDoc.mbRTLdoc), + mbPgnrestart(false), mbTitlePageHdFtUsed(false), mbPageHdFtUsed(false) +{ +}; + +SectPageInformation::SectPageInformation(const SectPageInformation &rSect) + : maColumns(rSect.maColumns), maBox(rSect.maBox), + maNumType(rSect.maNumType), mpTitlePageHdFt(rSect.mpTitlePageHdFt), + mpPageHdFt(rSect.mpPageHdFt), mnPgwsxn(rSect.mnPgwsxn), + mnPghsxn(rSect.mnPghsxn), mnMarglsxn(rSect.mnMarglsxn), + mnMargrsxn(rSect.mnMargrsxn), mnMargtsxn(rSect.mnMargtsxn), + mnMargbsxn(rSect.mnMargbsxn), mnGutterxsn(rSect.mnGutterxsn), + mnHeadery(rSect.mnHeadery), mnFootery(rSect.mnFootery), + mnPgnStarts(rSect.mnPgnStarts), mnCols(rSect.mnCols), + mnColsx(rSect.mnColsx), mnStextflow(rSect.mnStextflow), mnBkc(rSect.mnBkc), + mbLndscpsxn(rSect.mbLndscpsxn), mbTitlepg(rSect.mbTitlepg), + mbFacpgsxn(rSect.mbFacpgsxn), mbRTLsection(rSect.mbRTLsection), + mbPgnrestart(rSect.mbPgnrestart), + mbTitlePageHdFtUsed(rSect.mbTitlePageHdFtUsed), + mbPageHdFtUsed(rSect.mbPageHdFtUsed) +{ +}; + +rtfSection::rtfSection(const SwPosition &rPos, + const SectPageInformation &rPageInfo) + : maStart(rPos.nNode), maPageInfo(rPageInfo), mpSection(0), mpTitlePage(0), + mpPage(0) +{ +} + +void rtfSections::push_back(const rtfSection &rSect) +{ + if (!maSegments.empty() && (maSegments.back().maStart == rSect.maStart)) + maSegments.pop_back(); + maSegments.push_back(rSect); +} + +// lese alle Dokument-Controls ein +void SwRTFParser::SetPageInformationAsDefault(const DocPageInformation &rInfo) +{ + //If we are at the beginning of the document then start the document with + //a segment with these properties. See #i14982# for this requirement + rtfSection aSect(*pPam->GetPoint(), SectPageInformation(rInfo)); + if (maSegments.empty() || (maSegments.back().maStart == aSect.maStart)) + maSegments.push_back(aSect); + + if (!bSwPageDesc && IsNewDoc()) + { + SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, rInfo.mnPaperw, rInfo.mnPaperh); + + SvxLRSpaceItem aLR( static_cast< USHORT >(rInfo.mnMargl), static_cast< USHORT >(rInfo.mnMargr), 0, 0, RES_LR_SPACE ); + SvxULSpaceItem aUL( static_cast< USHORT >(rInfo.mnMargt), static_cast< USHORT >(rInfo.mnMargb), RES_UL_SPACE ); + + UseOnPage eUseOn; + if (rInfo.mbFacingp) + eUseOn = UseOnPage(nsUseOnPage::PD_MIRROR | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE); + else + eUseOn = UseOnPage(nsUseOnPage::PD_ALL | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE); + + USHORT nPgStart = static_cast< USHORT >(rInfo.mnPgnStart); + + SvxFrameDirectionItem aFrmDir(rInfo.mbRTLdoc ? + FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR); + + // direkt an der Standartseite drehen + SwPageDesc& rPg = pDoc->_GetPageDesc( 0 ); + rPg.WriteUseOn( eUseOn ); + + if (rInfo.mbLandscape) + rPg.SetLandscape(true); + + SwFrmFmt &rFmt1 = rPg.GetMaster(), &rFmt2 = rPg.GetLeft(); + + rFmt1.SetFmtAttr( aFrmSize ); rFmt2.SetFmtAttr( aFrmSize ); + rFmt1.SetFmtAttr( aLR ); rFmt2.SetFmtAttr( aLR ); + rFmt1.SetFmtAttr( aUL ); rFmt2.SetFmtAttr( aUL ); + rFmt1.SetFmtAttr( aFrmDir ); rFmt2.SetFmtAttr( aFrmDir ); + + // StartNummer der Seiten setzen + if (nPgStart != 1) + { + SwFmtPageDesc aPgDsc( &rPg ); + aPgDsc.SetNumOffset( nPgStart ); + pDoc->InsertPoolItem( *pPam, aPgDsc, 0 ); + } + } +} + +void SwRTFParser::SetBorderLine(SvxBoxItem& rBox, sal_uInt16 nLine) +{ + int bWeiter = true; + short nLineThickness = 1; + short nPageDistance = 0; + BYTE nCol = 0; + short nIdx = 0; + + int nToken = GetNextToken(); + do { + switch( nToken ) + { + case RTF_BRDRS: + nIdx = 1; + break; + + case RTF_BRDRDB: + nIdx = 3; + break; + + case RTF_BRDRTRIPLE: + nIdx = 10; + break; + + case RTF_BRDRTNTHSG: + nIdx = 11; + break; + + case RTF_BRDRTHTNSG: + nIdx = 12; + break; + + case RTF_BRDRTNTHTNSG: + nIdx = 13; + break; + + case RTF_BRDRTNTHMG: + nIdx = 14; + break; + + case RTF_BRDRTHTNMG: + nIdx = 15; + break; + + case RTF_BRDRTNTHTNMG: + nIdx = 16; + break; + + case RTF_BRDRTNTHLG: + nIdx = 17; + break; + + case RTF_BRDRTHTNLG: + nIdx = 18; + break; + + case RTF_BRDRTNTHTNLG: + nIdx = 19; + break; + + case RTF_BRDRWAVY: + nIdx = 20; + break; + + case RTF_BRDRWAVYDB: + nIdx = 21; + break; + + case RTF_BRDREMBOSS: + nIdx = 24; + break; + + case RTF_BRDRENGRAVE: + nIdx = 25; + break; + + case RTF_BRSP: + nPageDistance = static_cast< short >(nTokenValue); + break; + + case RTF_BRDRDOT: // SO does not have dashed or dotted lines + case RTF_BRDRDASH: + case RTF_BRDRDASHSM: + case RTF_BRDRDASHD: + case RTF_BRDRDASHDD: + case RTF_BRDRDASHDOTSTR: + case RTF_BRDRSH: // shading not supported + case RTF_BRDRCF: // colors not supported + break; + + case RTF_BRDRW: + nLineThickness = static_cast< short >(nTokenValue); + break; + default: + bWeiter = false; + SkipToken(-1); + break; + } + if (bWeiter) + nToken = GetNextToken(); + } while (bWeiter && IsParserWorking()); + + GetLineIndex(rBox, nLineThickness, nPageDistance, nCol, nIdx, nLine, nLine, 0); +} + +// lese alle Dokument-Controls ein +void SwRTFParser::ReadDocControls( int nToken ) +{ + int bWeiter = true; + + SwFtnInfo aFtnInfo; + SwEndNoteInfo aEndInfo; + bool bSetHyph = false; + + BOOL bEndInfoChgd = FALSE, bFtnInfoChgd = FALSE; + + do { + USHORT nValue = USHORT( nTokenValue ); + switch( nToken ) + { + case RTF_RTLDOC: + maPageDefaults.mbRTLdoc = true; + break; + case RTF_LTRDOC: + maPageDefaults.mbRTLdoc = false; + break; + case RTF_LANDSCAPE: + maPageDefaults.mbLandscape = true; + break; + case RTF_PAPERW: + if( 0 < nTokenValue ) + maPageDefaults.mnPaperw = nTokenValue; + break; + case RTF_PAPERH: + if( 0 < nTokenValue ) + maPageDefaults.mnPaperh = nTokenValue; + break; + case RTF_MARGL: + if( 0 <= nTokenValue ) + maPageDefaults.mnMargl = nTokenValue; + break; + case RTF_MARGR: + if( 0 <= nTokenValue ) + maPageDefaults.mnMargr = nTokenValue; + break; + case RTF_MARGT: + if( 0 <= nTokenValue ) + maPageDefaults.mnMargt = nTokenValue; + break; + case RTF_MARGB: + if( 0 <= nTokenValue ) + maPageDefaults.mnMargb = nTokenValue; + break; + case RTF_FACINGP: + maPageDefaults.mbFacingp = true; + break; + case RTF_PGNSTART: + maPageDefaults.mnPgnStart = nTokenValue; + break; + case RTF_ENDDOC: + case RTF_ENDNOTES: + aFtnInfo.ePos = FTNPOS_CHAPTER; bFtnInfoChgd = TRUE; + break; + case RTF_FTNTJ: + case RTF_FTNBJ: + aFtnInfo.ePos = FTNPOS_PAGE; bFtnInfoChgd = TRUE; + break; + + case RTF_AENDDOC: + case RTF_AENDNOTES: + case RTF_AFTNTJ: + case RTF_AFTNBJ: + case RTF_AFTNRESTART: + case RTF_AFTNRSTCONT: + break; // wir kenn nur am Doc Ende und Doc weite Num.! + + case RTF_FTNSTART: + if( nValue ) + { + aFtnInfo.nFtnOffset = nValue-1; + bFtnInfoChgd = TRUE; + } + break; + case RTF_AFTNSTART: + if( nValue ) + { + aEndInfo.nFtnOffset = nValue-1; + bEndInfoChgd = TRUE; + } + break; + case RTF_FTNRSTPG: + aFtnInfo.eNum = FTNNUM_PAGE; bFtnInfoChgd = TRUE; + break; + case RTF_FTNRESTART: + aFtnInfo.eNum = FTNNUM_CHAPTER; bFtnInfoChgd = TRUE; + break; + case RTF_FTNRSTCONT: + aFtnInfo.eNum = FTNNUM_DOC; bFtnInfoChgd = TRUE; + break; + + case RTF_FTNNAR: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_ARABIC); bFtnInfoChgd = TRUE; break; + case RTF_FTNNALC: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER_N); bFtnInfoChgd = TRUE; break; + case RTF_FTNNAUC: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER_N); bFtnInfoChgd = TRUE; break; + case RTF_FTNNRLC: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER); bFtnInfoChgd = TRUE; break; + case RTF_FTNNRUC: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_ROMAN_UPPER); bFtnInfoChgd = TRUE; break; + case RTF_FTNNCHI: + aFtnInfo.aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL); bFtnInfoChgd = TRUE; break; + + case RTF_AFTNNAR: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_ARABIC); bEndInfoChgd = TRUE; break; + case RTF_AFTNNALC: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER_N); + bEndInfoChgd = TRUE; + break; + case RTF_AFTNNAUC: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER_N); + bEndInfoChgd = TRUE; + break; + case RTF_AFTNNRLC: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER); + bEndInfoChgd = TRUE; + break; + case RTF_AFTNNRUC: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_ROMAN_UPPER); + bEndInfoChgd = TRUE; + break; + case RTF_AFTNNCHI: + aEndInfo.aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL); + bEndInfoChgd = TRUE; + break; + case RTF_HYPHAUTO: + if (nTokenValue) + bSetHyph = true; + //FOO// + break; + case RTF_PGBRDRT: + SetBorderLine(maPageDefaults.maBox, BOX_LINE_TOP); + break; + + case RTF_PGBRDRB: + SetBorderLine(maPageDefaults.maBox, BOX_LINE_BOTTOM); + break; + + case RTF_PGBRDRL: + SetBorderLine(maPageDefaults.maBox, BOX_LINE_LEFT); + break; + + case RTF_PGBRDRR: + SetBorderLine(maPageDefaults.maBox, BOX_LINE_RIGHT); + break; + + case '{': + { + short nSkip = 0; + if( RTF_IGNOREFLAG != GetNextToken() ) + nSkip = -1; + else if( RTF_DOCFMT != (( nToken = GetNextToken() ) + & ~(0xff | RTF_SWGDEFS)) ) + nSkip = -2; + else + { + SkipGroup(); // erstmal komplett ueberlesen + // ueberlese noch die schliessende Klammer + GetNextToken(); + } + if( nSkip ) + { + SkipToken( nSkip ); // Ignore wieder zurueck + bWeiter = FALSE; + } + } + break; + + default: + if( RTF_DOCFMT == (nToken & ~(0xff | RTF_SWGDEFS)) || + RTF_UNKNOWNCONTROL == nToken ) + SvxRTFParser::NextToken( nToken ); + else + bWeiter = FALSE; + break; + } + if( bWeiter ) + nToken = GetNextToken(); + } while( bWeiter && IsParserWorking() ); + + if (IsNewDoc()) + { + if( bEndInfoChgd ) + pDoc->SetEndNoteInfo( aEndInfo ); + if( bFtnInfoChgd ) + pDoc->SetFtnInfo( aFtnInfo ); + } + + if (!bSwPageDesc) + { + SetPageInformationAsDefault(maPageDefaults); + + MakeStyleTab(); + + SwTxtFmtColl* pColl = aTxtCollTbl.Get(0); + if (!pColl) + { + pColl = pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false ); + } + + ASSERT(pColl, "impossible to have no standard style"); + + if (pColl) + { + if ( + IsNewDoc() && bSetHyph && + SFX_ITEM_SET != pColl->GetItemState(RES_PARATR_HYPHENZONE, + false) + ) + { + pColl->SetFmtAttr(SvxHyphenZoneItem(true, RES_PARATR_HYPHENZONE)); + } + + pDoc->SetTxtFmtColl( *pPam, pColl ); + } + } + + SkipToken( -1 ); +} + +void SwRTFParser::MakeStyleTab() +{ + // dann erzeuge aus der SvxStyle-Tabelle die Swg-Collections + if( GetStyleTbl().Count() ) + { + USHORT nValidOutlineLevels = 0; + if( !IsNewDoc() ) + { + // search all outlined collections + //BYTE nLvl; + const SwTxtFmtColls& rColls = *pDoc->GetTxtFmtColls(); + for( USHORT n = rColls.Count(); n; ) + //if( MAXLEVEL > (nLvl = rColls[ --n ]->GetOutlineLevel() ))//#outline level,zhaojianwei + // nValidOutlineLevels |= 1 << nLvl; + if( rColls[ --n ]->IsAssignedToListLevelOfOutlineStyle()) + nValidOutlineLevels |= 1 << rColls[ n ]->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei + } + + SvxRTFStyleType* pStyle = GetStyleTbl().First(); + do { + USHORT nNo = USHORT( GetStyleTbl().GetCurKey() ); + if( pStyle->bIsCharFmt ) + { + if( !aCharFmtTbl.Get( nNo ) ) + // existiert noch nicht, also anlegen + MakeCharStyle( nNo, *pStyle ); + } + else if( !aTxtCollTbl.Get( nNo ) ) + { + // existiert noch nicht, also anlegen + MakeStyle( nNo, *pStyle ); + } + + } while( 0 != (pStyle = GetStyleTbl().Next()) ); + bStyleTabValid = TRUE; + } +} + +BOOL lcl_SetFmtCol( SwFmt& rFmt, USHORT nCols, USHORT nColSpace, + const SvUShorts& rColumns ) +{ + BOOL bSet = FALSE; + if( nCols && USHRT_MAX != nCols ) + { + SwFmtCol aCol; + if( USHRT_MAX == nColSpace ) + nColSpace = 720; + + aCol.Init( nCols, nColSpace, USHRT_MAX ); + if( nCols == ( rColumns.Count() / 2 ) ) + { + aCol._SetOrtho( FALSE ); + USHORT nWishWidth = 0, nHalfPrev = 0; + for( USHORT n = 0, i = 0; n < rColumns.Count(); n += 2, ++i ) + { + SwColumn* pCol = aCol.GetColumns()[ i ]; + pCol->SetLeft( nHalfPrev ); + USHORT nSp = rColumns[ n+1 ]; + nHalfPrev = nSp / 2; + pCol->SetRight( nSp - nHalfPrev ); + pCol->SetWishWidth( rColumns[ n ] + + pCol->GetLeft() + pCol->GetRight() ); + nWishWidth = nWishWidth + pCol->GetWishWidth(); + } + aCol.SetWishWidth( nWishWidth ); + } + rFmt.SetFmtAttr( aCol ); + bSet = TRUE; + } + return bSet; +} + +void SwRTFParser::DoHairyWriterPageDesc(int nToken) +{ + int bWeiter = TRUE; + do { + if( '{' == nToken ) + { + switch( nToken = GetNextToken() ) + { + case RTF_IGNOREFLAG: + if( RTF_SECTFMT != (( nToken = GetNextToken() ) + & ~(0xff | RTF_SWGDEFS)) ) + { + SkipToken( -2 ); // Ignore und Token wieder zurueck + bWeiter = FALSE; + break; + } + // kein break, Gruppe ueberspringen + + case RTF_FOOTER: + case RTF_HEADER: + case RTF_FOOTERR: + case RTF_HEADERR: + case RTF_FOOTERL: + case RTF_HEADERL: + case RTF_FOOTERF: + case RTF_HEADERF: + SkipGroup(); // erstmal komplett ueberlesen + // ueberlese noch die schliessende Klammer + GetNextToken(); + break; + + default: + SkipToken( -1 ); // Ignore wieder zurueck + bWeiter = FALSE; + break; + } + } + else if( RTF_SECTFMT == (nToken & ~(0xff | RTF_SWGDEFS)) || + RTF_UNKNOWNCONTROL == nToken ) + SvxRTFParser::NextToken( nToken ); + else + bWeiter = FALSE; + if( bWeiter ) + nToken = GetNextToken(); + } while( bWeiter && IsParserWorking() ); + SkipToken( -1 ); // letztes Token wieder zurueck + return; +} + +void SwRTFParser::ReadSectControls( int nToken ) +{ + //this is some hairy stuff to try and retain writer style page descriptors + //in rtf, almost certainy a bad idea, but we've inherited it, so here it + //stays + if (bInPgDscTbl) + { + DoHairyWriterPageDesc(nToken); + return; + } + + ASSERT(!maSegments.empty(), "suspicious to have a section with no " + "page info, though probably legal"); + if (maSegments.empty()) + { + maSegments.push_back(rtfSection(*pPam->GetPoint(), + SectPageInformation(maPageDefaults))); + } + + SectPageInformation aNewSection(maSegments.back().maPageInfo); + + bool bNewSection = false; + bool bNewSectionHeader = false; + const SwFmtHeader* _pKeepHeader = NULL; + const SwFmtFooter* _pKeepFooter = NULL; + int bWeiter = true; + bool bKeepFooter = false; + do { + USHORT nValue = USHORT( nTokenValue ); + switch( nToken ) + { + case RTF_SECT: + bNewSection = true; + bForceNewTable = true; // #117882# + break; + case RTF_SECTD: { + //Reset to page defaults + SwPageDesc* oldPageDesc=aNewSection.mpPageHdFt; + aNewSection = SectPageInformation(maPageDefaults); + aNewSection.mpPageHdFt=oldPageDesc; + _pKeepHeader = NULL; + _pKeepFooter = NULL; + } break; + case RTF_PGWSXN: + if (0 < nTokenValue) + aNewSection.mnPgwsxn = nTokenValue; + break; + case RTF_PGHSXN: + if (0 < nTokenValue) + aNewSection.mnPghsxn = nTokenValue; + break; + case RTF_MARGLSXN: + if (0 <= nTokenValue) + aNewSection.mnMarglsxn = nTokenValue; + break; + case RTF_MARGRSXN: + if (0 <= nTokenValue) + aNewSection.mnMargrsxn = nTokenValue; + break; + case RTF_MARGTSXN: + if (0 <= nTokenValue) + aNewSection.mnMargtsxn = nTokenValue; + break; + case RTF_MARGBSXN: + if (0 <= nTokenValue) + aNewSection.mnMargbsxn = nTokenValue; + break; + case RTF_FACPGSXN: + aNewSection.mbFacpgsxn = true; + break; + case RTF_HEADERY: + aNewSection.mnHeadery = nTokenValue; + break; + case RTF_FOOTERY: + aNewSection.mnFootery = nTokenValue; + break; + case RTF_LNDSCPSXN: + aNewSection.mbLndscpsxn = true; + break; + case RTF_PGNSTARTS: + aNewSection.mnPgnStarts = nTokenValue; + break; + case RTF_PGNDEC: + aNewSection.maNumType.SetNumberingType(SVX_NUM_ARABIC); + break; + case RTF_PGNUCRM: + aNewSection.maNumType.SetNumberingType(SVX_NUM_ROMAN_UPPER); + break; + case RTF_PGNLCRM: + aNewSection.maNumType.SetNumberingType(SVX_NUM_ROMAN_LOWER); + break; + case RTF_PGNUCLTR: + aNewSection.maNumType.SetNumberingType( + SVX_NUM_CHARS_UPPER_LETTER_N); + break; + case RTF_PGNLCLTR: + aNewSection.maNumType.SetNumberingType( + SVX_NUM_CHARS_LOWER_LETTER_N); + break; + case RTF_SBKNONE: + aNewSection.mnBkc = 0; + break; + case RTF_SBKCOL: + aNewSection.mnBkc = 1; + break; + case RTF_PGBRDRT: + SetBorderLine(aNewSection.maBox, BOX_LINE_TOP); + break; + + case RTF_PGBRDRB: + SetBorderLine(aNewSection.maBox, BOX_LINE_BOTTOM); + break; + + case RTF_PGBRDRL: + SetBorderLine(aNewSection.maBox, BOX_LINE_LEFT); + break; + + case RTF_PGBRDRR: + SetBorderLine(aNewSection.maBox, BOX_LINE_RIGHT); + break; + + case RTF_PGBRDROPT: + case RTF_ENDNHERE: + case RTF_BINFSXN: + case RTF_BINSXN: + case RTF_SBKPAGE: + case RTF_SBKEVEN: + case RTF_SBKODD: + case RTF_LINEBETCOL: + case RTF_LINEMOD: + case RTF_LINEX: + case RTF_LINESTARTS: + case RTF_LINERESTART: + case RTF_LINEPAGE: + case RTF_LINECONT: + case RTF_GUTTERSXN: + case RTF_PGNCONT: + case RTF_PGNRESTART: + case RTF_PGNX: + case RTF_PGNY: + case RTF_VERTALT: + case RTF_VERTALB: + case RTF_VERTALC: + case RTF_VERTALJ: + break; + case RTF_TITLEPG: + aNewSection.mbTitlepg = true; + break; + case RTF_HEADER: + case RTF_HEADERL: + case RTF_HEADERR: + if (aNewSection.mpPageHdFt!=NULL) + { + _pKeepHeader = NULL; + bKeepFooter = true; // #i82008 + _pKeepFooter = &aNewSection.mpPageHdFt->GetMaster().GetFooter(); + } + case RTF_FOOTER: + case RTF_FOOTERL: + case RTF_FOOTERR: + if (aNewSection.mpPageHdFt!=NULL && !bKeepFooter ) + { + _pKeepFooter = NULL; + _pKeepHeader = &aNewSection.mpPageHdFt->GetMaster().GetHeader(); + } + bKeepFooter = false; + if (!bNewSectionHeader) { //see #117914# topic 2). If a header is redefined in a section + bNewSectionHeader=true; // a new header must be created. + aNewSection.mpPageHdFt=NULL; + } + if (!aNewSection.mpPageHdFt) + { + String aName(RTL_CONSTASCII_STRINGPARAM("rtfHdFt")); + aName += String::CreateFromInt32(maSegments.size()); + sal_uInt16 nPageNo = pDoc->MakePageDesc(aName); + aNewSection.mpPageHdFt = &pDoc->_GetPageDesc(nPageNo); + aNewSection.mbPageHdFtUsed = true; + maSegments.maDummyPageNos.push_back(nPageNo); + } + ReadHeaderFooter(nToken, aNewSection.mpPageHdFt); + if (_pKeepHeader) aNewSection.mpPageHdFt->GetMaster().SetFmtAttr(*_pKeepHeader); + if (_pKeepFooter) aNewSection.mpPageHdFt->GetMaster().SetFmtAttr(*_pKeepFooter); + break; + case RTF_FOOTERF: + case RTF_HEADERF: + if (!aNewSection.mpTitlePageHdFt) + { + String aTitle(RTL_CONSTASCII_STRINGPARAM("rtfTitleHdFt")); + aTitle += String::CreateFromInt32(maSegments.size()); + sal_uInt16 nPageNo = pDoc->MakePageDesc(aTitle); + aNewSection.mpTitlePageHdFt = &pDoc->_GetPageDesc(nPageNo); + aNewSection.mbTitlePageHdFtUsed = true; + maSegments.maDummyPageNos.push_back(nPageNo); + } + ReadHeaderFooter(nToken, aNewSection.mpTitlePageHdFt); + break; + case RTF_COLS: + aNewSection.mnCols = nTokenValue; + break; + case RTF_COLSX: + aNewSection.mnColsx = nTokenValue; + break; + case RTF_COLNO: + { + // next token must be either colw or colsr + unsigned long nAktCol = nValue; + long nWidth = 0, nSpace = 0; + int nColToken = GetNextToken(); + if (RTF_COLW == nColToken) + { + // next token could be colsr (but not required) + nWidth = nTokenValue; + if( RTF_COLSR == GetNextToken() ) + nSpace = nTokenValue; + else + SkipToken( -1 ); // put back token + } + else if (RTF_COLSR == nColToken) + { + // next token must be colw (what sense should it make to have colsr only?!) + nSpace = nTokenValue; + if( RTF_COLW == GetNextToken() ) + nWidth = nTokenValue; + else + // what should we do if an isolated colsr without colw is found? Doesn't make sense! + SkipToken( -1 ); // put back token + } + else + break; + + if (--nAktCol == (aNewSection.maColumns.size() / 2)) + { + aNewSection.maColumns.push_back(nWidth); + aNewSection.maColumns.push_back(nSpace); + } + } + break; + case RTF_STEXTFLOW: + aNewSection.mnStextflow = nTokenValue; + break; + case RTF_RTLSECT: + aNewSection.mbRTLsection = true; + break; + case RTF_LTRSECT: + aNewSection.mbRTLsection = false; + break; + case '{': + { + short nSkip = 0; + if( RTF_IGNOREFLAG != ( nToken = GetNextToken() )) + nSkip = -1; + else if( RTF_SECTFMT != (( nToken = GetNextToken() ) + & ~(0xff | RTF_SWGDEFS)) && + ( RTF_DOCFMT != ( nToken & ~(0xff | RTF_SWGDEFS))) ) + nSkip = -2; + else + { + // erstmal komplett ueberlesen + SkipGroup(); + // ueberlese noch die schliessende Klammer + GetNextToken(); + } + if (nSkip) + { + bWeiter = ((-1 == nSkip) && + ( + RTF_FOOTER == nToken || RTF_HEADER == nToken || + RTF_FOOTERR == nToken || RTF_HEADERR == nToken || + RTF_FOOTERL == nToken || RTF_HEADERL == nToken || + RTF_FOOTERF == nToken || RTF_HEADERF == nToken + )); + SkipToken (nSkip); // Ignore wieder zurueck + } + } + break; + case RTF_PAPERW: + case RTF_PAPERH: + case RTF_MARGL: + case RTF_MARGR: + case RTF_MARGT: + case RTF_MARGB: + case RTF_FACINGP: + ASSERT(!this, "why are these tokens found in this section?"); + ReadDocControls( nToken ); + break; + default: + if (RTF_DOCFMT == (nToken & ~(0xff | RTF_SWGDEFS))) + ReadDocControls( nToken ); + else if (RTF_SECTFMT == (nToken & ~(0xff | RTF_SWGDEFS)) || + RTF_UNKNOWNCONTROL == nToken) + { + SvxRTFParser::NextToken(nToken); + } + else + bWeiter = false; + break; + } + + if (bWeiter) + nToken = GetNextToken(); + } while (bWeiter && IsParserWorking()); + + if (bNewSection || maSegments.empty()) + { + AttrGroupEnd(); //#106493# + if(!bContainsPara && !bContainsTablePara) //#117881#: bContainsTablePara is set in rtftbl.cxx + pDoc->AppendTxtNode(*pPam->GetPoint()); + bContainsPara = false; + bContainsTablePara = false; + maSegments.push_back(rtfSection(*pPam->GetPoint(), aNewSection)); + } + else //modifying/replacing the current section + { + SwPaM aPamStart(maSegments.back().maStart); + maSegments.pop_back(); + maSegments.push_back(rtfSection(*aPamStart.GetPoint(), aNewSection)); + } + + SkipToken(-1); +} + +void SwRTFParser::EnterEnvironment() +{ +} + + +void SwRTFParser::LeaveEnvironment() +{ + if(pRedlineDelete) + { + delete pRedlineDelete; + pRedlineDelete = 0; + } + + if(pRedlineInsert) + { + delete pRedlineInsert; + pRedlineInsert = 0; + } +} + +void SwRTFParser::SkipPageDescTbl() +{ + // M.M. #117907# I have to use this glorified SkipGroup because the + // SvParser SkipGroup uses nNextCh which is not set correctly <groan> + int nNumOpenBrakets = 1; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( GetNextToken() ) + { + case '}': + { + --nNumOpenBrakets; + } + break; + + case '{': + { + nNumOpenBrakets++; + } + break; + } + } + + SkipToken( -1 ); +} + +void SwRTFParser::ReadPageDescTbl() +{ + // dann erzeuge aus der SvxStyle-Tabelle die Swg-Collections, damit + // diese auch in den Headers/Footer benutzt werden koennen! + MakeStyleTab(); + // das default-Style schon gleich am ersten Node setzen + SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 ); + if( !pColl ) + pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + pDoc->SetTxtFmtColl( *pPam, pColl ); + + int nToken, bSaveChkStyleAttr = IsChkStyleAttr(); + int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + + SetChkStyleAttr(FALSE); // Attribute nicht gegen die Styles checken + + bInPgDscTbl = true; + USHORT nPos = 0; + SwPageDesc* pPg = 0; + SwFrmFmt* pPgFmt = 0; + + SvxULSpaceItem aUL( RES_UL_SPACE ), aHUL( RES_UL_SPACE ), aFUL( RES_UL_SPACE ); + SvxLRSpaceItem aLR( RES_LR_SPACE ), aHLR( RES_LR_SPACE ), aFLR( RES_LR_SPACE ); + Size a4 = SvxPaperInfo::GetPaperSize(PAPER_A4); + SwFmtFrmSize aSz( ATT_FIX_SIZE, a4.Width(), a4.Height() ); // DIN A4 defaulten + SwFmtFrmSize aFSz( ATT_MIN_SIZE ), aHSz( ATT_MIN_SIZE ); + + SvxFrameDirectionItem aFrmDir(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR); + + USHORT nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0; + SvUShorts aColumns; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( nToken = GetNextToken() ) + { + case '{': + ++nNumOpenBrakets; + break; + case '}': + if (1 == --nNumOpenBrakets) + { + ASSERT(pPgFmt && pPg, "Serious problem here"); + if (pPgFmt && pPg) + { + // PageDesc ist fertig, setze am Doc + pPgFmt->SetFmtAttr(aFrmDir); + pPgFmt->SetFmtAttr(aLR); + pPgFmt->SetFmtAttr(aUL); + pPgFmt->SetFmtAttr(aSz); + ::lcl_SetFmtCol(*pPgFmt, nCols, nColSpace, aColumns); + if (pPgFmt->GetHeader().GetHeaderFmt()) + { + SwFrmFmt* pHFmt = + (SwFrmFmt*)pPgFmt->GetHeader().GetHeaderFmt(); + pHFmt->SetFmtAttr(aHUL); + pHFmt->SetFmtAttr(aHLR); + pHFmt->SetFmtAttr(aHSz); + } + if (pPgFmt->GetFooter().GetFooterFmt()) + { + SwFrmFmt* pFFmt = + (SwFrmFmt*)pPgFmt->GetFooter().GetFooterFmt(); + pFFmt->SetFmtAttr(aHUL); + pFFmt->SetFmtAttr(aHLR); + pFFmt->SetFmtAttr(aHSz); + } + if( nPos < pDoc->GetPageDescCnt() ) + pDoc->ChgPageDesc(nPos++, *pPg); + } + } + break; + case RTF_PGDSC: + if (nPos) // kein && wg MAC + { + if (nPos != pDoc->MakePageDesc( + String::CreateFromInt32(nTokenValue))) + { + ASSERT( FALSE, "PageDesc an falscher Position" ); + } + } + pPg = &pDoc->_GetPageDesc(nPos); + pPg->SetLandscape( FALSE ); + pPgFmt = &pPg->GetMaster(); +#ifndef CFRONT + SETPAGEDESC_DEFAULTS: +#endif + aSz.SetWidth( a4.Width() ); aSz.SetHeight( a4.Height() ); + aLR.SetLeft( 0 ); aLR.SetRight( 0 ); + aUL.SetLower( 0 ); aUL.SetUpper( 0 ); + aHLR.SetLeft( 0 ); aHLR.SetRight( 0 ); + aHUL.SetLower( 0 ); aHUL.SetUpper( 0 ); + aFLR.SetLeft( 0 ); aFLR.SetRight( 0 ); + aFUL.SetLower( 0 ); aFUL.SetUpper( 0 ); + nCols = USHRT_MAX; nColSpace = USHRT_MAX; nAktCol = 0; + aFSz.SetHeightSizeType( ATT_MIN_SIZE ); aFSz.SetHeight( 0 ); + aHSz.SetHeightSizeType( ATT_MIN_SIZE ); aHSz.SetHeight( 0 ); + break; + + case RTF_PGDSCUSE: + pPg->WriteUseOn( (UseOnPage)nTokenValue ); + break; + + case RTF_PGDSCNXT: + // setze erstmal nur die Nummer als Follow. Am Ende der + // Tabelle wird diese entsprechend korrigiert !! + if( nTokenValue ) + pPg->SetFollow( (const SwPageDesc*)nTokenValue ); + else + pPg->SetFollow( & const_cast<const SwDoc *>(pDoc) + ->GetPageDesc( 0 ) ); + break; + + case RTF_FORMULA: /* Zeichen "\|" !!! */ + pPgFmt->SetFmtAttr( aLR ); + pPgFmt->SetFmtAttr( aUL ); + pPgFmt->SetFmtAttr( aSz ); + ::lcl_SetFmtCol( *pPgFmt, nCols, nColSpace, aColumns ); + if( pPgFmt->GetHeader().GetHeaderFmt() ) + { + SwFrmFmt* pHFmt = (SwFrmFmt*)pPgFmt->GetHeader().GetHeaderFmt(); + pHFmt->SetFmtAttr( aHUL ); + pHFmt->SetFmtAttr( aHLR ); + pHFmt->SetFmtAttr( aHSz ); + } + if( pPgFmt->GetFooter().GetFooterFmt() ) + { + SwFrmFmt* pFFmt = (SwFrmFmt*)pPgFmt->GetFooter().GetFooterFmt(); + pFFmt->SetFmtAttr( aHUL ); + pFFmt->SetFmtAttr( aHLR ); + pFFmt->SetFmtAttr( aHSz ); + } + + pPgFmt = &pPg->GetLeft(); +#ifndef CFRONT + goto SETPAGEDESC_DEFAULTS; +#else + aLR.SetLeft( 0 ); aLR.SetRight( 0 ); + aUL.SetLower( 0 ); aUL.SetUpper( 0 ); + aHLR.SetLeft( 0 ); aHLR.SetRight( 0 ); + aHUL.SetLower( 0 ); aHUL.SetUpper( 0 ); + aFLR.SetLeft( 0 ); aFLR.SetRight( 0 ); + aFUL.SetLower( 0 ); aFUL.SetUpper( 0 ); + aSz.SetWidth( a4.Width() ); aSz.SetHeight( a4.Height() ); // DIN A4 default + nCols = USHRT_MAX; nColSpace = USHRT_MAX; nAktCol = 0; + aFSz.SetHeightSizeType( ATT_MIN_SIZE ); aFSz.SetHeight( 0 ); + aHSz.SetHeightSizeType( ATT_MIN_SIZE ); aHSz.SetHeight( 0 ); + break; +#endif + + case RTF_RTLSECT: + aFrmDir.SetValue(FRMDIR_HORI_RIGHT_TOP); + break; + + case RTF_LTRSECT: + aFrmDir.SetValue(FRMDIR_HORI_LEFT_TOP); + break; + + // alt: LI/RI/SA/SB, neu: MARG?SXN + case RTF_MARGLSXN: + case RTF_LI: aLR.SetLeft( (USHORT)nTokenValue ); break; + case RTF_MARGRSXN: + case RTF_RI: aLR.SetRight( (USHORT)nTokenValue ); break; + case RTF_MARGTSXN: + case RTF_SA: aUL.SetUpper( (USHORT)nTokenValue ); break; + case RTF_MARGBSXN: + case RTF_SB: aUL.SetLower( (USHORT)nTokenValue ); break; + case RTF_PGWSXN: aSz.SetWidth( nTokenValue ); break; + case RTF_PGHSXN: aSz.SetHeight( nTokenValue ); break; + + case RTF_HEADERY: aHUL.SetUpper( (USHORT)nTokenValue ); break; + case RTF_HEADER_YB: aHUL.SetLower( (USHORT)nTokenValue ); break; + case RTF_HEADER_XL: aHLR.SetLeft( (USHORT)nTokenValue ); break; + case RTF_HEADER_XR: aHLR.SetRight( (USHORT)nTokenValue ); break; + case RTF_FOOTERY: aFUL.SetLower( (USHORT)nTokenValue ); break; + case RTF_FOOTER_YT: aFUL.SetUpper( (USHORT)nTokenValue ); break; + case RTF_FOOTER_XL: aFLR.SetLeft( (USHORT)nTokenValue ); break; + case RTF_FOOTER_XR: aFLR.SetRight( (USHORT)nTokenValue ); break; + + case RTF_HEADER_YH: + if( 0 > nTokenValue ) + { + aHSz.SetHeightSizeType( ATT_FIX_SIZE ); + nTokenValue = -nTokenValue; + } + aHSz.SetHeight( (USHORT)nTokenValue ); + break; + + case RTF_FOOTER_YH: + if( 0 > nTokenValue ) + { + aFSz.SetHeightSizeType( ATT_FIX_SIZE ); + nTokenValue = -nTokenValue; + } + aFSz.SetHeight( (USHORT)nTokenValue ); + break; + + + case RTF_LNDSCPSXN: pPg->SetLandscape( TRUE ); break; + + case RTF_COLS: nCols = (USHORT)nTokenValue; break; + case RTF_COLSX: nColSpace = (USHORT)nTokenValue; break; + + case RTF_COLNO: + nAktCol = (USHORT)nTokenValue; + if( RTF_COLW == GetNextToken() ) + { + USHORT nWidth = USHORT( nTokenValue ), nSpace = 0; + if( RTF_COLSR == GetNextToken() ) + nSpace = USHORT( nTokenValue ); + else + SkipToken( -1 ); // wieder zurueck + + if( --nAktCol == ( aColumns.Count() / 2 ) ) + { + aColumns.Insert( nWidth, aColumns.Count() ); + aColumns.Insert( nSpace, aColumns.Count() ); + } + } + break; + + case RTF_PAGEBB: + { + pPgFmt->SetFmtAttr( SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ) ); + } + break; + + case RTF_HEADER: + case RTF_HEADERL: + case RTF_HEADERR: + case RTF_FOOTER: + case RTF_FOOTERL: + case RTF_FOOTERR: + case RTF_FOOTERF: + case RTF_HEADERF: + ReadHeaderFooter(nToken, pPg); + --nNumOpenBrakets; // Klammer wird im ReadAttr ueberlesen! + break; + case RTF_TEXTTOKEN: + if (!DelCharAtEnd(aToken, ';' ).Len()) + break; + ASSERT(pPg, "Unexpected missing pPg"); + if (pPg) + { + pPg->SetName(aToken); + + // sollte es eine Vorlage aus dem Pool sein ?? + USHORT n = SwStyleNameMapper::GetPoolIdFromUIName(aToken, + nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC); + if (USHRT_MAX != n) + { + // dann setze bei der Neuen die entsp. PoolId + pPg->SetPoolFmtId(n); + } + } + break; + case RTF_BRDBOX: + if (3 == nNumOpenBrakets) + { + ReadBorderAttr(SkipToken(-2), + (SfxItemSet&)pPgFmt->GetAttrSet()); + --nNumOpenBrakets; // Klammer wird im ReadAttr ueberlesen! + } + break; + case RTF_SHADOW: + if( 3 == nNumOpenBrakets ) + { + ReadAttr( SkipToken( -2 ), (SfxItemSet*)&pPgFmt->GetAttrSet() ); + --nNumOpenBrakets; // Klammer wird im ReadAttr ueberlesen! + } + break; + + + default: + if( (nToken & ~0xff ) == RTF_SHADINGDEF ) + ReadBackgroundAttr( nToken, (SfxItemSet&)pPgFmt->GetAttrSet() ); + break; + } + } + + + // setze jetzt noch bei allen die entsprechenden Follows !! + // Die, die ueber die Tabelle eingelesen wurden und einen + // Follow definiert haben, ist dieser als Tabposition im + // Follow schon gesetzt. + for( nPos = 0; nPos < pDoc->GetPageDescCnt(); ++nPos ) + { + SwPageDesc* pPgDsc = &pDoc->_GetPageDesc( nPos ); + if( (USHORT)(long)pPgDsc->GetFollow() < pDoc->GetPageDescCnt() ) + pPgDsc->SetFollow(& const_cast<const SwDoc *>(pDoc) + ->GetPageDesc((USHORT)(long) + pPgDsc->GetFollow())); + } + + SetChkStyleAttr( bSaveChkStyleAttr ); + + bInPgDscTbl = false; + nAktPageDesc = 0; + nAktFirstPageDesc = 0; + bSwPageDesc = true; + SkipToken( -1 ); +} + +// -------------- Methoden -------------------- + +/* +void SwRTFParser::ReadUnknownData() +{ + SvRTFParser::ReadUnknownData(); +} + +void SwRTFParser::ReadOLEData() +{ + SvRTFParser::ReadOLEData(); +} +*/ + +void SwRTFParser::ReadPrtData() +{ + while( IsParserWorking() ) + { + int nToken = GetNextToken(); + if( (RTF_TEXTTOKEN != nToken) && ('}' == nToken) ) + break; + } + + SkipToken( -1 ); // schliessende Klammer wieder zurueck!! +} + +static const SwNodeIndex* SetHeader(SwFrmFmt* pHdFtFmt, BOOL bReuseOld) +{ + ASSERT(pHdFtFmt, "Impossible, no header"); + const SwFrmFmt* pExisting = bReuseOld ? + pHdFtFmt->GetHeader().GetHeaderFmt() : 0; + if (!pExisting) + { + //No existing header, create a new one + pHdFtFmt->SetFmtAttr(SwFmtHeader(TRUE)); + pExisting = pHdFtFmt->GetHeader().GetHeaderFmt(); + } + return pExisting->GetCntnt().GetCntntIdx(); +} + +static const SwNodeIndex* SetFooter(SwFrmFmt* pHdFtFmt, BOOL bReuseOld) +{ + ASSERT(pHdFtFmt, "Impossible, no footer"); + const SwFrmFmt* pExisting = bReuseOld ? + pHdFtFmt->GetFooter().GetFooterFmt() : 0; + if (!pExisting) + { + //No exist footer, create a new one + pHdFtFmt->SetFmtAttr(SwFmtFooter(TRUE)); + pExisting = pHdFtFmt->GetFooter().GetFooterFmt(); + } + return pExisting->GetCntnt().GetCntntIdx(); +} + + +void SwRTFParser::ReadHeaderFooter( int nToken, SwPageDesc* pPageDesc ) +{ + ASSERT( RTF_FOOTNOTE == nToken || + RTF_FLY_INPARA == nToken || + pPageDesc, "PageDesc fehlt" ); + + bool bContainsParaCache = bContainsPara; + // alle wichtigen Sachen sichern + SwPosition aSavePos( *pPam->GetPoint() ); + SvxRTFItemStack aSaveStack; + aSaveStack.Insert( &GetAttrStack(), 0 ); + GetAttrStack().Remove( 0, GetAttrStack().Count() ); + + // save the fly array - after read, all flys may be set into + // the header/footer + SwFlySaveArr aSaveArray( 255 < aFlyArr.Count() ? aFlyArr.Count() : 255 ); + aSaveArray.Insert( &aFlyArr, 0 ); + aFlyArr.Remove( 0, aFlyArr.Count() ); + BOOL bSetFlyInDoc = TRUE; + + const SwNodeIndex* pSttIdx = 0; + SwFrmFmt* pHdFtFmt = 0; + SwTxtAttr* pTxtAttr = 0; + int bDelFirstChar = FALSE; + bool bOldIsFootnote = mbIsFootnote; + BOOL bOldGrpStt = sal::static_int_cast< BOOL, int >(IsNewGroup()); + + int nNumOpenBrakets = GetOpenBrakets() - 1; + + switch( nToken ) + { + case RTF_FOOTNOTE: + { + bool bIsEndNote = RTF_FTNALT == GetNextToken(); + if (!bIsEndNote) + SkipToken(-1); + + SwTxtNode* pTxtNd = pPam->GetNode()->GetTxtNode(); + SwFmtFtn aFtnNote(bIsEndNote); + xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex(); + + if (nPos && !bFootnoteAutoNum) + { + pPam->GetPoint()->nContent--; + nPos--; + aFtnNote.SetNumStr( pTxtNd->GetTxt().GetChar( nPos ) ); + ((String&)pTxtNd->GetTxt()).SetChar( nPos, CH_TXTATR_INWORD ); + bDelFirstChar = TRUE; + } + + pTxtAttr = pTxtNd->InsertItem( aFtnNote, nPos, nPos, + bDelFirstChar ? nsSetAttrMode::SETATTR_NOTXTATRCHR : 0 ); + + ASSERT( pTxtAttr, "konnte die Fussnote nicht einfuegen/finden" ); + + if( pTxtAttr ) + pSttIdx = ((SwTxtFtn*)pTxtAttr)->GetStartNode(); + mbIsFootnote = true; + + // wurde an der Position ein Escapement aufgespannt, so entferne + // das jetzt. Fussnoten sind bei uns immer hochgestellt. + SvxRTFItemStackTypePtr pTmp = aSaveStack.Top(); + if( pTmp && pTmp->GetSttNodeIdx() == + pPam->GetPoint()->nNode.GetIndex() && + pTmp->GetSttCnt() == nPos ) + pTmp->GetAttrSet().ClearItem( RES_CHRATR_ESCAPEMENT ); + } + break; + + case RTF_FLY_INPARA: + { + xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex(); + SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, + RES_FRMATR_END-1 ); + aSet.Put( SwFmtAnchor( FLY_AS_CHAR )); + pHdFtFmt = pDoc->MakeFlySection( FLY_AS_CHAR, + pPam->GetPoint(), &aSet ); + + pTxtAttr = pPam->GetNode()->GetTxtNode()->GetTxtAttrForCharAt( + nPos, RES_TXTATR_FLYCNT ); + ASSERT( pTxtAttr, "konnte den Fly nicht einfuegen/finden" ); + + pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx(); + bSetFlyInDoc = FALSE; + } + break; + + case RTF_HEADERF: + case RTF_HEADER: + pPageDesc->WriteUseOn( (UseOnPage)(pPageDesc->ReadUseOn() | nsUseOnPage::PD_HEADERSHARE) ); + pHdFtFmt = &pPageDesc->GetMaster(); + pSttIdx = SetHeader( pHdFtFmt, FALSE ); + break; + + case RTF_HEADERL: + // we cannot have left or right, must have always both + pPageDesc->WriteUseOn( (UseOnPage)((pPageDesc->ReadUseOn() & ~nsUseOnPage::PD_HEADERSHARE) | nsUseOnPage::PD_ALL)); + SetHeader( pPageDesc->GetRightFmt(), TRUE ); + pHdFtFmt = pPageDesc->GetLeftFmt(); + pSttIdx = SetHeader(pHdFtFmt, FALSE ); + break; + + case RTF_HEADERR: + // we cannot have left or right, must have always both + pPageDesc->WriteUseOn( (UseOnPage)((pPageDesc->ReadUseOn() & ~nsUseOnPage::PD_HEADERSHARE) | nsUseOnPage::PD_ALL)); + SetHeader( pPageDesc->GetLeftFmt(), TRUE ); + pHdFtFmt = pPageDesc->GetRightFmt(); + pSttIdx = SetHeader(pHdFtFmt, FALSE ); + break; + + case RTF_FOOTERF: + case RTF_FOOTER: + pPageDesc->WriteUseOn( (UseOnPage)(pPageDesc->ReadUseOn() | nsUseOnPage::PD_FOOTERSHARE) ); + pHdFtFmt = &pPageDesc->GetMaster(); + pSttIdx = SetFooter(pHdFtFmt, FALSE ); + break; + + case RTF_FOOTERL: + // we cannot have left or right, must have always both + pPageDesc->WriteUseOn( (UseOnPage)((pPageDesc->ReadUseOn() & ~nsUseOnPage::PD_FOOTERSHARE) | nsUseOnPage::PD_ALL)); + SetFooter( pPageDesc->GetRightFmt(), TRUE ); + pHdFtFmt = pPageDesc->GetLeftFmt(); + pSttIdx = SetFooter(pHdFtFmt, FALSE ); + break; + + case RTF_FOOTERR: + // we cannot have left or right, must have always both + pPageDesc->WriteUseOn( (UseOnPage)((pPageDesc->ReadUseOn() & ~nsUseOnPage::PD_FOOTERSHARE) | nsUseOnPage::PD_ALL)); + SetFooter( pPageDesc->GetLeftFmt(), TRUE ); + pHdFtFmt = pPageDesc->GetRightFmt(); + pSttIdx = SetFooter(pHdFtFmt, FALSE ); + break; + } + + USHORT nOldFlyArrCnt = aFlyArr.Count(); + if( !pSttIdx ) + SkipGroup(); + else + { + // es ist auf jedenfall jetzt ein TextNode im Kopf/Fusszeilen-Bereich + // vorhanden. Dieser muss jetzt nur noch gefunden und der neue Cursor + // dort hinein gesetzt werden. + SwCntntNode *pNode = pDoc->GetNodes()[ pSttIdx->GetIndex()+1 ]-> + GetCntntNode(); + + // immer ans Ende der Section einfuegen !! + pPam->GetPoint()->nNode = *pNode->EndOfSectionNode(); + pPam->Move( fnMoveBackward ); + + SwTxtFmtColl* pColl = aTxtCollTbl.Get( 0 ); + if( !pColl ) + pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + pDoc->SetTxtFmtColl( *pPam, pColl ); + + SetNewGroup( TRUE ); + + while( !( nNumOpenBrakets == GetOpenBrakets() && !GetStackPos()) && IsParserWorking() ) + { + switch( nToken = GetNextToken() ) + { + case RTF_U: + if( bDelFirstChar ) + { + bDelFirstChar = FALSE; + nToken = 0; + } + break; + + case RTF_TEXTTOKEN: + if( bDelFirstChar ) + { + if( !aToken.Erase( 0, 1 ).Len() ) + nToken = 0; + bDelFirstChar = FALSE; + } + break; + } + if( nToken ) + NextToken( nToken ); + } + + SetAllAttrOfStk(); + if( aFlyArr.Count() && bSetFlyInDoc ) + SetFlysInDoc(); + + // sollte der letze Node leer sein, dann loesche ihn + // (\par heisst ja Absatzende und nicht neuer Absatz!) + DelLastNode(); + } + + // vom FlyFmt noch die richtigen Attribute setzen + if( pTxtAttr && RES_TXTATR_FLYCNT == pTxtAttr->Which() ) + { + // is add a new fly ? + if( nOldFlyArrCnt < aFlyArr.Count() ) + { + SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ]; + pFlySave->aFlySet.ClearItem( RES_ANCHOR ); + pHdFtFmt->SetFmtAttr( pFlySave->aFlySet ); + aFlyArr.DeleteAndDestroy( aFlyArr.Count() - 1 ); + } + else + { + // no, so remove the created textattribute + SwFrmFmt* pFlyFmt = pTxtAttr->GetFlyCnt().GetFrmFmt(); + // remove the pam from the flynode + *pPam->GetPoint() = aSavePos; + pDoc->DelLayoutFmt( pFlyFmt ); + } + } + + bFootnoteAutoNum = FALSE; // default auf aus! + + // und alles wieder zurueck + *pPam->GetPoint() = aSavePos; + if (mbIsFootnote) + SetNewGroup( bOldGrpStt ); // Status wieder zurueck + else + SetNewGroup( FALSE ); // { - Klammer war kein Group-Start! + mbIsFootnote = bOldIsFootnote; + GetAttrStack().Insert( &aSaveStack, 0 ); + + aFlyArr.Insert( &aSaveArray, 0 ); + aSaveArray.Remove( 0, aSaveArray.Count() ); + bContainsPara = bContainsParaCache; +} + +void SwRTFParser::SetSwgValues( SfxItemSet& rSet ) +{ + const SfxPoolItem* pItem; + // Escapement korrigieren + if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ESCAPEMENT, FALSE, &pItem )) + { + /* prozentuale Veraenderung errechnen ! + * Formel : (FontSize * 1/20 ) pts Escapement * 2 + * ----------------------- = ---------------- + * 100% x + */ + + // die richtige + long nEsc = ((SvxEscapementItem*)pItem)->GetEsc(); + + // automatische Ausrichtung wurde schon richtig berechnet + if( DFLT_ESC_AUTO_SUPER != nEsc && DFLT_ESC_AUTO_SUB != nEsc ) + { + const SvxFontHeightItem& rFH = GetSize( rSet ); + nEsc *= 1000L; + if(rFH.GetHeight()) nEsc /= long(rFH.GetHeight()); // #i77256# + + SvxEscapementItem aEsc( (short) nEsc, + ((SvxEscapementItem*)pItem)->GetProp(), RES_CHRATR_ESCAPEMENT); + rSet.Put( aEsc ); + } + } + + // TabStops anpassen + if( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_TABSTOP, FALSE, &pItem )) + { + const SvxLRSpaceItem& rLR = GetLRSpace( rSet ); + SvxTabStopItem aTStop( *(SvxTabStopItem*)pItem ); + + long nOffset = rLR.GetTxtLeft(); + if( nOffset ) + { + // Tabs anpassen !! + SvxTabStop* pTabs = (SvxTabStop*)aTStop.GetStart(); + for( USHORT n = aTStop.Count(); n; --n, ++pTabs) + if( SVX_TAB_ADJUST_DEFAULT != pTabs->GetAdjustment() ) + pTabs->GetTabPos() -= nOffset; + + // negativer Einzug, dann auf 0 Pos einen Tab setzen + if( rLR.GetTxtFirstLineOfst() < 0 ) + aTStop.Insert( SvxTabStop() ); + } + + if( !aTStop.Count() ) + { + const SvxTabStopItem& rDflt = (const SvxTabStopItem&)rSet. + GetPool()->GetDefaultItem(RES_PARATR_TABSTOP); + if( rDflt.Count() ) + aTStop.Insert( &rDflt, 0 ); + } + rSet.Put( aTStop ); + } + else if( SFX_ITEM_SET == rSet.GetItemState( RES_LR_SPACE, FALSE, &pItem ) + && ((SvxLRSpaceItem*)pItem)->GetTxtFirstLineOfst() < 0 ) + { + // negativer Einzug, dann auf 0 Pos einen Tab setzen + rSet.Put( SvxTabStopItem( 1, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP )); + } + + // NumRules anpassen + if( !bStyleTabValid && + SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem )) + { + // dann steht im Namen nur ein Verweis in das ListArray + SwNumRule* pRule = GetNumRuleOfListNo( ((SwNumRuleItem*)pItem)-> + GetValue().ToInt32() ); + if( pRule ) + rSet.Put( SwNumRuleItem( pRule->GetName() )); + else + rSet.ClearItem( RES_PARATR_NUMRULE ); + + } + + +/* + ???????????????????????????????????????????????????????????????????? + ?? muss die LineSpacing Hoehe 200Twip betragen ?? + ?? in rtfitem.hxx wird es auf 0 defaultet. Wenn ja, dann muss hier + ?? ein neues Item gesetzt werden!!!! + ???????????????????????????????????????????????????????????????????? + + // LineSpacing korrigieren + if( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_LINESPACING, FALSE, &pItem )) + { + const SvxLineSpacingItem* pLS = (const SvxLineSpacingItem*)pItem; + SvxLineSpacingItem aNew; + + aNew.SetInterLineSpace( pLS->GetInterLineSpace() ); + aNew.GetLineSpaceRule() = pLS->GetLineSpaceRule(); + aNew.SetPropLineSpace( pLS->GetPropLineSpace() ); + aNew.GetInterLineSpaceRule() = pLS->GetInterLineSpaceRule(); + + rSet.Put( aNew ); + } +?????????????????????????????????????????????????????????????????? */ + +} + + +SwTxtFmtColl* SwRTFParser::MakeColl(const String& rName, USHORT nPos, + BYTE nOutlineLevel, bool& rbCollExist) +{ + if( BYTE(-1) == nOutlineLevel ) + //nOutlineLevel = NO_NUMBERING; + nOutlineLevel = MAXLEVEL;//#outline level,zhaojianwei + + rbCollExist = false; + SwTxtFmtColl* pColl; + String aNm( rName ); + if( !aNm.Len() ) + { + ASSERT(!this, "not a bug, but I (cmc) want to see an example of this"); + if( !nPos ) + { + pColl = pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + //pColl->SetOutlineLevel( nOutlineLevel ); //#outline level,removed by zhaojianwei + if(nOutlineLevel < MAXLEVEL ) //->add by zhaojianwei + pColl->AssignToListLevelOfOutlineStyle( nOutlineLevel ); + else + pColl->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end,zhaojianwei + return pColl; + } + + // erzeuge einen Namen + aNm.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NoName(" )); + aNm += String::CreateFromInt32( nPos ); + aNm += ')'; + } + ww::sti eSti = ww::GetCanonicalStiFromEnglishName(rName); + sw::util::ParaStyleMapper::StyleResult aResult = + maParaStyleMapper.GetStyle(rName, eSti); + pColl = aResult.first; + rbCollExist = aResult.second; + if (IsNewDoc() && rbCollExist) + { + // --> OD 2007-01-25 #i73790# - method renamed + pColl->ResetAllFmtAttr(); + // <-- + rbCollExist = false; + } + + if (!rbCollExist) + { + //pColl->SetOutlineLevel( nOutlineLevel ); //#outline level,removed by zhaojianwei + if(nOutlineLevel < MAXLEVEL) //->add by zhaojianwei + pColl->AssignToListLevelOfOutlineStyle( nOutlineLevel ); + else + pColl->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end,zhaojianwei + } + + return pColl; +} + +SwCharFmt* SwRTFParser::MakeCharFmt(const String& rName, USHORT nPos, + int& rbCollExist) +{ + rbCollExist = FALSE; + SwCharFmt* pFmt; + String aNm( rName ); + if( !aNm.Len() ) + { + ASSERT(!this, "not a bug, but I (cmc) want to see an example of this"); + aNm.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NoName(" )); + aNm += String::CreateFromInt32( nPos ); + aNm += ')'; + } + + ww::sti eSti = ww::GetCanonicalStiFromEnglishName(rName); + sw::util::CharStyleMapper::StyleResult aResult = + maCharStyleMapper.GetStyle(rName, eSti); + pFmt = aResult.first; + rbCollExist = aResult.second; + if (IsNewDoc() && rbCollExist) + { + // --> OD 2007-01-25 #i73790# - method renamed + pFmt->ResetAllFmtAttr(); + // <-- + rbCollExist = false; + } + return pFmt; +} + +void SwRTFParser::SetStyleAttr( SfxItemSet& rCollSet, + const SfxItemSet& rStyleSet, + const SfxItemSet& rDerivedSet ) +{ + rCollSet.Put( rStyleSet ); + if( rDerivedSet.Count() ) + { + // suche alle Attribute, die neu gesetzt werden: + const SfxPoolItem* pItem; + SfxItemIter aIter( rDerivedSet ); + USHORT nWhich = aIter.GetCurItem()->Which(); + while( TRUE ) + { + switch( rStyleSet.GetItemState( nWhich, FALSE, &pItem ) ) + { + case SFX_ITEM_DEFAULT: + // auf default zuruecksetzen + if( RES_FRMATR_END > nWhich ) + rCollSet.Put( rCollSet.GetPool()->GetDefaultItem( nWhich )); + break; + case SFX_ITEM_SET: + if( *pItem == *aIter.GetCurItem() ) // gleiches Attribut? + // definition kommt aus dem Parent + rCollSet.ClearItem( nWhich ); // loeschen + break; + } + + if( aIter.IsAtEnd() ) + break; + nWhich = aIter.NextItem()->Which(); + } + } + // und jetzt noch auf unsere Werte abgleichen + SetSwgValues( rCollSet ); +} + +SwTxtFmtColl* SwRTFParser::MakeStyle( USHORT nNo, const SvxRTFStyleType& rStyle) +{ + bool bCollExist; + SwTxtFmtColl* pColl = MakeColl( rStyle.sName, USHORT(nNo), + rStyle.nOutlineNo, bCollExist); + aTxtCollTbl.Insert( nNo, pColl ); + + // in bestehendes Dok einfuegen, dann keine Ableitung usw. setzen + if( bCollExist ) + return pColl; + + USHORT nStyleNo = rStyle.nBasedOn; + if( rStyle.bBasedOnIsSet && nStyleNo != nNo ) + { + SvxRTFStyleType* pDerivedStyle = GetStyleTbl().Get( nStyleNo ); + SwTxtFmtColl* pDerivedColl = aTxtCollTbl.Get( nStyleNo ); + if( !pDerivedColl ) // noch nicht vorhanden, also anlegen + { + // ist die ueberhaupt als Style vorhanden ? + pDerivedColl = pDerivedStyle + ? MakeStyle( nStyleNo, *pDerivedStyle ) + : pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + } + + if( pColl == pDerivedColl ) + ((SfxItemSet&)pColl->GetAttrSet()).Put( rStyle.aAttrSet ); + else + { + pColl->SetDerivedFrom( pDerivedColl ); + + // setze die richtigen Attribute + const SfxItemSet* pDerivedSet; + if( pDerivedStyle ) + pDerivedSet = &pDerivedStyle->aAttrSet; + else + pDerivedSet = &pDerivedColl->GetAttrSet(); + + SetStyleAttr( (SfxItemSet&)pColl->GetAttrSet(), + rStyle.aAttrSet, *pDerivedSet ); + } + } + else + ((SfxItemSet&)pColl->GetAttrSet()).Put( rStyle.aAttrSet ); + + + nStyleNo = rStyle.nNext; + if( nStyleNo != nNo ) + { + SwTxtFmtColl* pNext = aTxtCollTbl.Get( nStyleNo ); + if( !pNext ) // noch nicht vorhanden, also anlegen + { + // ist die ueberhaupt als Style vorhanden ? + SvxRTFStyleType* pMkStyle = GetStyleTbl().Get( nStyleNo ); + pNext = pMkStyle + ? MakeStyle( nStyleNo, *pMkStyle ) + : pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ); + } + pColl->SetNextTxtFmtColl( *pNext ); + } + return pColl; +} + +SwCharFmt* SwRTFParser::MakeCharStyle( USHORT nNo, const SvxRTFStyleType& rStyle ) +{ + int bCollExist; + SwCharFmt* pFmt = MakeCharFmt( rStyle.sName, USHORT(nNo), bCollExist ); + aCharFmtTbl.Insert( nNo, pFmt ); + + // in bestehendes Dok einfuegen, dann keine Ableitung usw. setzen + if( bCollExist ) + return pFmt; + + USHORT nStyleNo = rStyle.nBasedOn; + if( rStyle.bBasedOnIsSet && nStyleNo != nNo ) + { + SvxRTFStyleType* pDerivedStyle = GetStyleTbl().Get( nStyleNo ); + SwCharFmt* pDerivedFmt = aCharFmtTbl.Get( nStyleNo ); + if( !pDerivedFmt ) // noch nicht vorhanden, also anlegen + { + // ist die ueberhaupt als Style vorhanden ? + pDerivedFmt = pDerivedStyle + ? MakeCharStyle( nStyleNo, *pDerivedStyle ) + : pDoc->GetDfltCharFmt(); + } + + if( pFmt == pDerivedFmt ) + ((SfxItemSet&)pFmt->GetAttrSet()).Put( rStyle.aAttrSet ); + else + { + pFmt->SetDerivedFrom( pDerivedFmt ); + + // setze die richtigen Attribute + const SfxItemSet* pDerivedSet; + if( pDerivedStyle ) + pDerivedSet = &pDerivedStyle->aAttrSet; + else + pDerivedSet = &pDerivedFmt->GetAttrSet(); + + SetStyleAttr( (SfxItemSet&)pFmt->GetAttrSet(), + rStyle.aAttrSet, *pDerivedSet ); + } + } + else + ((SfxItemSet&)pFmt->GetAttrSet()).Put( rStyle.aAttrSet ); + + return pFmt; +} + +// loesche den letzten Node (Tabelle/Fly/Ftn/..) +void SwRTFParser::DelLastNode() +{ + // sollte der letze Node leer sein, dann loesche ihn + // (\par heisst ja Absatzende und nicht neuer Absatz!) + + if( !pPam->GetPoint()->nContent.GetIndex() ) + { + ULONG nNodeIdx = pPam->GetPoint()->nNode.GetIndex(); + SwCntntNode* pCNd = pDoc->GetNodes()[ nNodeIdx ]->GetCntntNode(); + // paragraphs with page break information are not empty! see #117914# topic 1) + if(const SfxPoolItem* pItem=&(pCNd->GetAttr( RES_PAGEDESC, FALSE))) + { + SwFmtPageDesc* pPageDescItem = ((SwFmtPageDesc*)pItem); + if (pPageDescItem->GetPageDesc()!=NULL) + return; + } + + if( pCNd && pCNd->StartOfSectionIndex()+2 < + pCNd->EndOfSectionIndex() ) + { + if( GetAttrStack().Count() ) + { + // Attribut Stack-Eintraege, muessen ans Ende des vorherigen + // Nodes verschoben werden. + BOOL bMove = FALSE; + for( USHORT n = GetAttrStack().Count(); n; ) + { + SvxRTFItemStackType* pStkEntry = (SvxRTFItemStackType*) + GetAttrStack()[ --n ]; + if( nNodeIdx == pStkEntry->GetSttNode().GetIdx() ) + { + if( !bMove ) + { + pPam->Move( fnMoveBackward ); + bMove = TRUE; + } + pStkEntry->SetStartPos( SwxPosition( pPam ) ); + } + } + if( bMove ) + pPam->Move( fnMoveForward ); + } + pPam->GetPoint()->nContent.Assign( 0, 0 ); + pPam->SetMark(); + pPam->DeleteMark(); + + pDoc->GetNodes().Delete( pPam->GetPoint()->nNode ); + } + } +} + + // fuer Tokens, die im ReadAttr nicht ausgewertet werden +void SwRTFParser::UnknownAttrToken( int nToken, SfxItemSet* pSet ) +{ + switch( nToken ) + { + case RTF_INTBL: + { + if( !pTableNode ) // Tabelle nicht mehr vorhanden ? + NewTblLine(); // evt. Line copieren + else + { + static int _do=0; //$flr See #117881# for explanation. + // Crsr nicht mehr in der Tabelle ? + if( !pPam->GetNode()->FindTableNode() && _do ) + { + ULONG nOldPos = pPam->GetPoint()->nNode.GetIndex(); + + // dann wieder in die letzte Box setzen + // (kann durch einlesen von Flys geschehen!) + pPam->GetPoint()->nNode = *pTableNode->EndOfSectionNode(); + pPam->Move( fnMoveBackward ); + + // alle Attribute, die schon auf den nachfolgen zeigen + // auf die neue Box umsetzen !! + SvxRTFItemStack& rAttrStk = GetAttrStack(); + const SvxRTFItemStackType* pStk; + for( USHORT n = 0; n < rAttrStk.Count(); ++n ) + if( ( pStk = rAttrStk[ n ])->GetSttNodeIdx() == nOldPos && + !pStk->GetSttCnt() ) + ((SvxRTFItemStackType*)pStk)->SetStartPos( SwxPosition( pPam ) ); + } + } + } + break; + + case RTF_PAGEBB: + { + pSet->Put( SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK )); + } + break; + + case RTF_PGBRK: + { + pSet->Put( SvxFmtBreakItem( 1 == nTokenValue ? + SVX_BREAK_PAGE_BOTH : SVX_BREAK_PAGE_AFTER, RES_BREAK )); + } + break; + + case RTF_PGDSCNO: + if( IsNewDoc() && bSwPageDesc && + USHORT(nTokenValue) < pDoc->GetPageDescCnt() ) + { + const SwPageDesc* pPgDsc = &const_cast<const SwDoc *>(pDoc) + ->GetPageDesc( (USHORT)nTokenValue ); + pDoc->InsertPoolItem( *pPam, SwFmtPageDesc( pPgDsc ), 0); + } + break; + case RTF_CS: + { + SwCharFmt* pFmt = aCharFmtTbl.Get( nTokenValue ); + if( pFmt ) + pSet->Put( SwFmtCharFmt( pFmt )); + } + break; + + case RTF_LS: + if( -1 != nTokenValue ) + { + if( bStyleTabValid ) + { + // dann ist auch die ListTabelle gueltig, also suche die + // enstprechende NumRule + SwNumRule* pRule = GetNumRuleOfListNo( nTokenValue ); + if( pRule ) + pSet->Put( SwNumRuleItem( pRule->GetName() )); + + if( SFX_ITEM_SET != pSet->GetItemState( FN_PARAM_NUM_LEVEL, FALSE )) + pSet->Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, 0 )); + } + else + { + // wir sind in der Style-Definitions - Phase. Der Name + // wird dann spaeter umgesetzt + //#117891# pSet->Put( SwNumRuleItem( String::CreateFromInt32( nTokenValue ))); + } + + } + break; + + case RTF_ILVL: + case RTF_SOUTLVL: + { + BYTE nLevel = MAXLEVEL <= nTokenValue ? MAXLEVEL - 1 + : BYTE( nTokenValue ); + pSet->Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, nLevel )); + } + break; + +/* + case RTF_SBYS: + case RTF_EXPND: + case RTF_KEEP: + case RTF_KEEPN: +*/ + + } +} + +void SwRTFParser::ReadInfo( const sal_Char* pChkForVerNo ) +{ +sal_Char __READONLY_DATA aChkForVerNo[] = "StarWriter"; + + // falls nicht schon was vorgegeben wurde, setzen wir unseren Namen + // rein. Wenn das im Kommentar match, wird im Parser die VersionNummer + // gelesen und gesetzt + if( !pChkForVerNo ) + pChkForVerNo = aChkForVerNo; + + SvxRTFParser::ReadInfo( pChkForVerNo ); +} + +void SwRTFParser::ReadUserProperties() +{ + // For now we don't support user properties but at least the parser is here. + // At the moment it just swallows the tokens to prevent them being displayed + int nNumOpenBrakets = 1, nToken; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( nToken = GetNextToken() ) + { + case '}': + --nNumOpenBrakets; + 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; + } + ++nNumOpenBrakets; + } + break; + + case RTF_PROPNAME: + SkipGroup(); + break; + + case RTF_PROPTYPE: + break; + + case RTF_STATICVAL: + SkipGroup(); + break; + +// default: + } + } + + SkipToken( -1 ); +} + + +#ifdef USED +void SwRTFParser::SaveState( int nToken ) +{ + SvxRTFParser::SaveState( nToken ); +} + +void SwRTFParser::RestoreState() +{ + SvxRTFParser::RestoreState(); +} +#endif + +/**/ + +BookmarkPosition::BookmarkPosition(const SwPaM &rPaM) + : maMkNode(rPaM.GetMark()->nNode), + mnMkCntnt(rPaM.GetMark()->nContent.GetIndex()) +{ +} + +BookmarkPosition::BookmarkPosition(const BookmarkPosition &rEntry) + : maMkNode(rEntry.maMkNode), mnMkCntnt(rEntry.mnMkCntnt) +{ +} + +bool BookmarkPosition::operator==(const BookmarkPosition rhs) +{ + return(maMkNode.GetIndex() == rhs.maMkNode.GetIndex() && mnMkCntnt == rhs.mnMkCntnt); +} + +ULONG SwNodeIdx::GetIdx() const +{ + return aIdx.GetIndex(); +} + +SvxNodeIdx* SwNodeIdx::Clone() const +{ + return new SwNodeIdx( aIdx ); +} + +SvxPosition* SwxPosition::Clone() const +{ + return new SwxPosition( pPam ); +} + +SvxNodeIdx* SwxPosition::MakeNodeIdx() const +{ + return new SwNodeIdx( pPam->GetPoint()->nNode ); +} + +ULONG SwxPosition::GetNodeIdx() const +{ + return pPam->GetPoint()->nNode.GetIndex(); +} + +xub_StrLen SwxPosition::GetCntIdx() const +{ + return pPam->GetPoint()->nContent.GetIndex(); +} + +/* vi:set tabstop=4 shiftwidth=4 expandtab: */ |