diff options
Diffstat (limited to 'sw/source/filter/html/swhtml.cxx')
-rw-r--r-- | sw/source/filter/html/swhtml.cxx | 5646 |
1 files changed, 5646 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..767de5bd214e --- /dev/null +++ b/sw/source/filter/html/swhtml.cxx @@ -0,0 +1,5646 @@ +/************************************************************************* + * + * $RCSfile: swhtml.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 17:14:56 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + + +#ifdef PRECOMPILED +#include "filt_pch.hxx" +#endif + +#pragma hdrstop + +#ifndef PRODUCT +#include <stdlib.h> +#endif + +#ifndef _HINTIDS_HXX +#include <hintids.hxx> +#endif + +#define _SVSTDARR_STRINGS +#include <svtools/svstdarr.hxx> + +#ifndef _SFXSTRITEM_HXX //autogen +#include <svtools/stritem.hxx> +#endif +#ifndef _IMAP_HXX //autogen +#include <svtools/imap.hxx> +#endif +#ifndef _HTMLTOKN_H +#include <svtools/htmltokn.h> +#endif +#ifndef _HTMLKYWD_HXX +#include <svtools/htmlkywd.hxx> +#endif +#ifndef _CTRLTOOL_HXX +#include <svtools/ctrltool.hxx> +#endif + +#ifndef _SV_SVAPP_HXX //autogen +#include <vcl/svapp.hxx> +#endif +#ifndef _WRKWIN_HXX //autogen +#include <vcl/wrkwin.hxx> +#endif +#ifndef _SFX_INIMGR_HXX +#include <sfx2/inimgr.hxx> +#endif +#ifndef _FSETOBJSH_HXX //autogen +#include <sfx2/fsetobsh.hxx> +#endif +#ifndef _SFX_FCONTNR_HXX //autogen +#include <sfx2/fcontnr.hxx> +#endif +#ifndef _SFXDOCINF_HXX //autogen +#include <sfx2/docinf.hxx> +#endif +#ifndef _SFXDOCFILE_HXX //autogen +#include <sfx2/docfile.hxx> +#endif + +#ifndef _OFF_APP_HXX //autogen +#include <offmgr/app.hxx> +#endif +#ifndef _OFA_HTMLCFG_HXX //autogen +#include <offmgr/htmlcfg.hxx> +#endif + +#ifndef _SVXLINKMGR_HXX +#include <svx/linkmgr.hxx> +#endif +#ifndef _SVX_KERNITEM_HXX //autogen +#include <svx/kernitem.hxx> +#endif +#ifndef _SVX_BOXITEM_HXX //autogen +#define ITEMID_BOXINFO SID_ATTR_BORDER_INNER +#include <svx/boxitem.hxx> +#endif +#ifndef _SVX_FHGTITEM_HXX //autogen +#include <svx/fhgtitem.hxx> +#endif +#ifndef _SVX_BRKITEM_HXX //autogen +#include <svx/brkitem.hxx> +#endif +#ifndef _SVX_POSTITEM_HXX //autogen +#include <svx/postitem.hxx> +#endif +#ifndef _SVX_WGHTITEM_HXX //autogen +#include <svx/wghtitem.hxx> +#endif +#ifndef _SVX_CRSDITEM_HXX //autogen +#include <svx/crsditem.hxx> +#endif +#ifndef _SVX_UDLNITEM_HXX //autogen +#include <svx/udlnitem.hxx> +#endif +#ifndef _SVX_ESCPITEM_HXX //autogen +#include <svx/escpitem.hxx> +#endif +#ifndef _SVX_BLNKITEM_HXX //autogen +#include <svx/blnkitem.hxx> +#endif +#ifndef _SVX_ULSPITEM_HXX //autogen +#include <svx/ulspitem.hxx> +#endif +#ifndef _SVX_COLRITEM_HXX //autogen +#include <svx/colritem.hxx> +#endif +#ifndef _SVX_FONTITEM_HXX //autogen +#include <svx/fontitem.hxx> +#endif +#ifndef _SVX_ADJITEM_HXX //autogen +#include <svx/adjitem.hxx> +#endif +#ifndef _SVX_LRSPITEM_HXX //autogen +#include <svx/lrspitem.hxx> +#endif +#ifndef _SVX_PROTITEM_HXX //autogen +#include <svx/protitem.hxx> +#endif +#ifndef _SVX_FLSTITEM_HXX +#include <svx/flstitem.hxx> +#endif + + +#ifndef _FRMATR_HXX +#include <frmatr.hxx> +#endif +#ifndef _CHARATR_HXX +#include <charatr.hxx> +#endif +#ifndef _FMTFLD_HXX //autogen +#include <fmtfld.hxx> +#endif +#ifndef _FMTPDSC_HXX //autogen +#include <fmtpdsc.hxx> +#endif +#ifndef _FMTHBSH_HXX //autogen +#include <fmthbsh.hxx> +#endif +#ifndef _TXTFLD_HXX //autogen +#include <txtfld.hxx> +#endif +#ifndef _FMTANCHR_HXX //autogen +#include <fmtanchr.hxx> +#endif +#ifndef _FMTSRND_HXX //autogen +#include <fmtsrnd.hxx> +#endif +#ifndef _FMTFSIZE_HXX //autogen +#include <fmtfsize.hxx> +#endif +#ifndef _FMTCLDS_HXX //autogen +#include <fmtclds.hxx> +#endif +#ifndef _FCHRFMT_HXX //autogen +#include <fchrfmt.hxx> +#endif +#ifndef _FMTINFMT_HXX //autogen +#include <fmtinfmt.hxx> +#endif +#ifndef _DOCARY_HXX +#include <docary.hxx> +#endif +#ifndef _DOCSTAT_HXX //autogen +#include <docstat.hxx> +#endif +#ifndef _DOC_HXX +#include <doc.hxx> +#endif +#ifndef _PAM_HXX +#include <pam.hxx> +#endif +#ifndef _NDTXT_HXX +#include <ndtxt.hxx> +#endif +#ifndef _MDIEXP_HXX +#include <mdiexp.hxx> // ...Percent() +#endif +#ifndef _EXPFLD_HXX +#include <expfld.hxx> +#endif +#ifndef _POOLFMT_HXX +#include <poolfmt.hxx> +#endif +#ifndef _PAGEDESC_HXX +#include <pagedesc.hxx> +#endif +#ifndef _BOOKMRK_HXX +#include <bookmrk.hxx> // fuer SwBookmark ... +#endif +#ifndef _DOCSH_HXX +#include <docsh.hxx> +#endif +#ifndef _EDITSH_HXX +#include <editsh.hxx> // fuer Start/EndAction +#endif +#ifndef _HINTS_HXX +#include <hints.hxx> // fuer SwObjectDying +#endif +#ifndef _DOCUFLD_HXX +#include <docufld.hxx> +#endif +#ifndef _SWCSS1_HXX +#include <swcss1.hxx> +#endif +#ifndef _HTMLVSH_HXX +#include <htmlvsh.hxx> +#endif +#ifndef _FLTINI_HXX +#include <fltini.hxx> +#endif +#ifndef _HTMLTBL_HXX +#include <htmltbl.hxx> +#endif +#ifndef _HTMLNUM_HXX +#include <htmlnum.hxx> +#endif +#ifndef _SWHTML_HXX +#include <swhtml.hxx> +#endif +#ifndef _LINKENUM_HXX +#include <linkenum.hxx> +#endif + +#ifndef _STATSTR_HRC +#include <statstr.hrc> // ResId fuer Statusleiste +#endif +#ifndef _SWSWERROR_H +#include <swerror.h> +#endif + +#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 + +// <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw. +HTMLOptionEnum __FAR_DATA aHTMLPAlignTable[] = +{ + { sHTML_AL_left, SVX_ADJUST_LEFT }, + { sHTML_AL_center, SVX_ADJUST_CENTER }, + { sHTML_AL_middle, SVX_ADJUST_CENTER }, // Netscape + { sHTML_AL_right, SVX_ADJUST_RIGHT }, + { sHTML_AL_justify, SVX_ADJUST_BLOCK }, + { sHTML_AL_char, SVX_ADJUST_LEFT }, + { 0, 0 } +}; + +// <SPACER TYPE=...> +static HTMLOptionEnum __FAR_DATA aHTMLSpacerTypeTable[] = +{ + { sHTML_SPTYPE_block, HTML_SPTYPE_BLOCK }, + { sHTML_SPTYPE_horizontal, HTML_SPTYPE_HORI }, + { sHTML_SPTYPE_vertical, HTML_SPTYPE_VERT }, + { 0, 0 } +}; + +SV_IMPL_PTRARR( _HTMLAttrs, _HTMLAttrPtr ) + +HTMLReader::HTMLReader() +{ + bTmplBrowseMode = TRUE; + + String sTemplate( + String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("internal")) ); + sTemplate += INET_PATH_TOKEN; + sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("html") ); +#ifndef MAC_WITHOUT_EXT + sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".vor") ); +#endif + + if( SFX_INIMANAGER()->SearchFile( sTemplate, SFX_KEY_TEMPLATE_PATH )) + SetTemplateName( sTemplate ); +#ifndef PRODUCT + else + ASSERT( !this, + "Die html.vor befindet sich nicht mehr im definierten Directory!"); +#endif +} + +int HTMLReader::SetStrmStgPtr() +{ + ASSERT( pMedium, "Wo ist das Medium??" ); + + if( pMedium->IsRemote() || !pMedium->IsStorage() ) + { + pStrm = pMedium->GetInStream(); + return TRUE; + } + return FALSE; + +} + + // Aufruf fuer die allg. Reader-Schnittstelle +ULONG HTMLReader::Read( SwDoc &rDoc,SwPaM &rPam, const String & rName ) +{ + if( !pStrm ) + { + ASSERT( pStrm, "HTML-Read ohne Stream" ); + return ERR_SWG_READ_ERROR; + } + + if( !bInsertMode ) + { + Reader::SetNoOutlineNum( rDoc ); + Reader::ResetFrmFmts( rDoc ); + + rDoc.SetBrowseMode( TRUE ); + + // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist, + // sonst ist sie schon gesetzt. + if( !rDoc.IsHTMLMode() ) + { + rDoc.Insert( rPam, SwFmtPageDesc( + rDoc.GetPageDescFromPool( RES_POOLPAGE_HTML )) ); + } + } + + // damit keiner das Doc klaut! + rDoc.AddLink(); + ULONG nRet = 0; + SvParserRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm, + rName, !bInsertMode, pMedium, + IsReadUTF8() ); + + 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, int bReadNewDoc, + SfxMedium* pMed, BOOL bReadUTF8 ) + : SfxHTMLParser( rIn, bReadNewDoc, pMed ), + SwClient( 0 ), + aPathToFile( rPath ), + pDoc( pD ), + pTable(0), pFormImpl( 0 ), pMarquee( 0 ), + pField( 0 ), + pCSS1Parser( 0 ), pNumRuleInfo( new SwHTMLNumRuleInfo ), + eParaAdjust( SVX_ADJUST_END ), + nScriptStartLineNr( 0 ), + nBaseFontStMin( 0 ), nFontStMin( 0 ), + nDefListDeep( 0 ), + nFontStHeadStart( 0 ), + nSBModuleCnt( 0 ), + nMissingImgMaps( 0 ), + nOpenParaToken( 0 ), + pImageMap( 0 ), + pImageMaps( 0 ), + pSttNdIdx( 0 ), + pPendStack( 0 ), + nParaCnt( 5 ), + pActionViewShell( 0 ), + pAppletImpl( 0 ), + pFootEndNoteImpl( 0 ), + nContextStMin( 0 ), + nContextStAttrMin( 0 ), + bInFloatingFrame( FALSE ), + bInNoEmbed( FALSE ), + bInField( FALSE ), bInTitle( FALSE ), + bInFootEndNoteAnchor( FALSE ), bInFootEndNoteSymbol( FALSE ), + bNoParSpace( FALSE ), bDocInitalized( FALSE ), bCallNextToken( FALSE ), + bDataAvailableLinkSet( FALSE ), + bIgnoreRawData( FALSE ), + bUpdateDocStat( FALSE ), + bFixSelectWidth( FALSE ), + bFixSelectHeight( FALSE ), + bTextArea( FALSE ), bSelect( FALSE ), + bSetModEnabled( FALSE ), + eJumpTo( JUMPTO_NONE ) +#ifndef PRODUCT + ,nContinue( 0 ) +#endif +{ + + bUpperSpace = bViewCreated = bChkJumpMark = + bSetCrsr = FALSE; + + eScriptLang = HTML_SL_UNKNOWN; + bAnyStarBasic = TRUE; + + pPam = new SwPaM( *rCrsr.GetPoint() ); + memset( &aAttrTab, 0, sizeof( _HTMLAttrTable )); + + // Die Font-Groessen 1-7 aus der INI-Datei lesen + OfaHtmlOptions* pHtmlOptions = OFF_APP()->GetHtmlOptions(); + 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(); + + pDoc->SetDefault( SvxFontHeightItem(aFontHeights[2]) ); + + // Waehrend des Imports in den HTML-Modus schalten, damit die + // richrigen Vorlagen angelegt werden + bOldIsHTMLMode = pDoc->IsHTMLMode(); + pDoc->SetHTMLMode( TRUE ); + + pCSS1Parser = new SwCSS1Parser( pDoc, aFontHeights, 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() ); + sBaseURL = INetURLObject::GetBaseURL(); + + // Timer nur bei ganz normalen Dokumenten aufsetzen! + SwDocShell* pDocSh = pDoc->GetDocShell(); + if( pDocSh ) + { + if( SFX_CREATE_MODE_INTERNAL == pDocSh->GetCreateMode() || + SFX_CREATE_MODE_PREVIEW == pDocSh->GetCreateMode() ) + bViewCreated = TRUE; // dann 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; + } + } + } +} + +__EXPORT SwHTMLParser::~SwHTMLParser() +{ +#ifndef PRODUCT + ASSERT( !nContinue, "DTOR im Continue - Das geht schief!!!" ); +#endif + BOOL bAsync = pDoc->IsInLoadAsynchron(); + pDoc->SetInLoadAsynchron( FALSE ); + pDoc->SetHTMLMode( bOldIsHTMLMode ); + + if( pDoc->GetDocShell() && aLoadEnv.Is() ) + { + // Den Link vor dem DocumentDetected austragen, damit + // wir waehrend des DocumentDetected nicht noch irgendwelche + // Daten bekommen, die zum nochmaligen Aufruf von + // DocumentDetected (in NextToken) fuehren. + ((SfxLoadEnvironment*)&aLoadEnv)->SetDataAvailableLink( Link() ); + bDataAvailableLinkSet = FALSE; + + // wenn noch nichts entschieden ist, dann aber hier + if( !bDocInitalized ) + { + ErrCode eError = ((SfxLoadEnvironment*)&aLoadEnv)-> + DocumentDetected( pDoc->GetDocShell(), 0 ); + } + } + + // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals + // abfragen + if( pDoc->GetDocShell() ) + { + // Gelinkte Bereiche updaten + USHORT nLinkMode = pDoc->GetLinkUpdMode(); + if( nLinkMode != NEVER && bAsync && + SFX_CREATE_MODE_INTERNAL!=pDoc->GetDocShell()->GetCreateMode() ) + pDoc->GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL, + TRUE, FALSE ); + + if( pDoc->GetDocShell()->IsLoading() ) + pDoc->GetDocShell()->StartLoadFinishedTimer(); + } + + delete pSttNdIdx; + + if( aSetAttrTab.Count() ) + { + ASSERT( !aSetAttrTab.Count(),"Es stehen noch Attribute auf dem Stack" ); + aSetAttrTab.DeleteAndDestroy( 0, aSetAttrTab.Count() ); + } + + delete pPam; + delete pCSS1Parser; + delete pNumRuleInfo; + DeleteFormImpl(); + DeleteFootEndNoteImpl(); + + ASSERT( !pTable, "Es existiert noch eine offene Tabelle" ); + delete pImageMaps; + //delete pTable; + + ASSERT( !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->RemoveLink() ) + { + // keiner will mehr das Doc haben, also weg damit + delete pDoc; + } +} + +SvParserState __EXPORT 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(); + SwTxtNode* pSttNd = pPos->nNode.GetNode().GetTxtNode(); + + pDoc->SplitNode( *pPos ); + + *pSttNdIdx = pPos->nNode.GetIndex()-1; + pDoc->SplitNode( *pPos ); + + pPam->Move( fnMoveBackward ); + pDoc->SetTxtFmtColl( *pPam, + pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD )); + } + + if( GetMedium() ) + { + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == GetMedium()->GetItemSet()->GetItemState( + SID_LOADENVIRONMENT, FALSE, &pItem )) + { + aLoadEnv = &((SfxRefItem*)pItem)->GetValue(); + } + + if( !bViewCreated && aLoadEnv.Is() ) + { + ((SfxLoadEnvironment*)&aLoadEnv)-> + SetDataAvailableLink( GetAsynchCallLink() ); + bDataAvailableLinkSet = TRUE; + } + else + bViewCreated = TRUE; + } + + // 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 __EXPORT SwHTMLParser::Continue( int nToken ) +{ +#ifndef PRODUCT + ASSERT( !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. + ASSERT( 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 && !pInitVSh && 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 = TRUE; + pDoc->SetInLoadAsynchron( TRUE ); + +#ifndef PRODUCT + nContinue--; +#endif + + return; + } + + bSetModEnabled = FALSE; + if( pDoc->GetDocShell() && + 0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) ) + { + pDoc->GetDocShell()->EnableSetModified( FALSE ); + } + + // waehrend des einlesens kein OLE-Modified rufen + Link aOLELink( pDoc->GetOle2Link() ); + pDoc->SetOle2Link( Link() ); + + BOOL bModified = pDoc->IsModified(); + BOOL bWasUndo = pDoc->DoesUndo(); + pDoc->DoUndo( FALSE ); + + GetSaveAndSetOwnBaseURL(); + + // 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 ) + { + ASSERT( !pPendStack || pPendStack->nToken, + "SwHTMLParser::Continue: Pending-Stack ohne Token" ); + if( pPendStack && pPendStack->nToken ) + NextToken( pPendStack->nToken ); + ASSERT( !pPendStack, + "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" ); + } + else + { + HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken ); + } + + SetSaveBaseURL(); + + // Laufbalken wieder abschalten + EndProgress( pDoc->GetDocShell() ); + + BOOL bLFStripped = 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, + FALSE ); + InsertAttr( SwFmtFld( aFld ) ); + } + + if( pAppletImpl ) + EndApplet(); + + // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen + if( IsNewDoc() ) + bLFStripped = StripTrailingLF() > 0; + + // noch offene Nummerierungen beenden. + while( GetNumInfo().GetNumRule() ) + EndNumBulList(); + + ASSERT( !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( 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 ); + } + +#ifndef PRODUCT +// !!! sollte nicht moeglich sein, oder ?? +ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( TRUE ).nNode.GetIndex(), + "Pam.Bound1 steht noch im Node" ); +ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( FALSE ).nNode.GetIndex(), + "Pam.Bound2 steht noch im Node" ); + +if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( TRUE ).nNode.GetIndex() ) +{ + register xub_StrLen nCntPos = pPam->GetBound( TRUE ).nContent.GetIndex(); + pPam->GetBound( TRUE ).nContent.Assign( pTxtNode, + pTxtNode->GetTxt().Len() + nCntPos ); +} +if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( FALSE ).nNode.GetIndex() ) +{ + register xub_StrLen nCntPos = pPam->GetBound( FALSE ).nContent.GetIndex(); + pPam->GetBound( 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; + ULONG nNodeIdx = pPos->nNode.GetIndex(); + + BOOL bHasFlysOrMarks = + HasCurrentParaFlys() || HasCurrentParaBookmarks( TRUE ); + + if( IsNewDoc() ) + { + if( pDoc->GetNodes()[ nNodeIdx -1 ]->IsCntntNode() && + !pPam->GetPoint()->nContent.GetIndex() ) + { + nNodeIdx = pPam->GetPoint()->nNode.GetIndex(); + SwCntntNode* pCNd = pPam->GetCntntNode(); + if( pCNd && pCNd->StartOfSectionIndex()+2 < + pCNd->EndOfSectionIndex() && !bHasFlysOrMarks ) + { + pPam->GetBound(TRUE).nContent.Assign( 0, 0 ); + pPam->GetBound(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->SwCntntNode::ResetAllAttr(); + + if( pPrev->GetpSwAttrSet() ) + pTxtNode->SwCntntNode::SetAttr( *pPrev->GetpSwAttrSet() ); + + if( &pPam->GetBound(TRUE).nNode.GetNode() == pPrev ) + pPam->GetBound(TRUE).nContent.Assign( pTxtNode, 0 ); + if( &pPam->GetBound(FALSE).nNode.GetNode() == pPrev ) + pPam->GetBound(FALSE).nContent.Assign( pTxtNode, 0 ); + + pTxtNode->JoinPrev(); + } + } + + // und noch die DocumentInfo aufbereiten + if( IsNewDoc() ) + { + const SfxDocumentInfo *pInfo = pDoc->GetInfo(); + if( pInfo->IsReloadEnabled() && + !pInfo->GetReloadURL().Len() ) + { + SfxDocumentInfo aInfo( *pDoc->GetInfo() ); + aInfo.SetReloadURL( aPathToFile ); + pDoc->SetInfo( aInfo ); + } + } + + if( bUpdateDocStat ) + { + SwDocStat aStat( pDoc->GetDocStat() ); + ViewShell *pTmpVSh = 0; + pDoc->GetEditShell( &pTmpVSh ); + USHORT nPages = pTmpVSh ? pTmpVSh->GetNumPages() : 1; + pDoc->UpdateDocStat( aStat, nPages ); + } + } + + 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->GetLinkCnt() ) + { + if( bWasUndo ) + { + pDoc->DelAllUndoObj(); + pDoc->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->DoUndo( TRUE ); + } + + pDoc->SetOle2Link( aOLELink ); + if( !bModified ) + pDoc->ResetModified(); + if( bSetModEnabled && pDoc->GetDocShell() ) + { + pDoc->GetDocShell()->EnableSetModified( TRUE ); + bSetModEnabled = 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( TRUE ); + +#ifndef PRODUCT + nContinue--; +#endif +} + +void SwHTMLParser::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew ) +{ + switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ) + { + case RES_OBJECTDYING: + if( ((SwPtrMsgPoolItem *)pOld)->pObject == pRegisteredIn ) + { + // dann uns selbst beenden + pRegisteredIn->Remove( this ); + ReleaseRef(); // ansonsten sind wir fertig! + } + break; + } +} + +void SwHTMLParser::DocumentDetected() +{ + ASSERT( !bDocInitalized, "DocumentDetected mehrfach aufgerufen" ); + bDocInitalized = TRUE; + if( IsNewDoc() ) + { + if( IsInHeader() ) + FinishHeader( TRUE ); + + CallEndAction( TRUE, TRUE ); + + SetSaveBaseURL(); + +#ifndef PRODUCT + ViewShell *pTmpVSh = 0; + pDoc->GetEditShell( &pTmpVSh ); + ASSERT( pTmpVSh==0, + "Dok-ViewShell existiert schon vor DocDetected" ); +#endif + ErrCode eError = ((SfxLoadEnvironment*)&aLoadEnv)-> + DocumentDetected( pDoc->GetDocShell(), 0 ); + if( eError ) + { + eState = SVPAR_ERROR; + return; + } + GetSaveAndSetOwnBaseURL(); + + pDoc->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(); + } +} + +// wird fuer jedes Token gerufen, das in CallParser erkannt wird +void __EXPORT SwHTMLParser::NextToken( int nToken ) +{ + if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() ) + || 1 == pDoc->GetLinkCnt() ) + { + // wurde der Import vom SFX abgebrochen? Wenn ein Pending-Stack + // existiert den noch aufraumen + eState = SVPAR_ERROR; + ASSERT( !pPendStack || pPendStack->nToken, + "SwHTMLParser::NextToken: Pending-Stack ohne Token" ); + if( 1 == pDoc->GetLinkCnt() || !pPendStack ) + return ; + } + +#ifndef PRODUCT + if( pPendStack ) + { + switch( nToken ) + { + // Tabellen werden ueber rekusive Methodenaufrufe gelesen + case HTML_TABLE_ON: + // Bei CSS-Deklarationen muss evtl. noch auf das + // Ende eines File-Downloads gewartet werden. + case HTML_LINK: + // Bei Controls muss evtl. noch die Groesse gesetzt werden. + case HTML_INPUT: + case HTML_TEXTAREA_ON: + case HTML_SELECT_ON: + case HTML_SELECT_OFF: + break; + default: + ASSERT( !pPendStack, "Unbekanntes Token fuer Pending-Stack" ); + break; + } + } +#endif + + // Die folgeneden Spezialfaelle muessen vor der Filter-Detection behandelt + // werden, denn der Inhalt des Titels, etc. wird auch in Netcape nicht + // zur Filter-Detection herangezogen. + if( !pPendStack ) + { + if( bInTitle ) + { + switch( nToken ) + { + case HTML_TITLE_OFF: + if( IsNewDoc() && sTitle.Len() ) + { + SfxDocumentInfo aInfo( *pDoc->GetInfo() ); + aInfo.SetTitle( sTitle ); + pDoc->SetInfo( aInfo ); + + if( pDoc->GetDocShell() ) + pDoc->GetDocShell()->SetTitle( sTitle ); + } + bInTitle = 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; + } + } + + // Wenn wir noch nicht wissen, was fuer ein Dokument wir vor uns haben, + // versuchen wir das erstmal rauszufinden. Das muss fuer Controls in + // Fall vor dem Einfuegen des Controls passieren, weil beim Einfuegen + // bereits eine View benoetigt wird. + if( !bDocInitalized && aLoadEnv.Is() ) + DocumentDetected(); + + BOOL bGetIDOption = FALSE, bInsertUnknown = FALSE; + BOOL bUpperSpaceSave = bUpperSpace; + bUpperSpace = FALSE; + + // Die folgenden Speziallfaelle muessen oder koennen nach der + // Filter-Detection erfolgen. + if( !pPendStack ) + { + if( bInFloatingFrame ) + { + // <SCRIPT> wird hier (von uns) ignoriert, weil es auch in + // Applets ignoriert wird! + if( HTML_IFRAME_OFF == nToken ) + { + bCallNextToken = FALSE; + EndFloatingFrame(); + } + + return; + } + else if( bInNoEmbed ) + { + switch( nToken ) + { + case HTML_NOEMBED_OFF: + aContents.ConvertLineEnd(); + InsertComment( aContents, sHTML_noembed ); + aContents.Erase(); + bCallNextToken = FALSE; + bInNoEmbed = FALSE; + break; + + case HTML_RAWDATA: + InsertCommentText( sHTML_noembed ); + break; + + default: + ASSERT( !this, "SwHTMLParser::NextToken: ungueltiges Tag" ); + break; + } + + return; + } + else if( pAppletImpl ) + { + // in einem Applet interessieren uns (erstmal) nur <PARAM>-Tags + // und das </APPLET>. + // <SCRIPT> wird hier (von Netscape) ignoriert! + + switch( nToken ) + { + case HTML_APPLET_OFF: + bCallNextToken = FALSE; + EndApplet(); + break; + + case HTML_PARAM: + InsertParam(); + break; + } + + return; + } + else if( bTextArea ) + { + // in einer TextArea wird alles bis zum </TEXTAREA> als Text + // eingefuegt + // <SCRIPT> wird hier (von Netscape) ignoriert! + + switch( nToken ) + { + case HTML_TEXTAREA_OFF: + bCallNextToken = FALSE; + EndTextArea(); + break; + + default: + InsertTextAreaText( nToken ); + break; + } + + return; + } + else if( bSelect ) + { + // MUSS nach bNoScript kommen! + switch( nToken ) + { + case HTML_SELECT_OFF: + bCallNextToken = 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: + // im normalen switch bahandeln + break; + + default: + // ignorieren + return; + } + } + else if( pMarquee ) + { + // in einer TextArea wird alles bis zum </TEXTAREA> als Text + // eingefuegt + // Die <SCRIPT>-Tags werden vom MS-IE ignoriert, von uns das + // geasmte Script + switch( nToken ) + { + case HTML_MARQUEE_OFF: + bCallNextToken = FALSE; + EndMarquee(); + break; + + case HTML_TEXTTOKEN: + InsertMarqueeText(); + break; + } + + return; + } + else if( bInField ) + { + switch( nToken ) + { + case HTML_SDFIELD_OFF: + bCallNextToken = FALSE; + EndField(); + break; + + case HTML_TEXTTOKEN: + InsertFieldText(); + break; + } + + return; + } + else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol ) + { + switch( nToken ) + { + case HTML_ANCHOR_OFF: + EndAnchor(); + bCallNextToken = FALSE; + break; + + case HTML_TEXTTOKEN: + InsertFootEndNoteText(); + break; + } + return; + } + else if( aUnknownToken.Len() ) + { + // Unbekannte Token im Header werden nur durch ein passendes + // End-Token, </HEAD> oder <BODY> wieder beendet. Darin wird Text + // ignoriert. + 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: // Warum auch immer Netscape das tut. + aUnknownToken.Erase(); + break; + case HTML_TEXTTOKEN: + return; + default: + break; + } + } + } + + switch( nToken ) + { + case HTML_BODY_ON: + if( aStyleSource.Len() ) + { + pCSS1Parser->ParseStyleSheet( aStyleSource ); + aStyleSource.Erase(); + } + if( IsNewDoc() ) + { + InsertBodyOptions(); + // Falls es eine Vorlage fuer die erste oder rechte Seite gibt, + // setzen wir die hier. + const SwPageDesc *pPageDesc = 0; + if( pCSS1Parser->IsSetFirstPageDesc() ) + pPageDesc = pCSS1Parser->GetFirstPageDesc(); + else if( pCSS1Parser->IsSetRightPageDesc() ) + pPageDesc = pCSS1Parser->GetRightPageDesc(); + + if( pPageDesc ) + pDoc->Insert( *pPam, SwFmtPageDesc( pPageDesc ) ); + } + break; + + case HTML_LINK: + InsertLink(); + break; + + case HTML_BASE: + { + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[ --i ]; + switch( pOption->GetToken() ) + { + case HTML_O_HREF: + sBaseURL = pOption->GetString(); + INetURLObject::SetBaseURL( sBaseURL ); + break; + case HTML_O_TARGET: + if( IsNewDoc() ) + { + SfxDocumentInfo aInfo( *pDoc->GetInfo() ); + aInfo.SetDefaultTarget( pOption->GetString() ); + pDoc->SetInfo( aInfo ); + } + break; + } + } + } + break; + + case HTML_META: + if( IsNewDoc() ) + { + SwDocShell *pDocSh = pDoc->GetDocShell(); + SvKeyValueIterator *pHTTPHeader = + pDocSh ? pDocSh->GetHeaderAttributes() : 0; + SfxDocumentInfo aInfo( *pDoc->GetInfo() ); + + if( ParseMetaOptions( &aInfo, pHTTPHeader ) ) + { + pDoc->SetInfo( aInfo ); + } + else + { + ParseMoreMetaOptions(); + } + } + break; + + case HTML_TITLE_ON: + bInTitle = TRUE; + break; + + case HTML_SCRIPT_ON: + NewScript(); + break; + + case HTML_SCRIPT_OFF: + EndScript(); + break; + + case HTML_NOSCRIPT_ON: + case HTML_NOSCRIPT_OFF: + bInsertUnknown = 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_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 = TRUE; + // <BR>s in <PRE> aehneln echten LFs, deshalb kein break + + case HTML_NEWPARA: + // CR in PRE/LISTING/XMP + { + if( HTML_NEWPARA==nToken || + pPam->GetPoint()->nContent.GetIndex() ) + { + AppendTxtNode(); // lf gibts hier nicht, deshalb unkritisch + SetTxtCollAttrs(); + } + // Laufbalkenanzeige + if( !GetMedium() || !GetMedium()->IsRemote() ) + ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() ); + } + break; + + case HTML_NONBREAKSPACE: + pDoc->Insert( *pPam, CHAR_HARDBLANK ); + break; + + case HTML_SOFTHYPH: + pDoc->Insert( *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) ); + EndAttr( aAttrTab.pBreak, 0, FALSE ); + } + break; + + case HTML_TEXTTOKEN: + // dann fuege den String ein, ohne das Attribute am Ende + // aufgespannt werden. + if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() ) + { + xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex(); + if( nPos ) + { + const String& rText = + pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->GetTxtNode() + ->GetTxt(); + register 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 && aLoadEnv.Is() ) + DocumentDetected(); + pDoc->Insert( *pPam, aToken ); + + // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber + // nicht leer ist, dann sind die Absatz-Attribute entgueltig. + if( aParaAttrs.Count() ) + aParaAttrs.Remove( 0, aParaAttrs.Count() ); + + SetAttr(); + } + break; + + case HTML_HORZRULE: + InsertHorzRule(); + break; + + case HTML_IMAGE: + InsertImage(); + // sollte der Parser der Letzte sein, der das Doc haelt, dann kann + // man hier abbrechen und einen Fehler setzen. + if( 1 == pDoc->GetLinkCnt() ) + { + eState = SVPAR_ERROR; + } + break; + + case HTML_SPACER: + InsertSpacer(); + break; + + case HTML_EMBED: + InsertEmbed(); + break; + + case HTML_NOEMBED_ON: + bInNoEmbed = TRUE; + bCallNextToken = pTable!=0; + ReadRawData( sHTML_noembed ); + break; + + case HTML_DEFLIST_ON: + if( nOpenParaToken ) + EndPara(); + NewDefList(); + break; + case HTML_DEFLIST_OFF: + if( nOpenParaToken ) + EndPara(); + EndDefListItem( 0, FALSE, 1==nDefListDeep ); + EndDefList(); + break; + + case HTML_DD_ON: + case HTML_DT_ON: + if( nOpenParaToken ) + EndPara(); + EndDefListItem( 0, FALSE );// <DD>/<DT> beenden und keine Vorl. setzen + NewDefListItem( nToken ); + break; + + case HTML_DD_OFF: + case HTML_DT_OFF: + // siehe HTML_LI_OFF + // eigentlich muesste man ein DD/DT jetzt beenden. Da aber sowhl + // Netscape als auch Microsoft das nicht tun, machen wir das eben + // auch nicht. + EndDefListItem( nToken, FALSE ); + break; + + // Bereiche + 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; + + // Vorlagen: + case HTML_PARABREAK_ON: + if( nOpenParaToken ) + EndPara( TRUE ); + NewPara(); + break; + + case HTML_PARABREAK_OFF: + EndPara( 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 = TRUE; // der letzte PRE-Absatz muss einen Zeilenabstand bekommen + 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(); + ASSERT( !pTable, "Tabelle in Tabelle darf hier nicht vorkommen" ); + if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) && + (pPam->GetPoint()->nNode.GetIndex() > + pDoc->GetNodes().GetEndOfExtras().GetIndex() || + !pPam->GetNode()->FindFootnoteStartNode() ) ) + { + if ( nParaCnt < 5 ) + Show(); // bis hierhin schon mal anzeigen + + SvxAdjust eAdjust = aAttrTab.pAdjust + ? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()). + GetAdjust() + : SVX_ADJUST_END; + BuildTable( eAdjust ); + } + else + bInsertUnknown = bKeepUnknown; + } + break; + + // Listen + 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, 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) ) + { + // nure bei <P><LI> den Absatz beenden, aber nicht bei <DD><LI> + EndPara(); + } + + EndNumBulListItem( 0, FALSE );// <LI>/<LH> beenden und keine Vorl. setzen + NewNumBulListItem( nToken ); + break; + + case HTML_LI_OFF: + case HTML_LISTHEADER_OFF: + EndNumBulListItem( nToken, FALSE ); + break; + + // Attribute : + case HTML_ITALIC_ON: + { + NewStdAttr( HTML_ITALIC_ON, &aAttrTab.pItalic, + SvxPostureItem(ITALIC_NORMAL) ); + } + break; + + case HTML_BOLD_ON: + { + NewStdAttr( HTML_BOLD_ON, &aAttrTab.pBold, + SvxWeightItem(WEIGHT_BOLD) ); + } + break; + + + case HTML_STRIKE_ON: + case HTML_STRIKETHROUGH_ON: + { + NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike, + SvxCrossedOutItem(STRIKEOUT_SINGLE) ); + } + break; + + case HTML_UNDERLINE_ON: + { + NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline, + SvxUnderlineItem(UNDERLINE_SINGLE) ); + } + break; + + case HTML_SUPERSCRIPT_ON: + { + NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement, + SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP) ); + } + break; + + case HTML_SUBSCRIPT_ON: + { + NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement, + SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP) ); + } + break; + + case HTML_BLINK_ON: + { + NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink, + SvxBlinkItem( TRUE ) ); + } + 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_ON: + case HTML_HTML_OFF: + case HTML_HEAD_ON: + case HTML_TITLE_OFF: + break; // nicht weiter auswerten, oder??? + + 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 ) + { + // als Post-It einfuegen + String aComment( aToken.Copy( 3, aToken.Len()-5 ) ); + aComment.EraseLeadingChars().EraseTrailingChars(); + InsertComment( aComment ); + } + break; + + case HTML_MAP_ON: + // Image Maps werden asynchron gelesen: Zunaechst wird nur eine + // ImageMap angelegt. Die Bereiche kommen spaeter. Trozdem wird + // die ImageMap schon in das IMap-Array eingetragen, denn sie + // koennte ja schon verwendet werden. + 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: + // jetzt gibt es keine ImageMap mehr (IMap nicht Loeschen, denn + // die stckt ja schon in dem Array!) + pImageMap = 0; + break; + + case HTML_AREA: + if( pImageMap ) + ParseAreaOptions( pImageMap, SFX_EVENT_MOUSEOVER_OBJECT, + SFX_EVENT_MOUSEOUT_OBJECT ); + break; + + case HTML_FRAMESET_ON: + bInsertUnknown = bKeepUnknown; + break; + + case HTML_NOFRAMES_ON: + if( IsInHeader() ) + FinishHeader( TRUE ); + bInsertUnknown = bKeepUnknown; + break; + + case HTML_UNKNOWNCONTROL_ON: + // Im Header muss der Inhalt von unbekannten Token ignoriert werden, + // es sei denn, das Token faengt mit einem '!' an. + if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() && + sSaveToken.Len() && '!' != sSaveToken.GetChar(0) && + '%' != sSaveToken.GetChar(0) ) + aUnknownToken = sSaveToken; + // kein 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 ); + } + + // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber + // nicht leer ist, dann sind die Absatz-Attribute entgueltig. + if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() ) + aParaAttrs.Remove( 0, aParaAttrs.Count() ); +} + +/* */ + +BOOL SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, 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 = + pDoc->GetNodes()[pPam->GetPoint()->nNode]->GetTxtNode(); + + const SvxULSpaceItem& rULSpace = + (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE ); + + BOOL bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0 + : rULSpace.GetLower() == 0; + + if( bChange ) + { + const SvxULSpaceItem& rCollULSpace = + pTxtNode->GetAnyFmtColl().GetULSpace(); + + BOOL bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0 + : rCollULSpace.GetLower() > 0; + + if( bMayReset && + rCollULSpace.GetUpper() == rULSpace.GetUpper() ) + { + pTxtNode->ResetAttr( RES_UL_SPACE ); + } + else + { + pTxtNode->SwCntntNode::SetAttr( + SvxULSpaceItem( rULSpace.GetUpper(), + AM_NOSPACE==eMode ? 0 : HTML_PARSPACE ) ); + } + } + } + bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode; + + SwPosition aOldPos( *pPam->GetPoint() ); + + 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( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* ); + nCnt--; ++pTbl ) + { + _HTMLAttr *pAttr = *pTbl; + if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN ) + { + BOOL bWholePara = FALSE; + + while( pAttr ) + { + _HTMLAttr *pNext = pAttr->GetNext(); + if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() || + (!bWholePara && + pAttr->GetSttPara() == rEndIdx && + pAttr->GetSttCnt() != nEndCnt) ) + { + // den besehrigen Teil setzen + _HTMLAttr *pSetAttr = + pAttr->Clone( rEndIdx, nEndCnt ); + pAttr->ClearPrev(); + + bWholePara = + pAttr->GetSttPara() == rEndIdx && + pAttr->GetSttCnt() == 0; + + // 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 (siehe #51020#) + if( !pNext || bWholePara ) + { + USHORT nTmp = pAttr->bInsAtStart ? 0 + : aSetAttrTab.Count(); + aSetAttrTab.Insert( pSetAttr, nTmp ); + } + else + pNext->InsertPrev( pSetAttr ); + } + + pAttr->SetStart( rPos ); + pAttr = pNext; + } + } + } + + if( bUpdateNum ) + { + if( GetNumInfo().GetDepth() ) + SetNodeNum( GetNumInfo().GetLevel() | NO_NUMLEVEL ); + else + pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE ); + } + + // Attrubute im Absatz davor sollte man jetzt setzen (wegen JavaScript) + SetAttr(); + + if( !pTable && !--nParaCnt ) + Show(); + + return bRet; +} + +void SwHTMLParser::AddParSpace() +{ + if( !bNoParSpace ) + return; + + bNoParSpace = FALSE; + + 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->SwCntntNode::SetAttr( + SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE ) ); + } + } +} + + +void SwHTMLParser::Show() +{ + // Hier wird + // - ein EndAction gerufen, damit formatiert wird + // - ein Reschedule gerufen, + // - die eiegen View-Shell wieder gesetzt + // - und Start-Action gerufen + + ASSERT( SVPAR_WORKING==eState, "Show nicht im Working-State - Das kann ins Auge gehen" ); + ViewShell *pOldVSh = CallEndAction(); + + SetSaveBaseURL(); + GetpApp()->Reschedule(); + GetSaveAndSetOwnBaseURL(); + + if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() ) + || 1 == pDoc->GetLinkCnt() ) + { + // 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 ); + ASSERT( pOldVSh == pVSh, "Show:: Shell wurde ausgetauscht" ); + + // ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir + // eine groessere Schrittweite + if( pVSh ) + nParaCnt = pDoc->GetNodes()[pPam->GetPoint()->nNode] + ->IsVisible(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. + + ASSERT( SVPAR_WORKING==eState, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" ); + + // Laufbalkenanzeige + SetSaveBaseURL(); + if( !GetMedium() || !GetMedium()->IsRemote() ) + { + ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() ); + GetSaveAndSetOwnBaseURL(); + CheckActionViewShell(); + } + else + { + GetpApp()->Reschedule(); + GetSaveAndSetOwnBaseURL(); + + if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() ) + || 1 == pDoc->GetLinkCnt() ) + // wurde der Import vom SFX abgebrochen? + eState = SVPAR_ERROR; + + ViewShell *pVSh = CheckActionViewShell(); + if( pVSh && pVSh->HasInvalidRect() ) + { + CallEndAction( FALSE, FALSE ); + CallStartAction( pVSh, FALSE ); + } + } +} + +ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, BOOL bChkPtr ) +{ + ASSERT( !pActionViewShell, "CallStartAction: ViewShell schon gesetzt" ); + + if( !pVSh || bChkPtr ) + { + ViewShell *pOldVSh = pVSh; + pDoc->GetEditShell( &pVSh ); + ASSERT( !pVSh || !pOldVSh || pOldVSh == pVSh, + "CallStartAction: Wer hat die ViewShell ausgetauscht?" ); +#ifdef DEBUG + 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( BOOL bChkAction, BOOL bChkPtr ) +{ + if( bChkPtr ) + { + ViewShell *pVSh = 0; + pDoc->GetEditShell( &pVSh ); + ASSERT( !pVSh || pActionViewShell == pVSh, + "CallEndAction: Wer hat die ViewShell ausgetauscht?" ); +#ifdef DEBUG + 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)->SttDoc(); + pSh = (ViewShell *)pSh->GetNext(); + } while( pSh != pActionViewShell ); + + bSetCrsr = FALSE; + } + if( pActionViewShell->ISA( SwEditShell ) ) + { + //Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt! + const FASTBOOL bOldLock = pActionViewShell->IsViewLocked(); + pActionViewShell->LockView( TRUE ); + const FASTBOOL bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev(); + pActionViewShell->SetEndActionByVirDev( 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 = 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->GetLinkCnt() ) + { + eState = SVPAR_ERROR; + } + + ViewShell *pVSh = pActionViewShell; + pActionViewShell = 0; + + return pVSh; +} + +ViewShell *SwHTMLParser::CheckActionViewShell() +{ + ViewShell *pVSh = 0; + pDoc->GetEditShell( &pVSh ); + ASSERT( !pVSh || pActionViewShell == pVSh, + "CheckActionViewShell: Wer hat die ViewShell ausgetauscht?" ); +#ifdef DEBUG + if( pActionViewShell && !pVSh ) + pVSh = 0; +#endif + if( pVSh != pActionViewShell ) + pActionViewShell = 0; + + return pActionViewShell; +} + +/* */ + +void SwHTMLParser::_SetAttr( BOOL bChkEnd, 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; + + _HTMLAttrs aFields( 5, 5 ); + + for( USHORT n = aSetAttrTab.Count(); n; ) + { + pAttr = aSetAttrTab[ --n ]; + USHORT nWhich = pAttr->pItem->Which(); + + ULONG nEndParaIdx = pAttr->GetEndParaIdx(); + BOOL bSetAttr; + if( bChkEnd ) + { + // fix #42192#: 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 && + RES_CHRATR_BEGIN <= nWhich && + RES_TXTATR_WITHEND_END > 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. + 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. + USHORT ii = aParaAttrs.Count(); + while( ii-- ) + { + ASSERT( 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 = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode(); + if( !pCNd ) + { + // durch die elende Loescherei von Nodes kann auch mal + // ein Index auf einen End-Node zeigen :-( + if( pAttr->GetSttPara() == pAttr->GetEndPara() && + (nWhich < RES_TXTATR_NOEND_BEGIN || + nWhich >= RES_TXTATR_NOEND_END) ) + { + // 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 + { + ASSERT( !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() && + (nWhich < RES_TXTATR_NOEND_BEGIN || + nWhich >= RES_TXTATR_NOEND_END) ) + { + pCNd = pDoc->GetNodes()[ pAttr->nEndPara ]->GetCntntNode(); + if( !pCNd ) + { + pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) ); + if( pCNd ) + pAttr->nEndCntnt = pCNd->Len(); + else + { + ASSERT( !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 && + (nWhich < RES_TXTATR_NOEND_BEGIN || + nWhich >= RES_TXTATR_NOEND_END) ) + { + if( pAttrPam->GetMark()->nNode.GetIndex() != + rEndIdx.GetIndex() ) + { + ASSERT( !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: // dann also ein Bookmark einfuegen + { + String aName( ((SfxStringItem*)pAttr->pItem)->GetValue() ); + USHORT nBookPos = pDoc->FindBookmark( aName ); + if( nBookPos != USHRT_MAX ) + { + const SwBookmark *pBkMk = + pDoc->GetBookmarks()[nBookPos]; + if( pBkMk->GetPos() != *pAttrPam->GetPoint() ) + pDoc->MakeUniqueBookmarkName( aName ); + else + break; // keine doppelte Bookmark an dieser Pos + } + pAttrPam->DeleteMark(); + pDoc->MakeBookmark( *pAttrPam, KeyCode(), + aName, aEmptyStr ); + + // ggfs. ein Bookmark anspringen + if( JUMPTO_MARK == eJumpTo && + aName == sJmpMark ) + { + bChkJumpMark = TRUE; + eJumpTo = JUMPTO_NONE; + } + } + break; + case RES_TXTATR_FIELD: + { + USHORT 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; + } + ASSERT( !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 = TRUE; + eJumpTo = JUMPTO_NONE; + } + + pDoc->Insert( *pAttrPam, *pAttr->pItem, SETATTR_DONTREPLACE ); + } + pAttrPam->DeleteMark(); + + delete pAttr; + pAttr = pPrev; + } + } + } + + for( n = aMoveFlyFrms.Count(); n; ) + { + SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ]; + + const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); + ASSERT( FLY_AT_CNTNT==rAnchor.GetAnchorId(), + "Nur Auto-Rahmen brauchen eine Spezialbehandlung" ); + const SwPosition *pFlyPos = rAnchor.GetCntntAnchor(); + ULONG nFlyParaIdx = pFlyPos->nNode.GetIndex(); + BOOL bMoveFly; + if( bChkEnd ) + { + bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() || + ( nFlyParaIdx == rEndIdx.GetIndex() && + aMoveFlyCnts[n] < nEndCnt ); + } + else + { + 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_AUTO_CNTNT ); + aAnchor.SetAnchor( pAttrPam->GetPoint() ); + pFrmFmt->SetAttr( aAnchor ); + + const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient(); + if( HORI_LEFT == rHoriOri.GetHoriOrient() ) + { + SwFmtHoriOrient aHoriOri( rHoriOri ); + aHoriOri.SetRelationOrient( REL_CHAR ); + pFrmFmt->SetAttr( aHoriOri ); + } + const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient(); + if( VERT_TOP == rVertOri.GetVertOrient() ) + { + SwFmtVertOrient aVertOri( rVertOri ); + aVertOri.SetRelationOrient( REL_CHAR ); + pFrmFmt->SetAttr( aVertOri ); + } + + pFrmFmt->MakeFrms(); + aMoveFlyFrms.Remove( n, 1 ); + aMoveFlyCnts.Remove( n, 1 ); + } + } + while( aFields.Count() ) + { + pAttr = aFields[0]; + + pCNd = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode(); + pAttrPam->GetPoint()->nNode = pAttr->nSttPara; + pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt ); + + if( bBeforeTable && + pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() ) + { + ASSERT( !bBeforeTable, "Aha, der Fall tritt also doch ein" ); + ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(), + "Content-Position vor Tabelle nicht 0???" ); + // !!! + pAttrPam->Move( fnMoveBackward ); + } + + pDoc->Insert( *pAttrPam, *pAttr->pItem ); + + 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, + BOOL bChkEmpty ) +{ + ASSERT( !ppDepAttr, "SwHTMLParser::EndAttr: ppDepAttr-Feature ungetestet?" ); + // Der Listenkopf ist im Attribut gespeichert + _HTMLAttr **ppHead = pAttr->ppHead; + + ASSERT( 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(); + + ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" ); + + // das Attribut nicht an der PaM-Psoition beenden, sondern da, + // wo das danch gestartete Attribut anfing??? + //pEndIdx = &pPrev->GetSttPara(); + //nEndCnt = pPrev->GetSttCnt(); + } + + BOOL bMoveBack = FALSE; + USHORT nWhich = pAttr->pItem->Which(); + if( /*!pLast &&*/ !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(); + + // ein Bereich ?? + if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) || + RES_PAGEDESC == nWhich || RES_BREAK == nWhich || + *pEndIdx != pAttr->GetSttPara() || + nEndCnt != pAttr->GetSttCnt() ) + { + 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 + { + USHORT 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 + { + USHORT 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!!! + ASSERT( !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; + + ASSERT( 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(); + + ASSERT( 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 + { + USHORT 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!!! + ASSERT( !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( USHORT 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, + BOOL bMoveEndBack ) +{ + // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die + // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!! + ASSERT( !aParaAttrs.Count(), + "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" ); + if( aParaAttrs.Count() ) + aParaAttrs.Remove( 0, aParaAttrs.Count() ); + + const SwNodeIndex& 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; + BOOL bSetAttr = TRUE; + xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex(); + xub_StrLen nEndCnt = nSttCnt; + + if( bMoveEndBack ) + { + ULONG nOldEnd = nEndIdx.GetIndex(); + 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( USHORT 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 + { + USHORT 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 + { + USHORT 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, + BOOL bSetNewStart ) +{ + // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die + // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!! + ASSERT( !aParaAttrs.Count(), + "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" ); + if( aParaAttrs.Count() ) + aParaAttrs.Remove( 0, aParaAttrs.Count() ); + + _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab; + _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab; + + for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* ); + nCnt--; (++pTbl, ++pSaveTbl) ) + { + ASSERT( !*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 ) + { + ASSERT( !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, BOOL bLikePara, + BOOL bInsAtStart ) +{ + _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), + rItem ); + if( bLikePara ) + pTmp->SetLikePara(); + USHORT 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; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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; + } + } + + // einen neuen Kontext anlegen + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( nToken ); + + // Styles parsen + if( HasStyleOptions( aStyle, aId, aClass ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) ) + { + if( HTML_SPAN_ON != nToken || !aClass.Len() || + !CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) ) + DoPositioning( aItemSet, aPropInfo, pCntxt ); + InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE ); + } + } + + // den Kontext merken + PushContext( pCntxt ); +} + +void SwHTMLParser::NewStdAttr( int nToken, _HTMLAttr **ppAttr, + const SfxPoolItem & rItem ) +{ + String aId, aStyle, aClass; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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; + } + } + + // einen neuen Kontext anlegen + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( nToken ); + + // Styles parsen + if( HasStyleOptions( aStyle, aId, aClass ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + aItemSet.Put( rItem ); + + if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) ) + DoPositioning( aItemSet, aPropInfo, pCntxt ); + + InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE ); + } + else + { + InsertAttr( ppAttr ,rItem, pCntxt ); + } + + // den Kontext merken + PushContext( pCntxt ); +} + +void SwHTMLParser::EndTag( int nToken ) +{ + // den Kontext holen + _HTMLAttrContext *pCntxt = PopContext( nToken & ~1 ); + if( pCntxt ) + { + // und ggf. die Attribute beenden + EndContext( pCntxt ); + delete pCntxt; + } +} + + +void SwHTMLParser::NewBasefontAttr() +{ + String aId, aStyle, aClass; + USHORT nSize = 3; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_SIZE: + nSize = (USHORT)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; + } + } + + 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 ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + aItemSet.Put( SvxFontHeightItem( aFontHeights[nSize-1] ) ); + + if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) ) + DoPositioning( aItemSet, aPropInfo, pCntxt ); + + InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE ); + } + else + { + InsertAttr( &aAttrTab.pFontHeight, SvxFontHeightItem( aFontHeights[nSize-1] ), 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 ) +{ + USHORT nBaseSize = + ( aBaseFontStack.Count() > nBaseFontStMin + ? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK) + : 3 ); + USHORT nFontSize = + ( aFontStack.Count() > nFontStMin + ? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK) + : nBaseSize ); + + String aFace, aId, aStyle, aClass; + Color aColor; + ULONG nFontHeight = 0; // tatsaechlich einzustellende Font-Hoehe + USHORT nSize = 0; // Fontgroesse in Netscape-Notation (1-7) + BOOL bColor = FALSE; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_SIZE: + if( HTML_FONT_ON==nToken && pOption->GetString().Len() ) + { + INT32 nSSize; + if( '+' == pOption->GetString().GetChar(0) || + '-' == pOption->GetString().GetChar(0) ) + nSSize = nBaseSize + pOption->GetSNumber(); + else + nSSize = (INT32)pOption->GetNumber(); + + if( nSSize < 1 ) + nSSize = 1; + else if( nSSize > 7 ) + nSSize = 7; + + nSize = (USHORT)nSSize; + nFontHeight = aFontHeights[nSize-1]; + } + break; + case HTML_O_COLOR: + if( HTML_FONT_ON==nToken ) + { + pOption->GetColor( aColor ); + bColor = 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; + } + } + + if( HTML_FONT_ON != nToken ) + { + // HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON + + // in Ueberschriften bestimmt die aktuelle Ueberschrift + // die Font-Hoehe und nicht BASEFONT + USHORT 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 = 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]; + } + + ASSERT( !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(); + } + + BOOL bFound = 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 = 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( nToken ); + + // Styles parsen + if( HasStyleOptions( aStyle, aId, aClass ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( nFontHeight ) + aItemSet.Put( SvxFontHeightItem( nFontHeight ) ); + if( bColor ) + aItemSet.Put( SvxColorItem(aColor) ); + if( aFontName.Len() ) + aItemSet.Put( SvxFontItem( eFamily, aFontName, aStyleName, + ePitch, eEnc ) ); + + + if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) ) + DoPositioning( aItemSet, aPropInfo, pCntxt ); + + InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE ); + } + else + { + if( nFontHeight ) + InsertAttr( &aAttrTab.pFontHeight, + SvxFontHeightItem( nFontHeight ), pCntxt ); + if( bColor ) + InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor), pCntxt ); + if( aFontName.Len() ) + InsertAttr( &aAttrTab.pFont, + SvxFontItem( eFamily, aFontName, aStyleName, ePitch, + eEnc ), 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; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_ID: + aId = pOption->GetString(); + break; + case HTML_O_ALIGN: + eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, eParaAdjust ); + break; + case HTML_O_STYLE: + aStyle = pOption->GetString(); + break; + case HTML_O_CLASS: + aClass = 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 ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo ) ) + { + ASSERT( !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), pCntxt ); + + // und auf den Stack packen + PushContext( pCntxt ); + + // die aktuelle Vorlage oder deren Attribute setzen + SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 ); + + // Laufbalkenanzeige + ShowStatline(); + + ASSERT( !nOpenParaToken, "Jetzt geht ein offenes Absatz-Element verloren" ); + nOpenParaToken = HTML_PARABREAK_ON; +} + +void SwHTMLParser::EndPara( BOOL bReal ) +{ + if( HTML_LI_ON==nOpenParaToken && pTable ) + { + const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule(); + ASSERT( pNumRule, "Wo ist die Numrule geblieben" ); + if( pNumRule ) + pDoc->UpdateNumRule( pNumRule->GetName(), + pPam->GetPoint()->nNode.GetIndex() ); + } + + // 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( 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; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_ID: + aId = pOption->GetString(); + break; + case HTML_O_ALIGN: + eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, eParaAdjust ); + break; + case HTML_O_STYLE: + aStyle = pOption->GetString(); + break; + case HTML_O_CLASS: + aClass = pOption->GetString(); + break; + } + } + + // einen neuen Absatz aufmachen + if( pPam->GetPoint()->nContent.GetIndex() ) + AppendTxtNode( AM_SPACE ); + else + AddParSpace(); + + // die passende Vorlage suchen + USHORT 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( nToken, nTxtColl, aClass ); + + // Styles parsen (zu Class siehe auch NewPara) + if( HasStyleOptions( aStyle, aId, aEmptyStr ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo ) ) + { + ASSERT( !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), 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; + USHORT 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, USHORT nColl ) +{ + String aId, aStyle, aClass; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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; + } + } + + // 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: + ASSERT( !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( nToken, nColl, aClass ); + + // Styles parsen (zu Class siehe auch NewPara) + if( HasStyleOptions( aStyle, aId, aEmptyStr ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo ) ) + { + ASSERT( !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: + ASSERT( !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( 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; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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; + } + } + + // einen neuen Absatz aufmachen + 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++; + + + BOOL bInDD = FALSE, bNotInDD = FALSE; + USHORT nPos = aContexts.Count(); + while( !bInDD && !bNotInDD && nPos>nContextStMin ) + { + USHORT 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 = TRUE; + break; + case HTML_DD_ON: + bInDD = TRUE; + break; + } + } + + + // ... und in einem Kontext merken + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON ); + + // darin auch die Raender merken + USHORT 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 += rLRSpace.GetTxtLeft(); + } + + pCntxt->SetMargins( nLeft, nRight, nIndent ); + + // Styles parsen + if( HasStyleOptions( aStyle, aId, aClass ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) ) + { + DoPositioning( aItemSet, aPropInfo, pCntxt ); + InsertAttrs( aItemSet, aPropInfo, pCntxt ); + } + } + + PushContext( pCntxt ); + + // die Attribute der neuen Vorlage setzen + if( nDefListDeep > 1 ) + SetTxtCollAttrs( pCntxt ); +} + +void SwHTMLParser::EndDefList() +{ + 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 + BOOL bInDefList = FALSE, bNotInDefList = FALSE; + USHORT nPos = aContexts.Count(); + while( !bInDefList && !bNotInDefList && nPos>nContextStMin ) + { + USHORT nCntxtToken = aContexts[--nPos]->GetToken(); + switch( nCntxtToken ) + { + case HTML_DEFLIST_ON: + bInDefList = TRUE; + break; + case HTML_DIRLIST_ON: + case HTML_MENULIST_ON: + case HTML_ORDERLIST_ON: + case HTML_UNORDERLIST_ON: + bNotInDefList = TRUE; + break; + } + } + + // wenn nicht, implizit eine neue DL aufmachen + if( !bInDefList ) + { + nDefListDeep++; + ASSERT( !nOpenParaToken, + "Jetzt geht ein offenes Absatz-Element verloren" ); + nOpenParaToken = nToken; + } + + NewTxtFmtColl( nToken, nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD + : RES_POOLCOLL_HTML_DT ); +} + +void SwHTMLParser::EndDefListItem( int nToken, BOOL bSetColl, + 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; + USHORT nPos = aContexts.Count(); + while( !pCntxt && nPos>nContextStMin ) + { + USHORT 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(); +} + +/* */ + +BOOL SwHTMLParser::HasCurrentParaFlys( BOOL bNoSurroundOnly, + 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; + + SwFrmFmt* pFmt; + const SwFmtAnchor* pAnchor; + const SwPosition* pAPos; + const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts(); + + USHORT i; + BOOL bFound = FALSE; + for( i=0; i<rFrmFmtTbl.Count(); i++ ) + { + pFmt = rFrmFmtTbl[i]; + 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 + + if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) && + (FLY_AT_CNTNT == pAnchor->GetAnchorId() || + FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) && + pAPos->nNode == rNodeIdx ) + { + if( !(bNoSurroundOnly || bSurroundOnly) ) + { + bFound = TRUE; + break; + } + else + { + // fix #42282#: 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 = TRUE; + break; + } + } + if( bSurroundOnly ) + { + if( SURROUND_NONE==eSurround ) + { + bFound = FALSE; + break; + } + else if( SURROUND_THROUGHT!=eSurround ) + { + bFound = 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 + USHORT nTopColl = pContext ? pContext->GetTxtFmtColl() : 0; + const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr; + USHORT nDfltColl = RES_POOLCOLL_TEXT; + + BOOL bInPRE=FALSE; // etwas Kontext Info + + USHORT nLeftMargin = 0, nRightMargin = 0; // die Einzuege und + short nFirstLineIndent = 0; // Abstaende + + for( USHORT i=nContextStAttrMin; i<aContexts.Count(); i++ ) + { + const _HTMLAttrContext *pCntxt = aContexts[i]; + + USHORT 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 + BOOL bSetThis = TRUE; + switch( nColl ) + { + case USHORT(RES_POOLCOLL_HTML_PRE): + bInPRE = TRUE; + break; + case USHORT(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 USHORT(RES_POOLCOLL_HTML_HR): + // <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie + // nicht mehr exportieren + break; + default: + if( bInPRE ) + bSetThis = 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() ) + { + USHORT 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,TRUE, &pItem) ) + { + const SvxLRSpaceItem *pLRItem = + (const SvxLRSpaceItem *)pItem; + + USHORT nLeft = pLRItem->GetTxtLeft(); + USHORT 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 += nLeft; + nRightMargin += nRight; + + pContext->SetMargins( nLeftMargin, nRightMargin, + nFirstLineIndent ); + } + if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,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 = rLRItem.GetTxtLeft(); + if( !nRightMargin ) + nRightMargin = 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(); + BOOL bSetLRSpace; + +#ifndef NUM_RELSPACE + SwTxtNode* pTxtNode = pPam->GetNode()->GetTxtNode(); + ASSERT( pTxtNode, "TxtFmtColl an Nicht-Text-Node setzen???" ); + const SwNodeNum *pNodeNum = pTxtNode->GetNum(); + if( GetNumInfo().GetDepth() > 0 || pNodeNum ) + { + // Die Werte fuer den linken Rand und den Einzug koennte man auch + // aus der NumRule holen. Berechnen ist aber einfacher. + + ASSERT( (GetNumInfo().GetDepth() > 0) == + (GetNumInfo().GetNumRule() != 0), + "Keine NumRule in Aufzaehlung oder umgekehrt" ); + + ASSERT( pNodeNum, "Kein SwNodeNum am Absatz in Aufzaehlung" ); + + BOOL bNumbered = FALSE; + if( pNodeNum && !(NO_NUMLEVEL & pNodeNum->GetLevel()) ) + { + // der Erstzeilen-Einzug des List-Items muss noch zu dem + // sowieso schon bestehenden addiert werden, weil er im + // LI-Kontext nicht gesetzt wurde. Das ist leider nicht moeglich, + // weil auch nicht-numerierte Absaetze in diesem Kontext + // vorkommen koennen. + nFirstLineIndent += HTML_NUMBUL_INDENT; + bNumbered = TRUE; + } + + // In LI-Absaetzen ausserhalb von OL/UL ist nNumBulListDeep 0, aber + // es muss trotzdem um die Breite des Bullet-Zeichens eingerueckt + // werden. + USHORT nLeftMarginNumBul = (GetNumInfo().GetDepth() * HTML_NUMBUL_MARGINLEFT); + if( !nLeftMarginNumBul ) + nLeftMarginNumBul = (USHORT)(-HTML_NUMBUL_INDENT); + + bSetLRSpace = nLeftMargin != nLeftMarginNumBul || + (bNumbered && nFirstLineIndent != HTML_NUMBUL_INDENT) || + (!bNumbered && nFirstLineIndent) || + nRightMargin != rLRItem.GetRight(); + + pTxtNode->SetNumLSpace( !bSetLRSpace ); + } + else + { +#endif + bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() || + nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() || + nRightMargin != rLRItem.GetRight(); +#ifndef NUM_RELSPACE + } +#endif + + 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, FALSE ); + } + } + + // und nun noch die Attribute setzen + if( pItemSet ) + { + InsertParaAttrs( *pItemSet ); + delete pItemSet; + } +} + +/* */ + +void SwHTMLParser::NewCharFmt( int nToken ) +{ + String aId, aStyle, aClass; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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; + } + } + + // einen neuen Kontext anlegen + _HTMLAttrContext *pCntxt = new _HTMLAttrContext( nToken ); + + // die Vorlage setzen und im Kontext merken + SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( nToken, aClass ); + ASSERT( pCFmt, "keine Zeichenvorlage zu Token gefunden" ); + + + // Styles parsen (zu Class siehe auch NewPara) + if( HasStyleOptions( aStyle, aId, aEmptyStr ) ) + { + SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() ); + SvxCSS1PropertyInfo aPropInfo; + + if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo ) ) + { + ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ), + "Class wird nicht beruecksichtigt" ); + DoPositioning( aItemSet, aPropInfo, pCntxt ); + InsertAttrs( aItemSet, aPropInfo, pCntxt, 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; + SwVertOrient eVertOri = VERT_TOP; + SwHoriOrient eHoriOri = HORI_NONE; + Size aSize( 0, 0); + long nSize = 0; + BOOL bPrcWidth = FALSE; + BOOL bPrcHeight = FALSE; + USHORT nType = HTML_SPTYPE_HORI; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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 = + (SwVertOrient)pOption->GetEnum( aHTMLImgVAlignTable, + eVertOri ); + eHoriOri = + (SwHoriOrient)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; + aProtectItem.SetCntntProtect( 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() + (USHORT)nSize ); + pTxtNode->SwCntntNode::SetAttr( aULSpace ); + } + else + { + NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (USHORT)nSize ) ); + EndAttr( aAttrTab.pULSpace, 0, 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() ) + { + USHORT nLeft=0, nRight=0; + short nIndent = 0; + + GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent ); + nIndent += (short)nSize; + + SvxLRSpaceItem aLRItem; + aLRItem.SetTxtLeft( nLeft ); + aLRItem.SetRight( nRight ); + aLRItem.SetTxtFirstLineOfst( nIndent ); + + NewAttr( &aAttrTab.pLRSpace, aLRItem ); + EndAttr( aAttrTab.pLRSpace, 0, FALSE ); + } + else + { + NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize ) ); + String aTmp( ' ' ); + pDoc->Insert( *pPam, aTmp /*, CHARSET_ANSI*/ ); + EndAttr( aAttrTab.pKerning ); + } + } + } +} + +USHORT SwHTMLParser::ToTwips( USHORT nPixel ) const +{ + if( nPixel && Application::GetDefaultDevice() ) + { + long nTwips = Application::GetDefaultDevice()->PixelToLogic( + Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width(); + return nTwips <= USHRT_MAX ? (USHORT)nTwips : USHRT_MAX; + } + else + return nPixel; +} + +const SwTwips SwHTMLParser::GetCurrentBrowseWidth() +{ + 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 *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--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 + BOOL bClearLeft = FALSE, bClearRight = FALSE; + BOOL bCleared = FALSE; // wurde ein CLEAR ausgefuehrt? + + // dann holen wir mal die Optionen + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_CLEAR: + { + const String &aClear = pOption->GetString(); + if( aClear.EqualsIgnoreCaseAscii( sHTML_AL_all ) ) + { + bClearLeft = TRUE; + bClearRight = TRUE; + } + else if( aClear.EqualsIgnoreCaseAscii( sHTML_AL_left ) ) + bClearLeft = TRUE; + else if( aClear.EqualsIgnoreCaseAscii( sHTML_AL_right ) ) + bClearRight = 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 ) + { + SwFrmFmt* pFmt; + const SwFmtAnchor* pAnchor; + const SwPosition* pAPos; + const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts(); + + for( USHORT i=0; i<rFrmFmtTbl.Count(); i++ ) + { + pFmt = rFrmFmtTbl[i]; + pAnchor = &pFmt->GetAnchor(); + if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) && + (FLY_AT_CNTNT == pAnchor->GetAnchorId() || + FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) && + pAPos->nNode == rNodeIdx && + pFmt->GetSurround().GetSurround() != SURROUND_NONE ) + { + SwHoriOrient eHori = RES_DRAWFRMFMT == pFmt->Which() + ? HORI_LEFT + : pFmt->GetHoriOrient().GetHoriOrient(); + + SwSurround eSurround = SURROUND_PARALLEL; + if( pPam->GetPoint()->nContent.GetIndex() ) + { + if( bClearLeft && HORI_LEFT==eHori ) + eSurround = SURROUND_RIGHT; + else if( bClearRight && HORI_RIGHT==eHori ) + eSurround = SURROUND_LEFT; + } + else if( (bClearLeft && HORI_LEFT==eHori) || + (bClearRight && HORI_RIGHT==eHori) ) + { + eSurround = SURROUND_NONE; + } + + if( SURROUND_PARALLEL != eSurround ) + { + SwFmtSurround aSurround( eSurround ); + if( SURROUND_NONE != eSurround ) + aSurround.SetAnchorOnly( TRUE ); + pFmt->SetAttr( aSurround ); + bCleared = TRUE; + } + } // Anker ist nicht im Node + } // Schleife ueber Fly-Frames + } // kein Text-Node + } // kein CLEAR + + // Styles parsen + SvxFmtBreakItem aBreakItem; + BOOL bBreakItem = 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 = TRUE; + } + if( aPropInfo.aId.Len() ) + InsertBookmark( aPropInfo.aId ); + } + } + + if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() ) + { + NewAttr( &aAttrTab.pBreak, aBreakItem ); + EndAttr( aAttrTab.pBreak, 0, FALSE ); + } + + if( !bCleared && !bBreakItem ) + { + // wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird + // ein Zeilenumbruch eingefgt + String sTmp( (sal_Unicode)0x0a ); // make the Mac happy :-) + pDoc->Insert( *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, FALSE ); + } +} + +void SwHTMLParser::InsertHorzRule() +{ + USHORT nSize = 0; + USHORT nWidth = 0; + + SvxAdjust eAdjust = SVX_ADJUST_END; + + BOOL bPrcWidth = FALSE; + BOOL bNoShade = FALSE; + BOOL bColor = FALSE; + + Color aColor; + String aId; + + // dann holen wir mal die Optionen + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[--i]; + switch( pOption->GetToken() ) + { + case HTML_O_ID: + aId = pOption->GetString(); + break; + case HTML_O_SIZE: + nSize = (USHORT)pOption->GetNumber(); + break; + case HTML_O_WIDTH: + bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND); + nWidth = (USHORT)pOption->GetNumber(); + if( bPrcWidth && nWidth>=100 ) + { + // 100%-Linien sind der default-Fall (keine Attrs neotig) + nWidth = 0; + bPrcWidth = FALSE; + } + break; + case HTML_O_ALIGN: + eAdjust = + (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, eAdjust ); + break; + case HTML_O_NOSHADE: + bNoShade = TRUE; + break; + case HTML_O_COLOR: + pOption->GetColor( aColor ); + bColor = 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 ); + SvxCSS1Parser::SetBorderWidth( aBorderLine, (USHORT)nPHeight, + !bNoShade ); + } + else if( bNoShade ) + { + aBorderLine.SetOutWidth( DEF_LINE_WIDTH_2 ); + } + else + { + aBorderLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT ); + aBorderLine.SetInWidth( DEF_DOUBLE_LINE0_IN ); + aBorderLine.SetDistance( DEF_DOUBLE_LINE0_DIST ); + } + + SvxBoxItem aBoxItem; + 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. +#ifdef FIX41370 + const SwFmtColl *pColl = GetCurrFmtColl(); + SvxLRSpaceItem aLRItem( pColl->GetLRSpace() ); +#endif + if( !pTable ) + { + // Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken" + long nBrowseWidth = GetCurrentBrowseWidth(); + nWidth = bPrcWidth ? (USHORT)((nWidth*nBrowseWidth) / 100) + : ToTwips( (USHORT)nBrowseWidth ); + if( nWidth < MINLAY ) + nWidth = MINLAY; + + if( (long)nWidth < nBrowseWidth ) + { +#ifndef FIX41370 + const SwFmtColl *pColl = GetCurrFmtColl(); + SvxLRSpaceItem aLRItem( pColl->GetLRSpace() ); +#endif + long nDist = nBrowseWidth - nWidth; + + switch( eAdjust ) + { + case SVX_ADJUST_RIGHT: + aLRItem.SetTxtLeft( (USHORT)nDist ); + break; + case SVX_ADJUST_LEFT: + aLRItem.SetRight( (USHORT)nDist ); + break; + case SVX_ADJUST_CENTER: + default: + nDist /= 2; + aLRItem.SetTxtLeft( (USHORT)nDist ); + aLRItem.SetRight( (USHORT)nDist ); + break; + } + +#ifndef FIX41370 + _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem ); + aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() ); +#endif + } + } + +#ifdef FIX41370 + _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem ); + aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() ); +#endif + } + + // Bookmarks koennen nicht in Hyperlinks eingefueht werden + if( aId.Len() ) + InsertBookmark( aId ); + + // den aktuellen Kontext vom Stack holen + _HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE ); + ASSERT( 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; + BOOL bHTTPEquiv = FALSE, bChanged = FALSE; + + const HTMLOptions *pOptions = GetOptions(); + for( USHORT i = pOptions->Count(); i; ) + { + const HTMLOption *pOption = (*pOptions)[ --i ]; + switch( pOption->GetToken() ) + { + case HTML_O_NAME: + aName = pOption->GetString(); + bHTTPEquiv = FALSE; + break; + case HTML_O_HTTPEQUIV: + aName = pOption->GetString(); + bHTTPEquiv = 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( sHTML_META_generator ) || + aName.EqualsIgnoreCaseAscii( sHTML_META_refresh ) || + aName.EqualsIgnoreCaseAscii( sHTML_META_content_type ) || + aName.EqualsIgnoreCaseAscii( sHTML_META_content_script_type ) ) + return; + + aContent.EraseAllChars( _CR ); + aContent.EraseAllChars( _LF ); + + if( aName.EqualsIgnoreCaseAscii( sHTML_META_sdendnote ) ) + { + FillEndNoteInfo( aContent ); + return; + } + + if( aName.EqualsIgnoreCaseAscii( sHTML_META_sdfootnote ) ) + { + FillFootNoteInfo( aContent ); + return; + } + + String sText( + String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(sHTML_meta) ); + sText.Append( ' ' ); + if( bHTTPEquiv ) + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(sHTML_O_httpequiv) ); + else + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(sHTML_O_name) ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") ); + sText.Append( aName ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(sHTML_O_content) ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") ); + sText.Append( aContent ); + sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") ); + + SwPostItField aPostItFld( + (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ), + aEmptyStr, sText, Date() ); + SwFmtFld aFmtFld( aPostItFld ); + InsertAttr( aFmtFld ); +} + +/* */ + +#ifdef USED +void __EXPORT SwHTMLParser::SaveState( int nToken ) +{ + HTMLParser::SaveState( nToken ); +} + +void __EXPORT SwHTMLParser::RestoreState() +{ + HTMLParser::RestoreState(); +} +#endif + +/* */ + +_HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem, + _HTMLAttr **ppHd ) + : nSttPara( rPos.nNode ), nEndPara( rPos.nNode ), + nSttCntnt( rPos.nContent.GetIndex() ), + nEndCntnt(rPos.nContent.GetIndex() ), + nCount( 1 ), pNext( 0 ), pPrev( 0 ), ppHead( ppHd ), + bInsAtStart( TRUE ), bLikePara( FALSE ), bValid( TRUE ) +{ + pItem = rItem.Clone(); +} + +_HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara, + USHORT nEndCnt, _HTMLAttr **ppHd ) : + nSttPara( rAttr.nSttPara ), nEndPara( rEndPara ), + nSttCntnt( rAttr.nSttCntnt ), nEndCntnt( nEndCnt ), + nCount( rAttr.nCount ), pNext( 0 ), pPrev( 0 ), ppHead( ppHd ), + bInsAtStart( rAttr.bInsAtStart ), bLikePara( rAttr.bLikePara ), + bValid( rAttr.bValid ) +{ + pItem = rAttr.pItem->Clone(); +} + +_HTMLAttr::~_HTMLAttr() +{ + delete pItem; +} + +_HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, USHORT 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, USHORT 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 ) +{ + ASSERT( !pPrv->pNext || pPrv->pNext == this, + "_HTMLAttr::InsertPrev: pNext falsch" ); + pPrv->pNext = 0; + + ASSERT( 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; +} + +/************************************************************************* + + $Log: not supported by cvs2svn $ + Revision 1.494 2000/09/18 16:04:47 willem.vandorp + OpenOffice header added. + + Revision 1.493 2000/09/05 14:01:29 mib + #78294#: removed support for frameset documents + + Revision 1.492 2000/08/04 10:55:23 jp + Soft-/HardHyphens & HardBlanks changed from attribute to unicode character + + Revision 1.491 2000/06/26 09:52:42 jp + must change: GetAppWindow->GetDefaultDevice + + Revision 1.490 2000/06/13 09:37:51 os + using UCB + + Revision 1.489 2000/04/10 12:20:58 mib + unicode + + Revision 1.488 2000/03/17 15:19:53 mib + #74249#: Call EndAction before collaing DocumentDetected + + Revision 1.487 2000/03/13 15:07:03 jp + remove JavaScript + + Revision 1.486 2000/03/03 15:21:01 os + StarView remainders removed + + Revision 1.485 2000/03/03 12:44:32 mib + Removed JavaScript + + Revision 1.484 2000/02/11 15:41:10 hr + #70473# changes for unicode + + Revision 1.483 2000/01/20 11:48:38 jp + Bug #72119#: HTML-Template is moved into an other directory + + Revision 1.482 1999/10/21 17:50:12 jp + have to change - SearchFile with SfxIniManager, dont use SwFinder for this + + Revision 1.481 1999/09/21 09:50:36 mib + multiple text encodings + + Revision 1.480 1999/09/17 12:14:52 mib + support of multiple and non system text encodings + + Revision 1.479 1999/07/21 14:11:18 JP + Bug #67779#: set any MsgBoxType at the StringErrorInfo + + + Rev 1.478 21 Jul 1999 16:11:18 JP + Bug #67779#: set any MsgBoxType at the StringErrorInfo + + Rev 1.477 11 Jun 1999 10:27:36 MIB + #66744#: EnableModified flag + + Rev 1.476 10 Jun 1999 10:34:32 JP + have to change: no AppWin from SfxApp + + Rev 1.475 27 Apr 1999 16:42:26 JP + Bug #65314#: neu: IsJavaScriptEnabled + + Rev 1.474 15 Apr 1999 13:48:30 MIB + #41833#: Styles fuer A-Tag + + Rev 1.473 13 Apr 1999 10:58:56 MIB + #64638#: ASP-tags wie unbekannte Tags behandeln + + Rev 1.472 09 Apr 1999 17:52:00 MA + #64467# EndAction und VirDev + + Rev 1.471 08 Apr 1999 17:33:44 MIB + #64522#: Styles fuer TD/TH auswerten + + Rev 1.470 08 Apr 1999 12:45:54 MA + #64467# F?r die EndAction immer alles per VirDev painten + + Rev 1.469 07 Apr 1999 13:50:46 MIB + #64327#: GetBrowseWidth fuer Tabellen in Rahmen richtig + + Rev 1.468 29 Mar 1999 16:06:08 MIB + #64051#: Undo auch nach JavaScript anschalten + + Rev 1.467 17 Mar 1999 16:41:52 MIB + #63049#: Numerierungen mit relativen Abstaenden + + Rev 1.466 15 Mar 1999 13:14:30 JP + Bug #63339#: Einfuegen Doc - Absaetze richtig zusammenfassen + + Rev 1.465 11 Mar 1999 23:55:22 JP + Task #63171#: Optionen fuer Feld-/LinkUpdate Doc oder Modul lokal + + Rev 1.464 10 Mar 1999 15:43:22 MIB + #62682#: Beim Setzen der Control-Groesse wenn noetig auf die ViewShell warten + + Rev 1.463 25 Feb 1999 17:27:10 MIB + #61691#: falscher Assert + + Rev 1.462 25 Feb 1999 16:01:58 MIB + #61949#: globale Shell entsorgti, #62261#: <BR CLEAR> auch fuer Controls + + Rev 1.461 23 Feb 1999 08:56:34 MA + Syntaxfehler fuer Update + + Rev 1.460 22 Feb 1999 08:40:30 MA + 1949globale Shell entsorgt, Shells am RootFrm + + Rev 1.459 11 Jan 1999 10:45:30 MIB + #60137#: UCS2-/UTF8-Unterstuetzung jetzt auch fuer F-Sets richtig + + Rev 1.458 18 Dec 1998 09:23:34 MIB + #60137#: UTF-8-/UCS-2-Unterstuetzung fuer HTML + + Rev 1.457 04 Dec 1998 14:23:58 MIB + #54626#: <LH> ausserhalb von <OL>/<UL> verbessert, entspricht #55072# + + Rev 1.456 02 Dec 1998 10:55:12 MIB + #59886#: Kein Assert bei Attributen in Previous-Listen mehr + + Rev 1.455 23 Nov 1998 13:12:46 OM + #58216# Enum fuer Aktualisieren von Verknuepfungen + + Rev 1.454 20 Nov 1998 11:51:24 MIB + #59064#: Unbekannte Token/<NOSCRIPT> und <NOEMEBED> beibehalten + + Rev 1.453 18 Nov 1998 10:24:30 MIB + #59579#: Inhalt von <TITLE> und <NOSCRIPT> nicht zur Filter-Detection heranziehen + + Rev 1.452 13 Nov 1998 14:38:26 MIB + Nachtrag zu #58450#: Fuss-/Endnoten: Assert bei Verwendung der Vorlegen weg + + Rev 1.451 11 Nov 1998 17:42:02 MIB + #59059#: Beim Abbrechen Pendung-Stack noch aufraeumen + + Rev 1.450 02 Nov 1998 17:14:26 MIB + #58480#: Fuss-/Endnoten + + Rev 1.449 23 Oct 1998 09:47:16 MIB + #58172#: Nach JS-Aufruf falls vorhanden zuletzt aktive ViewShell wieder setzten + + Rev 1.448 13 Oct 1998 17:28:34 MIB + #57901#: Fixed-Font-Namen vom System holen, alten Namen entfernt + + Rev 1.447 07 Oct 1998 11:07:26 MIB + #57559#: Erstes Token immer im Continue behandeln, 55072 erstmal raus + + Rev 1.446 01 Sep 1998 12:06:50 MIB + #55072#: <LI> ohne <OL>/<UL> verbessert + + Rev 1.445 01 Sep 1998 09:52:02 MIB + #55248#: Header beenden, wenn Dokuemnttyp erkannt wurde + + Rev 1.444 31 Aug 1998 18:43:54 MIB + #55134#: DocumentDetected zum Anlegen der View aufrufen, bevor Controls eingef. werden + + Rev 1.443 26 Aug 1998 13:29:00 MIB + #54970#: bCallNextToken nicht setzen, wenn keine Listbox, Applet, etc. einefuegt wurde + + Rev 1.442 26 Aug 1998 09:30:42 MIB + #55144#: Umlauf bei Tabellen in Rahmen richtig setzen und beachten + + Rev 1.441 25 Aug 1998 11:09:42 MIB + #50455#: Applet erst beim </APPLET> anlegen, weil erst dann alle Parameter da sind + + Rev 1.440 28 Jul 1998 12:04:58 MIB + #54025#: Auf ObjectDying der ViewShell achten, #52559#: JavaScript-Zeilennummern + + Rev 1.439 23 Jul 1998 11:14:12 JP + Task #52654#: Einfuegen Doc nicht mit einer CrsrShell sondern mit einen PaM + + Rev 1.438 13 Jul 1998 09:20:28 MIB + #50966#: Fonts optional ignorieren + + Rev 1.437 08 Jul 1998 17:19:46 MIB + StarScript + + Rev 1.436 02 Jul 1998 15:50:10 JP + Modules Path ueber den PathFinder herausfinden + + Rev 1.435 26 Jun 1998 12:21:48 OM + #51184# SubType an ExpressionFields richtig setzen und abfragen + + Rev 1.434 15 Jun 1998 15:39:02 JP + Bug #51132#: _SetAttr - nicht pAttr sonder pAttr->pItem ist das Attribut + + Rev 1.433 15 Jun 1998 13:13:28 MIB + fix #51020#: Im AppendTxtNode Attrs die den ganzen Absatz sofort setzen + + Rev 1.432 08 Jun 1998 12:08:42 MIB + fix #50795#: <BODY>-Tag ist sicheres Indiz fuer Text-Dokument + + Rev 1.431 05 Jun 1998 14:04:32 JP + Bug #42487#: Sprung zum Mark schon waehrend des Ladens ausfuehren + + Rev 1.430 20 May 1998 10:41:04 MIB + fix #50341#: Script-Feld fuer nicht beendetes Script einfuegen + + Rev 1.429 15 May 1998 11:31:02 MIB + UNO-Controls statt VC-Controls (noch geht nicht viel) + + Rev 1.428 12 May 1998 15:50:44 JP + rund um Flys/DrawObjs im Doc/FESh umgestellt/optimiert + + Rev 1.427 29 Apr 1998 17:37:52 MIB + fix: HTML-Seitenvorlage in SW-Doks wieder setzen + + Rev 1.426 21 Apr 1998 13:47:26 MIB + fix: Keine Bookmark fuer abs-pos Objekte mit ID einfuegen + + Rev 1.425 16 Apr 1998 11:36:42 MIB + Keine HTML-Seiten-Vorlage mehr setzen, Warnings + + Rev 1.424 15 Apr 1998 14:54:36 MIB + Zwei-seitige Printing-Extensions + + Rev 1.423 03 Apr 1998 12:22:16 MIB + Export des Rahmen-Namens als ID + + Rev 1.422 02 Apr 1998 19:42:40 MIB + Positionierung von spaltigen Rahmen + + Rev 1.421 27 Mar 1998 17:28:54 MIB + direkte absolute Positionierung und Groessen-Export von Controls und Marquee + + Rev 1.420 27 Mar 1998 09:58:32 MIB + direkte Positionierung von Grafiken etc. + + Rev 1.419 25 Mar 1998 12:13:26 MIB + abs.-pos. Container angefangen, Statistik-Feld + + Rev 1.418 20 Mar 1998 10:46:12 MIB + Font-Listen in Font-Attributen + + Rev 1.417 13 Mar 1998 09:29:36 MIB + Rahmen-Anker-Verschiebung entfernt + + Rev 1.416 28 Feb 1998 07:28:58 MH + chg: [OW|MTF] -> UNX + + Rev 1.415 27 Feb 1998 16:22:42 JP + ObjectDying-MessageItem umbenannt + + Rev 1.414 27 Feb 1998 14:05:42 MIB + Auto-gebundene Rahmen + + Rev 1.413 24 Feb 1998 11:31:22 MIB + Jetzt auch HTML_LISTING und HTML_XMP vernichtet (wegen #42029#) + + Rev 1.412 20 Feb 1998 19:02:22 MA + header + + Rev 1.411 20 Feb 1998 13:27:14 MA + headerfiles gewandert + + Rev 1.410 17 Feb 1998 10:51:04 MIB + HTML-H6 -> HEADLINE6 + + Rev 1.409 16 Feb 1998 12:28:42 MIB + DokInfo-Feld jetzt auch fixed + + Rev 1.408 10 Feb 1998 09:51:20 MIB + fix: Fuer Absatz-Abstand am Start-/Ende von Listen auch OL/UL/DL beachten + + Rev 1.407 29 Jan 1998 21:34:22 JP + GetEndOfIcons ersetzt durch GetEndOfExtras, das auf GetEndOfRedlines mappt + + Rev 1.406 23 Jan 1998 16:10:04 MA + includes + + Rev 1.405 22 Jan 1998 19:58:26 JP + CTOR des SwPaM umgestellt + + Rev 1.404 19 Jan 1998 16:24:02 MIB + Numerierungs-Umbau + + Rev 1.403 17 Dec 1997 15:48:26 ER + cast fuer IRIX + + Rev 1.402 16 Dec 1997 18:09:04 JP + GetSearchDelim gegen SFX_SEARCH_DELIMITER ausgetauscht + + Rev 1.401 03 Dec 1997 12:42:50 JP + Extensions auf dem MAC zulassen + + Rev 1.400 26 Nov 1997 19:09:52 MA + includes + + Rev 1.399 25 Nov 1997 11:53:20 TJ + include svhtml.hxx + + Rev 1.398 17 Nov 1997 10:17:28 JP + Umstellung Numerierung + + Rev 1.397 30 Oct 1997 18:19:26 JP + DocumentVorlagen-Verwaltung in die Basisklasse verschoben + + Rev 1.396 20 Oct 1997 12:21:42 MIB + fix: Kleine CSS1-Attribute aus Class hart setzen, wenn Vorlage benutzt wird. + + Rev 1.395 20 Oct 1997 09:52:58 MIB + Nur fuer absolute positioning benoetigten Code groesstenteils auskommentiert + + Rev 1.394 17 Oct 1997 13:21:30 MIB + page-break-xxx auch uber STYLE/CLASS und ID-Optionen + + Rev 1.393 14 Oct 1997 14:36:42 JP + pNext vom Ring wurde privat; zugriff ueber GetNext() + + Rev 1.392 14 Oct 1997 14:30:20 MIB + fix #44228#: ViewShell-Zerstoerung/Rekonstruktion ueber Clients + + Rev 1.391 09 Oct 1997 14:40:46 JP + Umstellung NodeIndex/-Array/BigPtrArray + + Rev 1.390 06 Oct 1997 15:41:24 OM + Feldumstellung + + Rev 1.389 06 Oct 1997 15:27:24 MIB + Kein NewApplet aufrufen, wenn SOLAR_JAVA nicht gesetzt + + Rev 1.388 19 Sep 1997 12:20:24 MIB + fix: Seiten-Umbruch auch vor Tabellen temporaer setzen + + Rev 1.387 19 Sep 1997 11:27:38 MIB + fix #41370#: HRs in Tabellen-Zellen (nicht freigeschaltet) + + Rev 1.386 18 Sep 1997 16:38:12 JP + Continue: beim Einfuegen von nur einem Node nicht falsch zusammenfassen + + Rev 1.385 18 Sep 1997 09:18:34 JP + Teilfix fuer Bug 42487 + + Rev 1.384 16 Sep 1997 17:23:52 MIB + abs. Positioning fuer Absatz-Tags + + Rev 1.383 16 Sep 1997 14:55:36 MIB + ITEMID_BOXINFOITEM (voreubergendend) definieren + + Rev 1.382 16 Sep 1997 11:00:44 MIB + Kopf-/Fusszeilen ohne Moven von Nodes, autom. Beenden von Bereichen/Rahmen + + Rev 1.381 12 Sep 1997 11:51:20 MIB + fix #41136#: &(xxx);-Makros + + Rev 1.380 10 Sep 1997 11:00:24 MIB + HTMLReader::IsFormat() wieder raus + + Rev 1.379 09 Sep 1997 14:09:48 MIB + Ueberall Browse-View-Breite statt Seitenbreite verwenden + + Rev 1.378 08 Sep 1997 17:41:40 MIB + Verankerung von AUTO_CNTNT-Rahmen nicht mehr verschieben + + Rev 1.377 04 Sep 1997 12:36:54 JP + Umstellungen fuer FilterDetection im SwModule und SwDLL + + Rev 1.376 02 Sep 1997 20:45:32 OS + Header + + Rev 1.375 02 Sep 1997 11:12:08 MIB + fix #42192#: Attribute schnellstmoeglich setzen + + Rev 1.374 01 Sep 1997 11:54:46 MIB + fix #42679#: Im Titel nur auf </TITLE> achten, keine Schleife mehr. + + Rev 1.373 29 Aug 1997 16:50:20 OS + DLL-Umstellung + + Rev 1.372 15 Aug 1997 12:47:46 OS + charatr/frmatr/txtatr aufgeteilt + + Rev 1.371 14 Aug 1997 13:38:10 MA + #42534# Error in NextToken abfragen und State setzen + + Rev 1.370 12 Aug 1997 13:44:22 OS + Header-Umstellung + + Rev 1.369 11 Aug 1997 14:06:24 OM + Headerfile-Umstellung + + Rev 1.368 07 Aug 1997 13:15:18 MIB + fix #42192#: Zeichen-Attribute moeglicht frueh setzen. Noch nicht freigeschaltet + + Rev 1.367 04 Aug 1997 13:53:42 MIB + aboslute psoitioning (fuer fast alle Zeichen-Attribute/-Vorlagen) + + Rev 1.366 31 Jul 1997 10:44:44 MIB + DIV-Stack weg + + Rev 1.365 25 Jul 1997 13:00:38 MIB + fix #40408#: <NOEMBED>-Tag + + Rev 1.364 18 Jul 1997 10:54:32 MIB + fix #40951#: In Reschedule/DocDetected absichtlich geaenderte URLs beachten + + Rev 1.363 16 Jul 1997 18:38:40 MIB + non-pro: Asserts zur Call-Stack-Kontrolle, kein Assert f. frueher gesetze Attrs + + Rev 1.362 10 Jul 1997 16:44:46 MIB + fix #41379#: Keine Absatz-Attribute fuer leere Absaetze (auch hinter Tabellen) + + Rev 1.361 10 Jul 1997 12:02:50 MIB + fix #41547#: Keine Tabellen in Tabellen einfuegen + +*************************************************************************/ + |