/************************************************************** * * 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 "hintids.hxx" #include #include #include #include #include #include #include "doc.hxx" #include "pam.hxx" #include "ndtxt.hxx" #include "shellio.hxx" #include "paratr.hxx" #include "htmlnum.hxx" #include "css1kywd.hxx" #include "swcss1.hxx" #include "swhtml.hxx" using namespace ::com::sun::star; /* */ class _HTMLAttrContext_SaveDoc { SwHTMLNumRuleInfo aNumRuleInfo; // In Umgebung gueltige Numerierung SwPosition *pPos; // hierhin beim verlassen den // Kontexts zurueckgesprungen _HTMLAttrTable *pAttrTab; // In Umgebung gueltige Attribute, // wenn Attributierung nicht // beibehalten werden soll. sal_uInt16 nContextStMin; // In Umgebung gueltige Stack- // Untergrenze, wenn der Stack // geschuetzt werden soll. sal_uInt16 nContextStAttrMin; // In Umgebung gueltige Stack- // Untergrenze, wenn die Attribute // nicht beibehalten werden sollen. sal_Bool bStripTrailingPara : 1; // letzen Absatz entfernen? sal_Bool bKeepNumRules : 1; // Numerierung beibehalten? sal_Bool bPopStack : 1; // Stack-Elemente oberhalb des // zu schliessenden entfernen? sal_Bool bFixHeaderDist : 1; sal_Bool bFixFooterDist : 1; public: _HTMLAttrContext_SaveDoc() : pPos( 0 ), pAttrTab( 0 ), nContextStMin( USHRT_MAX ), nContextStAttrMin( USHRT_MAX ), bStripTrailingPara( sal_False ), bKeepNumRules( sal_False ), bPopStack( sal_False ), bFixHeaderDist( sal_False ), bFixFooterDist( sal_False ) {} ~_HTMLAttrContext_SaveDoc() { delete pPos; delete pAttrTab; } // Die Position gehoert uns, muss also angelegt und zerstoert werden void SetPos( const SwPosition& rPos ) { pPos = new SwPosition(rPos); } const SwPosition *GetPos() const { return pPos; } // Der Index gehoert uns nicht. Kein Anlgen und Zerstoeren. void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); } const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; } _HTMLAttrTable *GetAttrTab( sal_Bool bCreate= sal_False ); void SetContextStMin( sal_uInt16 nMin ) { nContextStMin = nMin; } sal_uInt16 GetContextStMin() const { return nContextStMin; } void SetContextStAttrMin( sal_uInt16 nMin ) { nContextStAttrMin = nMin; } sal_uInt16 GetContextStAttrMin() const { return nContextStAttrMin; } void SetStripTrailingPara( sal_Bool bSet ) { bStripTrailingPara = bSet; } sal_Bool GetStripTrailingPara() const { return bStripTrailingPara; } void SetKeepNumRules( sal_Bool bSet ) { bKeepNumRules = bSet; } sal_Bool GetKeepNumRules() const { return bKeepNumRules; } void SetFixHeaderDist( sal_Bool bSet ) { bFixHeaderDist = bSet; } sal_Bool GetFixHeaderDist() const { return bFixHeaderDist; } void SetFixFooterDist( sal_Bool bSet ) { bFixFooterDist = bSet; } sal_Bool GetFixFooterDist() const { return bFixFooterDist; } }; _HTMLAttrTable *_HTMLAttrContext_SaveDoc::GetAttrTab( sal_Bool bCreate ) { if( !pAttrTab && bCreate ) { pAttrTab = new _HTMLAttrTable; memset( pAttrTab, 0, sizeof( _HTMLAttrTable )); } return pAttrTab; } /* */ _HTMLAttrContext_SaveDoc *_HTMLAttrContext::GetSaveDocContext( sal_Bool bCreate ) { if( !pSaveDocContext && bCreate ) pSaveDocContext = new _HTMLAttrContext_SaveDoc; return pSaveDocContext; } void _HTMLAttrContext::ClearSaveDocContext() { delete pSaveDocContext; pSaveDocContext = 0; } /* */ void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos ) { // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!! ASSERT( !aParaAttrs.Count(), "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" ); if( aParaAttrs.Count() ) aParaAttrs.Remove( 0, aParaAttrs.Count() ); const SwNodeIndex* pOldEndPara = &pPam->GetPoint()->nNode; xub_StrLen nOldEndCnt = pPam->GetPoint()->nContent.GetIndex(); const SwNodeIndex& rNewSttPara = rNewPos.nNode; xub_StrLen nNewSttCnt = rNewPos.nContent.GetIndex(); sal_Bool bMoveBack = sal_False; // alle noch offenen Attribute beenden und hinter der Tabelle // neu aufspannen _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab; for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* ); nCnt--; ++pTbl ) { _HTMLAttr *pAttr = *pTbl; while( pAttr ) { _HTMLAttr *pNext = pAttr->GetNext(); _HTMLAttr *pPrev = pAttr->GetPrev(); sal_uInt16 nWhich = pAttr->pItem->Which(); if( !nOldEndCnt && RES_PARATR_BEGIN <= nWhich && pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() ) { // Das Attribut muss eine Content-Position weiter vorne // beendet werden if( !bMoveBack ) { bMoveBack = pPam->Move( fnMoveBackward ); nOldEndCnt = pPam->GetPoint()->nContent.GetIndex(); } } else if( bMoveBack ) { pPam->Move( fnMoveForward ); nOldEndCnt = pPam->GetPoint()->nContent.GetIndex(); } if( (RES_PARATR_BEGIN <= nWhich && bMoveBack) || pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() || (pAttr->GetSttPara() == *pOldEndPara && pAttr->GetSttCnt() != nOldEndCnt) ) { // Das Attribut muss gesetzt werden. Da wir // das Original noch brauchen, weil Zeiger auf das Attribut // noch in den Kontexten existieren, muessen wir es clonen. // Die Next-Liste geht dabei verloren, aber die // Previous-Liste bleibt erhalten _HTMLAttr *pSetAttr = pAttr->Clone( *pOldEndPara, nOldEndCnt ); if( pNext ) pNext->InsertPrev( pSetAttr ); else { sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0 : aSetAttrTab.Count(); aSetAttrTab.Insert( pSetAttr, nTmp ); } } else if( pPrev ) { // Wenn das Attribut nicht gesetzt vor der Tabelle // gesetzt werden muss, muessen der Previous-Attribute // trotzdem gesetzt werden. if( pNext ) pNext->InsertPrev( pPrev ); else { sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count(); aSetAttrTab.Insert( pPrev, nTmp ); } } // den Start des Attributs neu setzen pAttr->nSttPara = rNewSttPara; pAttr->nEndPara = rNewSttPara; pAttr->nSttCntnt = nNewSttCnt; pAttr->nEndCntnt = nNewSttCnt; pAttr->pPrev = 0; pAttr = pNext; } } if( bMoveBack ) pPam->Move( fnMoveForward ); } void SwHTMLParser::SaveDocContext( _HTMLAttrContext *pCntxt, sal_uInt16 nFlags, const SwPosition *pNewPos ) { _HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext( sal_True ); pSave->SetStripTrailingPara( (HTML_CNTXT_STRIP_PARA & nFlags) != 0 ); pSave->SetKeepNumRules( (HTML_CNTXT_KEEP_NUMRULE & nFlags) != 0 ); pSave->SetFixHeaderDist( (HTML_CNTXT_HEADER_DIST & nFlags) != 0 ); pSave->SetFixFooterDist( (HTML_CNTXT_FOOTER_DIST & nFlags) != 0 ); if( pNewPos ) { // Wenn der PaM an eine andere Position gesetzt wird, muss // die Numerierung gerettet werden.. if( !pSave->GetKeepNumRules() ) { // Die Numerierung soll nicht beibehalten werden. Also muss // der aktuelle Zustand gerettet und die Numerierung // anschliessend ausgeschaltet werden. pSave->SetNumInfo( GetNumInfo() ); GetNumInfo().Clear(); } if( (HTML_CNTXT_KEEP_ATTRS & nFlags) != 0 ) { // Attribute an aktueller Position beenden und an neuer neu anfangen SplitAttrTab( *pNewPos ); } else { _HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab( sal_True ); SaveAttrTab( *pSaveAttrTab ); } pSave->SetPos( *pPam->GetPoint() ); *pPam->GetPoint() = *pNewPos; } // Mit dem Setzen von nContextStMin koennen automatisch auch // keine gerade offenen Listen (DL/OL/UL) mehr beendet werden. if( (HTML_CNTXT_PROTECT_STACK & nFlags) != 0 ) { pSave->SetContextStMin( nContextStMin ); nContextStMin = aContexts.Count(); if( (HTML_CNTXT_KEEP_ATTRS & nFlags) == 0 ) { pSave->SetContextStAttrMin( nContextStAttrMin ); nContextStAttrMin = aContexts.Count(); } } } void SwHTMLParser::RestoreDocContext( _HTMLAttrContext *pCntxt ) { _HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext(); if( !pSave ) return; if( pSave->GetStripTrailingPara() ) StripTrailingPara(); if( pSave->GetPos() ) { if( pSave->GetFixHeaderDist() || pSave->GetFixFooterDist() ) FixHeaderFooterDistance( pSave->GetFixHeaderDist(), pSave->GetPos() ); _HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab(); if( !pSaveAttrTab ) { // Attribute an aktueller Position beenden und an alter neu // anfangen. SplitAttrTab( *pSave->GetPos() ); } else { RestoreAttrTab( *pSaveAttrTab ); } *pPam->GetPoint() = *pSave->GetPos(); // Die bisherigen Attribute koennen wir schonmal setzen. SetAttr(); } if( USHRT_MAX != pSave->GetContextStMin() ) { nContextStMin = pSave->GetContextStMin(); if( USHRT_MAX != pSave->GetContextStAttrMin() ) nContextStAttrMin = pSave->GetContextStAttrMin(); } if( !pSave->GetKeepNumRules() ) { // Die bisherige gemerkte Numerierung wieder setzen GetNumInfo().Set( pSave->GetNumInfo() ); } pCntxt->ClearSaveDocContext(); } /* */ void SwHTMLParser::EndContext( _HTMLAttrContext *pContext ) { if( pContext->GetPopStack() ) { // Alle noch offenen Kontexte beenden. Der eigene // Kontext muss bereits geloscht sein! while( aContexts.Count() > nContextStMin ) { _HTMLAttrContext *pCntxt = PopContext(); ASSERT( pCntxt != pContext, "Kontext noch im Stack" ); if( pCntxt == pContext ) break; EndContext( pCntxt ); delete pCntxt; } } // Alle noch offenen Attribute beenden if( pContext->HasAttrs() ) EndContextAttrs( pContext ); // Falls ein Bereich geoeffnet wurde, den verlassen. Da Bereiche // auch innerhalb von absolut positionierten Objekten angelegt werden, // muss das passieren, bever ein alter Dokument-Kontext restauriert wird. if( pContext->GetSpansSection() ) EndSection(); // Rahmen und sonstige Sonderbereiche verlassen. if( pContext->HasSaveDocContext() ) RestoreDocContext( pContext ); // Ggf. noch einen Ansatz-Umbruch einfuegen if( AM_NONE != pContext->GetAppendMode() && pPam->GetPoint()->nContent.GetIndex() ) AppendTxtNode( pContext->GetAppendMode() ); // PRE-/LISTING- und XMP-Umgebungen wieder starten if( pContext->IsFinishPREListingXMP() ) FinishPREListingXMP(); if( pContext->IsRestartPRE() ) StartPRE(); if( pContext->IsRestartXMP() ) StartXMP(); if( pContext->IsRestartListing() ) StartListing(); } void SwHTMLParser::ClearContext( _HTMLAttrContext *pContext ) { _HTMLAttrs &rAttrs = pContext->GetAttrs(); for( sal_uInt16 i=0; iGetSpansSection(), "Bereich kann nicht mehr verlassen werden" ); ASSERT( !pContext->HasSaveDocContext(), "Rahmen kann nicht mehr verlassen werden" ); // PRE-/LISTING- und XMP-Umgebungen wieder starten if( pContext->IsFinishPREListingXMP() ) FinishPREListingXMP(); if( pContext->IsRestartPRE() ) StartPRE(); if( pContext->IsRestartXMP() ) StartXMP(); if( pContext->IsRestartListing() ) StartListing(); } /* */ sal_Bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, _HTMLAttrContext *pContext ) { sal_Bool bRet = sal_False; // Unter folgenden Umstaenden wird jetzt ein Rahmen aufgemacht: // - das Tag wird absolut positioniert und left/top sind beide // gegeben und enthalten auch keine %-Angabe, oder // - das Tag soll fliessen, und // - es wurde eine Breite angegeben (in beiden Faellen noetig) if( SwCSS1Parser::MayBePositioned( rPropInfo ) ) { SfxItemSet aFrmItemSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); if( !IsNewDoc() ) Reader::ResetFrmFmtAttrs(aFrmItemSet ); // Ausrichtung setzen SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, rItemSet, rPropInfo, aFrmItemSet ); // Groesse setzen SetVarSize( rItemSet, rPropInfo, aFrmItemSet ); // Abstaende setzen SetSpace( Size(0,0), rItemSet, rPropInfo, aFrmItemSet ); // Sonstige CSS1-Attribute Setzen SetFrmFmtAttrs( rItemSet, rPropInfo, HTML_FF_BOX|HTML_FF_PADDING|HTML_FF_BACKGROUND|HTML_FF_DIRECTION, aFrmItemSet ); InsertFlyFrame( aFrmItemSet, pContext, rPropInfo.aId, CONTEXT_FLAGS_ABSPOS ); pContext->SetPopStack( sal_True ); rPropInfo.aId.Erase(); bRet = sal_True; } return bRet; } sal_Bool SwHTMLParser::CreateContainer( const String& rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, _HTMLAttrContext *pContext ) { sal_Bool bRet = sal_False; if( rClass.EqualsIgnoreCaseAscii(sCSS1_class_abs_pos) && pCSS1Parser->MayBePositioned( rPropInfo ) ) { // Container-Klasse SfxItemSet *pFrmItemSet = pContext->GetFrmItemSet( pDoc ); if( !IsNewDoc() ) Reader::ResetFrmFmtAttrs( *pFrmItemSet ); SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, rItemSet, rPropInfo, *pFrmItemSet ); Size aDummy(0,0); SetFixSize( aDummy, aDummy, sal_False, sal_False, rItemSet, rPropInfo, *pFrmItemSet ); SetSpace( aDummy, rItemSet, rPropInfo, *pFrmItemSet ); SetFrmFmtAttrs( rItemSet, rPropInfo, HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_DIRECTION, *pFrmItemSet ); bRet = sal_True; } return bRet; } /* */ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, _HTMLAttrContext *pContext, sal_Bool bCharLvl ) { // Ein DropCap-Attribut basteln, wenn auf Zeichen-Ebene vor dem // ersten Zeichen ein float: left vorkommt if( bCharLvl && !pPam->GetPoint()->nContent.GetIndex() && SVX_ADJUST_LEFT == rPropInfo.eFloat ) { SwFmtDrop aDrop; aDrop.GetChars() = 1; pCSS1Parser->FillDropCap( aDrop, rItemSet ); // Nur wenn das Initial auch ueber mehrere Zeilen geht, wird das // DropCap-Attribut gesetzt. Sonst setzten wir die Attribute hart. if( aDrop.GetLines() > 1 ) { NewAttr( &aAttrTab.pDropCap, aDrop ); _HTMLAttrs &rAttrs = pContext->GetAttrs(); rAttrs.Insert( aAttrTab.pDropCap, rAttrs.Count() ); return; } } // Feature: PrintExt if( !bCharLvl ) pCSS1Parser->SetFmtBreak( rItemSet, rPropInfo ); // /Feature: PrintExt ASSERT( aContexts.Count() <= nContextStAttrMin || aContexts[aContexts.Count()-1] != pContext, "SwHTMLParser::InsertAttrs: Kontext doch schon auf dem Stack" ); SfxItemIter aIter( rItemSet ); const SfxPoolItem *pItem = aIter.FirstItem(); while( pItem ) { _HTMLAttr **ppAttr = 0; switch( pItem->Which() ) { case RES_LR_SPACE: { // Absatz-Einzuege muessen addiert werden und werden immer // nur absatzweise gesetzt (fuer den ersten Absatz hier, // fuer alle folgenden in SetTxtCollAttrs) const SvxLRSpaceItem *pLRItem = (const SvxLRSpaceItem *)pItem; // die bisherigen Absatz-Abstaende holen (ohne die vom // obersten Kontext, denn den veraendern wir ja gerade) ... sal_uInt16 nOldLeft = 0, nOldRight = 0; short nOldIndent = 0; sal_Bool bIgnoreTop = aContexts.Count() > nContextStMin && aContexts[aContexts.Count()-1] == pContext; GetMarginsFromContext( nOldLeft, nOldRight, nOldIndent, bIgnoreTop ); // und noch die aktuell gueltigen sal_uInt16 nLeft = nOldLeft, nRight = nOldRight; short nIndent = nOldIndent; pContext->GetMargins( nLeft, nRight, nIndent ); // ... und die neuen Abstaende zu den alten addieren // Hier werden nicht die aus dem Item genommen, sondern die // extra gemerkten, weil die auch negativ sein koennen. Die // Abfrage ueber das Item funktioniert aber trotzdem, denn // fuer negative Werte wird das Item (mit Wert 0) auch // eingefuegt. if( rPropInfo.bLeftMargin ) { ASSERT( rPropInfo.nLeftMargin < 0 || rPropInfo.nLeftMargin == pLRItem->GetTxtLeft(), "linker Abstand stimmt nicht mit Item ueberein" ); if( rPropInfo.nLeftMargin < 0 && -rPropInfo.nLeftMargin > nOldLeft ) nLeft = 0; else nLeft = nOldLeft + static_cast< sal_uInt16 >(rPropInfo.nLeftMargin); } if( rPropInfo.bRightMargin ) { ASSERT( rPropInfo.nRightMargin < 0 || rPropInfo.nRightMargin == pLRItem->GetRight(), "rechter Abstand stimmt nicht mit Item ueberein" ); if( rPropInfo.nRightMargin < 0 && -rPropInfo.nRightMargin > nOldRight ) nRight = 0; else nRight = nOldRight + static_cast< sal_uInt16 >(rPropInfo.nRightMargin); } if( rPropInfo.bTextIndent ) nIndent = pLRItem->GetTxtFirstLineOfst(); // und die Werte fuer nachfolgende Absaetze merken pContext->SetMargins( nLeft, nRight, nIndent ); // das Attribut noch am aktuellen Absatz setzen SvxLRSpaceItem aLRItem( *pLRItem ); aLRItem.SetTxtFirstLineOfst( nIndent ); aLRItem.SetTxtLeft( nLeft ); aLRItem.SetRight( nRight ); NewAttr( &aAttrTab.pLRSpace, aLRItem ); EndAttr( aAttrTab.pLRSpace, 0, sal_False ); } break; case RES_UL_SPACE: if( !rPropInfo.bTopMargin || !rPropInfo.bBottomMargin ) { sal_uInt16 nUpper = 0, nLower = 0; GetULSpaceFromContext( nUpper, nLower ); SvxULSpaceItem aULSpace( *((const SvxULSpaceItem *)pItem) ); if( !rPropInfo.bTopMargin ) aULSpace.SetUpper( nUpper ); if( !rPropInfo.bBottomMargin ) aULSpace.SetLower( nLower ); NewAttr( &aAttrTab.pULSpace, aULSpace ); // ... und noch die Kontext-Information speichern _HTMLAttrs &rAttrs = pContext->GetAttrs(); rAttrs.Insert( aAttrTab.pULSpace, rAttrs.Count() ); pContext->SetULSpace( aULSpace.GetUpper(), aULSpace.GetLower() ); } else { ppAttr = &aAttrTab.pULSpace; } break; case RES_CHRATR_FONTSIZE: // es werden keine Attribute mit %-Angaben gesetzt if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 ) ppAttr = &aAttrTab.pFontHeight; break; case RES_CHRATR_CJK_FONTSIZE: // es werden keine Attribute mit %-Angaben gesetzt if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 ) ppAttr = &aAttrTab.pFontHeightCJK; break; case RES_CHRATR_CTL_FONTSIZE: // es werden keine Attribute mit %-Angaben gesetzt if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 ) ppAttr = &aAttrTab.pFontHeightCTL; break; case RES_BACKGROUND: if( bCharLvl ) { // das Frame-Attr ggf. in ein Char-Attr umwandeln SvxBrushItem aBrushItem( *(const SvxBrushItem *)pItem ); aBrushItem.SetWhich( RES_CHRATR_BACKGROUND ); // Das Attribut setzen ... NewAttr( &aAttrTab.pCharBrush, aBrushItem ); // ... und noch die Kontext-Information speichern _HTMLAttrs &rAttrs = pContext->GetAttrs(); rAttrs.Insert( aAttrTab.pCharBrush, rAttrs.Count() ); } else if( pContext->GetToken() != HTML_TABLEHEADER_ON && pContext->GetToken() != HTML_TABLEDATA_ON ) { ppAttr = &aAttrTab.pBrush; } break; default: // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ... ppAttr = GetAttrTabEntry( pItem->Which() ); break; } if( ppAttr ) { // Das Attribut setzen ... NewAttr( ppAttr, *pItem ); // ... und noch die Kontext-Information speichern _HTMLAttrs &rAttrs = pContext->GetAttrs(); rAttrs.Insert( *ppAttr, rAttrs.Count() ); } // auf zum naechsten Item pItem = aIter.NextItem(); } if( rPropInfo.aId.Len() ) InsertBookmark( rPropInfo.aId ); } void SwHTMLParser::InsertAttr( _HTMLAttr **ppAttr, const SfxPoolItem & rItem, _HTMLAttrContext *pCntxt ) { if( !ppAttr ) { ppAttr = GetAttrTabEntry( rItem.Which() ); if( !ppAttr ) return; } // das Attribut setzen NewAttr( ppAttr, rItem ); // und im Kontext merken _HTMLAttrs &rAttrs = pCntxt->GetAttrs(); rAttrs.Insert( *ppAttr, rAttrs.Count() ); } void SwHTMLParser::SplitPREListingXMP( _HTMLAttrContext *pCntxt ) { // PRE/Listing/XMP soll beim beenden des Kontexts beendet werden. pCntxt->SetFinishPREListingXMP( sal_True ); // Und die jetzt gueltigen Flags sollen wieder gesetzt werden. if( IsReadPRE() ) pCntxt->SetRestartPRE( sal_True ); if( IsReadXMP() ) pCntxt->SetRestartXMP( sal_True ); if( IsReadListing() ) pCntxt->SetRestartListing( sal_True ); // PRE/Listing/XMP wird auuserdem sofort beendet FinishPREListingXMP(); } SfxItemSet *_HTMLAttrContext::GetFrmItemSet( SwDoc *pCreateDoc ) { if( !pFrmItemSet && pCreateDoc ) pFrmItemSet = new SfxItemSet( pCreateDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); return pFrmItemSet; }