| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| #include <rtl/uri.hxx> |
| |
| #include <svl/urihelper.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/wrkwin.hxx> |
| #include <editeng/adjitem.hxx> |
| #include <editeng/ulspitem.hxx> |
| #include <editeng/brkitem.hxx> |
| #include <svtools/htmltokn.h> |
| #include <svtools/htmlkywd.hxx> |
| #include <sfx2/linkmgr.hxx> |
| |
| #include "hintids.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" |
| |
| #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 *) &rCntntStIdx.GetNode(); |
| 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 (aPrvNdIdx.GetNode().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; |
| } |
| |
| SwSectionData aSection( (aHRef.Len()) ? FILE_LINK_SECTION |
| : CONTENT_SECTION, aName ); |
| if( aHRef.Len() ) |
| { |
| aSection.SetLinkFileName( aHRef ); |
| aSection.SetProtectFlag(true); |
| } |
| |
| 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, 0, &aFrmItemSet, false ); |
| |
| // ggfs. einen Bereich anspringen |
| if( JUMPTO_REGION == eJumpTo && aName == sJmpMark ) |
| { |
| bChkJumpMark = sal_True; |
| eJumpTo = JUMPTO_NONE; |
| } |
| |
| SwTxtNode* pOldTxtNd = |
| (bAppended) ? 0 : pPam->GetPoint()->nNode.GetNode().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(); |
| |
| sal_uLong nPrvNxtIdx; |
| if( bHeader ) |
| { |
| nPrvNxtIdx = rCntntStIdx.GetNode().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 (aPrvNdIdx.GetNode().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 ) ); |
| SwSectionData 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, 0, &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 : pPam->GetPoint()->nNode.GetNode().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, |
| sal_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 ); |
| } |
| } |
| } |
| |