summaryrefslogtreecommitdiff
path: root/sw/source/filter/html/htmlsect.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/html/htmlsect.cxx')
-rw-r--r--sw/source/filter/html/htmlsect.cxx873
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 );
+ }
+ }
+}
+