diff options
Diffstat (limited to 'sw/source/filter/html/htmlsect.cxx')
-rw-r--r-- | sw/source/filter/html/htmlsect.cxx | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/sw/source/filter/html/htmlsect.cxx b/sw/source/filter/html/htmlsect.cxx new file mode 100644 index 000000000000..a4fb7f70ff66 --- /dev/null +++ b/sw/source/filter/html/htmlsect.cxx @@ -0,0 +1,873 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: htmlsect.cxx,v $ + * $Revision: 1.20 $ + * + * 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" + + + + +#include "hintids.hxx" + +#ifndef _APP_HXX //autogen +#include <vcl/svapp.hxx> +#endif +#ifndef _WRKWIN_HXX //autogen +#include <vcl/wrkwin.hxx> +#endif +#include <svx/adjitem.hxx> +#include <svx/ulspitem.hxx> +#include <svx/brkitem.hxx> +#include <svtools/htmltokn.h> +#ifndef _HTMLKYWD_H +#include <svtools/htmlkywd.hxx> +#endif +#include <sfx2/linkmgr.hxx> +#include <rtl/uri.hxx> +#include <fmtornt.hxx> +#include <fmthdft.hxx> +#include <fmtcntnt.hxx> +#include <fmtfsize.hxx> +#include <fmtclds.hxx> +#include <fmtanchr.hxx> +#include <fmtpdsc.hxx> +#include <fmtsrnd.hxx> +#include <fmtflcnt.hxx> +#include "frmatr.hxx" +#include "doc.hxx" +#include "pam.hxx" +#include "ndtxt.hxx" +#include "shellio.hxx" +#include "section.hxx" +#include "poolfmt.hxx" +#include "pagedesc.hxx" +#include "swtable.hxx" +#include "viewsh.hxx" +#include "swcss1.hxx" +#include "swhtml.hxx" +#include <svtools/urihelper.hxx> + +#define CONTEXT_FLAGS_MULTICOL (HTML_CNTXT_STRIP_PARA | \ + HTML_CNTXT_KEEP_NUMRULE | \ + HTML_CNTXT_KEEP_ATTRS) +//#define CONTEXT_FLAGS_HDRFTR (HTML_CNTXT_STRIP_PARA|HTML_CNTXT_PROTECT_STACK) +#define CONTEXT_FLAGS_HDRFTR (CONTEXT_FLAGS_MULTICOL) +#define CONTEXT_FLAGS_FTN (CONTEXT_FLAGS_MULTICOL) + + +using namespace ::com::sun::star; + + +/* */ + +void SwHTMLParser::NewDivision( int nToken ) +{ + String aId, aHRef, aStyle, aClass, aLang, aDir; + SvxAdjust eAdjust = HTML_CENTER_ON==nToken ? SVX_ADJUST_CENTER + : SVX_ADJUST_END; + + sal_Bool bHeader=sal_False, bFooter=sal_False; + const HTMLOptions *pHTMLOptions = GetOptions(); + for( sal_uInt16 i = pHTMLOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pHTMLOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_ID: + aId = pOption->GetString(); + break; + case HTML_O_ALIGN: + if( HTML_DIVISION_ON==nToken ) + eAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, + static_cast< sal_uInt16 >(eAdjust) ); + break; + case HTML_O_STYLE: + aStyle = pOption->GetString(); + break; + case HTML_O_CLASS: + aClass = pOption->GetString(); + break; + case HTML_O_LANG: + aLang = pOption->GetString(); + break; + case HTML_O_DIR: + aDir = pOption->GetString(); + break; + case HTML_O_HREF: + aHRef = pOption->GetString(); + break; + case HTML_O_TYPE: + { + const String& rType = pOption->GetString(); + if( rType.EqualsIgnoreCaseAscii( "HEADER" ) ) + bHeader = sal_True; + else if( rType.EqualsIgnoreCaseAscii( "FOOTER" ) ) + bFooter = sal_True; + } + } + } + + sal_Bool bAppended = sal_False; + if( pPam->GetPoint()->nContent.GetIndex() ) + { + AppendTxtNode( bHeader||bFooter||aId.Len()||aHRef.Len() ? AM_NORMAL + : AM_NOSPACE ); + bAppended = sal_True; + } + + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) ); + + sal_Bool bStyleParsed = sal_False, bPositioned = sal_False; + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) ) + { + bStyleParsed = ParseStyleOptions( aStyle, aId, aClass, + aItemSet, aPropInfo, &aLang, &aDir ); + if( bStyleParsed ) + { + bPositioned = HTML_DIVISION_ON == nToken && aClass.Len() && + CreateContainer( aClass, aItemSet, aPropInfo, + pCntxt ); + if( !bPositioned ) + bPositioned = DoPositioning( aItemSet, aPropInfo, pCntxt ); + } + } + + if( !bPositioned && (bHeader || bFooter) && IsNewDoc() ) + { + SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc(); + SwFrmFmt& rPageFmt = pPageDesc->GetMaster(); + + SwFrmFmt *pHdFtFmt; + sal_Bool bNew = sal_False; + sal_uInt16 nFlags = CONTEXT_FLAGS_HDRFTR; + if( bHeader ) + { + pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt(); + if( !pHdFtFmt ) + { + // noch keine Header, dann erzeuge einen. + rPageFmt.SetFmtAttr( SwFmtHeader( sal_True )); + pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt(); + bNew = sal_True; + } + nFlags |= HTML_CNTXT_HEADER_DIST; + } + else + { + pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt(); + if( !pHdFtFmt ) + { + // noch keine Footer, dann erzeuge einen. + rPageFmt.SetFmtAttr( SwFmtFooter( sal_True )); + pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt(); + bNew = sal_True; + } + nFlags |= HTML_CNTXT_FOOTER_DIST; + } + + const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt(); + const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx(); + SwCntntNode *pCNd; + + if( bNew ) + { + pCNd = pDoc->GetNodes()[rCntntStIdx.GetIndex()+1] + ->GetCntntNode(); + } + else + { + // Einen neuen Node zu Beginn der Section anlegen + SwNodeIndex aSttIdx( rCntntStIdx, 1 ); + pCNd = pDoc->GetNodes().MakeTxtNode( aSttIdx, + pCSS1Parser->GetTxtCollFromPool(RES_POOLCOLL_TEXT)); + + // Den bisherigen Inhalt der Section loeschen + SwPaM aDelPam( aSttIdx ); + aDelPam.SetMark(); + + const SwStartNode *pStNd = + (const SwStartNode *)pDoc->GetNodes()[rCntntStIdx]; + aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex() - 1; + + pDoc->DelFullPara( aDelPam ); + + // Die Seitenvorlage aktualisieren + for( sal_uInt16 i=0; i < pDoc->GetPageDescCnt(); i++ ) + { + if( RES_POOLPAGE_HTML==const_cast<const SwDoc *>(pDoc) + ->GetPageDesc(i).GetPoolFmtId() ) + { + pDoc->ChgPageDesc( i, *pPageDesc ); + break; + } + } + } + + SwPosition aNewPos( SwNodeIndex( rCntntStIdx, 1 ), SwIndex( pCNd, 0 ) ); + SaveDocContext( pCntxt, nFlags, &aNewPos ); + } + else if( !bPositioned && aId.Len() > 9 && + ('s' == aId.GetChar(0) || 'S' == aId.GetChar(0) ) && + ('d' == aId.GetChar(1) || 'D' == aId.GetChar(1) ) ) + { + sal_Bool bEndNote = sal_False, bFootNote = sal_False; + if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdendnote, 9 ) == COMPARE_EQUAL ) + bEndNote = sal_True; + else if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdfootnote, 10 ) == COMPARE_EQUAL ) + bFootNote = sal_True; + if( bFootNote || bEndNote ) + { + SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId ); + if( pStartNdIdx ) + { + SwCntntNode *pCNd = + pDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetCntntNode(); + SwNodeIndex aTmpSwNodeIndex = SwNodeIndex(*pCNd); + SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) ); + SaveDocContext( pCntxt, CONTEXT_FLAGS_FTN, &aNewPos ); + aId = aPropInfo.aId = aEmptyStr; + } + } + } + + // Bereiche fuegen wir in Rahmen nur dann ein, wenn der Bereich gelinkt ist. + if( (aId.Len() && !bPositioned) || aHRef.Len() ) + { + // Bereich einfuegen (muss vor dem Setzten von Attributen erfolgen, + // weil die Section vor der PaM-Position eingefuegt. + + // wenn wir im ersten Node einer Section stehen, wir die neue + // Section nicht in der aktuellen, sondern vor der aktuellen + // Section eingefuegt. Deshalb muessen wir dann einen Node + // einfuegen. UND IN LOESCHEN!!! + if( !bAppended ) + { + SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 ); + if( (pDoc->GetNodes()[aPrvNdIdx])->IsSectionNode() ) + { + AppendTxtNode(); + bAppended = sal_True; + } + } + _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs; + SetAttr( sal_True, sal_True, pPostIts ); + + // Namen der Section eindeutig machen + String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) ); + + if( aHRef.Len() ) + { + sal_Unicode cDelim = 255U; + String aURL; + xub_StrLen nPos = aHRef.SearchBackward( cDelim ); + xub_StrLen nPos2 = STRING_NOTFOUND; + if( STRING_NOTFOUND != nPos ) + { + nPos2 = aHRef.SearchBackward( cDelim, nPos ); + if( STRING_NOTFOUND != nPos2 ) + { + xub_StrLen nTmp = nPos; + nPos = nPos2; + nPos2 = nTmp; + } + } + if( STRING_NOTFOUND == nPos ) + { + aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef, Link(), false); + } + else + { + aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef.Copy( 0, nPos ), Link(), false ); + aURL += sfx2::cTokenSeperator; + if( STRING_NOTFOUND == nPos2 ) + { + aURL += aHRef.Copy( nPos+1 ); + } + else + { + aURL += aHRef.Copy( nPos+1, nPos2 - (nPos+1) ); + aURL += sfx2::cTokenSeperator; + aURL += String(rtl::Uri::decode( aHRef.Copy( nPos2+1 ), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_ISO_8859_1 )); + } + } + aHRef = aURL; + } + + SwSection aSection( aHRef.Len() ? FILE_LINK_SECTION + : CONTENT_SECTION, aName ); + if( aHRef.Len() ) + { + aSection.SetLinkFileName( aHRef ); + aSection.SetProtect(); + } + + SfxItemSet aFrmItemSet( pDoc->GetAttrPool(), + RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); + if( !IsNewDoc() ) + Reader::ResetFrmFmtAttrs(aFrmItemSet ); + + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False, + &pItem ) ) + { + aFrmItemSet.Put( *pItem ); + aItemSet.ClearItem( RES_BACKGROUND ); + } + if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False, + &pItem ) ) + { + aFrmItemSet.Put( *pItem ); + aItemSet.ClearItem( RES_FRAMEDIR ); + } + + pDoc->InsertSwSection( *pPam, aSection, &aFrmItemSet, false ); + + // ggfs. einen Bereich anspringen + if( JUMPTO_REGION == eJumpTo && aName == sJmpMark ) + { + bChkJumpMark = sal_True; + eJumpTo = JUMPTO_NONE; + } + + SwTxtNode* pOldTxtNd = + bAppended ? 0 : pDoc->GetNodes()[pPam->GetPoint()->nNode] + ->GetTxtNode(); + + pPam->Move( fnMoveBackward ); + + // PageDesc- und SwFmtBreak Attribute vom aktuellen Node in den + // (ersten) Node des Bereich verschieben. + if( pOldTxtNd ) + MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(), + sal_True ); + + if( pPostIts ) + { + // noch vorhandene PostIts in den ersten Absatz + // der Tabelle setzen + InsertAttrs( *pPostIts ); + delete pPostIts; + pPostIts = 0; + } + + pCntxt->SetSpansSection( sal_True ); + + // keine text::Bookmarks mit dem gleichen Namen wie Bereiche einfuegen + if( aPropInfo.aId.Len() && aPropInfo.aId==aName ) + aPropInfo.aId.Erase(); + } + else + { + pCntxt->SetAppendMode( AM_NOSPACE ); + } + + if( SVX_ADJUST_END != eAdjust ) + { + InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), pCntxt ); + } + + // Style parsen + if( bStyleParsed ) + InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True ); + + PushContext( pCntxt ); +} + +void SwHTMLParser::EndDivision( int /*nToken*/ ) +{ + // Stack-Eintrag zu dem Token suchen (weil wir noch den Div-Stack + // haben unterscheiden wir erst einmal nicht zwischen DIV und CENTER + _HTMLAttrContext *pCntxt = 0; + sal_uInt16 nPos = aContexts.Count(); + while( !pCntxt && nPos>nContextStMin ) + { + switch( aContexts[--nPos]->GetToken() ) + { + case HTML_CENTER_ON: + case HTML_DIVISION_ON: + pCntxt = aContexts[nPos]; + aContexts.Remove( nPos, 1 ); + break; + } + } + + if( pCntxt ) + { + // Attribute beenden + EndContext( pCntxt ); + SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen + + delete pCntxt; + } +} + +void SwHTMLParser::FixHeaderFooterDistance( sal_Bool bHeader, + const SwPosition *pOldPos ) +{ + SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc(); + SwFrmFmt& rPageFmt = pPageDesc->GetMaster(); + + SwFrmFmt *pHdFtFmt = + bHeader ? (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt() + : (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt(); + ASSERT( pHdFtFmt, "Doch keine Kopf- oder Fusszeile" ); + + const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt(); + const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx(); + + ULONG nPrvNxtIdx; + if( bHeader ) + { + nPrvNxtIdx = pDoc->GetNodes()[rCntntStIdx]->EndOfSectionIndex()-1; + } + else + { + nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1; + } + + sal_uInt16 nSpace = 0; + SwTxtNode *pTxtNode = pDoc->GetNodes()[nPrvNxtIdx]->GetTxtNode(); + if( pTxtNode ) + { + const SvxULSpaceItem& rULSpace = + ((const SvxULSpaceItem&)pTxtNode + ->SwCntntNode::GetAttr( RES_UL_SPACE )); + + // Der untere Absatz-Abstand wird zum Abstand zur + // Kopf- oder Fusszeile + nSpace = rULSpace.GetLower(); + + // und anschliessend auf einen vernuenftigen Wert + // gesetzt + const SvxULSpaceItem& rCollULSpace = + pTxtNode->GetAnyFmtColl().GetULSpace(); + if( rCollULSpace.GetUpper() == rULSpace.GetUpper() ) + pTxtNode->ResetAttr( RES_UL_SPACE ); + else + pTxtNode->SetAttr( + SvxULSpaceItem( rULSpace.GetUpper(), + rCollULSpace.GetLower(), RES_UL_SPACE ) ); + } + + if( bHeader ) + { + nPrvNxtIdx = pOldPos->nNode.GetIndex(); + } + else + { + nPrvNxtIdx = rCntntStIdx.GetIndex() + 1; + } + + pTxtNode = pDoc->GetNodes()[nPrvNxtIdx] + ->GetTxtNode(); + if( pTxtNode ) + { + const SvxULSpaceItem& rULSpace = + ((const SvxULSpaceItem&)pTxtNode + ->SwCntntNode::GetAttr( RES_UL_SPACE )); + + // Der obere Absatz-Abstand wird zum Abstand zur + // Kopf- oder Fusszeile, wenn er groesser ist als + // der untere vom Absatz davor + if( rULSpace.GetUpper() > nSpace ) + nSpace = rULSpace.GetUpper(); + + // und anschliessend auf einen vernuenftigen Wert gesetzt + const SvxULSpaceItem& rCollULSpace = + pTxtNode->GetAnyFmtColl().GetULSpace(); + if( rCollULSpace.GetLower() == rULSpace.GetLower() ) + pTxtNode->ResetAttr( RES_UL_SPACE ); + else + pTxtNode->SetAttr( + SvxULSpaceItem( rCollULSpace.GetUpper(), + rULSpace.GetLower(), RES_UL_SPACE ) ); + } + + SvxULSpaceItem aULSpace( RES_UL_SPACE ); + if( bHeader ) + aULSpace.SetLower( nSpace ); + else + aULSpace.SetUpper( nSpace ); + + pHdFtFmt->SetFmtAttr( aULSpace ); +} + +sal_Bool SwHTMLParser::EndSection( sal_Bool bLFStripped ) +{ + SwEndNode *pEndNd = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()+1] + ->GetEndNode(); + if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() ) + { + // den Bereich beenden + if( !bLFStripped ) + StripTrailingPara(); + pPam->Move( fnMoveForward ); + return sal_True; + } + + ASSERT( !this, "Falsche PaM Position Beenden eines Bereichs" ); + + return sal_False; +} + +sal_Bool SwHTMLParser::EndSections( sal_Bool bLFStripped ) +{ + sal_Bool bSectionClosed = sal_False; + sal_uInt16 nPos = aContexts.Count(); + while( nPos>nContextStMin ) + { + _HTMLAttrContext *pCntxt = aContexts[--nPos]; + if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) ) + { + bSectionClosed = sal_True; + pCntxt->SetSpansSection( sal_False ); + bLFStripped = sal_False; + } + } + + return bSectionClosed; +} + +/* */ + +void SwHTMLParser::NewMultiCol() +{ + String aId, aStyle, aClass, aLang, aDir; + long nWidth = 100; + sal_uInt16 nCols = 0, nGutter = 10; + sal_Bool bPrcWidth = sal_True; + + const HTMLOptions *pHTMLOptions = GetOptions(); + sal_uInt16 i; + + for( i = pHTMLOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pHTMLOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_ID: + aId = pOption->GetString(); + break; + case HTML_O_STYLE: + aStyle = pOption->GetString(); + break; + case HTML_O_CLASS: + aClass = pOption->GetString(); + break; + case HTML_O_LANG: + aLang = pOption->GetString(); + break; + case HTML_O_DIR: + aDir = pOption->GetString(); + break; + case HTML_O_COLS: + nCols = (sal_uInt16)pOption->GetNumber(); + break; + case HTML_O_WIDTH: + nWidth = pOption->GetNumber(); + bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND); + if( bPrcWidth && nWidth>100 ) + nWidth = 100; + break; + case HTML_O_GUTTER: + nGutter = (sal_uInt16)pOption->GetNumber(); + break; + + } + } + + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_MULTICOL_ON ); + + //.is the multicol elememt contained in a container? That may be the + // case for 5.0 documents. + sal_Bool bInCntnr = sal_False; + i = aContexts.Count(); + while( !bInCntnr && i > nContextStMin ) + bInCntnr = 0 != aContexts[--i]->GetFrmItemSet(); + + // Parse style sheets, but don't position anything by now. + sal_Bool bStyleParsed = sal_False; + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) ) + bStyleParsed = ParseStyleOptions( aStyle, aId, aClass, + aItemSet, aPropInfo, &aLang, &aDir ); + + // Calculate width. + sal_uInt8 nPrcWidth = bPrcWidth ? (sal_uInt8)nWidth : 0; + sal_uInt16 nTwipWidth = 0; + if( !bPrcWidth && nWidth && Application::GetDefaultDevice() ) + { + nTwipWidth = (sal_uInt16)Application::GetDefaultDevice() + ->PixelToLogic( Size(nWidth, 0), + MapMode(MAP_TWIP) ).Width(); + } + + if( !nPrcWidth && nTwipWidth < MINFLY ) + nTwipWidth = MINFLY; + + // Do positioning. + sal_Bool bPositioned = sal_False; + if( bInCntnr || pCSS1Parser->MayBePositioned( aPropInfo, sal_True ) ) + { + SfxItemSet aFrmItemSet( pDoc->GetAttrPool(), + RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); + if( !IsNewDoc() ) + Reader::ResetFrmFmtAttrs(aFrmItemSet ); + + SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, aItemSet, aPropInfo, + aFrmItemSet ); + + // The width is either the WIDTH attribute's value or contained + // in some style option. + SetVarSize( aItemSet, aPropInfo, aFrmItemSet, nTwipWidth, nPrcWidth ); + + SetSpace( Size(0,0), aItemSet, aPropInfo, aFrmItemSet ); + + // Set some other frame attributes. If the background is set, its + // it will be cleared here. That for, it won't be set at the section, + // too. + SetFrmFmtAttrs( aItemSet, aPropInfo, + HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_PADDING|HTML_FF_DIRECTION, + aFrmItemSet ); + + // Insert fly frame. If the are columns, the fly frame's name is not + // the sections name but a generated one. + String aFlyName( aEmptyStr ); + if( nCols < 2 ) + { + aFlyName = aId; + aPropInfo.aId.Erase(); + } + + InsertFlyFrame( aFrmItemSet, pCntxt, aFlyName, CONTEXT_FLAGS_ABSPOS ); + + pCntxt->SetPopStack( sal_True ); + bPositioned = sal_True; + } + + sal_Bool bAppended = sal_False; + if( !bPositioned ) + { + if( pPam->GetPoint()->nContent.GetIndex() ) + { + AppendTxtNode( AM_SPACE ); + bAppended = sal_True; + } + else + { + AddParSpace(); + } + } + + // If there are less then 2 columns, no section is inserted. + if( nCols >= 2 ) + { + if( !bAppended ) + { + // If the pam is at the start of a section, a additional text + // node must be inserted. Otherwise, the new section will be + // inserted in front of the old one. + SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 ); + if( (pDoc->GetNodes()[aPrvNdIdx])->IsSectionNode() ) + { + AppendTxtNode(); + bAppended = sal_True; + } + } + _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs; + SetAttr( sal_True, sal_True, pPostIts ); + + // Make section name unique. + String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) ); + SwSection aSection( CONTENT_SECTION, aName ); + + SfxItemSet aFrmItemSet( pDoc->GetAttrPool(), + RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); + if( !IsNewDoc() ) + Reader::ResetFrmFmtAttrs(aFrmItemSet ); + + if( nGutter && Application::GetDefaultDevice() ) + { + nGutter = (sal_uInt16)Application::GetDefaultDevice() + ->PixelToLogic( Size(nGutter, 0), + MapMode(MAP_TWIP) ).Width(); + } + + SwFmtCol aFmtCol; +#ifndef WIDTH_SUPPORTED_BY_SECTIONS + nPrcWidth = 100; +#endif + + aFmtCol.Init( nCols, nGutter, nPrcWidth ? USHRT_MAX : nTwipWidth ); + aFrmItemSet.Put( aFmtCol ); + + const SfxPoolItem *pItem; + if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False, + &pItem ) ) + { + aFrmItemSet.Put( *pItem ); + aItemSet.ClearItem( RES_BACKGROUND ); + } + if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False, + &pItem ) ) + { + aFrmItemSet.Put( *pItem ); + aItemSet.ClearItem( RES_FRAMEDIR ); + } + pDoc->InsertSwSection( *pPam, aSection, &aFrmItemSet, false ); + + // Jump to section, if this is requested. + if( JUMPTO_REGION == eJumpTo && aName == sJmpMark ) + { + bChkJumpMark = sal_True; + eJumpTo = JUMPTO_NONE; + } + + SwTxtNode* pOldTxtNd = + bAppended ? 0 : pDoc->GetNodes()[pPam->GetPoint()->nNode] + ->GetTxtNode(); + + pPam->Move( fnMoveBackward ); + + // Move PageDesc and SwFmtBreak attributes of the current node + // to the section's first node. + if( pOldTxtNd ) + MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(), + sal_True ); + + if( pPostIts ) + { + // Move pending PostIts into the section. + InsertAttrs( *pPostIts ); + delete pPostIts; + pPostIts = 0; + } + + pCntxt->SetSpansSection( sal_True ); + + // Insert a bookmark if its name differs from the section's name only. + if( aPropInfo.aId.Len() && aPropInfo.aId==aName ) + aPropInfo.aId.Erase(); + } + + // Additional attributes must be set as hard ones. + if( bStyleParsed ) + InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True ); + + PushContext( pCntxt ); +} + +/* */ + +void SwHTMLParser::InsertFlyFrame( const SfxItemSet& rItemSet, + _HTMLAttrContext *pCntxt, + const String& rName, + sal_uInt16 nFlags ) +{ + RndStdIds eAnchorId = + ((const SwFmtAnchor&)rItemSet.Get( RES_ANCHOR )).GetAnchorId(); + + // Den Rahmen anlegen + SwFlyFrmFmt* pFlyFmt = pDoc->MakeFlySection( eAnchorId, pPam->GetPoint(), + &rItemSet ); + // Ggf. den Namen setzen + if( rName.Len() ) + pFlyFmt->SetName( rName ); + + RegisterFlyFrm( pFlyFmt ); + + const SwFmtCntnt& rFlyCntnt = pFlyFmt->GetCntnt(); + const SwNodeIndex& rFlyCntIdx = *rFlyCntnt.GetCntntIdx(); + SwCntntNode *pCNd = pDoc->GetNodes()[rFlyCntIdx.GetIndex()+1] + ->GetCntntNode(); + + SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) ); + SaveDocContext( pCntxt, nFlags, &aNewPos ); +} + + +/* */ + +void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd, + ULONG nDestIdx, + sal_Bool bFmtBreak ) +{ + SwCntntNode* pDestCntntNd = + pDoc->GetNodes()[nDestIdx]->GetCntntNode(); + + ASSERT( pDestCntntNd, "Wieso ist das Ziel kein Content-Node?" ); + + if( pSrcNd->IsCntntNode() ) + { + SwCntntNode* pSrcCntntNd = pSrcNd->GetCntntNode(); + + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet() + .GetItemState( RES_PAGEDESC, sal_False, &pItem ) && + ((SwFmtPageDesc *)pItem)->GetPageDesc() ) + { + pDestCntntNd->SetAttr( *pItem ); + pSrcCntntNd->ResetAttr( RES_PAGEDESC ); + } + if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet() + .GetItemState( RES_BREAK, sal_False, &pItem ) ) + { + switch( ((SvxFmtBreakItem *)pItem)->GetBreak() ) + { + case SVX_BREAK_PAGE_BEFORE: + case SVX_BREAK_PAGE_AFTER: + case SVX_BREAK_PAGE_BOTH: + if( bFmtBreak ) + pDestCntntNd->SetAttr( *pItem ); + pSrcCntntNd->ResetAttr( RES_BREAK ); + default: + ; + } + } + } + else if( pSrcNd->IsTableNode() ) + { + SwFrmFmt *pFrmFmt = pSrcNd->GetTableNode()->GetTable().GetFrmFmt(); + + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pFrmFmt->GetAttrSet(). + GetItemState( RES_PAGEDESC, sal_False, &pItem ) ) + { + pDestCntntNd->SetAttr( *pItem ); + pFrmFmt->ResetFmtAttr( RES_PAGEDESC ); + } + } +} + |