summaryrefslogtreecommitdiff
path: root/sw/source/filter/html/swhtml.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/html/swhtml.cxx')
-rw-r--r--sw/source/filter/html/swhtml.cxx5513
1 files changed, 5513 insertions, 0 deletions
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
new file mode 100644
index 000000000000..05cb2a22ec71
--- /dev/null
+++ b/sw/source/filter/html/swhtml.cxx
@@ -0,0 +1,5513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <sfx2/sfx.hrc>
+#include <svx/svxids.hrc>
+#if OSL_DEBUG_LEVEL > 1
+#include <stdlib.h>
+#endif
+#include <hintids.hxx>
+
+#define _SVSTDARR_STRINGS
+#include <svl/svstdarr.hxx>
+#include <svl/stritem.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/htmltokn.h>
+#include <svtools/htmlkywd.hxx>
+#include <svtools/ctrltool.hxx>
+#include <unotools/pathoptions.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfx2/docfile.hxx>
+
+#include <svtools/htmlcfg.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/flstitem.hxx>
+
+
+#include <frmatr.hxx>
+#include <charatr.hxx>
+#include <fmtfld.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfld.hxx>
+#include <fmtanchr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtfsize.hxx>
+#include <fmtclds.hxx>
+#include <fchrfmt.hxx>
+#include <fmtinfmt.hxx>
+#include <docary.hxx>
+#include <docstat.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <mdiexp.hxx> // ...Percent()
+#include <expfld.hxx>
+#include <poolfmt.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx> // fuer SwBookmark ...
+#include <docsh.hxx>
+#include <editsh.hxx> // fuer Start/EndAction
+#include <docufld.hxx>
+#include <swcss1.hxx>
+#include <htmlvsh.hxx>
+#include <fltini.hxx>
+#include <htmltbl.hxx>
+#include <htmlnum.hxx>
+#include <swhtml.hxx>
+#include <linkenum.hxx>
+#include <breakit.hxx>
+#include <SwAppletImpl.hxx>
+
+#include <sfx2/viewfrm.hxx>
+
+#include <statstr.hrc> // ResId fuer Statusleiste
+#include <swerror.h>
+
+#define FONTSIZE_MASK 7
+#define FONTCOLOR_MASK (1<<15)
+#define FONT_MASK (1<<14)
+
+#define HTML_ESC_PROP 80
+#define HTML_ESC_SUPER DFLT_ESC_SUPER
+#define HTML_ESC_SUB DFLT_ESC_SUB
+
+#define HTML_SPTYPE_NONE 0
+#define HTML_SPTYPE_BLOCK 1
+#define HTML_SPTYPE_HORI 2
+#define HTML_SPTYPE_VERT 3
+
+#ifndef TOOLS_CONSTASCII_STRINGPARAM
+#define TOOLS_CONSTASCII_STRINGPARAM( constAsciiStr ) constAsciiStr, sizeof( constAsciiStr )-1
+#endif
+
+using editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+
+// <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw.
+HTMLOptionEnum aHTMLPAlignTable[] =
+{
+ { OOO_STRING_SVTOOLS_HTML_AL_left, SVX_ADJUST_LEFT },
+ { OOO_STRING_SVTOOLS_HTML_AL_center, SVX_ADJUST_CENTER },
+ { OOO_STRING_SVTOOLS_HTML_AL_middle, SVX_ADJUST_CENTER }, // Netscape
+ { OOO_STRING_SVTOOLS_HTML_AL_right, SVX_ADJUST_RIGHT },
+ { OOO_STRING_SVTOOLS_HTML_AL_justify, SVX_ADJUST_BLOCK },
+ { OOO_STRING_SVTOOLS_HTML_AL_char, SVX_ADJUST_LEFT },
+ { 0, 0 }
+};
+
+// <SPACER TYPE=...>
+static HTMLOptionEnum aHTMLSpacerTypeTable[] =
+{
+ { OOO_STRING_SVTOOLS_HTML_SPTYPE_block, HTML_SPTYPE_BLOCK },
+ { OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal, HTML_SPTYPE_HORI },
+ { OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical, HTML_SPTYPE_VERT },
+ { 0, 0 }
+};
+
+SV_IMPL_PTRARR( _HTMLAttrs, _HTMLAttrPtr )
+
+HTMLReader::HTMLReader()
+{
+ bTmplBrowseMode = sal_True;
+}
+
+String HTMLReader::GetTemplateName() const
+{
+ String sTemplate(
+ String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("internal")) );
+ sTemplate += INET_PATH_TOKEN;
+ sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("html") );
+ String sTemplateWithoutExt( sTemplate );
+#ifndef MAC_WITHOUT_EXT
+ // first search for OpenDocument Writer/Web template
+ sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".oth") );
+#endif
+
+ SvtPathOptions aPathOpt;
+ // OpenDocument Writer/Web template (extension .oth)
+ sal_Bool bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
+
+#ifndef MAC_WITHOUT_EXT
+ if( !bSet )
+ {
+ // 6.0 (extension .stw)
+ sTemplate = sTemplateWithoutExt;
+ // no OpenDocument Writer/Web template found.
+ // search for OpenOffice.org Writer/Web template
+ sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".stw") );
+ // <--
+ bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
+ }
+#endif
+
+ if( !bSet )
+ {
+ sTemplate.Erase();
+ OSL_ENSURE( !this,
+ "Die html.vor befindet sich nicht mehr im definierten Directory!");
+ }
+
+ return sTemplate;
+}
+
+int HTMLReader::SetStrmStgPtr()
+{
+ OSL_ENSURE( pMedium, "Wo ist das Medium??" );
+
+ if( pMedium->IsRemote() || !pMedium->IsStorage() )
+ {
+ pStrm = pMedium->GetInStream();
+ return sal_True;
+ }
+ return sal_False;
+
+}
+
+ // Aufruf fuer die allg. Reader-Schnittstelle
+sal_uLong HTMLReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & rName )
+{
+ if( !pStrm )
+ {
+ OSL_ENSURE( pStrm, "HTML-Read ohne Stream" );
+ return ERR_SWG_READ_ERROR;
+ }
+
+ if( !bInsertMode )
+ {
+ Reader::SetNoOutlineNum( rDoc );
+ Reader::ResetFrmFmts( rDoc );
+
+ // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist,
+ // sonst ist sie schon gesetzt.
+ if( !rDoc.get(IDocumentSettingAccess::HTML_MODE) )
+ {
+ rDoc.InsertPoolItem( rPam, SwFmtPageDesc(
+ rDoc.GetPageDescFromPool( RES_POOLPAGE_HTML, false )), 0 );
+ }
+ }
+
+ // damit keiner das Doc klaut!
+ rDoc.acquire();
+ sal_uLong nRet = 0;
+ SvParserRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm,
+ rName, rBaseURL, !bInsertMode, pMedium,
+ IsReadUTF8(),
+ bIgnoreHTMLComments );
+
+ SvParserState eState = xParser->CallParser();
+
+ if( SVPAR_PENDING == eState )
+ pStrm->ResetError();
+ else if( SVPAR_ACCEPTED != eState )
+ {
+ String sErr( String::CreateFromInt32((sal_Int32)xParser->GetLineNr()));
+ sErr += ',';
+ sErr += String::CreateFromInt32((sal_Int32)xParser->GetLinePos());
+
+ // den Stream als Fehlernummer Transporter benutzen
+ nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr,
+ ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR );
+ }
+
+
+ return nRet;
+}
+
+
+/* */
+
+SwHTMLParser::SwHTMLParser( SwDoc* pD, const SwPaM& rCrsr, SvStream& rIn,
+ const String& rPath,
+ const String& rBaseURL,
+ int bReadNewDoc,
+ SfxMedium* pMed, sal_Bool bReadUTF8,
+ sal_Bool bNoHTMLComments )
+ : SfxHTMLParser( rIn, static_cast< sal_Bool >(bReadNewDoc), pMed ),
+ SwClient( 0 ),
+ aPathToFile( rPath ),
+ sBaseURL( rBaseURL ),
+ pAppletImpl( 0 ),
+ pCSS1Parser( 0 ),
+ pNumRuleInfo( new SwHTMLNumRuleInfo ),
+ pPendStack( 0 ),
+ pDoc( pD ),
+ pActionViewShell( 0 ),
+ pSttNdIdx( 0 ),
+ pTable(0),
+ pFormImpl( 0 ),
+ pMarquee( 0 ),
+ pField( 0 ),
+ pImageMap( 0 ),
+ pImageMaps( 0 ),
+ pFootEndNoteImpl( 0 ),
+ nScriptStartLineNr( 0 ),
+ nBaseFontStMin( 0 ),
+ nFontStMin( 0 ),
+ nDefListDeep( 0 ),
+ nFontStHeadStart( 0 ),
+ nSBModuleCnt( 0 ),
+ nMissingImgMaps( 0 ),
+ nParaCnt( 5 ),
+ // #i83625#
+ nContextStMin( 0 ),
+ nContextStAttrMin( 0 ),
+ // <--
+ nOpenParaToken( 0 ),
+ eJumpTo( JUMPTO_NONE ),
+#if OSL_DEBUG_LEVEL > 1
+ nContinue( 0 ),
+#endif
+ eParaAdjust( SVX_ADJUST_END ),
+ bDocInitalized( sal_False ),
+ bSetModEnabled( sal_False ),
+ bInFloatingFrame( sal_False ),
+ bInField( sal_False ),
+ bCallNextToken( sal_False ),
+ bIgnoreRawData( sal_False ),
+ bNoParSpace( sal_False ),
+ bInNoEmbed( sal_False ),
+ bInTitle( sal_False ),
+ bUpdateDocStat( sal_False ),
+ bFixSelectWidth( sal_False ),
+ bFixSelectHeight( sal_False ),
+ bTextArea( sal_False ),
+ bSelect( sal_False ),
+ bInFootEndNoteAnchor( sal_False ),
+ bInFootEndNoteSymbol( sal_False ),
+ bIgnoreHTMLComments( bNoHTMLComments ),
+ bRemoveHidden( sal_False ),
+ pTempViewFrame(0)
+{
+ nEventId = 0;
+ bUpperSpace = bViewCreated = bChkJumpMark =
+ bSetCrsr = sal_False;
+
+ eScriptLang = HTML_SL_UNKNOWN;
+ bAnyStarBasic = sal_True;
+
+ pPam = new SwPaM( *rCrsr.GetPoint() );
+ memset( &aAttrTab, 0, sizeof( _HTMLAttrTable ));
+
+ // Die Font-Groessen 1-7 aus der INI-Datei lesen
+ SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
+ aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20;
+ aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20;
+ aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20;
+ aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20;
+ aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20;
+ aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20;
+ aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20;
+
+ bKeepUnknown = pHtmlOptions->IsImportUnknown();
+
+ if(bReadNewDoc)
+ {
+ SvxFontHeightItem aFontHeight(aFontHeights[2], 100, RES_CHRATR_FONTSIZE);
+ pDoc->SetDefault( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ pDoc->SetDefault( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ pDoc->SetDefault( aFontHeight );
+ }
+
+ // Waehrend des Imports in den HTML-Modus schalten, damit die
+ // richrigen Vorlagen angelegt werden
+ bOldIsHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
+ pDoc->set(IDocumentSettingAccess::HTML_MODE, true);
+
+ pCSS1Parser = new SwCSS1Parser( pDoc, aFontHeights, sBaseURL, IsNewDoc() );
+ pCSS1Parser->SetIgnoreFontFamily( pHtmlOptions->IsIgnoreFontFamily() );
+
+ if( bReadUTF8 )
+ {
+ SetSrcEncoding( RTL_TEXTENCODING_UTF8 );
+ }
+ else
+ {
+ SwDocShell *pDocSh = pDoc->GetDocShell();
+ SvKeyValueIterator *pHeaderAttrs =
+ pDocSh->GetHeaderAttributes();
+ if( pHeaderAttrs )
+ SetEncodingByHTTPHeader( pHeaderAttrs );
+ }
+ pCSS1Parser->SetDfltEncoding( gsl_getSystemTextEncoding() );
+
+ // Timer nur bei ganz normalen Dokumenten aufsetzen!
+ SwDocShell* pDocSh = pDoc->GetDocShell();
+ if( pDocSh )
+ {
+ bViewCreated = sal_True; // nicht, synchron laden
+
+ // es ist ein Sprungziel vorgegeben.
+
+ if( pMed )
+ {
+ sJmpMark = pMed->GetURLObject().GetMark();
+ if( sJmpMark.Len() )
+ {
+ eJumpTo = JUMPTO_MARK;
+ String sCmp;
+ xub_StrLen nLastPos, nPos = 0;
+ while( STRING_NOTFOUND != ( nLastPos =
+ sJmpMark.Search( cMarkSeperator, nPos + 1 )) )
+ nPos = nLastPos;
+
+ if( nPos && ( sCmp = sJmpMark.Copy( nPos + 1 ) ).
+ EraseAllChars().Len() )
+ {
+ sCmp.ToLowerAscii();
+ if( sCmp.EqualsAscii( pMarkToRegion ) )
+ eJumpTo = JUMPTO_REGION;
+ else if( sCmp.EqualsAscii( pMarkToTable ) )
+ eJumpTo = JUMPTO_TABLE;
+ else if( sCmp.EqualsAscii( pMarkToGraphic ) )
+ eJumpTo = JUMPTO_GRAPHIC;
+ else if( sCmp.EqualsAscii( pMarkToOutline ) ||
+ sCmp.EqualsAscii( pMarkToText ) ||
+ sCmp.EqualsAscii( pMarkToFrame ) )
+ eJumpTo = JUMPTO_NONE; // das ist nichts gueltiges!
+ else
+ // ansonsten ist das ein normaler (Book)Mark
+ nPos = STRING_LEN;
+ }
+ else
+ nPos = STRING_LEN;
+
+ sJmpMark.Erase( nPos );
+ if( !sJmpMark.Len() )
+ eJumpTo = JUMPTO_NONE;
+ }
+ }
+ }
+}
+
+SwHTMLParser::~SwHTMLParser()
+{
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !nContinue, "DTOR im Continue - Das geht schief!!!" );
+#endif
+ sal_Bool bAsync = pDoc->IsInLoadAsynchron();
+ pDoc->SetInLoadAsynchron( sal_False );
+ pDoc->set(IDocumentSettingAccess::HTML_MODE, bOldIsHTMLMode);
+
+ if( pDoc->GetDocShell() && nEventId )
+ Application::RemoveUserEvent( nEventId );
+
+ // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals
+ // abfragen
+ if( pDoc->GetDocShell() )
+ {
+ // Gelinkte Bereiche updaten
+ sal_uInt16 nLinkMode = pDoc->getLinkUpdateMode( true );
+ if( nLinkMode != NEVER && bAsync &&
+ SFX_CREATE_MODE_INTERNAL!=pDoc->GetDocShell()->GetCreateMode() )
+ pDoc->GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL,
+ sal_True, sal_False );
+
+ if ( pDoc->GetDocShell()->IsLoading() )
+ {
+ // #i59688#
+ pDoc->GetDocShell()->LoadingFinished();
+ }
+ }
+
+ delete pSttNdIdx;
+
+ if( aSetAttrTab.Count() )
+ {
+ OSL_ENSURE( !aSetAttrTab.Count(),"Es stehen noch Attribute auf dem Stack" );
+ aSetAttrTab.DeleteAndDestroy( 0, aSetAttrTab.Count() );
+ }
+
+ delete pPam;
+ delete pCSS1Parser;
+ delete pNumRuleInfo;
+ DeleteFormImpl();
+ DeleteFootEndNoteImpl();
+
+ OSL_ENSURE( !pTable, "Es existiert noch eine offene Tabelle" );
+ delete pImageMaps;
+
+ OSL_ENSURE( !pPendStack,
+ "SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" );
+ while( pPendStack )
+ {
+ SwPendingStack* pTmp = pPendStack;
+ pPendStack = pPendStack->pNext;
+ delete pTmp->pData;
+ delete pTmp;
+ }
+
+ if( !pDoc->release() )
+ {
+ // keiner will mehr das Doc haben, also weg damit
+ delete pDoc;
+ pDoc = NULL;
+ }
+
+ if ( pTempViewFrame )
+ {
+ pTempViewFrame->DoClose();
+
+ // the temporary view frame is hidden, so the hidden flag might need to be removed
+ if ( bRemoveHidden && pDoc && pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() )
+ pDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
+ }
+}
+
+IMPL_LINK( SwHTMLParser, AsyncCallback, void*, /*pVoid*/ )
+{
+ nEventId=0;
+
+ // #i47907# - If the document has already been destructed,
+ // the parser should be aware of this:
+ if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
+ || 1 == pDoc->getReferenceCount() )
+ {
+ // wurde der Import vom SFX abgebrochen?
+ eState = SVPAR_ERROR;
+ }
+ // <--
+
+ GetAsynchCallLink().Call(0);
+ return 0;
+}
+
+SvParserState SwHTMLParser::CallParser()
+{
+ // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt!
+ pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() );
+ if( !IsNewDoc() ) // in ein Dokument einfuegen ?
+ {
+ const SwPosition* pPos = pPam->GetPoint();
+
+ pDoc->SplitNode( *pPos, false );
+
+ *pSttNdIdx = pPos->nNode.GetIndex()-1;
+ pDoc->SplitNode( *pPos, false );
+
+ SwPaM aInsertionRangePam( *pPos );
+
+ pPam->Move( fnMoveBackward );
+
+ // split any redline over the insertion point
+ aInsertionRangePam.SetMark();
+ *aInsertionRangePam.GetPoint() = *pPam->GetPoint();
+ aInsertionRangePam.Move( fnMoveBackward );
+ pDoc->SplitRedline( aInsertionRangePam );
+
+ pDoc->SetTxtFmtColl( *pPam,
+ pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
+ }
+
+ if( GetMedium() )
+ {
+ if( !bViewCreated )
+ {
+ nEventId = Application::PostUserEvent( LINK( this, SwHTMLParser, AsyncCallback ), 0 );
+ }
+ else
+ {
+ bViewCreated = sal_True;
+ nEventId = 0;
+ }
+ }
+
+ // Laufbalken anzeigen
+ else if( !GetMedium() || !GetMedium()->IsRemote() )
+ {
+ rInput.Seek(STREAM_SEEK_TO_END);
+ rInput.ResetError();
+ ::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(),
+ pDoc->GetDocShell() );
+ rInput.Seek(STREAM_SEEK_TO_BEGIN);
+ rInput.ResetError();
+ }
+
+ SwPageDesc& rDesc = pDoc->_GetPageDesc( 0 );
+ rDesc.Add( this );
+
+ SvParserState eRet = HTMLParser::CallParser();
+ return eRet;
+}
+
+void SwHTMLParser::Continue( int nToken )
+{
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !nContinue, "Continue im Continue - Das sollte doch nicht sein, oder?" );
+ nContinue++;
+#endif
+
+ // Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler
+ // gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig
+ // aufgeraeumt wird.
+ OSL_ENSURE( SVPAR_ERROR!=eState,
+ "SwHTMLParser::Continue: bereits ein Fehler gesetzt" );
+ if( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
+ eState = SVPAR_ERROR;
+
+ // Die ViewShell vom Dokument holen, merken und als aktuelle setzen.
+ ViewShell *pInitVSh = CallStartAction();
+
+ if( SVPAR_ERROR != eState && GetMedium() && !bViewCreated )
+ {
+ // Beim ersten Aufruf erstmal returnen, Doc anzeigen
+ // und auf Timer Callback warten.
+ // An dieser Stelle wurde im CallParser gerade mal ein Zeichen
+ // gelesen und ein SaveState(0) gerufen.
+ eState = SVPAR_PENDING;
+ bViewCreated = sal_True;
+ pDoc->SetInLoadAsynchron( sal_True );
+
+#if OSL_DEBUG_LEVEL > 1
+ nContinue--;
+#endif
+
+ return;
+ }
+
+ bSetModEnabled = sal_False;
+ if( pDoc->GetDocShell() &&
+ 0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) )
+ {
+ pDoc->GetDocShell()->EnableSetModified( sal_False );
+ }
+
+ // waehrend des einlesens kein OLE-Modified rufen
+ Link aOLELink( pDoc->GetOle2Link() );
+ pDoc->SetOle2Link( Link() );
+
+ sal_Bool bModified = pDoc->IsModified();
+ bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+
+ // Wenn der Import abgebrochen wird, kein Continue mehr rufen.
+ // Falls ein Pending-Stack existiert aber durch einen Aufruf
+ // von NextToken dafuer sorgen, dass der Pending-Stack noch
+ // beendet wird.
+ if( SVPAR_ERROR == eState )
+ {
+ OSL_ENSURE( !pPendStack || pPendStack->nToken,
+ "SwHTMLParser::Continue: Pending-Stack ohne Token" );
+ if( pPendStack && pPendStack->nToken )
+ NextToken( pPendStack->nToken );
+ OSL_ENSURE( !pPendStack,
+ "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" );
+ }
+ else
+ {
+ HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken );
+ }
+
+ // Laufbalken wieder abschalten
+ EndProgress( pDoc->GetDocShell() );
+
+ sal_Bool bLFStripped = sal_False;
+ if( SVPAR_PENDING != GetStatus() )
+ {
+ // noch die letzten Attribute setzen
+ {
+ if( aScriptSource.Len() )
+ {
+ SwScriptFieldType *pType =
+ (SwScriptFieldType*)pDoc->GetSysFldType( RES_SCRIPTFLD );
+
+ SwScriptField aFld( pType, aScriptType, aScriptSource,
+ sal_False );
+ InsertAttr( SwFmtFld( aFld ) );
+ }
+
+ if( pAppletImpl )
+ {
+ if( pAppletImpl->GetApplet().is() )
+ EndApplet();
+ else
+ EndObject();
+ }
+
+ // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen
+ if( IsNewDoc() )
+ bLFStripped = StripTrailingLF() > 0;
+
+ // noch offene Nummerierungen beenden.
+ while( GetNumInfo().GetNumRule() )
+ EndNumBulList();
+
+ OSL_ENSURE( !nContextStMin, "Es gibt geschuetzte Kontexte" );
+ nContextStMin = 0;
+ while( aContexts.Count() )
+ {
+ _HTMLAttrContext *pCntxt = PopContext();
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ delete pCntxt;
+ }
+ }
+
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ SetAttr( sal_False );
+
+ // Noch die erst verzoegert gesetzten Styles setzen
+ pCSS1Parser->SetDelayedStyles();
+ }
+
+ // den Start wieder korrigieren
+ if( !IsNewDoc() && pSttNdIdx->GetIndex() )
+ {
+ SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode();
+ SwNodeIndex aNxtIdx( *pSttNdIdx );
+ if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ))
+ {
+ xub_StrLen nStt = pTxtNode->GetTxt().Len();
+ // wenn der Cursor noch in dem Node steht, dann setze in an das Ende
+ if( pPam->GetPoint()->nNode == aNxtIdx )
+ {
+ pPam->GetPoint()->nNode = *pSttNdIdx;
+ pPam->GetPoint()->nContent.Assign( pTxtNode, nStt );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+// !!! sollte nicht moeglich sein, oder ??
+OSL_ENSURE( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_True ).nNode.GetIndex(),
+ "Pam.Bound1 steht noch im Node" );
+OSL_ENSURE( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_False ).nNode.GetIndex(),
+ "Pam.Bound2 steht noch im Node" );
+
+if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_True ).nNode.GetIndex() )
+{
+ xub_StrLen nCntPos = pPam->GetBound( sal_True ).nContent.GetIndex();
+ pPam->GetBound( sal_True ).nContent.Assign( pTxtNode,
+ pTxtNode->GetTxt().Len() + nCntPos );
+}
+if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_False ).nNode.GetIndex() )
+{
+ xub_StrLen nCntPos = pPam->GetBound( sal_False ).nContent.GetIndex();
+ pPam->GetBound( sal_False ).nContent.Assign( pTxtNode,
+ pTxtNode->GetTxt().Len() + nCntPos );
+}
+#endif
+ // Zeichen Attribute beibehalten!
+ SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode();
+ if( pTxtNode->GetTxt().Len() )
+ pDelNd->FmtToTxtAttr( pTxtNode );
+ else
+ pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() );
+ pTxtNode->JoinNext();
+ }
+ }
+ }
+
+ if( SVPAR_ACCEPTED == eState )
+ {
+ if( nMissingImgMaps )
+ {
+ // es fehlen noch ein paar Image-Map zuordungen.
+ // vielleicht sind die Image-Maps ja jetzt da?
+ ConnectImageMaps();
+ }
+
+ // jetzt noch den letzten ueberfluessigen Absatz loeschen
+ SwPosition* pPos = pPam->GetPoint();
+ if( !pPos->nContent.GetIndex() && !bLFStripped )
+ {
+ SwTxtNode* pAktNd;
+ sal_uLong nNodeIdx = pPos->nNode.GetIndex();
+
+ sal_Bool bHasFlysOrMarks =
+ HasCurrentParaFlys() || HasCurrentParaBookmarks( sal_True );
+
+ if( IsNewDoc() )
+ {
+ const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
+ if( !pPam->GetPoint()->nContent.GetIndex() &&
+ ( pPrev->IsCntntNode() ||
+ (pPrev->IsEndNode() &&
+ pPrev->StartOfSectionNode()->IsSectionNode()) ) )
+ {
+ SwCntntNode* pCNd = pPam->GetCntntNode();
+ if( pCNd && pCNd->StartOfSectionIndex()+2 <
+ pCNd->EndOfSectionIndex() && !bHasFlysOrMarks )
+ {
+ ViewShell *pVSh = CheckActionViewShell();
+ SwCrsrShell *pCrsrSh = pVSh && pVSh->ISA(SwCrsrShell)
+ ? static_cast < SwCrsrShell * >( pVSh )
+ : 0;
+ if( pCrsrSh &&
+ pCrsrSh->GetCrsr()->GetPoint()
+ ->nNode.GetIndex() == nNodeIdx )
+ {
+ pCrsrSh->MovePara(fnParaPrev, fnParaEnd );
+ pCrsrSh->SetMark();
+ pCrsrSh->ClearMark();
+ }
+ pPam->GetBound(sal_True).nContent.Assign( 0, 0 );
+ pPam->GetBound(sal_False).nContent.Assign( 0, 0 );
+ pDoc->GetNodes().Delete( pPam->GetPoint()->nNode );
+ }
+ }
+ }
+ else if( 0 != ( pAktNd = pDoc->GetNodes()[ nNodeIdx ]->GetTxtNode()) && !bHasFlysOrMarks )
+ {
+ if( pAktNd->CanJoinNext( &pPos->nNode ))
+ {
+ SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode();
+ pPos->nContent.Assign( pNextNd, 0 );
+ pPam->SetMark(); pPam->DeleteMark();
+ pNextNd->JoinPrev();
+ }
+ else if( !pAktNd->GetTxt().Len() )
+ {
+ pPos->nContent.Assign( 0, 0 );
+ pPam->SetMark(); pPam->DeleteMark();
+ pDoc->GetNodes().Delete( pPos->nNode, 1 );
+ pPam->Move( fnMoveBackward );
+ }
+ }
+ }
+
+ // nun noch das SplitNode vom Anfang aufheben
+ else if( !IsNewDoc() )
+ {
+ if( pPos->nContent.GetIndex() ) // dann gabs am Ende kein <P>,
+ pPam->Move( fnMoveForward, fnGoNode ); // als zum naechsten Node
+ SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ SwNodeIndex aPrvIdx( pPos->nNode );
+ if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) &&
+ *pSttNdIdx <= aPrvIdx )
+ {
+ // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor
+ // usw. sind im pTxtNode angemeldet, so dass der bestehen
+ // bleiben MUSS.
+
+ // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die
+ // Absatzattribute und die Vorlage uebernehmen!
+ SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode();
+ pTxtNode->ChgFmtColl( pPrev->GetTxtColl() );
+ pTxtNode->FmtToTxtAttr( pPrev );
+ pTxtNode->ResetAllAttr();
+
+ if( pPrev->HasSwAttrSet() )
+ pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() );
+
+ if( &pPam->GetBound(sal_True).nNode.GetNode() == pPrev )
+ pPam->GetBound(sal_True).nContent.Assign( pTxtNode, 0 );
+ if( &pPam->GetBound(sal_False).nNode.GetNode() == pPrev )
+ pPam->GetBound(sal_False).nContent.Assign( pTxtNode, 0 );
+
+ pTxtNode->JoinPrev();
+ }
+ }
+
+ // und noch die DocumentInfo aufbereiten
+ if( IsNewDoc() )
+ {
+ SwDocShell *pDocShell(pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+ if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) &&
+ (xDocProps->getAutoloadURL().getLength() == 0) )
+ {
+ xDocProps->setAutoloadURL(aPathToFile);
+ }
+ }
+ }
+
+ if( bUpdateDocStat )
+ {
+ SwDocStat aStat( pDoc->GetDocStat() );
+ pDoc->UpdateDocStat( aStat );
+ }
+ }
+
+ if( SVPAR_PENDING != GetStatus() )
+ delete pSttNdIdx, pSttNdIdx = 0;
+
+ // sollte der Parser der Letzte sein, der das Doc haelt, dann braucht
+ // man hier auch nichts mehr tun, Doc wird gleich zerstoert!
+ if( 1 < pDoc->getReferenceCount() )
+ {
+ if( bWasUndo )
+ {
+ pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ pDoc->GetIDocumentUndoRedo().DoUndo(true);
+ }
+ else if( !pInitVSh )
+ {
+ // Wenn zu Beginn des Continue keine Shell vorhanden war,
+ // kann trotzdem mitlerweile eine angelegt worden sein.
+ // In dieses Fall stimmt das bWasUndo-Flag nicht und
+ // wir muessen das Undo noch anschalten.
+ ViewShell *pTmpVSh = CheckActionViewShell();
+ if( pTmpVSh )
+ {
+ pDoc->GetIDocumentUndoRedo().DoUndo(true);
+ }
+ }
+
+ pDoc->SetOle2Link( aOLELink );
+ if( !bModified )
+ pDoc->ResetModified();
+ if( bSetModEnabled && pDoc->GetDocShell() )
+ {
+ pDoc->GetDocShell()->EnableSetModified( sal_True );
+ bSetModEnabled = sal_False; // this is unnecessary here
+ }
+ }
+
+
+ // Wenn die Dokuemnt-ViewShell noch existiert und eine Action
+ // offen ist (muss bei Abbruch nicht sein), die Action beenden,
+ // uns von der Shell abmelden und schliesslich die alte Shell
+ // wieder rekonstruieren.
+ CallEndAction( sal_True );
+
+#if OSL_DEBUG_LEVEL > 1
+ nContinue--;
+#endif
+}
+
+void SwHTMLParser::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
+ {
+ case RES_OBJECTDYING:
+ if( ((SwPtrMsgPoolItem *)pOld)->pObject == GetRegisteredIn() )
+ {
+ // dann uns selbst beenden
+ GetRegisteredInNonConst()->Remove( this );
+ ReleaseRef(); // ansonsten sind wir fertig!
+ }
+ break;
+ }
+}
+
+void SwHTMLParser::DocumentDetected()
+{
+ OSL_ENSURE( !bDocInitalized, "DocumentDetected mehrfach aufgerufen" );
+ bDocInitalized = sal_True;
+ if( IsNewDoc() )
+ {
+ if( IsInHeader() )
+ FinishHeader( sal_True );
+
+ CallEndAction( sal_True, sal_True );
+
+ pDoc->GetIDocumentUndoRedo().DoUndo(false);
+ // Durch das DocumentDetected wurde im allgemeinen eine
+ // ViewShell angelegt. Es kann aber auch sein, dass sie
+ // erst spaeter angelegt wird, naemlich dann, wenn die UI
+ // gecaptured ist.
+ CallStartAction();
+ }
+}
+
+// is called for every token that is recognised in CallParser
+void SwHTMLParser::NextToken( int nToken )
+{
+ if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
+ || 1 == pDoc->getReferenceCount() )
+ {
+ // Was the import cancelled by SFX? If a pending stack
+ // exists, clean it.
+ eState = SVPAR_ERROR;
+ OSL_ENSURE( !pPendStack || pPendStack->nToken,
+ "SwHTMLParser::NextToken: Pending-Stack without token" );
+ if( 1 == pDoc->getReferenceCount() || !pPendStack )
+ return ;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ if( pPendStack )
+ {
+ switch( nToken )
+ {
+ // tables are read by recursive method calls
+ case HTML_TABLE_ON:
+ // For CSS declarations we might have to wait
+ // for a file download to finish
+ case HTML_LINK:
+ // For controls we might have to set the size.
+ case HTML_INPUT:
+ case HTML_TEXTAREA_ON:
+ case HTML_SELECT_ON:
+ case HTML_SELECT_OFF:
+ break;
+ default:
+ OSL_ENSURE( !pPendStack, "Unbekanntes Token fuer Pending-Stack" );
+ break;
+ }
+ }
+#endif
+
+ // The following special cases have to be treated before the
+ // filter detection, because Netscape doesn't reference the content
+ // of the title for filter detection either.
+ if( !pPendStack )
+ {
+ if( bInTitle )
+ {
+ switch( nToken )
+ {
+ case HTML_TITLE_OFF:
+ if( IsNewDoc() && sTitle.Len() )
+ {
+ if( pDoc->GetDocShell() ) {
+ uno::Reference<document::XDocumentPropertiesSupplier>
+ xDPS(pDoc->GetDocShell()->GetModel(),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
+ if (xDocProps.is()) {
+ xDocProps->setTitle(sTitle);
+ }
+
+ pDoc->GetDocShell()->SetTitle( sTitle );
+ }
+ }
+ bInTitle = sal_False;
+ sTitle.Erase();
+ break;
+
+ case HTML_NONBREAKSPACE:
+ sTitle += ' ';
+ break;
+
+ case HTML_SOFTHYPH:
+ sTitle += '-';
+ break;
+
+ case HTML_TEXTTOKEN:
+ sTitle += aToken;
+ break;
+
+ default:
+ sTitle += '<';
+ if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
+ sTitle += '/';
+ sTitle += sSaveToken;
+ if( aToken.Len() )
+ {
+ sTitle += ' ';
+ sTitle += aToken;
+ }
+ sTitle += '>';
+ break;
+ }
+
+ return;
+ }
+ }
+
+ // Find out what type of document it is if we don't know already.
+ // For Controls this has to be finished before the control is inserted
+ // because for inserting a View is needed.
+ if( !bDocInitalized )
+ DocumentDetected();
+
+ sal_Bool bGetIDOption = sal_False, bInsertUnknown = sal_False;
+ sal_Bool bUpperSpaceSave = bUpperSpace;
+ bUpperSpace = sal_False;
+
+ // The following special cases may or have to be treated after the
+ // filter detection
+ if( !pPendStack )
+ {
+ if( bInFloatingFrame )
+ {
+ // <SCRIPT> is ignored here (from us), because it is ignored in
+ // Applets as well
+ if( HTML_IFRAME_OFF == nToken )
+ {
+ bCallNextToken = sal_False;
+ EndFloatingFrame();
+ }
+
+ return;
+ }
+ else if( bInNoEmbed )
+ {
+ switch( nToken )
+ {
+ case HTML_NOEMBED_OFF:
+ aContents.ConvertLineEnd();
+ InsertComment( aContents, OOO_STRING_SVTOOLS_HTML_noembed );
+ aContents.Erase();
+ bCallNextToken = sal_False;
+ bInNoEmbed = sal_False;
+ break;
+
+ case HTML_RAWDATA:
+ InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed );
+ break;
+
+ default:
+ OSL_ENSURE( !this, "SwHTMLParser::NextToken: invalid tag" );
+ break;
+ }
+
+ return;
+ }
+ else if( pAppletImpl )
+ {
+ // in an applet only <PARAM> tags and the </APPLET> tag
+ // are of interest for us (for the moment)
+ // <SCRIPT> is ignored here (from Netscape)!
+
+ switch( nToken )
+ {
+ case HTML_APPLET_OFF:
+ bCallNextToken = sal_False;
+ EndApplet();
+ break;
+ case HTML_OBJECT_OFF:
+ bCallNextToken = sal_False;
+ EndObject();
+ break;
+
+ case HTML_PARAM:
+ InsertParam();
+ break;
+ }
+
+ return;
+ }
+ else if( bTextArea )
+ {
+ // in a TextArea everything up to </TEXTAREA> is inserted as text.
+ // <SCRIPT> is ignored here (from Netscape)!
+
+ switch( nToken )
+ {
+ case HTML_TEXTAREA_OFF:
+ bCallNextToken = sal_False;
+ EndTextArea();
+ break;
+
+ default:
+ InsertTextAreaText( static_cast< sal_uInt16 >(nToken) );
+ break;
+ }
+
+ return;
+ }
+ else if( bSelect )
+ {
+ // HAS to be treated after bNoScript!
+ switch( nToken )
+ {
+ case HTML_SELECT_OFF:
+ bCallNextToken = sal_False;
+ EndSelect();
+ return;
+
+ case HTML_OPTION:
+ InsertSelectOption();
+ return;
+
+ case HTML_TEXTTOKEN:
+ InsertSelectText();
+ return;
+
+ case HTML_INPUT:
+ case HTML_SCRIPT_ON:
+ case HTML_SCRIPT_OFF:
+ case HTML_NOSCRIPT_ON:
+ case HTML_NOSCRIPT_OFF:
+ case HTML_RAWDATA:
+ // treat in normal switch
+ break;
+
+ default:
+ // ignore
+ return;
+ }
+ }
+ else if( pMarquee )
+ {
+ // in a TextArea everything up to </TEXTAREA> is inserted as text.
+ // The <SCRIPT> tags are ignored from MS-IE, we ignore the whole
+ // script.
+ switch( nToken )
+ {
+ case HTML_MARQUEE_OFF:
+ bCallNextToken = sal_False;
+ EndMarquee();
+ break;
+
+ case HTML_TEXTTOKEN:
+ InsertMarqueeText();
+ break;
+ }
+
+ return;
+ }
+ else if( bInField )
+ {
+ switch( nToken )
+ {
+ case HTML_SDFIELD_OFF:
+ bCallNextToken = sal_False;
+ EndField();
+ break;
+
+ case HTML_TEXTTOKEN:
+ InsertFieldText();
+ break;
+ }
+
+ return;
+ }
+ else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol )
+ {
+ switch( nToken )
+ {
+ case HTML_ANCHOR_OFF:
+ EndAnchor();
+ bCallNextToken = sal_False;
+ break;
+
+ case HTML_TEXTTOKEN:
+ InsertFootEndNoteText();
+ break;
+ }
+ return;
+ }
+ else if( aUnknownToken.Len() )
+ {
+ // Paste content of unknown tags.
+ if (aToken.Len() > 0)
+ {
+ if( !bDocInitalized )
+ DocumentDetected();
+ pDoc->InsertString( *pPam, aToken );
+
+ // if there are temporary paragraph attributes and the
+ // paragraph isn't empty then the paragraph attributes
+ // are final.
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ SetAttr();
+ }
+
+ // Unknown token in the header are only closed by a matching
+ // end-token, </HEAD> or <BODY>. Text inside is ignored.
+ switch( nToken )
+ {
+ case HTML_UNKNOWNCONTROL_OFF:
+ if( aUnknownToken.CompareTo(sSaveToken) != COMPARE_EQUAL )
+ return;
+ case HTML_FRAMESET_ON:
+ case HTML_HEAD_OFF:
+ case HTML_BODY_ON:
+ case HTML_IMAGE: // Don't know why Netscape acts this way.
+ aUnknownToken.Erase();
+ break;
+ case HTML_TEXTTOKEN:
+ return;
+ default:
+ aUnknownToken.Erase();
+ break;
+ }
+ }
+ }
+
+ switch( nToken )
+ {
+ case HTML_BODY_ON:
+ if( aStyleSource.Len() )
+ {
+ pCSS1Parser->ParseStyleSheet( aStyleSource );
+ aStyleSource.Erase();
+ }
+ if( IsNewDoc() )
+ {
+ InsertBodyOptions();
+ // If there is a template for the first or the right page,
+ // it is set here.
+ const SwPageDesc *pPageDesc = 0;
+ if( pCSS1Parser->IsSetFirstPageDesc() )
+ pPageDesc = pCSS1Parser->GetFirstPageDesc();
+ else if( pCSS1Parser->IsSetRightPageDesc() )
+ pPageDesc = pCSS1Parser->GetRightPageDesc();
+
+ if( pPageDesc )
+ {
+ pDoc->InsertPoolItem( *pPam, SwFmtPageDesc( pPageDesc ), 0 );
+ }
+ }
+ break;
+
+ case HTML_LINK:
+ InsertLink();
+ break;
+
+ case HTML_BASE:
+ {
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_HREF:
+ sBaseURL = pOption->GetString();
+ break;
+ case HTML_O_TARGET:
+ if( IsNewDoc() )
+ {
+ SwDocShell *pDocShell(pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties>
+ xDocProps(xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(),"no DocumentProperties");
+ if (xDocProps.is()) {
+ xDocProps->setDefaultTarget(
+ pOption->GetString());
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case HTML_META:
+ {
+ SvKeyValueIterator *pHTTPHeader = 0;
+ if( IsNewDoc() )
+ {
+ SwDocShell *pDocSh = pDoc->GetDocShell();
+ if( pDocSh )
+ pHTTPHeader = pDocSh->GetHeaderAttributes();
+ }
+ SwDocShell *pDocShell(pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ if (pDocShell)
+ {
+ uno::Reference<document::XDocumentProperties> xDocProps;
+ if (IsNewDoc())
+ {
+ const uno::Reference<document::XDocumentPropertiesSupplier>
+ xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
+ xDocProps = xDPS->getDocumentProperties();
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+ }
+ ParseMetaOptions( xDocProps, pHTTPHeader );
+ }
+ }
+ break;
+
+ case HTML_TITLE_ON:
+ bInTitle = sal_True;
+ break;
+
+ case HTML_SCRIPT_ON:
+ NewScript();
+ break;
+
+ case HTML_SCRIPT_OFF:
+ EndScript();
+ break;
+
+ case HTML_NOSCRIPT_ON:
+ case HTML_NOSCRIPT_OFF:
+ bInsertUnknown = sal_True;
+ break;
+
+ case HTML_STYLE_ON:
+ NewStyle();
+ break;
+
+ case HTML_STYLE_OFF:
+ EndStyle();
+ break;
+
+ case HTML_RAWDATA:
+ if( !bIgnoreRawData )
+ {
+ if( IsReadScript() )
+ {
+ AddScriptSource();
+ }
+ else if( IsReadStyle() )
+ {
+ if( aStyleSource.Len() )
+ aStyleSource += '\n';
+ aStyleSource += aToken;
+ }
+ }
+ break;
+
+ case HTML_OBJECT_ON:
+#ifdef SOLAR_JAVA
+ NewObject();
+ bCallNextToken = pAppletImpl!=0 && pTable!=0;
+#endif
+ break;
+
+ case HTML_APPLET_ON:
+#ifdef SOLAR_JAVA
+ InsertApplet();
+ bCallNextToken = pAppletImpl!=0 && pTable!=0;
+#endif
+ break;
+
+ case HTML_IFRAME_ON:
+ InsertFloatingFrame();
+ bCallNextToken = bInFloatingFrame && pTable!=0;
+ break;
+
+ case HTML_LINEBREAK:
+ if( !IsReadPRE() )
+ {
+ InsertLineBreak();
+ break;
+ }
+ else
+ bGetIDOption = sal_True;
+ // <BR>s in <PRE> resemble true LFs, hence no break
+
+ case HTML_NEWPARA:
+ // CR in PRE/LISTING/XMP
+ {
+ if( HTML_NEWPARA==nToken ||
+ pPam->GetPoint()->nContent.GetIndex() )
+ {
+ AppendTxtNode(); // there is no LF at this place
+ // therefore it will cause no problems
+ SetTxtCollAttrs();
+ }
+ // progress bar
+ if( !GetMedium() || !GetMedium()->IsRemote() )
+ ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
+ }
+ break;
+
+ case HTML_NONBREAKSPACE:
+ pDoc->InsertString( *pPam, CHAR_HARDBLANK );
+ break;
+
+ case HTML_SOFTHYPH:
+ pDoc->InsertString( *pPam, CHAR_SOFTHYPHEN );
+ break;
+
+ case HTML_LINEFEEDCHAR:
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode();
+ if( !pTable && !pDoc->IsInHeaderFooter( pPam->GetPoint()->nNode ) )
+ {
+ NewAttr( &aAttrTab.pBreak, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
+ EndAttr( aAttrTab.pBreak, 0, sal_False );
+ }
+ break;
+
+ case HTML_TEXTTOKEN:
+ // insert string without spanning attributes at the end.
+ if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() )
+ {
+ xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
+ if( nPos )
+ {
+ const String& rText =
+ pPam->GetPoint()->nNode.GetNode().GetTxtNode()->GetTxt();
+ sal_Unicode cLast = rText.GetChar(--nPos);
+ if( ' ' == cLast || '\x0a' == cLast)
+ aToken.Erase(0,1);
+ }
+ else
+ aToken.Erase(0,1);
+
+ if( !aToken.Len() )
+ {
+ bUpperSpace = bUpperSpaceSave;
+ break;
+ }
+ }
+
+ if( aToken.Len() )
+ {
+ if( !bDocInitalized )
+ DocumentDetected();
+ pDoc->InsertString( *pPam, aToken );
+
+ // if there are temporary paragraph attributes and the
+ // paragraph isn't empty then the paragraph attributes
+ // are final.
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ SetAttr();
+ }
+ break;
+
+ case HTML_HORZRULE:
+ InsertHorzRule();
+ break;
+
+ case HTML_IMAGE:
+ InsertImage();
+ // if only the parser references the doc, we can break and set
+ // an error code
+ if( 1 == pDoc->getReferenceCount() )
+ {
+ eState = SVPAR_ERROR;
+ }
+ break;
+
+ case HTML_SPACER:
+ InsertSpacer();
+ break;
+
+ case HTML_EMBED:
+ InsertEmbed();
+ break;
+
+ case HTML_NOEMBED_ON:
+ bInNoEmbed = sal_True;
+ bCallNextToken = pTable!=0;
+ ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed );
+ break;
+
+ case HTML_DEFLIST_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewDefList();
+ break;
+ case HTML_DEFLIST_OFF:
+ if( nOpenParaToken )
+ EndPara();
+ EndDefListItem( 0, sal_False, 1==nDefListDeep );
+ EndDefList();
+ break;
+
+ case HTML_DD_ON:
+ case HTML_DT_ON:
+ if( nOpenParaToken )
+ EndPara();
+ EndDefListItem( 0, sal_False );// close <DD>/<DT> and set no template
+ NewDefListItem( nToken );
+ break;
+
+ case HTML_DD_OFF:
+ case HTML_DT_OFF:
+ // c.f. HTML_LI_OFF
+ // Actually we should close a DD/DT now.
+ // But neither Netscape nor Microsoft do this and so don't we.
+ EndDefListItem( nToken, sal_False );
+ break;
+
+ // divisions
+ case HTML_DIVISION_ON:
+ case HTML_CENTER_ON:
+ if( nOpenParaToken )
+ {
+ if( IsReadPRE() )
+ nOpenParaToken = 0;
+ else
+ EndPara();
+ }
+ NewDivision( nToken );
+ break;
+
+ case HTML_DIVISION_OFF:
+ case HTML_CENTER_OFF:
+ if( nOpenParaToken )
+ {
+ if( IsReadPRE() )
+ nOpenParaToken = 0;
+ else
+ EndPara();
+ }
+ EndDivision( nToken );
+ break;
+
+ case HTML_MULTICOL_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewMultiCol();
+ break;
+
+ case HTML_MULTICOL_OFF:
+ if( nOpenParaToken )
+ EndPara();
+ EndTag( HTML_MULTICOL_ON );
+ break;
+
+ case HTML_MARQUEE_ON:
+ NewMarquee();
+ bCallNextToken = pMarquee!=0 && pTable!=0;
+ break;
+
+ case HTML_FORM_ON:
+ NewForm();
+ break;
+ case HTML_FORM_OFF:
+ EndForm();
+ break;
+
+ // templates
+ case HTML_PARABREAK_ON:
+ if( nOpenParaToken )
+ EndPara( sal_True );
+ NewPara();
+ break;
+
+ case HTML_PARABREAK_OFF:
+ EndPara( sal_True );
+ break;
+
+ case HTML_ADDRESS_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewTxtFmtColl( HTML_ADDRESS_ON, RES_POOLCOLL_SENDADRESS );
+ break;
+
+ case HTML_ADDRESS_OFF:
+ if( nOpenParaToken )
+ EndPara();
+ EndTxtFmtColl( HTML_ADDRESS_OFF );
+ break;
+
+ case HTML_BLOCKQUOTE_ON:
+ case HTML_BLOCKQUOTE30_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewTxtFmtColl( HTML_BLOCKQUOTE_ON, RES_POOLCOLL_HTML_BLOCKQUOTE );
+ break;
+
+ case HTML_BLOCKQUOTE_OFF:
+ case HTML_BLOCKQUOTE30_OFF:
+ if( nOpenParaToken )
+ EndPara();
+ EndTxtFmtColl( HTML_BLOCKQUOTE_ON );
+ break;
+
+ case HTML_PREFORMTXT_ON:
+ case HTML_LISTING_ON:
+ case HTML_XMP_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewTxtFmtColl( nToken, RES_POOLCOLL_HTML_PRE );
+ break;
+
+ case HTML_PREFORMTXT_OFF:
+ bNoParSpace = sal_True; // the last PRE-paragraph gets a spacing
+ EndTxtFmtColl( HTML_PREFORMTXT_OFF );
+ break;
+
+ case HTML_LISTING_OFF:
+ case HTML_XMP_OFF:
+ EndTxtFmtColl( nToken );
+ break;
+
+ case HTML_HEAD1_ON:
+ case HTML_HEAD2_ON:
+ case HTML_HEAD3_ON:
+ case HTML_HEAD4_ON:
+ case HTML_HEAD5_ON:
+ case HTML_HEAD6_ON:
+ if( nOpenParaToken )
+ {
+ if( IsReadPRE() )
+ nOpenParaToken = 0;
+ else
+ EndPara();
+ }
+ NewHeading( nToken );
+ break;
+
+ case HTML_HEAD1_OFF:
+ case HTML_HEAD2_OFF:
+ case HTML_HEAD3_OFF:
+ case HTML_HEAD4_OFF:
+ case HTML_HEAD5_OFF:
+ case HTML_HEAD6_OFF:
+ EndHeading();
+ break;
+
+ case HTML_TABLE_ON:
+ if( pPendStack )
+ BuildTable( SVX_ADJUST_END );
+ else
+ {
+ if( nOpenParaToken )
+ EndPara();
+ OSL_ENSURE( !pTable, "table in table not allowed here" );
+ if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) &&
+ (pPam->GetPoint()->nNode.GetIndex() >
+ pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
+ !pPam->GetNode()->FindFootnoteStartNode() ) )
+ {
+ if ( nParaCnt < 5 )
+ Show(); // show what we have up to here
+
+ SvxAdjust eAdjust = aAttrTab.pAdjust
+ ? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()).
+ GetAdjust()
+ : SVX_ADJUST_END;
+ BuildTable( eAdjust );
+ }
+ else
+ bInsertUnknown = bKeepUnknown;
+ }
+ break;
+
+ // lists
+ case HTML_DIRLIST_ON:
+ case HTML_MENULIST_ON:
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ if( nOpenParaToken )
+ EndPara();
+ NewNumBulList( nToken );
+ break;
+
+ case HTML_DIRLIST_OFF:
+ case HTML_MENULIST_OFF:
+ case HTML_ORDERLIST_OFF:
+ case HTML_UNORDERLIST_OFF:
+ if( nOpenParaToken )
+ EndPara();
+ EndNumBulListItem( 0, sal_True, GetNumInfo().GetDepth()==1 );
+ EndNumBulList( nToken );
+ break;
+
+ case HTML_LI_ON:
+ case HTML_LISTHEADER_ON:
+ if( nOpenParaToken &&
+ (pPam->GetPoint()->nContent.GetIndex()
+ || HTML_PARABREAK_ON==nOpenParaToken) )
+ {
+ // only finish paragraph for <P><LI>, not for <DD><LI>
+ EndPara();
+ }
+
+ EndNumBulListItem( 0, sal_False );// close <LI>/<LH> and don't set a template
+ NewNumBulListItem( nToken );
+ break;
+
+ case HTML_LI_OFF:
+ case HTML_LISTHEADER_OFF:
+ EndNumBulListItem( nToken, sal_False );
+ break;
+
+ // Attribute :
+ case HTML_ITALIC_ON:
+ {
+ SvxPostureItem aPosture( ITALIC_NORMAL, RES_CHRATR_POSTURE );
+ SvxPostureItem aPostureCJK( ITALIC_NORMAL, RES_CHRATR_CJK_POSTURE );
+ SvxPostureItem aPostureCTL( ITALIC_NORMAL, RES_CHRATR_CTL_POSTURE );
+ NewStdAttr( HTML_ITALIC_ON,
+ &aAttrTab.pItalic, aPosture,
+ &aAttrTab.pItalicCJK, &aPostureCJK,
+ &aAttrTab.pItalicCTL, &aPostureCTL );
+ }
+ break;
+
+ case HTML_BOLD_ON:
+ {
+ SvxWeightItem aWeight( WEIGHT_BOLD, RES_CHRATR_WEIGHT );
+ SvxWeightItem aWeightCJK( WEIGHT_BOLD, RES_CHRATR_CJK_WEIGHT );
+ SvxWeightItem aWeightCTL( WEIGHT_BOLD, RES_CHRATR_CTL_WEIGHT );
+ NewStdAttr( HTML_BOLD_ON,
+ &aAttrTab.pBold, aWeight,
+ &aAttrTab.pBoldCJK, &aWeightCJK,
+ &aAttrTab.pBoldCTL, &aWeightCTL );
+ }
+ break;
+
+
+ case HTML_STRIKE_ON:
+ case HTML_STRIKETHROUGH_ON:
+ {
+ NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike,
+ SvxCrossedOutItem(STRIKEOUT_SINGLE, RES_CHRATR_CROSSEDOUT) );
+ }
+ break;
+
+ case HTML_UNDERLINE_ON:
+ {
+ NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline,
+ SvxUnderlineItem(UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE) );
+ }
+ break;
+
+ case HTML_SUPERSCRIPT_ON:
+ {
+ NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement,
+ SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
+ }
+ break;
+
+ case HTML_SUBSCRIPT_ON:
+ {
+ NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement,
+ SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
+ }
+ break;
+
+ case HTML_BLINK_ON:
+ {
+ NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink,
+ SvxBlinkItem( sal_True, RES_CHRATR_BLINK ) );
+ }
+ break;
+
+ case HTML_SPAN_ON:
+ NewStdAttr( HTML_SPAN_ON );
+ break;
+
+
+ case HTML_ITALIC_OFF:
+ case HTML_BOLD_OFF:
+ case HTML_STRIKE_OFF:
+ case HTML_UNDERLINE_OFF:
+ case HTML_SUPERSCRIPT_OFF:
+ case HTML_SUBSCRIPT_OFF:
+ case HTML_BLINK_OFF:
+ case HTML_SPAN_OFF:
+ EndTag( nToken );
+ break;
+
+ case HTML_STRIKETHROUGH_OFF:
+ EndTag( HTML_STRIKE_OFF );
+ break;
+
+ case HTML_BASEFONT_ON:
+ NewBasefontAttr();
+ break;
+ case HTML_BASEFONT_OFF:
+ EndBasefontAttr();
+ break;
+ case HTML_FONT_ON:
+ case HTML_BIGPRINT_ON:
+ case HTML_SMALLPRINT_ON:
+ NewFontAttr( nToken );
+ break;
+ case HTML_FONT_OFF:
+ case HTML_BIGPRINT_OFF:
+ case HTML_SMALLPRINT_OFF:
+ EndFontAttr( nToken );
+ break;
+
+ case HTML_EMPHASIS_ON:
+ case HTML_CITIATION_ON:
+ case HTML_STRONG_ON:
+ case HTML_CODE_ON:
+ case HTML_SAMPLE_ON:
+ case HTML_KEYBOARD_ON:
+ case HTML_VARIABLE_ON:
+ case HTML_DEFINSTANCE_ON:
+ case HTML_SHORTQUOTE_ON:
+ case HTML_LANGUAGE_ON:
+ case HTML_AUTHOR_ON:
+ case HTML_PERSON_ON:
+ case HTML_ACRONYM_ON:
+ case HTML_ABBREVIATION_ON:
+ case HTML_INSERTEDTEXT_ON:
+ case HTML_DELETEDTEXT_ON:
+
+ case HTML_TELETYPE_ON:
+ NewCharFmt( nToken );
+ break;
+
+ case HTML_SDFIELD_ON:
+ NewField();
+ bCallNextToken = bInField && pTable!=0;
+ break;
+
+ case HTML_EMPHASIS_OFF:
+ case HTML_CITIATION_OFF:
+ case HTML_STRONG_OFF:
+ case HTML_CODE_OFF:
+ case HTML_SAMPLE_OFF:
+ case HTML_KEYBOARD_OFF:
+ case HTML_VARIABLE_OFF:
+ case HTML_DEFINSTANCE_OFF:
+ case HTML_SHORTQUOTE_OFF:
+ case HTML_LANGUAGE_OFF:
+ case HTML_AUTHOR_OFF:
+ case HTML_PERSON_OFF:
+ case HTML_ACRONYM_OFF:
+ case HTML_ABBREVIATION_OFF:
+ case HTML_INSERTEDTEXT_OFF:
+ case HTML_DELETEDTEXT_OFF:
+
+ case HTML_TELETYPE_OFF:
+ EndTag( nToken );
+ break;
+
+ case HTML_HEAD_OFF:
+ if( aStyleSource.Len() )
+ {
+ pCSS1Parser->ParseStyleSheet( aStyleSource );
+ aStyleSource.Erase();
+ }
+ break;
+
+ case HTML_DOCTYPE:
+ case HTML_BODY_OFF:
+ case HTML_HTML_OFF:
+ case HTML_HEAD_ON:
+ case HTML_TITLE_OFF:
+ break; // don't evaluate further???
+ case HTML_HTML_ON:
+ {
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
+ if( HTML_O_DIR == pOption->GetToken() )
+ {
+ const String& rDir = pOption->GetString();
+ SfxItemSet aItemSet( pDoc->GetAttrPool(),
+ pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+ String aDummy;
+ ParseStyleOptions( aDummy, aDummy, aDummy, aItemSet,
+ aPropInfo, 0, &rDir );
+
+ pCSS1Parser->SetPageDescAttrs( 0, &aItemSet );
+ break;
+ }
+ }
+ }
+ break;
+
+ case HTML_INPUT:
+ InsertInput();
+ break;
+
+ case HTML_TEXTAREA_ON:
+ NewTextArea();
+ bCallNextToken = bTextArea && pTable!=0;
+ break;
+
+ case HTML_SELECT_ON:
+ NewSelect();
+ bCallNextToken = bSelect && pTable!=0;
+ break;
+
+ case HTML_ANCHOR_ON:
+ NewAnchor();
+ break;
+
+ case HTML_ANCHOR_OFF:
+ EndAnchor();
+ break;
+
+ case HTML_COMMENT:
+ if( ( aToken.Len() > 5 ) && ( ! bIgnoreHTMLComments ) )
+ {
+ // insert as Post-It
+ // If there are no space characters right behind
+ // the <!-- and on front of the -->, leave the comment untouched.
+ if( ' ' == aToken.GetChar( 3 ) &&
+ ' ' == aToken.GetChar( aToken.Len()-3 ) )
+ {
+ String aComment( aToken.Copy( 3, aToken.Len()-5 ) );
+ aComment.EraseLeadingChars().EraseTrailingChars();
+ InsertComment( aComment );
+ }
+ else
+ {
+ String aComment( '<' );
+ (aComment += aToken) += '>';
+ InsertComment( aComment );
+ }
+ }
+ break;
+
+ case HTML_MAP_ON:
+ // Image Maps are read asynchronously: At first only an image map is created
+ // Areas are processed later. Nevertheless the
+ // ImageMap is inserted into the IMap-Array, because it might be used
+ // already.
+ pImageMap = new ImageMap;
+ if( ParseMapOptions( pImageMap) )
+ {
+ if( !pImageMaps )
+ pImageMaps = new ImageMaps;
+ pImageMaps->Insert( pImageMap, pImageMaps->Count() );
+ }
+ else
+ {
+ delete pImageMap;
+ pImageMap = 0;
+ }
+ break;
+
+ case HTML_MAP_OFF:
+ // there is no ImageMap anymore (don't delete IMap, because it's
+ // already contained in the array!)
+ pImageMap = 0;
+ break;
+
+ case HTML_AREA:
+ if( pImageMap )
+ ParseAreaOptions( pImageMap, sBaseURL, SFX_EVENT_MOUSEOVER_OBJECT,
+ SFX_EVENT_MOUSEOUT_OBJECT );
+ break;
+
+ case HTML_FRAMESET_ON:
+ bInsertUnknown = bKeepUnknown;
+ break;
+
+ case HTML_NOFRAMES_ON:
+ if( IsInHeader() )
+ FinishHeader( sal_True );
+ bInsertUnknown = bKeepUnknown;
+ break;
+
+ case HTML_UNKNOWNCONTROL_ON:
+ // Ignore content of unknown token in the header, if the token
+ // does not start with a '!'.
+ if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() &&
+ sSaveToken.Len() && '!' != sSaveToken.GetChar(0) &&
+ '%' != sSaveToken.GetChar(0) )
+ aUnknownToken = sSaveToken;
+ // no break
+
+ default:
+ bInsertUnknown = bKeepUnknown;
+ break;
+ }
+
+ if( bGetIDOption )
+ InsertIDOption();
+
+ if( bInsertUnknown )
+ {
+ String aComment(
+ String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
+ if( (HTML_TOKEN_ONOFF & nToken) != 0 && (1 & nToken) != 0 )
+ aComment += '/';
+ aComment += sSaveToken;
+ if( aToken.Len() )
+ {
+ UnescapeToken();
+ (aComment += ' ') += aToken;
+ }
+ aComment += '>';
+ InsertComment( aComment );
+ }
+
+ // if there are temporary paragraph attributes and the
+ // paragraph isn't empty then the paragraph attributes are final.
+ if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+}
+
+
+extern sal_Bool lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
+
+void lcl_swhtml_getItemInfo( const _HTMLAttr& rAttr,
+ sal_Bool& rScriptDependent, sal_Bool& rFont,
+ sal_uInt16& rScriptType )
+{
+ sal_uInt16 nWhich = rAttr.GetItem().Which();
+ switch( nWhich )
+ {
+ case RES_CHRATR_FONT:
+ rFont = sal_True;
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ rScriptType = i18n::ScriptType::LATIN;
+ rScriptDependent = sal_True;
+ break;
+ case RES_CHRATR_CJK_FONT:
+ rFont = sal_True;
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ rScriptType = i18n::ScriptType::ASIAN;
+ rScriptDependent = sal_True;
+ break;
+ case RES_CHRATR_CTL_FONT:
+ rFont = sal_True;
+ case RES_CHRATR_CTL_FONTSIZE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_CTL_WEIGHT:
+ rScriptType = i18n::ScriptType::COMPLEX;
+ rScriptDependent = sal_True;
+ break;
+ default:
+ rScriptDependent = sal_False;
+ rFont = sal_False;
+ break;
+ }
+}
+
+sal_Bool SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, sal_Bool bUpdateNum )
+{
+ // Ein harter Zeilen-Umbruch am Ende muss immer entfernt werden.
+ // Einen zweiten ersetzen wir durch einen Absatz-Abstand.
+ xub_StrLen nLFStripped = StripTrailingLF();
+ if( (AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode) && nLFStripped > 1 )
+ eMode = AM_SPACE;
+
+ // die harten Attribute an diesem Absatz werden nie mehr ungueltig
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ if( AM_SPACE==eMode || AM_NOSPACE==eMode )
+ {
+ SwTxtNode *pTxtNode =
+ pPam->GetPoint()->nNode.GetNode().GetTxtNode();
+
+ const SvxULSpaceItem& rULSpace =
+ (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
+
+ sal_Bool bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0
+ : rULSpace.GetLower() == 0;
+
+ if( bChange )
+ {
+ const SvxULSpaceItem& rCollULSpace =
+ pTxtNode->GetAnyFmtColl().GetULSpace();
+
+ sal_Bool bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0
+ : rCollULSpace.GetLower() > 0;
+
+ if( bMayReset &&
+ rCollULSpace.GetUpper() == rULSpace.GetUpper() )
+ {
+ pTxtNode->ResetAttr( RES_UL_SPACE );
+ }
+ else
+ {
+ pTxtNode->SetAttr(
+ SvxULSpaceItem( rULSpace.GetUpper(),
+ AM_NOSPACE==eMode ? 0 : HTML_PARSPACE, RES_UL_SPACE ) );
+ }
+ }
+ }
+ bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode;
+
+ SwPosition aOldPos( *pPam->GetPoint() );
+
+ sal_Bool bRet = pDoc->AppendTxtNode( *pPam->GetPoint() );
+
+ // Zeichen-Attribute aufspalten und ggf keine setzen, die ueber den
+ // ganzen Absatz gesetzt sind
+ const SwNodeIndex& rEndIdx = aOldPos.nNode;
+ xub_StrLen nEndCnt = aOldPos.nContent.GetIndex();
+ const SwPosition& rPos = *pPam->GetPoint();
+
+ _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
+ for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
+ nCnt--; ++pTbl )
+ {
+ _HTMLAttr *pAttr = *pTbl;
+ if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN )
+ {
+ sal_Bool bWholePara = sal_False;
+
+ while( pAttr )
+ {
+ _HTMLAttr *pNext = pAttr->GetNext();
+ if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() ||
+ (!bWholePara &&
+ pAttr->GetSttPara() == rEndIdx &&
+ pAttr->GetSttCnt() != nEndCnt) )
+ {
+ bWholePara =
+ pAttr->GetSttPara() == rEndIdx &&
+ pAttr->GetSttCnt() == 0;
+
+ xub_StrLen nStt = pAttr->nSttCntnt;
+ sal_Bool bScript = sal_False, bFont = sal_False;
+ sal_uInt16 nScriptItem;
+ sal_Bool bInsert = sal_True;
+ lcl_swhtml_getItemInfo( *pAttr, bScript, bFont,
+ nScriptItem );
+ // den besehrigen Teil setzen
+ if( bInsert && bScript )
+ {
+ const SwTxtNode *pTxtNd =
+ pAttr->GetSttPara().GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "No text node" );
+ if( pTxtNd )
+ {
+ const String& rText = pTxtNd->GetTxt();
+ sal_uInt16 nScriptTxt =
+ pBreakIt->GetBreakIter()->getScriptType(
+ rText, pAttr->GetSttCnt() );
+ xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
+ ->endOfScript( rText, nStt, nScriptTxt );
+ while( nScriptEnd < nEndCnt )
+ {
+ if( nScriptItem == nScriptTxt )
+ {
+ _HTMLAttr *pSetAttr =
+ pAttr->Clone( rEndIdx, nScriptEnd );
+ pSetAttr->nSttCntnt = nStt;
+ pSetAttr->ClearPrev();
+ if( !pNext || bWholePara )
+ {
+ sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
+ : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pSetAttr, nTmp );
+ }
+ else
+ pNext->InsertPrev( pSetAttr );
+ }
+ nStt = nScriptEnd;
+ nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
+ rText, nStt );
+ nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
+ ->endOfScript( rText, nStt, nScriptTxt );
+ }
+ bInsert = nScriptItem == nScriptTxt;
+ }
+ }
+ if( bInsert )
+ {
+ _HTMLAttr *pSetAttr =
+ pAttr->Clone( rEndIdx, nEndCnt );
+ pSetAttr->nSttCntnt = nStt;
+
+ // Wenn das Attribut den gesamten Absatz umspannt, werden
+ // alle auesseren Attribute nicht mehr beachtet. Deshalb
+ // darf es auch nicht in die Prev-Liste eines ausseren
+ // Attributs eingetragen werden, denn dieses wird ja
+ // erstmal nicht gesetzt. Das fuehrt zu verschiebenungen,
+ // wenn Felder ins Rennen kommen
+ if( !pNext || bWholePara )
+ {
+ sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
+ : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pSetAttr, nTmp );
+ }
+ else
+ pNext->InsertPrev( pSetAttr );
+ }
+ else
+ {
+ _HTMLAttr *pPrev = pAttr->GetPrev();
+ if( pPrev )
+ {
+ // Die Previous-Attribute muessen trotzdem gesetzt werden.
+ if( !pNext || bWholePara )
+ {
+ sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pPrev, nTmp );
+ }
+ else
+ pNext->InsertPrev( pPrev );
+ }
+ }
+ pAttr->ClearPrev();
+ }
+
+ pAttr->SetStart( rPos );
+ pAttr = pNext;
+ }
+ }
+ }
+
+ if( bUpdateNum )
+ {
+ if( GetNumInfo().GetDepth() )
+ {
+ sal_uInt8 nLvl = GetNumInfo().GetLevel();
+ SetNodeNum( nLvl, false );
+ }
+ else
+ pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
+ }
+
+ // Attrubute im Absatz davor sollte man jetzt setzen (wegen JavaScript)
+ SetAttr();
+
+ // Now it is time to get rid of all script dependent hints that are
+ // equal to the settings in the style
+ SwTxtNode *pTxtNd = rEndIdx.GetNode().GetTxtNode();
+ OSL_ENSURE( pTxtNd, "There is the txt node" );
+ sal_uInt16 nCntAttr = (pTxtNd && pTxtNd->GetpSwpHints())
+ ? pTxtNd->GetSwpHints().Count() : 0;
+ if( nCntAttr )
+ {
+ // These are the end position of all script depenent hints.
+ // If we find a hint that starts before the current end position,
+ // we have to set it. If we finf a hint that start behind or at
+ // that position, we have to take the hint's value into account.
+ // If it is equal to the style, or in fact the paragarph's value
+ // for that hint, the hint is removed. Otherwise it's end position
+ // is remembered.
+ xub_StrLen aEndPos[15] =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ SwpHints& rHints = pTxtNd->GetSwpHints();
+ for( sal_uInt16 i=0; i < nCntAttr; i++ )
+ {
+ SwTxtAttr *pHt = rHints.GetTextHint( i );
+ sal_uInt16 nWhich = pHt->Which();
+ sal_Int16 nIdx = -1;
+ if( RES_CHRATR_CJK_FONT <= nWhich &&
+ nWhich <= RES_CHRATR_CTL_WEIGHT )
+ {
+ nIdx = static_cast< sal_uInt16 >(nWhich - RES_CHRATR_CJK_FONT + 5);
+ }
+ else switch( nWhich )
+ {
+ case RES_CHRATR_FONT: nIdx = 0; break;
+ case RES_CHRATR_FONTSIZE: nIdx = 1; break;
+ case RES_CHRATR_LANGUAGE: nIdx = 2; break;
+ case RES_CHRATR_POSTURE: nIdx = 3; break;
+ case RES_CHRATR_WEIGHT: nIdx = 4; break;
+ }
+ if( nIdx != -1 )
+ {
+ xub_StrLen nStt = *pHt->GetStart();
+ if( nStt >= aEndPos[nIdx] )
+ {
+ sal_Bool bFont = (nIdx % 5) == 0;
+ const SfxPoolItem& rItem =
+ ((const SwCntntNode *)pTxtNd)->GetAttr( nWhich );
+ if( bFont ? lcl_css1atr_equalFontItems(rItem,pHt->GetAttr())
+ : rItem == pHt->GetAttr() )
+ {
+ // The hint is the same as set in the paragraph and
+ // therfor, it can be deleted
+ // CAUTION!!! This WILL delete the hint and it MAY
+ // also delete the SwpHints!!! To avoid any trouble
+ // we leave the loop immediately if this is the last
+ // hint.
+ pTxtNd->DeleteAttribute( pHt );
+ if( 1 == nCntAttr )
+ break;
+ i--;
+ nCntAttr--;
+ }
+ else
+ {
+ // The hint is deifferent. Therfor all hints within that
+ // hint have to be ignored.
+ aEndPos[nIdx] = pHt->GetEnd() ? *pHt->GetEnd() : nStt;
+ }
+ }
+ else
+ {
+ // The hint starts before another one ends.
+ // The hint in this case is not deleted
+ OSL_ENSURE( pHt->GetEnd() && *pHt->GetEnd() <= aEndPos[nIdx],
+ "hints aren't nested properly!" );
+ }
+ }
+ }
+ }
+
+
+ if( !pTable && !--nParaCnt )
+ Show();
+
+ return bRet;
+}
+
+void SwHTMLParser::AddParSpace()
+{
+ if( !bNoParSpace )
+ return;
+
+ bNoParSpace = sal_False;
+
+ sal_uLong nNdIdx = pPam->GetPoint()->nNode.GetIndex() - 1;
+
+ SwTxtNode *pTxtNode = pDoc->GetNodes()[nNdIdx]->GetTxtNode();
+ if( !pTxtNode )
+ return;
+
+ SvxULSpaceItem rULSpace =
+ (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
+ if( !rULSpace.GetLower() )
+ {
+ const SvxULSpaceItem& rCollULSpace =
+ pTxtNode->GetAnyFmtColl().GetULSpace();
+ if( rCollULSpace.GetLower() &&
+ rCollULSpace.GetUpper() == rULSpace.GetUpper() )
+ {
+ pTxtNode->ResetAttr( RES_UL_SPACE );
+ }
+ else
+ {
+ pTxtNode->SetAttr(
+ SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE, RES_UL_SPACE ) );
+ }
+ }
+}
+
+
+void SwHTMLParser::Show()
+{
+ // Hier wird
+ // - ein EndAction gerufen, damit formatiert wird
+ // - ein Reschedule gerufen,
+ // - die eiegen View-Shell wieder gesetzt
+ // - und Start-Action gerufen
+
+ OSL_ENSURE( SVPAR_WORKING==eState, "Show nicht im Working-State - Das kann ins Auge gehen" );
+ ViewShell *pOldVSh = CallEndAction();
+
+ GetpApp()->Reschedule();
+
+ if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
+ || 1 == pDoc->getReferenceCount() )
+ {
+ // wurde der Import vom SFX abgebrochen?
+ eState = SVPAR_ERROR;
+ }
+
+ // Die ViewShell nochmal holen, denn sie koennte im Reschedule
+ // zerstoert wirden sein.
+ ViewShell *pVSh = CallStartAction( pOldVSh );
+
+ // ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir
+ // eine groessere Schrittweite
+ if( pVSh )
+ {
+ nParaCnt = (pPam->GetPoint()->nNode.GetNode().IsInVisibleArea(pVSh))
+ ? 5 : 50;
+ }
+}
+
+void SwHTMLParser::ShowStatline()
+{
+ // Hier wird
+ // - ein Reschedule gerufen, damit gescrollt werden kann
+ // - die eiegen View-Shell wieder gesetzt
+ // - ein Start/End-Action gerufen, wenn gescrollt wurde.
+
+ OSL_ENSURE( SVPAR_WORKING==eState, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" );
+
+ // Laufbalkenanzeige
+ if( !GetMedium() || !GetMedium()->IsRemote() )
+ {
+ ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
+ CheckActionViewShell();
+ }
+ else
+ {
+ GetpApp()->Reschedule();
+
+ if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
+ || 1 == pDoc->getReferenceCount() )
+ // wurde der Import vom SFX abgebrochen?
+ eState = SVPAR_ERROR;
+
+ ViewShell *pVSh = CheckActionViewShell();
+ if( pVSh && pVSh->HasInvalidRect() )
+ {
+ CallEndAction( sal_False, sal_False );
+ CallStartAction( pVSh, sal_False );
+ }
+ }
+}
+
+ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, sal_Bool bChkPtr )
+{
+ OSL_ENSURE( !pActionViewShell, "CallStartAction: ViewShell schon gesetzt" );
+
+ if( !pVSh || bChkPtr )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ViewShell *pOldVSh = pVSh;
+#endif
+ pDoc->GetEditShell( &pVSh );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( !pVSh || !pOldVSh || pOldVSh == pVSh, "CallStartAction: Wer hat die ViewShell ausgetauscht?" );
+ if( pOldVSh && !pVSh )
+ pVSh = 0;
+#endif
+ }
+ pActionViewShell = pVSh;
+
+ if( pActionViewShell )
+ {
+ if( pActionViewShell->ISA( SwEditShell ) )
+ ((SwEditShell*)pActionViewShell)->StartAction();
+ else
+ pActionViewShell->StartAction();
+ }
+
+ return pActionViewShell;
+}
+
+ViewShell *SwHTMLParser::CallEndAction( sal_Bool bChkAction, sal_Bool bChkPtr )
+{
+ if( bChkPtr )
+ {
+ ViewShell *pVSh = 0;
+ pDoc->GetEditShell( &pVSh );
+ OSL_ENSURE( !pVSh || pActionViewShell == pVSh,
+ "CallEndAction: Wer hat die ViewShell ausgetauscht?" );
+#if OSL_DEBUG_LEVEL > 1
+ if( pActionViewShell && !pVSh )
+ pVSh = 0;
+#endif
+ if( pVSh != pActionViewShell )
+ pActionViewShell = 0;
+ }
+
+ if( !pActionViewShell || (bChkAction && !pActionViewShell->ActionPend()) )
+ return pActionViewShell;
+
+ if( bSetCrsr )
+ {
+ // an allen CrsrEditShells die Cursor auf den Doc-Anfang setzen
+ ViewShell *pSh = pActionViewShell;
+ do {
+ if( pSh->IsA( TYPE( SwCrsrShell ) ) )
+ ((SwCrsrShell*)pSh)->SttEndDoc(sal_True);
+ pSh = (ViewShell *)pSh->GetNext();
+ } while( pSh != pActionViewShell );
+
+ bSetCrsr = sal_False;
+ }
+ if( pActionViewShell->ISA( SwEditShell ) )
+ {
+ //Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt!
+ const sal_Bool bOldLock = pActionViewShell->IsViewLocked();
+ pActionViewShell->LockView( sal_True );
+ const sal_Bool bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev();
+ pActionViewShell->SetEndActionByVirDev( sal_True );;
+ ((SwEditShell*)pActionViewShell)->EndAction();
+ pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev );
+ pActionViewShell->LockView( bOldLock );
+
+ // bChkJumpMark ist nur gesetzt, wenn das Object auch gefunden wurde
+ if( bChkJumpMark )
+ {
+ const Point aVisSttPos( DOCUMENTBORDER, DOCUMENTBORDER );
+ if( GetMedium() && aVisSttPos == pActionViewShell->VisArea().Pos() )
+ ::JumpToSwMark( pActionViewShell,
+ GetMedium()->GetURLObject().GetMark() );
+ bChkJumpMark = sal_False;
+ }
+ }
+ else
+ pActionViewShell->EndAction();
+
+ // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
+ // man hier abbrechen und einen Fehler setzen.
+ if( 1 == pDoc->getReferenceCount() )
+ {
+ eState = SVPAR_ERROR;
+ }
+
+ ViewShell *pVSh = pActionViewShell;
+ pActionViewShell = 0;
+
+ return pVSh;
+}
+
+ViewShell *SwHTMLParser::CheckActionViewShell()
+{
+ ViewShell *pVSh = 0;
+ pDoc->GetEditShell( &pVSh );
+ OSL_ENSURE( !pVSh || pActionViewShell == pVSh,
+ "CheckActionViewShell: Wer hat die ViewShell ausgetauscht?" );
+#if OSL_DEBUG_LEVEL > 1
+ if( pActionViewShell && !pVSh )
+ pVSh = 0;
+#endif
+ if( pVSh != pActionViewShell )
+ pActionViewShell = 0;
+
+ return pActionViewShell;
+}
+
+/* */
+
+void SwHTMLParser::_SetAttr( sal_Bool bChkEnd, sal_Bool bBeforeTable,
+ _HTMLAttrs *pPostIts )
+{
+ SwPaM* pAttrPam = new SwPaM( *pPam->GetPoint() );
+ const SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
+ xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
+ _HTMLAttr* pAttr;
+ SwCntntNode* pCNd;
+ sal_uInt16 n;
+
+ _HTMLAttrs aFields( 5, 5 );
+
+ for( n = aSetAttrTab.Count(); n; )
+ {
+ pAttr = aSetAttrTab[ --n ];
+ sal_uInt16 nWhich = pAttr->pItem->Which();
+
+ sal_uLong nEndParaIdx = pAttr->GetEndParaIdx();
+ sal_Bool bSetAttr;
+ if( bChkEnd )
+ {
+ // Zechen-Attribute mit Ende moeglich frueh,
+ // also noch im aktuellen Absatz setzen (wegen JavaScript
+ // und diversen Chats). das darf man aber nicht fuer Attribute,
+ // die ueber den ganzen Absatz aufgspannt werden sollen, weil
+ // sie aus Absatzvorlgen stammen, die nicht gesetzt werden
+ // koennen. Weil die Attribute mit SETATTR_DONTREPLACE
+ // eingefuegt werden, sollte man sie auch anchtraeglich
+ // noch setzen koennen.
+ bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() &&
+ (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) ||
+ ( !pAttr->IsLikePara() &&
+ nEndParaIdx == rEndIdx.GetIndex() &&
+ pAttr->GetEndCnt() < nEndCnt &&
+ (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) ||
+ ( bBeforeTable &&
+ nEndParaIdx == rEndIdx.GetIndex() &&
+ !pAttr->GetEndCnt() );
+ }
+ else
+ {
+ // Attribiute im Content-Bereich duerfen nicht gesetzt
+ // werden, wenn wir in einem Sonderbereich stehen, aber
+ // umgekekehrt schon.
+ sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ bSetAttr = nEndParaIdx < rEndIdx.GetIndex() ||
+ rEndIdx.GetIndex() > nEndOfIcons ||
+ nEndParaIdx <= nEndOfIcons;
+ }
+
+ if( bSetAttr )
+ {
+ // Das Attribute darf nicht in der liste der vorlaeufigen
+ // Absatz-Attribute stehen, weil es sonst geloescht wurde.
+ sal_uInt16 ii = aParaAttrs.Count();
+ while( ii-- )
+ {
+ OSL_ENSURE( pAttr != aParaAttrs[ii],
+ "SetAttr: Attribut duerfte noch nicht gesetzt werden" );
+ aParaAttrs.Remove( ii );
+ }
+
+
+ // dann also setzen
+ aSetAttrTab.Remove( n, 1 );
+
+ while( pAttr )
+ {
+ _HTMLAttr *pPrev = pAttr->GetPrev();
+ if( !pAttr->bValid )
+ {
+ // ungueltige Attribute koennen gloescht werden
+ delete pAttr;
+ pAttr = pPrev;
+ continue; //break;
+ }
+
+
+ pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ // durch die elende Loescherei von Nodes kann auch mal
+ // ein Index auf einen End-Node zeigen :-(
+ if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) &&
+ !isTXTATR_NOEND(nWhich) )
+ {
+ // wenn der End-Index auch auf den Node zeigt
+ // brauchen wir auch kein Attribut mehr zu setzen,
+ // es sei denn, es ist ein Text-Attribut.
+ delete pAttr;
+ pAttr = pPrev;
+ continue; //break;
+ }
+ pCNd = pDoc->GetNodes().GoNext( &(pAttr->nSttPara) );
+ if( pCNd )
+ pAttr->nSttCntnt = 0;
+ else
+ {
+ OSL_ENSURE( !this, "SetAttr: GoNext() failed!" );
+ delete pAttr;
+ pAttr = pPrev;
+ continue; // break;
+ }
+ }
+ pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
+
+
+
+ // durch das Loeschen von BRs kann der Start-Index
+ // auch mal hinter das Ende des Textes zeigen
+ if( pAttr->nSttCntnt > pCNd->Len() )
+ pAttr->nSttCntnt = pCNd->Len();
+ pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
+
+ pAttrPam->SetMark();
+ if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) &&
+ !isTXTATR_NOEND(nWhich) )
+ {
+ pCNd = pAttr->nEndPara.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) );
+ if( pCNd )
+ pAttr->nEndCntnt = pCNd->Len();
+ else
+ {
+ OSL_ENSURE( !this, "SetAttr: GoPrevious() failed!" );
+ pAttrPam->DeleteMark();
+ delete pAttr;
+ pAttr = pPrev;
+ continue; // break;
+ }
+ }
+
+ pAttrPam->GetPoint()->nNode = pAttr->nEndPara;
+ }
+ else if( pAttr->IsLikePara() )
+ {
+ pAttr->nEndCntnt = pCNd->Len();
+ }
+
+ // durch das Loeschen von BRs kann der End-Index
+ // auch mal hinter das Ende des Textes zeigen
+ if( pAttr->nEndCntnt > pCNd->Len() )
+ pAttr->nEndCntnt = pCNd->Len();
+
+ pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nEndCntnt );
+ if( bBeforeTable &&
+ pAttrPam->GetPoint()->nNode.GetIndex() ==
+ rEndIdx.GetIndex() )
+ {
+ // wenn wir vor dem Einfuegen einer Tabelle stehen
+ // und das Attribut im aktuellen Node beendet wird,
+ // muessen wir es im Node davor beenden oder wegschmeissen,
+ // wenn es erst in dem Node beginnt
+ if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC &&
+ !isTXTATR_NOEND(nWhich) )
+ {
+ if( pAttrPam->GetMark()->nNode.GetIndex() !=
+ rEndIdx.GetIndex() )
+ {
+ OSL_ENSURE( !pAttrPam->GetPoint()->nContent.GetIndex(),
+ "Content-Position vor Tabelle nicht 0???" );
+ pAttrPam->Move( fnMoveBackward );
+ }
+ else
+ {
+ pAttrPam->DeleteMark();
+ delete pAttr;
+ pAttr = pPrev;
+ continue;
+ }
+ }
+ }
+
+ switch( nWhich )
+ {
+ case RES_FLTR_BOOKMARK: // insert bookmark
+ {
+ const String sName( ((SfxStringItem*)pAttr->pItem)->GetValue() );
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName );
+ if( ppBkmk != pMarkAccess->getMarksEnd() &&
+ ppBkmk->get()->GetMarkStart() == *pAttrPam->GetPoint() )
+ break; // do not generate duplicates on this position
+ pAttrPam->DeleteMark();
+ const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
+ *pAttrPam,
+ sName,
+ IDocumentMarkAccess::BOOKMARK );
+
+ // jump to bookmark
+ if( JUMPTO_MARK == eJumpTo && pNewMark->GetName() == ::rtl::OUString(sJmpMark) )
+ {
+ bChkJumpMark = sal_True;
+ eJumpTo = JUMPTO_NONE;
+ }
+ }
+ break;
+ case RES_TXTATR_FIELD:
+ {
+ sal_uInt16 nFldWhich =
+ pPostIts ? ((const SwFmtFld *)pAttr->pItem)
+ ->GetFld()->GetTyp()->Which() : 0;
+ if( pPostIts && (RES_POSTITFLD == nFldWhich ||
+ RES_SCRIPTFLD == nFldWhich) )
+ {
+ pPostIts->Insert( pAttr, 0 );
+ }
+ else
+ {
+ aFields.Insert( pAttr, aFields.Count() );
+ }
+ }
+ pAttrPam->DeleteMark();
+ pAttr = pPrev;
+ continue;
+
+ case RES_LR_SPACE:
+ if( pAttrPam->GetPoint()->nNode.GetIndex() ==
+ pAttrPam->GetMark()->nNode.GetIndex() &&
+ pCNd )
+ {
+ // wegen Numerierungen dieses Attribut direkt
+ // am Node setzen
+ pCNd->SetAttr( *pAttr->pItem );
+ break;
+ }
+ OSL_ENSURE( !this,
+ "LRSpace ueber mehrere Absaetze gesetzt!" );
+ // kein break (hier sollen wir trotzdem nie hinkommen;
+ default:
+
+ // ggfs. ein Bookmark anspringen
+ if( RES_TXTATR_INETFMT == nWhich &&
+ JUMPTO_MARK == eJumpTo &&
+ sJmpMark == ((SwFmtINetFmt*)pAttr->pItem)->GetName() )
+ {
+ bChkJumpMark = sal_True;
+ eJumpTo = JUMPTO_NONE;
+ }
+
+ pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, nsSetAttrMode::SETATTR_DONTREPLACE );
+ }
+ pAttrPam->DeleteMark();
+
+ delete pAttr;
+ pAttr = pPrev;
+ }
+ }
+ }
+
+ for( n = aMoveFlyFrms.Count(); n; )
+ {
+ SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ];
+
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ OSL_ENSURE( FLY_AT_PARA == rAnchor.GetAnchorId(),
+ "Nur Auto-Rahmen brauchen eine Spezialbehandlung" );
+ const SwPosition *pFlyPos = rAnchor.GetCntntAnchor();
+ sal_uLong nFlyParaIdx = pFlyPos->nNode.GetIndex();
+ sal_Bool bMoveFly;
+ if( bChkEnd )
+ {
+ bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
+ ( nFlyParaIdx == rEndIdx.GetIndex() &&
+ aMoveFlyCnts[n] < nEndCnt );
+ }
+ else
+ {
+ sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
+ rEndIdx.GetIndex() > nEndOfIcons ||
+ nFlyParaIdx <= nEndOfIcons;
+ }
+ if( bMoveFly )
+ {
+ pFrmFmt->DelFrms();
+ *pAttrPam->GetPoint() = *pFlyPos;
+ pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetCntntNode(),
+ aMoveFlyCnts[n] );
+ SwFmtAnchor aAnchor( rAnchor );
+ aAnchor.SetType( FLY_AT_CHAR );
+ aAnchor.SetAnchor( pAttrPam->GetPoint() );
+ pFrmFmt->SetFmtAttr( aAnchor );
+
+ const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient();
+ if( text::HoriOrientation::LEFT == rHoriOri.GetHoriOrient() )
+ {
+ SwFmtHoriOrient aHoriOri( rHoriOri );
+ aHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
+ pFrmFmt->SetFmtAttr( aHoriOri );
+ }
+ const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient();
+ if( text::VertOrientation::TOP == rVertOri.GetVertOrient() )
+ {
+ SwFmtVertOrient aVertOri( rVertOri );
+ aVertOri.SetRelationOrient( text::RelOrientation::CHAR );
+ pFrmFmt->SetFmtAttr( aVertOri );
+ }
+
+ pFrmFmt->MakeFrms();
+ aMoveFlyFrms.Remove( n, 1 );
+ aMoveFlyCnts.erase( aMoveFlyCnts.begin() + n );
+ }
+ }
+ while( aFields.Count() )
+ {
+ pAttr = aFields[0];
+
+ pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
+ pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
+ pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
+
+ if( bBeforeTable &&
+ pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() )
+ {
+ OSL_ENSURE( !bBeforeTable, "Aha, der Fall tritt also doch ein" );
+ OSL_ENSURE( !pAttrPam->GetPoint()->nContent.GetIndex(),
+ "Content-Position vor Tabelle nicht 0???" );
+ // !!!
+ pAttrPam->Move( fnMoveBackward );
+ }
+
+ pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, 0 );
+
+ aFields.Remove( 0, 1 );
+ delete pAttr;
+ }
+
+ delete pAttrPam;
+}
+
+void SwHTMLParser::NewAttr( _HTMLAttr **ppAttr, const SfxPoolItem& rItem )
+{
+ // Font-Hoehen und -Farben- sowie Escapement-Attribute duerfen nicht
+ // zusammengefasst werden. Sie werden deshalb in einer Liste gespeichert,
+ // in der das zuletzt aufgespannte Attribut vorne steht und der Count
+ // immer 1 ist. Fuer alle anderen Attribute wird der Count einfach
+ // hochgezaehlt.
+ if( *ppAttr )
+ {
+ _HTMLAttr *pAttr = new _HTMLAttr( *pPam->GetPoint(), rItem,
+ ppAttr );
+ pAttr->InsertNext( *ppAttr );
+ (*ppAttr) = pAttr;
+ }
+ else
+ (*ppAttr) = new _HTMLAttr( *pPam->GetPoint(), rItem, ppAttr );
+}
+
+
+void SwHTMLParser::EndAttr( _HTMLAttr* pAttr, _HTMLAttr **ppDepAttr,
+ sal_Bool bChkEmpty )
+{
+ OSL_ENSURE( !ppDepAttr, "SwHTMLParser::EndAttr: ppDepAttr-Feature ungetestet?" );
+ // Der Listenkopf ist im Attribut gespeichert
+ _HTMLAttr **ppHead = pAttr->ppHead;
+
+ OSL_ENSURE( ppHead, "keinen Attributs-Listenkopf gefunden!" );
+
+ // die aktuelle Psoition als Ende-Position merken
+ const SwNodeIndex* pEndIdx = &pPam->GetPoint()->nNode;
+ xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
+
+ // WIrd das zueltzt gestartete oder ein frueher gestartetes Attribut
+ // beendet?
+ _HTMLAttr *pLast = 0;
+ if( ppHead && pAttr != *ppHead )
+ {
+ // Es wird nicht das zuletzt gestartete Attribut beendet
+
+ // Dann suche wir das unmittelbar danach gestartete Attribut, das
+ // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
+ // mehr in der Liste
+ pLast = *ppHead;
+ while( pLast && pLast->GetNext() != pAttr )
+ pLast = pLast->GetNext();
+
+ OSL_ENSURE( pLast, "Attribut nicht in eigener Liste gefunden!" );
+ }
+
+ sal_Bool bMoveBack = sal_False;
+ sal_uInt16 nWhich = pAttr->pItem->Which();
+ if( !nEndCnt && RES_PARATR_BEGIN <= nWhich &&
+ *pEndIdx != pAttr->GetSttPara() )
+ {
+ // dann eine Cntntnt Position zurueck!
+ bMoveBack = pPam->Move( fnMoveBackward );
+ nEndCnt = pPam->GetPoint()->nContent.GetIndex();
+ }
+
+ // nun das Attrubut beenden
+ _HTMLAttr *pNext = pAttr->GetNext();
+
+
+ sal_Bool bInsert;
+ sal_uInt16 nScriptItem = 0;
+ sal_Bool bScript = sal_False, bFont = sal_False;
+ // ein Bereich ??
+ if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
+ RES_PAGEDESC == nWhich || RES_BREAK == nWhich ||
+ *pEndIdx != pAttr->GetSttPara() ||
+ nEndCnt != pAttr->GetSttCnt() )
+ {
+ bInsert = sal_True;
+ // We do some optimization for script depenedent attribtes here.
+ if( *pEndIdx == pAttr->GetSttPara() )
+ {
+ lcl_swhtml_getItemInfo( *pAttr, bScript, bFont, nScriptItem );
+ }
+ }
+ else
+ {
+ bInsert = sal_False;
+ }
+
+ if( bInsert && bScript )
+ {
+ const SwTxtNode *pTxtNd = pAttr->GetSttPara().GetNode()
+ .GetTxtNode();
+ OSL_ENSURE( pTxtNd, "No text node" );
+ const String& rText = pTxtNd->GetTxt();
+ sal_uInt16 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
+ rText, pAttr->GetSttCnt() );
+ xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
+ ->endOfScript( rText, pAttr->GetSttCnt(), nScriptTxt );
+ while( nScriptEnd < nEndCnt )
+ {
+ if( nScriptItem == nScriptTxt )
+ {
+ _HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd );
+ pSetAttr->ClearPrev();
+ if( pNext )
+ pNext->InsertPrev( pSetAttr );
+ else
+ {
+ sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
+ : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pSetAttr, nTmp );
+ }
+ }
+ pAttr->nSttCntnt = nScriptEnd;
+ nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
+ rText, nScriptEnd );
+ nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
+ ->endOfScript( rText, nScriptEnd, nScriptTxt );
+ }
+ bInsert = nScriptItem == nScriptTxt;
+ }
+ if( bInsert )
+ {
+ pAttr->nEndPara = *pEndIdx;
+ pAttr->nEndCntnt = nEndCnt;
+ pAttr->bInsAtStart = RES_TXTATR_INETFMT != nWhich &&
+ RES_TXTATR_CHARFMT != nWhich;
+
+ if( !pNext )
+ {
+ // keine offenen Attribute dieses Typs mehr da,
+ // dann koennen alle gesetzt werden, es sei denn
+ // sie haengen noch von einem anderen Attribut ab,
+ // dann werden sie dort angehaengt
+ if( ppDepAttr && *ppDepAttr )
+ (*ppDepAttr)->InsertPrev( pAttr );
+ else
+ {
+ sal_uInt16 nTmp = pAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pAttr, nTmp );
+ }
+ }
+ else
+ {
+ // es gibt noch andere offene Attribute des Typs,
+ // daher muss das Setzen zurueckgestellt werden.
+ // das aktuelle Attribut wird deshalb hinten an die
+ // Previous-Liste des Nachfolgers angehaengt
+ pNext->InsertPrev( pAttr );
+ }
+ }
+ else
+ {
+ // dann nicht einfuegen, sondern Loeschen. Durch das "tuerken" von
+ // Vorlagen durch harte Attributierung koennen sich auch mal andere
+ // leere Attribute in der Prev-Liste befinden, die dann trotzdem
+ // gesetzt werden muessen
+ _HTMLAttr *pPrev = pAttr->GetPrev();
+ delete pAttr;
+
+ if( pPrev )
+ {
+ // Die Previous-Attribute muessen trotzdem gesetzt werden.
+ if( pNext )
+ pNext->InsertPrev( pPrev );
+ else
+ {
+ sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pPrev, nTmp );
+ }
+ }
+
+ }
+
+ // wenn das erste Attribut der Liste gesetzt wurde muss noch der
+ // Listenkopf korrigiert werden.
+ if( pLast )
+ pLast->pNext = pNext;
+ else if( ppHead )
+ *ppHead = pNext;
+
+ if( bMoveBack )
+ pPam->Move( fnMoveForward );
+}
+
+void SwHTMLParser::DeleteAttr( _HTMLAttr* pAttr )
+{
+ // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
+ // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
+ OSL_ENSURE( !aParaAttrs.Count(),
+ "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ // Der Listenkopf ist im Attribut gespeichert
+ _HTMLAttr **ppHead = pAttr->ppHead;
+
+ OSL_ENSURE( ppHead, "keinen Attributs-Listenkopf gefunden!" );
+
+ // Wird das zueltzt gestartete oder ein frueher gestartetes Attribut
+ // entfernt?
+ _HTMLAttr *pLast = 0;
+ if( ppHead && pAttr != *ppHead )
+ {
+ // Es wird nicht das zuletzt gestartete Attribut beendet
+
+ // Dann suche wir das unmittelbar danach gestartete Attribut, das
+ // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
+ // mehr in der Liste
+ pLast = *ppHead;
+ while( pLast && pLast->GetNext() != pAttr )
+ pLast = pLast->GetNext();
+
+ OSL_ENSURE( pLast, "Attribut nicht in eigener Liste gefunden!" );
+ }
+
+ // nun das Attrubut entfernen
+ _HTMLAttr *pNext = pAttr->GetNext();
+ _HTMLAttr *pPrev = pAttr->GetPrev();
+ delete pAttr;
+
+ if( pPrev )
+ {
+ // Die Previous-Attribute muessen trotzdem gesetzt werden.
+ if( pNext )
+ pNext->InsertPrev( pPrev );
+ else
+ {
+ sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pPrev, nTmp );
+ }
+ }
+
+ // wenn das erste Attribut der Liste entfernt wurde muss noch der
+ // Listenkopf korrigiert werden.
+ if( pLast )
+ pLast->pNext = pNext;
+ else if( ppHead )
+ *ppHead = pNext;
+}
+
+void SwHTMLParser::SaveAttrTab( _HTMLAttrTable& rNewAttrTab )
+{
+ // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
+ // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
+ OSL_ENSURE( !aParaAttrs.Count(),
+ "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
+ _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
+
+ for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
+ nCnt--; (++pTbl, ++pSaveTbl) )
+ {
+ *pSaveTbl = *pTbl;
+
+ _HTMLAttr *pAttr = *pSaveTbl;
+ while( pAttr )
+ {
+ pAttr->SetHead( pSaveTbl );
+ pAttr = pAttr->GetNext();
+ }
+
+ *pTbl = 0;
+ }
+}
+
+void SwHTMLParser::SplitAttrTab( _HTMLAttrTable& rNewAttrTab,
+ sal_Bool bMoveEndBack )
+{
+ // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
+ // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
+ OSL_ENSURE( !aParaAttrs.Count(),
+ "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ const SwNodeIndex& nSttIdx = pPam->GetPoint()->nNode;
+ SwNodeIndex nEndIdx( nSttIdx );
+
+ // alle noch offenen Attribute beenden und hinter der Tabelle
+ // neu aufspannen
+ _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
+ _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
+ sal_Bool bSetAttr = sal_True;
+ xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex();
+ xub_StrLen nEndCnt = nSttCnt;
+
+ if( bMoveEndBack )
+ {
+ sal_uLong nOldEnd = nEndIdx.GetIndex();
+ sal_uLong nTmpIdx;
+ if( ( nTmpIdx = pDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd ||
+ ( nTmpIdx = pDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd )
+ {
+ nTmpIdx = pDoc->GetNodes().GetEndOfInserts().GetIndex();
+ }
+ SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious(&nEndIdx);
+
+ // keine Attribute setzen, wenn der PaM aus dem Content-Bereich
+ // herausgeschoben wurde.
+ bSetAttr = pCNd && nTmpIdx < nEndIdx.GetIndex();
+
+ nEndCnt = (bSetAttr ? pCNd->Len() : 0);
+ }
+ for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
+ nCnt--; (++pTbl, ++pSaveTbl) )
+ {
+ _HTMLAttr *pAttr = *pTbl;
+ *pSaveTbl = 0;
+ while( pAttr )
+ {
+ _HTMLAttr *pNext = pAttr->GetNext();
+ _HTMLAttr *pPrev = pAttr->GetPrev();
+
+ if( bSetAttr &&
+ ( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() ||
+ (pAttr->GetSttPara() == nEndIdx &&
+ pAttr->GetSttCnt() != nEndCnt) ) )
+ {
+ // das Attribut muss vor der Liste 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( nEndIdx, nEndCnt );
+
+ 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 und die Verkettungen
+ // aufbrechen
+ pAttr->Reset( nSttIdx, nSttCnt, pSaveTbl );
+
+ if( *pSaveTbl )
+ {
+ _HTMLAttr *pSAttr = *pSaveTbl;
+ while( pSAttr->GetNext() )
+ pSAttr = pSAttr->GetNext();
+ pSAttr->InsertNext( pAttr );
+ }
+ else
+ *pSaveTbl = pAttr;
+
+ pAttr = pNext;
+ }
+
+ *pTbl = 0;
+ }
+}
+
+void SwHTMLParser::RestoreAttrTab( const _HTMLAttrTable& rNewAttrTab,
+ sal_Bool bSetNewStart )
+{
+ // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
+ // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
+ OSL_ENSURE( !aParaAttrs.Count(),
+ "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
+ _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
+
+ for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
+ nCnt--; (++pTbl, ++pSaveTbl) )
+ {
+ OSL_ENSURE( !*pTbl, "Die Attribut-Tabelle ist nicht leer!" );
+
+ const SwPosition *pPos = pPam->GetPoint();
+ const SwNodeIndex& rSttPara = pPos->nNode;
+ xub_StrLen nSttCnt = pPos->nContent.GetIndex();
+
+ *pTbl = *pSaveTbl;
+
+ _HTMLAttr *pAttr = *pTbl;
+ while( pAttr )
+ {
+ OSL_ENSURE( !pAttr->GetPrev() || !pAttr->GetPrev()->ppHead,
+ "Previous-Attribut hat noch einen Header" );
+ pAttr->SetHead( pTbl );
+ if( bSetNewStart )
+ {
+ pAttr->nSttPara = rSttPara;
+ pAttr->nEndPara = rSttPara;
+ pAttr->nSttCntnt = nSttCnt;
+ pAttr->nEndCntnt = nSttCnt;
+ }
+ pAttr = pAttr->GetNext();
+ }
+
+ *pSaveTbl = 0;
+ }
+}
+
+void SwHTMLParser::InsertAttr( const SfxPoolItem& rItem, sal_Bool bLikePara,
+ sal_Bool bInsAtStart )
+{
+ _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(),
+ rItem );
+ if( bLikePara )
+ pTmp->SetLikePara();
+ sal_uInt16 nTmp = bInsAtStart ? 0 : aSetAttrTab.Count();
+ aSetAttrTab.Insert( pTmp, nTmp );
+}
+
+void SwHTMLParser::InsertAttrs( _HTMLAttrs& rAttrs )
+{
+ while( rAttrs.Count() )
+ {
+ _HTMLAttr *pAttr = rAttrs[0];
+ InsertAttr( pAttr->GetItem() );
+ rAttrs.Remove( 0, 1 );
+ delete pAttr;
+ }
+}
+
+/* */
+
+void SwHTMLParser::NewStdAttr( int nToken )
+{
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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_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;
+ }
+ }
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ if( HTML_SPAN_ON != nToken || !aClass.Len() ||
+ !CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) )
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
+ }
+ }
+
+ // den Kontext merken
+ PushContext( pCntxt );
+}
+
+void SwHTMLParser::NewStdAttr( int nToken,
+ _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
+ _HTMLAttr **ppAttr2, const SfxPoolItem *pItem2,
+ _HTMLAttr **ppAttr3, const SfxPoolItem *pItem3 )
+{
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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_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;
+ }
+ }
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ aItemSet.Put( rItem );
+ if( pItem2 )
+ aItemSet.Put( *pItem2 );
+ if( pItem3 )
+ aItemSet.Put( *pItem3 );
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+
+ InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
+ }
+ else
+ {
+ InsertAttr( ppAttr ,rItem, pCntxt );
+ if( pItem2 )
+ {
+ OSL_ENSURE( ppAttr2, "missing table entry for item2" );
+ InsertAttr( ppAttr2, *pItem2, pCntxt );
+ }
+ if( pItem3 )
+ {
+ OSL_ENSURE( ppAttr3, "missing table entry for item3" );
+ InsertAttr( ppAttr3, *pItem3, pCntxt );
+ }
+ }
+
+ // den Kontext merken
+ PushContext( pCntxt );
+}
+
+void SwHTMLParser::EndTag( int nToken )
+{
+ // den Kontext holen
+ _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
+ if( pCntxt )
+ {
+ // und ggf. die Attribute beenden
+ EndContext( pCntxt );
+ delete pCntxt;
+ }
+}
+
+
+void SwHTMLParser::NewBasefontAttr()
+{
+ String aId, aStyle, aClass, aLang, aDir;
+ sal_uInt16 nSize = 3;
+
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_SIZE:
+ nSize = (sal_uInt16)pOption->GetNumber();
+ break;
+ 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;
+ }
+ }
+
+ if( nSize < 1 )
+ nSize = 1;
+
+ if( nSize > 7 )
+ nSize = 7;
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_BASEFONT_ON );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+
+ InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
+ }
+ else
+ {
+ SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
+ aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
+ aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
+ }
+
+ // den Kontext merken
+ PushContext( pCntxt );
+
+ // die Font-Size merken
+ aBaseFontStack.Insert( nSize, aBaseFontStack.Count() );
+}
+
+void SwHTMLParser::EndBasefontAttr()
+{
+ EndTag( HTML_BASEFONT_ON );
+
+ // Stack-Unterlauf in Tabellen vermeiden
+ if( aBaseFontStack.Count() > nBaseFontStMin )
+ aBaseFontStack.Remove( aBaseFontStack.Count()-1, 1 );
+}
+
+void SwHTMLParser::NewFontAttr( int nToken )
+{
+ sal_uInt16 nBaseSize =
+ ( aBaseFontStack.Count() > nBaseFontStMin
+ ? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK)
+ : 3 );
+ sal_uInt16 nFontSize =
+ ( aFontStack.Count() > nFontStMin
+ ? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK)
+ : nBaseSize );
+
+ String aFace, aId, aStyle, aClass, aLang, aDir;
+ Color aColor;
+ sal_uLong nFontHeight = 0; // tatsaechlich einzustellende Font-Hoehe
+ sal_uInt16 nSize = 0; // Fontgroesse in Netscape-Notation (1-7)
+ sal_Bool bColor = sal_False;
+
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_SIZE:
+ if( HTML_FONT_ON==nToken && pOption->GetString().Len() )
+ {
+ sal_Int32 nSSize;
+ if( '+' == pOption->GetString().GetChar(0) ||
+ '-' == pOption->GetString().GetChar(0) )
+ nSSize = nBaseSize + pOption->GetSNumber();
+ else
+ nSSize = (sal_Int32)pOption->GetNumber();
+
+ if( nSSize < 1 )
+ nSSize = 1;
+ else if( nSSize > 7 )
+ nSSize = 7;
+
+ nSize = (sal_uInt16)nSSize;
+ nFontHeight = aFontHeights[nSize-1];
+ }
+ break;
+ case HTML_O_COLOR:
+ if( HTML_FONT_ON==nToken )
+ {
+ pOption->GetColor( aColor );
+ bColor = sal_True;
+ }
+ break;
+ case HTML_O_FACE:
+ if( HTML_FONT_ON==nToken )
+ aFace = pOption->GetString();
+ break;
+ 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;
+ }
+ }
+
+ if( HTML_FONT_ON != nToken )
+ {
+ // HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON
+
+ // in Ueberschriften bestimmt die aktuelle Ueberschrift
+ // die Font-Hoehe und nicht BASEFONT
+ sal_uInt16 nPoolId = GetCurrFmtColl()->GetPoolFmtId();
+ if( (nPoolId>=RES_POOLCOLL_HEADLINE1 &&
+ nPoolId<=RES_POOLCOLL_HEADLINE6) )
+ {
+ // wenn die Schriftgroesse in der Ueberschrift noch
+ // nicht veraendert ist, die aus der Vorlage nehmen
+ if( nFontStHeadStart==aFontStack.Count() )
+ nFontSize = static_cast< sal_uInt16 >(6 - (nPoolId - RES_POOLCOLL_HEADLINE1));
+ }
+ else
+ nPoolId = 0;
+
+ if( HTML_BIGPRINT_ON == nToken )
+ nSize = ( nFontSize<7 ? nFontSize+1 : 7 );
+ else
+ nSize = ( nFontSize>1 ? nFontSize-1 : 1 );
+
+ // in Ueberschriften wird die neue Fonthoehe wenn moeglich aus
+ // den Vorlagen geholt.
+ if( nPoolId && nSize>=1 && nSize <=6 )
+ nFontHeight =
+ pCSS1Parser->GetTxtCollFromPool(
+ RES_POOLCOLL_HEADLINE1+6-nSize )->GetSize().GetHeight();
+ else
+ nFontHeight = aFontHeights[nSize-1];
+ }
+
+ OSL_ENSURE( !nSize == !nFontHeight, "HTML-Font-Size != Font-Height" );
+
+ String aFontName, aStyleName;
+ FontFamily eFamily = FAMILY_DONTKNOW; // Family und Pitch,
+ FontPitch ePitch = PITCH_DONTKNOW; // falls nicht gefunden
+ rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
+
+ if( aFace.Len() && !pCSS1Parser->IsIgnoreFontFamily() )
+ {
+ const FontList *pFList = 0;
+ SwDocShell *pDocSh = pDoc->GetDocShell();
+ if( pDocSh )
+ {
+ const SvxFontListItem *pFListItem =
+ (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
+ if( pFListItem )
+ pFList = pFListItem->GetFontList();
+ }
+
+ sal_Bool bFound = sal_False;
+ xub_StrLen nStrPos = 0;
+ while( nStrPos!=STRING_NOTFOUND )
+ {
+ String aFName = aFace.GetToken( 0, ',', nStrPos );
+ aFName.EraseTrailingChars().EraseLeadingChars();
+ if( aFName.Len() )
+ {
+ if( !bFound && pFList )
+ {
+ sal_Handle hFont = pFList->GetFirstFontInfo( aFName );
+ if( 0 != hFont )
+ {
+ const FontInfo& rFInfo = pFList->GetFontInfo( hFont );
+ if( RTL_TEXTENCODING_DONTKNOW != rFInfo.GetCharSet() )
+ {
+ bFound = sal_True;
+ if( RTL_TEXTENCODING_SYMBOL == rFInfo.GetCharSet() )
+ eEnc = RTL_TEXTENCODING_SYMBOL;
+ }
+ }
+ }
+ if( aFontName.Len() )
+ aFontName += ';';
+ aFontName += aFName;
+ }
+ }
+ }
+
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( nFontHeight )
+ {
+ SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ aItemSet.Put( aFontHeight );
+ }
+ if( bColor )
+ aItemSet.Put( SvxColorItem(aColor, RES_CHRATR_COLOR) );
+ if( aFontName.Len() )
+ {
+ SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
+ aItemSet.Put( aFont );
+ aFont.SetWhich( RES_CHRATR_CJK_FONT );
+ aItemSet.Put( aFont );
+ aFont.SetWhich( RES_CHRATR_CTL_FONT );
+ aItemSet.Put( aFont );
+ }
+
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+
+ InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
+ }
+ else
+ {
+ if( nFontHeight )
+ {
+ SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
+ aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
+ aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
+ }
+ if( bColor )
+ InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor, RES_CHRATR_COLOR), pCntxt );
+ if( aFontName.Len() )
+ {
+ SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
+ InsertAttr( &aAttrTab.pFont, aFont, pCntxt );
+ aFont.SetWhich( RES_CHRATR_CJK_FONT );
+ InsertAttr( &aAttrTab.pFontCJK, aFont, pCntxt );
+ aFont.SetWhich( RES_CHRATR_CTL_FONT );
+ InsertAttr( &aAttrTab.pFontCTL, aFont, pCntxt );
+ }
+ }
+
+ // den Kontext merken
+ PushContext( pCntxt );
+
+ aFontStack.Insert( nSize, aFontStack.Count() );
+}
+
+void SwHTMLParser::EndFontAttr( int nToken )
+{
+ EndTag( nToken );
+
+ // Stack-Unterlauf in Tabellen vermeiden
+ if( aFontStack.Count() > nFontStMin )
+ aFontStack.Remove( aFontStack.Count()-1, 1 );
+}
+
+/* */
+
+void SwHTMLParser::NewPara()
+{
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_SPACE );
+ else
+ AddParSpace();
+
+ eParaAdjust = SVX_ADJUST_END;
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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:
+ eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
+ 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;
+ }
+ }
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt =
+ aClass.Len() ? new _HTMLAttrContext( HTML_PARABREAK_ON,
+ RES_POOLCOLL_TEXT, aClass )
+ : new _HTMLAttrContext( HTML_PARABREAK_ON );
+
+ // Styles parsen (Class nicht beruecksichtigen. Das geht nur, solange
+ // keine der CSS1-Properties der Klasse hart formatiert werden muss!!!)
+ if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ OSL_ENSURE( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
+ "Class wird nicht beruecksichtigt" );
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ if( SVX_ADJUST_END != eParaAdjust )
+ InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
+
+ // und auf den Stack packen
+ PushContext( pCntxt );
+
+ // die aktuelle Vorlage oder deren Attribute setzen
+ SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 );
+
+ // Laufbalkenanzeige
+ ShowStatline();
+
+ OSL_ENSURE( !nOpenParaToken, "Jetzt geht ein offenes Absatz-Element verloren" );
+ nOpenParaToken = HTML_PARABREAK_ON;
+}
+
+void SwHTMLParser::EndPara( sal_Bool bReal )
+{
+ if( HTML_LI_ON==nOpenParaToken && pTable )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule();
+ OSL_ENSURE( pNumRule, "Wo ist die Numrule geblieben" );
+#endif
+ }
+
+ // leere Absaetze werden von Netscape uebersprungen, von uns jetzt auch
+ if( bReal )
+ {
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_SPACE );
+ else
+ AddParSpace();
+ }
+
+ // wenn ein DD oder DT offen war, handelt es sich um eine
+ // implizite Def-Liste, die jetzt beendet werden muss
+ if( (nOpenParaToken==HTML_DT_ON || nOpenParaToken==HTML_DD_ON) &&
+ nDefListDeep)
+ {
+ nDefListDeep--;
+ }
+
+ // den Kontext vom Stack holen. Er kann auch von einer implizit
+ // geoeffneten Definitionsliste kommen
+ _HTMLAttrContext *pCntxt =
+ PopContext( static_cast< sal_uInt16 >(nOpenParaToken ? (nOpenParaToken & ~1)
+ : HTML_PARABREAK_ON) );
+
+ // Attribute beenden
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+ delete pCntxt;
+ }
+
+ // und die bisherige Vorlage neu setzen
+ if( bReal )
+ SetTxtCollAttrs();
+
+ nOpenParaToken = 0;
+}
+
+
+void SwHTMLParser::NewHeading( int nToken )
+{
+ eParaAdjust = SVX_ADJUST_END;
+
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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:
+ eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
+ 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;
+ }
+ }
+
+ // einen neuen Absatz aufmachen
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_SPACE );
+ else
+ AddParSpace();
+
+ // die passende Vorlage suchen
+ sal_uInt16 nTxtColl;
+ switch( nToken )
+ {
+ case HTML_HEAD1_ON: nTxtColl = RES_POOLCOLL_HEADLINE1; break;
+ case HTML_HEAD2_ON: nTxtColl = RES_POOLCOLL_HEADLINE2; break;
+ case HTML_HEAD3_ON: nTxtColl = RES_POOLCOLL_HEADLINE3; break;
+ case HTML_HEAD4_ON: nTxtColl = RES_POOLCOLL_HEADLINE4; break;
+ case HTML_HEAD5_ON: nTxtColl = RES_POOLCOLL_HEADLINE5; break;
+ case HTML_HEAD6_ON: nTxtColl = RES_POOLCOLL_HEADLINE6; break;
+ default: nTxtColl = RES_POOLCOLL_STANDARD; break;
+ }
+
+ // den Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nTxtColl, aClass );
+
+ // Styles parsen (zu Class siehe auch NewPara)
+ if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ OSL_ENSURE( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
+ "Class wird nicht beruecksichtigt" );
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ if( SVX_ADJUST_END != eParaAdjust )
+ InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
+
+ // udn auf den Stack packen
+ PushContext( pCntxt );
+
+ // und die Vorlage oder deren Attribute setzen
+ SetTxtCollAttrs( pCntxt );
+
+ nFontStHeadStart = aFontStack.Count();
+
+ // Laufbalkenanzeige
+ ShowStatline();
+}
+
+void SwHTMLParser::EndHeading()
+{
+ // einen neuen Absatz aufmachen
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_SPACE );
+ else
+ AddParSpace();
+
+ // Kontext zu dem Token suchen und vom Stack holen
+ _HTMLAttrContext *pCntxt = 0;
+ sal_uInt16 nPos = aContexts.Count();
+ while( !pCntxt && nPos>nContextStMin )
+ {
+ switch( aContexts[--nPos]->GetToken() )
+ {
+ case HTML_HEAD1_ON:
+ case HTML_HEAD2_ON:
+ case HTML_HEAD3_ON:
+ case HTML_HEAD4_ON:
+ case HTML_HEAD5_ON:
+ case HTML_HEAD6_ON:
+ pCntxt = aContexts[nPos];
+ aContexts.Remove( nPos, 1 );
+ break;
+ }
+ }
+
+ // und noch Attribute beenden
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+ delete pCntxt;
+ }
+
+ // die bisherige Vorlage neu setzen
+ SetTxtCollAttrs();
+
+ nFontStHeadStart = nFontStMin;
+}
+
+/* */
+
+void SwHTMLParser::NewTxtFmtColl( int nToken, sal_uInt16 nColl )
+{
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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_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;
+ }
+ }
+
+ // einen neuen Absatz aufmachen
+ SwHTMLAppendMode eMode = AM_NORMAL;
+ switch( nToken )
+ {
+ case HTML_LISTING_ON:
+ case HTML_XMP_ON:
+ // Diese beiden Tags werden jetzt auf die PRE-Vorlage gemappt.
+ // Fuer dem Fall, dass ein CLASS angegeben ist, loeschen wir
+ // es damit wir nicht die CLASS der PRE-Vorlage bekommen.
+ aClass = aEmptyStr;
+ case HTML_BLOCKQUOTE_ON:
+ case HTML_BLOCKQUOTE30_ON:
+ case HTML_PREFORMTXT_ON:
+ eMode = AM_SPACE;
+ break;
+ case HTML_ADDRESS_ON:
+ eMode = AM_NOSPACE; // ADDRESS kann auf einen <P> ohne </P> folgen
+ break;
+ case HTML_DT_ON:
+ case HTML_DD_ON:
+ eMode = AM_SOFTNOSPACE;
+ break;
+ default:
+ OSL_ENSURE( !this, "unbekannte Vorlage" );
+ break;
+ }
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( eMode );
+ else if( AM_SPACE==eMode )
+ AddParSpace();
+
+ // ... und in einem Kontext merken
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nColl, aClass );
+
+ // Styles parsen (zu Class siehe auch NewPara)
+ if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ OSL_ENSURE( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
+ "Class wird nicht beruecksichtigt" );
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ PushContext( pCntxt );
+
+ // die neue Vorlage setzen
+ SetTxtCollAttrs( pCntxt );
+
+ // Laufbalkenanzeige aktualisieren
+ ShowStatline();
+}
+
+void SwHTMLParser::EndTxtFmtColl( int nToken )
+{
+ SwHTMLAppendMode eMode = AM_NORMAL;
+ switch( nToken & ~1 )
+ {
+ case HTML_BLOCKQUOTE_ON:
+ case HTML_BLOCKQUOTE30_ON:
+ case HTML_PREFORMTXT_ON:
+ case HTML_LISTING_ON:
+ case HTML_XMP_ON:
+ eMode = AM_SPACE;
+ break;
+ case HTML_ADDRESS_ON:
+ case HTML_DT_ON:
+ case HTML_DD_ON:
+ eMode = AM_SOFTNOSPACE;
+ break;
+ default:
+ OSL_ENSURE( !this, "unbekannte Vorlage" );
+ break;
+ }
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( eMode );
+ else if( AM_SPACE==eMode )
+ AddParSpace();
+
+ // den aktuellen Kontext vom Stack holen
+ _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
+
+ // und noch Attribute beenden
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+ delete pCntxt;
+ }
+
+ // und die bisherige Vorlage setzen
+ SetTxtCollAttrs();
+}
+
+/* */
+
+void SwHTMLParser::NewDefList()
+{
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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_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;
+ }
+ }
+
+ // einen neuen Absatz aufmachen
+ sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 0;
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
+ else if( bSpace )
+ AddParSpace();
+
+ // ein Level mehr
+ nDefListDeep++;
+
+
+ sal_Bool bInDD = sal_False, bNotInDD = sal_False;
+ sal_uInt16 nPos = aContexts.Count();
+ while( !bInDD && !bNotInDD && nPos>nContextStMin )
+ {
+ sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
+ switch( nCntxtToken )
+ {
+ case HTML_DEFLIST_ON:
+ case HTML_DIRLIST_ON:
+ case HTML_MENULIST_ON:
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ bNotInDD = sal_True;
+ break;
+ case HTML_DD_ON:
+ bInDD = sal_True;
+ break;
+ }
+ }
+
+
+ // ... und in einem Kontext merken
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON );
+
+ // darin auch die Raender merken
+ sal_uInt16 nLeft=0, nRight=0;
+ short nIndent=0;
+ GetMarginsFromContext( nLeft, nRight, nIndent );
+
+ // Die Einrueckung, die sich schon aus einem DL-ergibt, entspricht der
+ // eines DT auf dem aktuellen Level, und die entspricht der eines
+ // DD auf dem Level davor. Fue einen Level >=2 muss also ein DD-Abstand
+ // hinzugefuegt werden
+ if( !bInDD && nDefListDeep > 1 )
+ {
+
+ // und den der DT-Vorlage des aktuellen Levels
+ SvxLRSpaceItem rLRSpace =
+ pCSS1Parser->GetTxtFmtColl( RES_POOLCOLL_HTML_DD, aEmptyStr )
+ ->GetLRSpace();
+ nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTxtLeft());
+ }
+
+ pCntxt->SetMargins( nLeft, nRight, nIndent );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ PushContext( pCntxt );
+
+ // die Attribute der neuen Vorlage setzen
+ if( nDefListDeep > 1 )
+ SetTxtCollAttrs( pCntxt );
+}
+
+void SwHTMLParser::EndDefList()
+{
+ sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 1;
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
+ else if( bSpace )
+ AddParSpace();
+
+ // ein Level weniger
+ if( nDefListDeep > 0 )
+ nDefListDeep--;
+
+ // den aktuellen Kontext vom Stack holen
+ _HTMLAttrContext *pCntxt = PopContext( HTML_DEFLIST_ON );
+
+ // und noch Attribute beenden
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+ delete pCntxt;
+ }
+
+ // und Vorlage setzen
+ SetTxtCollAttrs();
+}
+
+void SwHTMLParser::NewDefListItem( int nToken )
+{
+ // festellen, ob das DD/DT in einer DL vorkommt
+ sal_Bool bInDefList = sal_False, bNotInDefList = sal_False;
+ sal_uInt16 nPos = aContexts.Count();
+ while( !bInDefList && !bNotInDefList && nPos>nContextStMin )
+ {
+ sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
+ switch( nCntxtToken )
+ {
+ case HTML_DEFLIST_ON:
+ bInDefList = sal_True;
+ break;
+ case HTML_DIRLIST_ON:
+ case HTML_MENULIST_ON:
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ bNotInDefList = sal_True;
+ break;
+ }
+ }
+
+ // wenn nicht, implizit eine neue DL aufmachen
+ if( !bInDefList )
+ {
+ nDefListDeep++;
+ OSL_ENSURE( !nOpenParaToken,
+ "Jetzt geht ein offenes Absatz-Element verloren" );
+ nOpenParaToken = static_cast< sal_uInt16 >(nToken);
+ }
+
+ NewTxtFmtColl( nToken, static_cast< sal_uInt16 >(nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD
+ : RES_POOLCOLL_HTML_DT) );
+}
+
+void SwHTMLParser::EndDefListItem( int nToken, sal_Bool bSetColl,
+ sal_Bool /*bLastPara*/ )
+{
+ // einen neuen Absatz aufmachen
+ if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_SOFTNOSPACE );
+
+ // Kontext zu dem Token suchen und vom Stack holen
+ nToken &= ~1;
+ _HTMLAttrContext *pCntxt = 0;
+ sal_uInt16 nPos = aContexts.Count();
+ while( !pCntxt && nPos>nContextStMin )
+ {
+ sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
+ switch( nCntxtToken )
+ {
+ case HTML_DD_ON:
+ case HTML_DT_ON:
+ if( !nToken || nToken == nCntxtToken )
+ {
+ pCntxt = aContexts[nPos];
+ aContexts.Remove( nPos, 1 );
+ }
+ break;
+ case HTML_DEFLIST_ON:
+ // keine DD/DT ausserhalb der aktuelen DefListe betrachten
+ case HTML_DIRLIST_ON:
+ case HTML_MENULIST_ON:
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ // und auch nicht ausserhalb einer anderen Liste
+ nPos = nContextStMin;
+ break;
+ }
+ }
+
+ // und noch Attribute beenden
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+ delete pCntxt;
+ }
+
+ // und die bisherige Vorlage setzen
+ if( bSetColl )
+ SetTxtCollAttrs();
+}
+
+/* */
+
+sal_Bool SwHTMLParser::HasCurrentParaFlys( sal_Bool bNoSurroundOnly,
+ sal_Bool bSurroundOnly ) const
+{
+ // bNoSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
+ // ohne Umlauf
+ // bSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
+ // mit Umlauf aber keinen ohne Umlauf
+ // sonst: Der Absatz enthaelt irgendeinen Rahmen
+ SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
+
+ const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
+
+ sal_Bool bFound = sal_False;
+ for ( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
+ {
+ SwFrmFmt *const pFmt = rFrmFmtTbl[i];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ // Ein Rahmen wurde gefunden, wenn
+ // - er absatzgebunden ist, und
+ // - im aktuellen Absatz verankert ist, und
+ // - jeder absatzgebunene Rahmen zaehlt, oder
+ // - (nur Rahmen oder umlauf zaehlen und ) der Rahmen keinen
+ // Umlauf besitzt
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ pAPos->nNode == rNodeIdx )
+ {
+ if( !(bNoSurroundOnly || bSurroundOnly) )
+ {
+ bFound = sal_True;
+ break;
+ }
+ else
+ {
+ // Wenn Rahmen mit Umlauf gesucht sind,
+ // auch keine mit Durchlauf beachten. Dabei handelt es
+ // sich (noch) um HIDDEN-Controls, und denen weicht man
+ // besser auch nicht aus.
+ SwSurround eSurround = pFmt->GetSurround().GetSurround();
+ if( bNoSurroundOnly )
+ {
+ if( SURROUND_NONE==eSurround )
+ {
+ bFound = sal_True;
+ break;
+ }
+ }
+ if( bSurroundOnly )
+ {
+ if( SURROUND_NONE==eSurround )
+ {
+ bFound = sal_False;
+ break;
+ }
+ else if( SURROUND_THROUGHT!=eSurround )
+ {
+ bFound = sal_True;
+ // weitersuchen: Es koennten ja noch welche ohne
+ // Umlauf kommen ...
+ }
+ }
+ }
+ }
+ }
+
+ return bFound;
+}
+
+/* */
+
+// die speziellen Methoden zum Einfuegen von Objecten
+
+const SwFmtColl *SwHTMLParser::GetCurrFmtColl() const
+{
+ const SwCntntNode* pCNd = pPam->GetCntntNode();
+ return &pCNd->GetAnyFmtColl();
+}
+
+
+void SwHTMLParser::SetTxtCollAttrs( _HTMLAttrContext *pContext )
+{
+ SwTxtFmtColl *pCollToSet = 0; // die zu setzende Vorlage
+ SfxItemSet *pItemSet = 0; // der Set fuer harte Attrs
+ sal_uInt16 nTopColl = pContext ? pContext->GetTxtFmtColl() : 0;
+ const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr;
+ sal_uInt16 nDfltColl = RES_POOLCOLL_TEXT;
+
+ sal_Bool bInPRE=sal_False; // etwas Kontext Info
+
+ sal_uInt16 nLeftMargin = 0, nRightMargin = 0; // die Einzuege und
+ short nFirstLineIndent = 0; // Abstaende
+ sal_uInt16 i;
+
+ for( i = nContextStAttrMin; i < aContexts.Count(); i++ )
+ {
+ const _HTMLAttrContext *pCntxt = aContexts[i];
+
+ sal_uInt16 nColl = pCntxt->GetTxtFmtColl();
+ if( nColl )
+ {
+ // Es gibt eine Vorlage, die zu setzen ist. Dann
+ // muss zunaechst einmal entschieden werden,
+ // ob die Vorlage auch gesetzt werden kann
+ sal_Bool bSetThis = sal_True;
+ switch( nColl )
+ {
+ case sal_uInt16(RES_POOLCOLL_HTML_PRE):
+ bInPRE = sal_True;
+ break;
+ case sal_uInt16(RES_POOLCOLL_TEXT):
+ // <TD><P CLASS=xxx> muss TD.xxx werden
+ if( nDfltColl==RES_POOLCOLL_TABLE ||
+ nDfltColl==RES_POOLCOLL_TABLE_HDLN )
+ nColl = nDfltColl;
+ break;
+ case sal_uInt16(RES_POOLCOLL_HTML_HR):
+ // <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie
+ // nicht mehr exportieren
+ break;
+ default:
+ if( bInPRE )
+ bSetThis = sal_False;
+ break;
+ }
+
+ SwTxtFmtColl *pNewColl =
+ pCSS1Parser->GetTxtFmtColl( nColl, pCntxt->GetClass() );
+
+ if( bSetThis )
+ {
+ // wenn jetzt eine andere Vorlage gesetzt werden soll als
+ // bisher, muss die bishere Vorlage durch harte Attributierung
+ // ersetzt werden
+
+ if( pCollToSet )
+ {
+ // die Attribute, die die bisherige Vorlage setzt
+ // hart einfuegen
+ if( !pItemSet )
+ pItemSet = new SfxItemSet( pCollToSet->GetAttrSet() );
+ else
+ {
+ const SfxItemSet& rCollSet = pCollToSet->GetAttrSet();
+ SfxItemSet aItemSet( *rCollSet.GetPool(),
+ rCollSet.GetRanges() );
+ aItemSet.Set( rCollSet );
+ pItemSet->Put( aItemSet );
+ }
+ // aber die Attribute, die aktuelle Vorlage setzt
+ // entfernen, weil sie sonst spaeter ueberschrieben
+ // werden
+ pItemSet->Differentiate( pNewColl->GetAttrSet() );
+ }
+
+ pCollToSet = pNewColl;
+ }
+ else
+ {
+ // hart Attributieren
+ if( !pItemSet )
+ pItemSet = new SfxItemSet( pNewColl->GetAttrSet() );
+ else
+ {
+ const SfxItemSet& rCollSet = pNewColl->GetAttrSet();
+ SfxItemSet aItemSet( *rCollSet.GetPool(),
+ rCollSet.GetRanges() );
+ aItemSet.Set( rCollSet );
+ pItemSet->Put( aItemSet );
+ }
+ }
+ }
+ else
+ {
+ // vielliecht gibt es ja eine Default-Vorlage?
+ nColl = pCntxt->GetDfltTxtFmtColl();
+ if( nColl )
+ nDfltColl = nColl;
+ }
+
+ // ggf. neue Absatz-Einzuege holen
+ if( pCntxt->IsLRSpaceChanged() )
+ {
+ sal_uInt16 nLeft=0, nRight=0;
+
+ pCntxt->GetMargins( nLeft, nRight, nFirstLineIndent );
+ nLeftMargin = nLeft;
+ nRightMargin = nRight;
+ }
+ }
+
+ // wenn im aktuellen Kontext eine neue Vorlage gesetzt werden soll,
+ // muessen deren Absatz-Abstaende noch in den Kontext eingetragen werden
+ if( pContext && nTopColl )
+ {
+ // <TD><P CLASS=xxx> muss TD.xxx werden
+ if( nTopColl==RES_POOLCOLL_TEXT &&
+ (nDfltColl==RES_POOLCOLL_TABLE ||
+ nDfltColl==RES_POOLCOLL_TABLE_HDLN) )
+ nTopColl = nDfltColl;
+
+ const SwTxtFmtColl *pTopColl =
+ pCSS1Parser->GetTxtFmtColl( nTopColl, rTopClass );
+ const SfxItemSet& rItemSet = pTopColl->GetAttrSet();
+ const SfxPoolItem *pItem;
+ if( SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,sal_True, &pItem) )
+ {
+ const SvxLRSpaceItem *pLRItem =
+ (const SvxLRSpaceItem *)pItem;
+
+ sal_Int32 nLeft = pLRItem->GetTxtLeft();
+ sal_Int32 nRight = pLRItem->GetRight();
+ nFirstLineIndent = pLRItem->GetTxtFirstLineOfst();
+
+ // In Definitions-Listen enthalten die Abstaende auch die der
+ // vorhergehenden Level
+ if( RES_POOLCOLL_HTML_DD == nTopColl )
+ {
+ const SvxLRSpaceItem& rDTLRSpace = pCSS1Parser
+ ->GetTxtFmtColl( RES_POOLCOLL_HTML_DT, aEmptyStr )
+ ->GetLRSpace();
+ nLeft -= rDTLRSpace.GetTxtLeft();
+ nRight -= rDTLRSpace.GetRight();
+ }
+ else if( RES_POOLCOLL_HTML_DT == nTopColl )
+ {
+ nLeft = 0;
+ nRight = 0;
+ }
+
+ // die Absatz-Abstaende addieren sich
+ nLeftMargin = nLeftMargin + static_cast< sal_uInt16 >(nLeft);
+ nRightMargin = nRightMargin + static_cast< sal_uInt16 >(nRight);
+
+ pContext->SetMargins( nLeftMargin, nRightMargin,
+ nFirstLineIndent );
+ }
+ if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,sal_True, &pItem) )
+ {
+ const SvxULSpaceItem *pULItem =
+ (const SvxULSpaceItem *)pItem;
+ pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() );
+ }
+ }
+
+ // wenn gar keine Vorlage im Kontext gesetzt ist, Textkoerper nehmen
+ if( !pCollToSet )
+ {
+ pCollToSet = pCSS1Parser->GetTxtCollFromPool( nDfltColl );
+ const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
+ if( !nLeftMargin )
+ nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTxtLeft());
+ if( !nRightMargin )
+ nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight());
+ if( !nFirstLineIndent )
+ nFirstLineIndent = rLRItem.GetTxtFirstLineOfst();
+ }
+
+ // bisherige harte Attributierung des Absatzes entfernen
+ if( aParaAttrs.Count() )
+ {
+ for( i=0; i<aParaAttrs.Count(); i++ )
+ aParaAttrs[i]->Invalidate();
+
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+ }
+
+ // Die Vorlage setzen
+ pDoc->SetTxtFmtColl( *pPam, pCollToSet );
+
+ // ggf. noch den Absatz-Einzug korrigieren
+ const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
+ sal_Bool bSetLRSpace;
+
+ bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() ||
+ nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() ||
+ nRightMargin != rLRItem.GetRight();
+
+ if( bSetLRSpace )
+ {
+ SvxLRSpaceItem aLRItem( rLRItem );
+ aLRItem.SetTxtLeft( nLeftMargin );
+ aLRItem.SetRight( nRightMargin );
+ aLRItem.SetTxtFirstLineOfst( nFirstLineIndent );
+ if( pItemSet )
+ pItemSet->Put( aLRItem );
+ else
+ {
+ NewAttr( &aAttrTab.pLRSpace, aLRItem );
+ aAttrTab.pLRSpace->SetLikePara();
+ aParaAttrs.Insert( aAttrTab.pLRSpace, aParaAttrs.Count() );
+ EndAttr( aAttrTab.pLRSpace, 0, sal_False );
+ }
+ }
+
+ // und nun noch die Attribute setzen
+ if( pItemSet )
+ {
+ InsertParaAttrs( *pItemSet );
+ delete pItemSet;
+ }
+}
+
+/* */
+
+void SwHTMLParser::NewCharFmt( int nToken )
+{
+ String aId, aStyle, aClass, aLang, aDir;
+
+ 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_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;
+ }
+ }
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ // die Vorlage setzen und im Kontext merken
+ SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( static_cast< sal_uInt16 >(nToken), aClass );
+ OSL_ENSURE( pCFmt, "keine Zeichenvorlage zu Token gefunden" );
+
+
+ // Styles parsen (zu Class siehe auch NewPara)
+ if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ OSL_ENSURE( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
+ "Class wird nicht beruecksichtigt" );
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
+ }
+ }
+
+ // Zeichen-Vorlagen werden in einem eigenen Stack gehalten und
+ // koennen nie durch Styles eingefuegt werden. Das Attribut ist deshalb
+ // auch gar nicht im CSS1-Which-Range enthalten
+ if( pCFmt )
+ InsertAttr( &aAttrTab.pCharFmts, SwFmtCharFmt( pCFmt ), pCntxt );
+
+ // den Kontext merken
+ PushContext( pCntxt );
+}
+
+
+/* */
+
+void SwHTMLParser::InsertSpacer()
+{
+ // und es ggf. durch die Optionen veraendern
+ String aId;
+ sal_Int16 eVertOri = text::VertOrientation::TOP;
+ sal_Int16 eHoriOri = text::HoriOrientation::NONE;
+ Size aSize( 0, 0);
+ long nSize = 0;
+ sal_Bool bPrcWidth = sal_False;
+ sal_Bool bPrcHeight = sal_False;
+ sal_uInt16 nType = HTML_SPTYPE_HORI;
+
+ 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_TYPE:
+ pOption->GetEnum( nType, aHTMLSpacerTypeTable );
+ break;
+ case HTML_O_ALIGN:
+ eVertOri =
+ pOption->GetEnum( aHTMLImgVAlignTable,
+ eVertOri );
+ eHoriOri =
+ pOption->GetEnum( aHTMLImgHAlignTable,
+ eHoriOri );
+ break;
+ case HTML_O_WIDTH:
+ // erstmal nur als Pixelwerte merken!
+ bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
+ aSize.Width() = (long)pOption->GetNumber();
+ break;
+ case HTML_O_HEIGHT:
+ // erstmal nur als Pixelwerte merken!
+ bPrcHeight = (pOption->GetString().Search('%') != STRING_NOTFOUND);
+ aSize.Height() = (long)pOption->GetNumber();
+ break;
+ case HTML_O_SIZE:
+ // erstmal nur als Pixelwerte merken!
+ nSize = pOption->GetNumber();
+ break;
+ }
+ }
+
+ switch( nType )
+ {
+ case HTML_SPTYPE_BLOCK:
+ {
+ // einen leeren Textrahmen anlegen
+
+ // den Itemset holen
+ SfxItemSet aFrmSet( pDoc->GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
+ if( !IsNewDoc() )
+ Reader::ResetFrmFmtAttrs( aFrmSet );
+
+ // den Anker und die Ausrichtung setzen
+ SetAnchorAndAdjustment( eVertOri, eHoriOri, aFrmSet );
+
+ // und noch die Groesse des Rahmens
+ Size aDfltSz( MINFLY, MINFLY );
+ Size aSpace( 0, 0 );
+ SfxItemSet aDummyItemSet( pDoc->GetAttrPool(),
+ pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aDummyPropInfo;
+
+ SetFixSize( aSize, aDfltSz, bPrcWidth, bPrcHeight,
+ aDummyItemSet, aDummyPropInfo, aFrmSet );
+ SetSpace( aSpace, aDummyItemSet, aDummyPropInfo, aFrmSet );
+
+ // den Inhalt schuetzen
+ SvxProtectItem aProtectItem( RES_PROTECT) ;
+ aProtectItem.SetCntntProtect( sal_True );
+ aFrmSet.Put( aProtectItem );
+
+ // der Rahmen anlegen
+ RndStdIds eAnchorId =
+ ((const SwFmtAnchor &)aFrmSet.Get(RES_ANCHOR)).GetAnchorId();
+ SwFrmFmt *pFlyFmt = pDoc->MakeFlySection( eAnchorId,
+ pPam->GetPoint(), &aFrmSet );
+ // Ggf Frames anlegen und auto-geb. Rahmen registrieren
+ RegisterFlyFrm( pFlyFmt );
+ }
+ break;
+ case HTML_SPTYPE_VERT:
+ if( nSize > 0 )
+ {
+ if( nSize && Application::GetDefaultDevice() )
+ {
+ nSize = Application::GetDefaultDevice()
+ ->PixelToLogic( Size(0,nSize),
+ MapMode(MAP_TWIP) ).Height();
+ }
+
+ // einen Absatz-Abstand setzen
+ SwTxtNode *pTxtNode = 0;
+ if( !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ // den unteren Absatz-Abstand des vorherigen Nodes aendern,
+ // wenn moeglich
+
+ SetAttr(); // noch offene Absatz-Attribute setzen
+
+ pTxtNode = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()-1]
+ ->GetTxtNode();
+
+ // Wenn der Abstz davor kein Txtenode ist, dann wird jetzt
+ // ein leere Absatz angelegt, der eh schon eine Zeilenhoehe
+ // Abstand erzeugt.
+ if( !pTxtNode )
+ nSize = nSize>HTML_PARSPACE ? nSize-HTML_PARSPACE : 0;
+ }
+
+ if( pTxtNode )
+ {
+ SvxULSpaceItem aULSpace( (const SvxULSpaceItem&)pTxtNode
+ ->SwCntntNode::GetAttr( RES_UL_SPACE ) );
+ aULSpace.SetLower( aULSpace.GetLower() + (sal_uInt16)nSize );
+ pTxtNode->SetAttr( aULSpace );
+ }
+ else
+ {
+ NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (sal_uInt16)nSize, RES_UL_SPACE ) );
+ EndAttr( aAttrTab.pULSpace, 0, sal_False );
+
+ AppendTxtNode(); // nicht am Abstand drehen!
+ }
+ }
+ break;
+ case HTML_SPTYPE_HORI:
+ if( nSize > 0 )
+ {
+ // wenn der Absatz noch leer ist, einen Erstzeilen-Einzug
+ // setzen, sondern Sperrschrift ueber einem Space aufspannen
+
+ if( nSize && Application::GetDefaultDevice() )
+ {
+ nSize = Application::GetDefaultDevice()
+ ->PixelToLogic( Size(nSize,0),
+ MapMode(MAP_TWIP) ).Width();
+ }
+
+ if( !pPam->GetPoint()->nContent.GetIndex() )
+ {
+ sal_uInt16 nLeft=0, nRight=0;
+ short nIndent = 0;
+
+ GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent );
+ nIndent = nIndent + (short)nSize;
+
+ SvxLRSpaceItem aLRItem( RES_LR_SPACE );
+ aLRItem.SetTxtLeft( nLeft );
+ aLRItem.SetRight( nRight );
+ aLRItem.SetTxtFirstLineOfst( nIndent );
+
+ NewAttr( &aAttrTab.pLRSpace, aLRItem );
+ EndAttr( aAttrTab.pLRSpace, 0, sal_False );
+ }
+ else
+ {
+ NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize, RES_CHRATR_KERNING ) );
+ String aTmp( ' ' );
+ pDoc->InsertString( *pPam, aTmp );
+ EndAttr( aAttrTab.pKerning );
+ }
+ }
+ }
+}
+
+sal_uInt16 SwHTMLParser::ToTwips( sal_uInt16 nPixel ) const
+{
+ if( nPixel && Application::GetDefaultDevice() )
+ {
+ long nTwips = Application::GetDefaultDevice()->PixelToLogic(
+ Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width();
+ return nTwips <= USHRT_MAX ? (sal_uInt16)nTwips : USHRT_MAX;
+ }
+ else
+ return nPixel;
+}
+
+SwTwips SwHTMLParser::GetCurrentBrowseWidth()
+{
+ const SwTwips nWidth = SwHTMLTableLayout::GetBrowseWidth( *pDoc );
+ if( nWidth )
+ return nWidth;
+
+ if( !aHTMLPageSize.Width() )
+ {
+ const SwFrmFmt& rPgFmt = pCSS1Parser->GetMasterPageDesc()->GetMaster();
+
+ const SwFmtFrmSize& rSz = rPgFmt.GetFrmSize();
+ const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
+ const SvxULSpaceItem& rUL = rPgFmt.GetULSpace();
+ const SwFmtCol& rCol = rPgFmt.GetCol();
+
+ aHTMLPageSize.Width() = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
+ aHTMLPageSize.Height() = rSz.GetHeight() - rUL.GetUpper() - rUL.GetLower();
+
+ if( 1 < rCol.GetNumCols() )
+ aHTMLPageSize.Width() /= rCol.GetNumCols();
+ }
+
+ return aHTMLPageSize.Width();
+}
+
+
+/* */
+
+void SwHTMLParser::InsertIDOption()
+{
+ String aId;
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ if( HTML_O_ID==pOption->GetToken() )
+ {
+ aId = pOption->GetString();
+ break;
+ }
+ }
+
+ if( aId.Len() )
+ InsertBookmark( aId );
+}
+
+
+/* */
+
+
+void SwHTMLParser::InsertLineBreak()
+{
+ // <BR CLEAR=xxx> wird wie folgt behandelt:
+ // 1.) Es werden nur nur absatzgebundene Rahmen betrachtet, die
+ // im aktuellen Absatz verankert sind.
+ // 2.) Fuer linksbuendig ausgerichtete Rahmen wird bei CLEAR=LEFT
+ // oder ALL und auf rechtsbuendige ausgerichtete Rahmen bei
+ // CLEAR=RIGHT oder ALL der Durchlauf wie folgt geaendert:
+ // 3.) Wenn der Absatz keinen Text enthaelt, bekommt der Rahmen keinen
+ // Umlauf
+ // 4.) sonst erhaelt ein links ausgerichteter Rahmen eine rechten
+ // "nur Anker" Umlauf und recht rechst ausg. Rahmen einen linken
+ // "nur Anker" Umlauf.
+ // 5.) wenn in einem nicht-leeren Absatz der Umlauf eines Rahmens
+ // geaendert wird, wird ein neuer Absatz aufgemacht
+ // 6.) Wenn von keinem Rahmen der Umlauf geaendert wird, wird ein
+ // harter Zeilenumbruch eingefuegt
+
+ String aId, aStyle, aClass; // die ID der Bookmark
+ sal_Bool bClearLeft = sal_False, bClearRight = sal_False;
+ sal_Bool bCleared = sal_False; // wurde ein CLEAR ausgefuehrt?
+
+ // dann holen wir mal die Optionen
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_CLEAR:
+ {
+ const String &aClear = pOption->GetString();
+ if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_all ) )
+ {
+ bClearLeft = sal_True;
+ bClearRight = sal_True;
+ }
+ else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
+ bClearLeft = sal_True;
+ else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
+ bClearRight = sal_True;
+ }
+ break;
+ case HTML_O_ID:
+ aId = pOption->GetString();
+ break;
+ case HTML_O_STYLE:
+ aStyle = pOption->GetString();
+ break;
+ case HTML_O_CLASS:
+ aClass = pOption->GetString();
+ break;
+ }
+ }
+
+ // CLEAR wird nur fuer den aktuellen Absaetz unterstuetzt
+ if( bClearLeft || bClearRight )
+ {
+ SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
+ SwTxtNode* pTxtNd = rNodeIdx.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
+
+ for( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
+ {
+ SwFrmFmt *const pFmt = rFrmFmtTbl[i];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ pAPos->nNode == rNodeIdx &&
+ pFmt->GetSurround().GetSurround() != SURROUND_NONE )
+ {
+ sal_Int16 eHori = RES_DRAWFRMFMT == pFmt->Which()
+ ? text::HoriOrientation::LEFT
+ : pFmt->GetHoriOrient().GetHoriOrient();
+
+ SwSurround eSurround = SURROUND_PARALLEL;
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ {
+ if( bClearLeft && text::HoriOrientation::LEFT==eHori )
+ eSurround = SURROUND_RIGHT;
+ else if( bClearRight && text::HoriOrientation::RIGHT==eHori )
+ eSurround = SURROUND_LEFT;
+ }
+ else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) ||
+ (bClearRight && text::HoriOrientation::RIGHT==eHori) )
+ {
+ eSurround = SURROUND_NONE;
+ }
+
+ if( SURROUND_PARALLEL != eSurround )
+ {
+ SwFmtSurround aSurround( eSurround );
+ if( SURROUND_NONE != eSurround )
+ aSurround.SetAnchorOnly( sal_True );
+ pFmt->SetFmtAttr( aSurround );
+ bCleared = sal_True;
+ }
+ } // Anker ist nicht im Node
+ } // Schleife ueber Fly-Frames
+ } // kein Text-Node
+ } // kein CLEAR
+
+ // Styles parsen
+ SvxFmtBreakItem aBreakItem( SVX_BREAK_NONE, RES_BREAK );
+ sal_Bool bBreakItem = sal_False;
+ if( HasStyleOptions( aStyle, aId, aClass ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) )
+ {
+ if( pCSS1Parser->SetFmtBreak( aItemSet, aPropInfo ) )
+ {
+ aBreakItem = (const SvxFmtBreakItem &)aItemSet.Get( RES_BREAK );
+ bBreakItem = sal_True;
+ }
+ if( aPropInfo.aId.Len() )
+ InsertBookmark( aPropInfo.aId );
+ }
+ }
+
+ if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() )
+ {
+ NewAttr( &aAttrTab.pBreak, aBreakItem );
+ EndAttr( aAttrTab.pBreak, 0, sal_False );
+ }
+
+ if( !bCleared && !bBreakItem )
+ {
+ // wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird
+ // ein Zeilenumbruch eingef?gt
+ String sTmp( (sal_Unicode)0x0a ); // make the Mac happy :-)
+ pDoc->InsertString( *pPam, sTmp );
+ }
+ else if( pPam->GetPoint()->nContent.GetIndex() )
+ {
+ // wenn ein Claer in einem nicht-leeren Absatz ausgefuehrt wurde,
+ // muss anschliessen ein neuer Absatz aufgemacht werden
+ // MIB 21.02.97: Eigentlich muesste man hier den unteren Absatz-
+ // Absatnd auf 0 drehen. Das geht aber bei sowas wie <BR ..><P>
+ // schief (>Netacpe). Deshalb lassen wir das erstmal.
+ AppendTxtNode( AM_NOSPACE );
+ }
+ if( bBreakItem && SVX_BREAK_PAGE_BEFORE==aBreakItem.GetBreak() )
+ {
+ NewAttr( &aAttrTab.pBreak, aBreakItem );
+ EndAttr( aAttrTab.pBreak, 0, sal_False );
+ }
+}
+
+void SwHTMLParser::InsertHorzRule()
+{
+ sal_uInt16 nSize = 0;
+ sal_uInt16 nWidth = 0;
+
+ SvxAdjust eAdjust = SVX_ADJUST_END;
+
+ sal_Bool bPrcWidth = sal_False;
+ sal_Bool bNoShade = sal_False;
+ sal_Bool bColor = sal_False;
+
+ Color aColor;
+ String aId;
+
+ // dann holen wir mal die Optionen
+ 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_SIZE:
+ nSize = (sal_uInt16)pOption->GetNumber();
+ break;
+ case HTML_O_WIDTH:
+ bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
+ nWidth = (sal_uInt16)pOption->GetNumber();
+ if( bPrcWidth && nWidth>=100 )
+ {
+ // 100%-Linien sind der default-Fall (keine Attrs neotig)
+ nWidth = 0;
+ bPrcWidth = sal_False;
+ }
+ break;
+ case HTML_O_ALIGN:
+ eAdjust =
+ (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
+ break;
+ case HTML_O_NOSHADE:
+ bNoShade = sal_True;
+ break;
+ case HTML_O_COLOR:
+ pOption->GetColor( aColor );
+ bColor = sal_True;
+ break;
+ }
+ }
+
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_NOSPACE );
+ if( nOpenParaToken )
+ EndPara();
+ AppendTxtNode();
+ pPam->Move( fnMoveBackward );
+
+ // ... und in einem Kontext merken
+ _HTMLAttrContext *pCntxt =
+ new _HTMLAttrContext( HTML_HORZRULE, RES_POOLCOLL_HTML_HR, aEmptyStr );
+
+ PushContext( pCntxt );
+
+ // die neue Vorlage setzen
+ SetTxtCollAttrs( pCntxt );
+
+ // die harten Attribute an diesem Absatz werden nie mehr ungueltig
+ if( aParaAttrs.Count() )
+ aParaAttrs.Remove( 0, aParaAttrs.Count() );
+
+ if( nSize>0 || bColor || bNoShade )
+ {
+ // Farbe und/oder Breite der Linie setzen
+ if( !bColor )
+ aColor.SetColor( COL_GRAY );
+
+ SvxBorderLine aBorderLine( &aColor );
+ if( nSize )
+ {
+ long nPWidth = 0;
+ long nPHeight = (long)nSize;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ if ( !bNoShade )
+ aBorderLine.SetStyle( ::editeng::DOUBLE );
+ aBorderLine.SetWidth( nPHeight );
+ }
+ else if( bNoShade )
+ {
+ aBorderLine.SetWidth( DEF_LINE_WIDTH_2 );
+ }
+ else
+ {
+ aBorderLine.SetStyle( ::editeng::DOUBLE );
+ aBorderLine.SetWidth( DEF_LINE_WIDTH_0 );
+ }
+
+ SvxBoxItem aBoxItem(RES_BOX);
+ aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
+ _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aBoxItem );
+ aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
+ }
+ if( nWidth )
+ {
+ // Wenn wir in keiner Tabelle sind, wird die Breitenangabe durch
+ // Absatz-Einzuege "getuerkt". In einer Tabelle macht das wenig
+ // Sinn. Um zu Vermeiden, dass die Linie bei der Breitenberechnung
+ // beruecksichtigt wird, bekommt sie aber trotzdem entsprechendes
+ // LRSpace-Item verpasst.
+ if( !pTable )
+ {
+ // Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken"
+ long nBrowseWidth = GetCurrentBrowseWidth();
+ nWidth = bPrcWidth ? (sal_uInt16)((nWidth*nBrowseWidth) / 100)
+ : ToTwips( (sal_uInt16)nBrowseWidth );
+ if( nWidth < MINLAY )
+ nWidth = MINLAY;
+
+ if( (long)nWidth < nBrowseWidth )
+ {
+ const SwFmtColl *pColl = GetCurrFmtColl();
+ SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
+ long nDist = nBrowseWidth - nWidth;
+
+ switch( eAdjust )
+ {
+ case SVX_ADJUST_RIGHT:
+ aLRItem.SetTxtLeft( (sal_uInt16)nDist );
+ break;
+ case SVX_ADJUST_LEFT:
+ aLRItem.SetRight( (sal_uInt16)nDist );
+ break;
+ case SVX_ADJUST_CENTER:
+ default:
+ nDist /= 2;
+ aLRItem.SetTxtLeft( (sal_uInt16)nDist );
+ aLRItem.SetRight( (sal_uInt16)nDist );
+ break;
+ }
+
+ _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
+ aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
+ }
+ }
+ }
+
+ // Bookmarks koennen nicht in Hyperlinks eingefueht werden
+ if( aId.Len() )
+ InsertBookmark( aId );
+
+ // den aktuellen Kontext vom Stack holen
+ _HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE );
+ OSL_ENSURE( pPoppedContext==pCntxt, "wo kommt denn da ein HR-Kontext her?" );
+ delete pPoppedContext;
+
+ pPam->Move( fnMoveForward );
+
+ // und im Absatz danach die dort aktuelle Vorlage setzen
+ SetTxtCollAttrs();
+}
+
+void SwHTMLParser::ParseMoreMetaOptions()
+{
+ String aName, aContent;
+ sal_Bool bHTTPEquiv = sal_False;
+
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_NAME:
+ aName = pOption->GetString();
+ bHTTPEquiv = sal_False;
+ break;
+ case HTML_O_HTTPEQUIV:
+ aName = pOption->GetString();
+ bHTTPEquiv = sal_True;
+ break;
+ case HTML_O_CONTENT:
+ aContent = pOption->GetString();
+ break;
+ }
+ }
+
+ // Hier wird es etwas tricky: Wir wissen genau, da? die Dok-Info
+ // nicht geaendert wurde. Deshalb genuegt es, auf Generator und
+ // auf refresh abzufragen, um noch nicht verarbeitete Token zu finden,
+ // denn das sind die einzigen, die die Dok-Info nicht modifizieren.
+ if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_generator ) ||
+ aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_refresh ) ||
+ aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) ||
+ aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
+ return;
+
+ aContent.EraseAllChars( _CR );
+ aContent.EraseAllChars( _LF );
+
+ if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdendnote ) )
+ {
+ FillEndNoteInfo( aContent );
+ return;
+ }
+
+ if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdfootnote ) )
+ {
+ FillFootNoteInfo( aContent );
+ return;
+ }
+
+ String sText(
+ String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_meta) );
+ sText.Append( ' ' );
+ if( bHTTPEquiv )
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_httpequiv) );
+ else
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_name) );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
+ sText.Append( aName );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_content) );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
+ sText.Append( aContent );
+ sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") );
+
+ SwPostItField aPostItFld(
+ (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ),
+ aEmptyStr, sText, DateTime() );
+ SwFmtFld aFmtFld( aPostItFld );
+ InsertAttr( aFmtFld );
+}
+
+/* */
+
+_HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem,
+ _HTMLAttr **ppHd ) :
+ nSttPara( rPos.nNode ),
+ nEndPara( rPos.nNode ),
+ nSttCntnt( rPos.nContent.GetIndex() ),
+ nEndCntnt(rPos.nContent.GetIndex() ),
+ bInsAtStart( sal_True ),
+ bLikePara( sal_False ),
+ bValid( sal_True ),
+ nCount( 1 ),
+ pNext( 0 ),
+ pPrev( 0 ),
+ ppHead( ppHd )
+{
+ pItem = rItem.Clone();
+}
+
+_HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara,
+ sal_uInt16 nEndCnt, _HTMLAttr **ppHd ) :
+ nSttPara( rAttr.nSttPara ),
+ nEndPara( rEndPara ),
+ nSttCntnt( rAttr.nSttCntnt ),
+ nEndCntnt( nEndCnt ),
+ bInsAtStart( rAttr.bInsAtStart ),
+ bLikePara( rAttr.bLikePara ),
+ bValid( rAttr.bValid ),
+ nCount( rAttr.nCount ),
+ pNext( 0 ),
+ pPrev( 0 ),
+ ppHead( ppHd )
+{
+ pItem = rAttr.pItem->Clone();
+}
+
+_HTMLAttr::~_HTMLAttr()
+{
+ delete pItem;
+}
+
+_HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, sal_uInt16 nEndCnt ) const
+{
+ // das Attribut mit der alten Start-Position neu anlegen
+ _HTMLAttr *pNew = new _HTMLAttr( *this, rEndPara, nEndCnt, ppHead );
+
+ // die Previous-Liste muss uebernommen werden, die Next-Liste nicht!
+ pNew->pPrev = pPrev;
+
+ return pNew;
+}
+
+void _HTMLAttr::Reset( const SwNodeIndex& rSttPara, sal_uInt16 nSttCnt,
+ _HTMLAttr **ppHd )
+{
+ // den Anfang (und das Ende) neu setzen
+ nSttPara = rSttPara;
+ nSttCntnt = nSttCnt;
+ nEndPara = rSttPara;
+ nEndCntnt = nSttCnt;
+
+ // den Head korrigieren und die Verkettungen aufheben
+ pNext = 0;
+ pPrev = 0;
+ ppHead = ppHd;
+}
+
+void _HTMLAttr::InsertPrev( _HTMLAttr *pPrv )
+{
+ OSL_ENSURE( !pPrv->pNext || pPrv->pNext == this,
+ "_HTMLAttr::InsertPrev: pNext falsch" );
+ pPrv->pNext = 0;
+
+ OSL_ENSURE( 0 == pPrv->ppHead || ppHead == pPrv->ppHead,
+ "_HTMLAttr::InsertPrev: ppHead falsch" );
+ pPrv->ppHead = 0;
+
+ _HTMLAttr *pAttr = this;
+ while( pAttr->GetPrev() )
+ pAttr = pAttr->GetPrev();
+
+ pAttr->pPrev = pPrv;
+}
+
+bool SwHTMLParser::ParseMetaOptions(
+ const uno::Reference<document::XDocumentProperties> & i_xDocProps,
+ SvKeyValueIterator *i_pHeader )
+{
+ // always call base ParseMetaOptions, it sets the encoding (#i96700#)
+ bool ret( HTMLParser::ParseMetaOptions(i_xDocProps, i_pHeader) );
+ if (!ret && IsNewDoc())
+ {
+ ParseMoreMetaOptions();
+ }
+ return ret;
+}
+
+// override so we can parse DOCINFO field subtypes INFO[1-4]
+void SwHTMLParser::AddMetaUserDefined( ::rtl::OUString const & i_rMetaName )
+{
+ // unless we already have 4 names, append the argument to m_InfoNames
+ ::rtl::OUString* pName // the first empty string in m_InfoNames
+ (!m_InfoNames[0].getLength() ? &m_InfoNames[0] :
+ (!m_InfoNames[1].getLength() ? &m_InfoNames[1] :
+ (!m_InfoNames[2].getLength() ? &m_InfoNames[2] :
+ (!m_InfoNames[3].getLength() ? &m_InfoNames[3] : 0 ))));
+ if (pName)
+ {
+ (*pName) = i_rMetaName;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */