blob: 15d0605e7784c5346501a2e3ee55ffb4f1e08cae [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_editeng.hxx"
#include <vcl/wrkwin.hxx>
#include <vcl/dialog.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>
#include <eehtml.hxx>
#include <impedit.hxx>
#include <editeng/adjitem.hxx>
#include <editeng/flditem.hxx>
#include <tools/urlobj.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/wghtitem.hxx>
#include <svtools/htmltokn.h>
#include <svtools/htmlkywd.hxx>
#include <tools/tenccvt.hxx>
#define ACTION_INSERTTEXT 1
#define ACTION_INSERTPARABRK 2
#define STYLE_PRE 101
EditHTMLParser::EditHTMLParser( SvStream& rIn, const String& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs )
: HTMLParser( rIn, true )
, aBaseURL( rBaseURL )
{
pImpEditEngine = 0;
pCurAnchor = 0;
bInPara = sal_False;
bWasInPara = sal_False;
nInTable = 0;
nInCell = 0;
bInTitle = sal_False;
nDefListLevel = 0;
nBulletLevel = 0;
nNumberingLevel = 0;
bFieldsInserted = sal_False;
DBG_ASSERT( RTL_TEXTENCODING_DONTKNOW == GetSrcEncoding( ), "EditHTMLParser::EditHTMLParser: Where does the encoding come from?" );
DBG_ASSERT( !IsSwitchToUCS2(), "EditHTMLParser::::EditHTMLParser: Switch to UCS2?" );
// Altough the real default encoding is ISO8859-1, we use MS-1252
// als default encoding.
SetSrcEncoding( GetExtendedCompatibilityTextEncoding( RTL_TEXTENCODING_ISO_8859_1 ) );
// If the file starts with a BOM, switch to UCS2.
SetSwitchToUCS2( sal_True );
if ( pHTTPHeaderAttrs )
SetEncodingByHTTPHeader( pHTTPHeaderAttrs );
}
EditHTMLParser::~EditHTMLParser()
{
delete pCurAnchor;
}
SvParserState EditHTMLParser::CallParser( ImpEditEngine* pImpEE, const EditPaM& rPaM )
{
DBG_ASSERT( pImpEE, "CallParser: ImpEditEngine ?!" );
pImpEditEngine = pImpEE;
SvParserState _eState = SVPAR_NOTSTARTED;
if ( pImpEditEngine )
{
// Umbrechmimik vom RTF-Import einbauen?
aCurSel = EditSelection( rPaM, rPaM );
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_START, this, pImpEditEngine->CreateESel( aCurSel ) );
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
ImpSetStyleSheet( 0 );
_eState = HTMLParser::CallParser();
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_END, this, pImpEditEngine->CreateESel( aCurSel ) );
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
if ( bFieldsInserted )
pImpEditEngine->UpdateFields();
}
return _eState;
}
void EditHTMLParser::NextToken( int nToken )
{
#ifdef DBG_UTIL
HTML_TOKEN_IDS xID = (HTML_TOKEN_IDS)nToken;
(void)xID;
#endif
switch( nToken )
{
case HTML_META:
{
const HTMLOptions *_pOptions = GetOptions();
sal_uInt16 nArrLen = _pOptions->Count();
sal_Bool bEquiv = sal_False;
for ( sal_uInt16 i = 0; i < nArrLen; i++ )
{
const HTMLOption *pOption = (*_pOptions)[i];
switch( pOption->GetToken() )
{
case HTML_O_HTTPEQUIV:
{
bEquiv = sal_True;
}
break;
case HTML_O_CONTENT:
{
if ( bEquiv )
{
rtl_TextEncoding eEnc = GetEncodingByMIME( pOption->GetString() );
if ( eEnc != RTL_TEXTENCODING_DONTKNOW )
SetSrcEncoding( eEnc );
}
}
break;
}
}
}
break;
case HTML_PLAINTEXT_ON:
case HTML_PLAINTEXT2_ON:
bInPara = sal_True;
break;
case HTML_PLAINTEXT_OFF:
case HTML_PLAINTEXT2_OFF:
bInPara = sal_False;
break;
case HTML_LINEBREAK:
case HTML_NEWPARA:
{
if ( ( bInPara || nInTable ) &&
( ( nToken == HTML_LINEBREAK ) || HasTextInCurrentPara() ) )
{
ImpInsertParaBreak();
}
}
break;
case HTML_HORZRULE:
{
if ( HasTextInCurrentPara() )
ImpInsertParaBreak();
ImpInsertParaBreak();
}
case HTML_NONBREAKSPACE:
{
if ( bInPara )
{
ImpInsertText( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
}
}
break;
case HTML_TEXTTOKEN:
{
// #i110937# for <title> content, call aImportHdl (no SkipGroup), but don't insert the text into the EditEngine
if (!bInTitle)
{
if ( !bInPara )
StartPara( sal_False );
// if ( bInPara || pCurAnchor )
String aText = aToken;
if ( aText.Len() && ( aText.GetChar( 0 ) == ' ' )
&& ThrowAwayBlank() && !IsReadPRE() )
aText.Erase( 0, 1 );
if ( pCurAnchor )
{
pCurAnchor->aText += aText;
}
else
{
// Nur bis HTML mit 319 geschrieben ?!
if ( IsReadPRE() )
{
sal_uInt16 nTabPos = aText.Search( '\t', 0 );
while ( nTabPos != STRING_NOTFOUND )
{
aText.Erase( nTabPos, 1 );
aText.Insert( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ), nTabPos );
nTabPos = aText.Search( '\t', nTabPos+8 );
}
}
ImpInsertText( aText );
}
}
}
break;
case HTML_CENTER_ON:
case HTML_CENTER_OFF: // if ( bInPara )
{
sal_uInt16 nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
aItems.ClearItem( EE_PARA_JUST );
if ( nToken == HTML_CENTER_ON )
aItems.Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
pImpEditEngine->SetParaAttribs( nNode, aItems );
}
break;
case HTML_ANCHOR_ON: AnchorStart();
break;
case HTML_ANCHOR_OFF: AnchorEnd();
break;
case HTML_PARABREAK_ON:
if( bInPara && HasTextInCurrentPara() )
EndPara( sal_True );
StartPara( sal_True );
break;
case HTML_PARABREAK_OFF:
if( bInPara )
EndPara( sal_True );
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:
{
HeadingStart( 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:
{
HeadingEnd( nToken );
}
break;
case HTML_PREFORMTXT_ON:
case HTML_XMP_ON:
case HTML_LISTING_ON:
{
StartPara( sal_True );
ImpSetStyleSheet( STYLE_PRE );
}
break;
case HTML_DEFLIST_ON:
{
nDefListLevel++;
}
break;
case HTML_DEFLIST_OFF:
{
if( nDefListLevel )
nDefListLevel--;
}
break;
case HTML_TABLE_ON: nInTable++;
break;
case HTML_TABLE_OFF: DBG_ASSERT( nInTable, "Nicht in Table, aber TABLE_OFF?" );
nInTable--;
break;
case HTML_TABLEHEADER_ON:
case HTML_TABLEDATA_ON:
nInCell++;
// fallthru
case HTML_BLOCKQUOTE_ON:
case HTML_BLOCKQUOTE_OFF:
case HTML_BLOCKQUOTE30_ON:
case HTML_BLOCKQUOTE30_OFF:
case HTML_LISTHEADER_ON:
case HTML_LI_ON:
case HTML_DD_ON:
case HTML_DT_ON:
case HTML_ORDERLIST_ON:
case HTML_UNORDERLIST_ON:
{
sal_Bool bHasText = HasTextInCurrentPara();
if ( bHasText )
ImpInsertParaBreak();
StartPara( sal_False );
}
break;
case HTML_TABLEHEADER_OFF:
case HTML_TABLEDATA_OFF:
{
if ( nInCell )
nInCell--;
}
// fallthru
case HTML_LISTHEADER_OFF:
case HTML_LI_OFF:
case HTML_DD_OFF:
case HTML_DT_OFF:
case HTML_ORDERLIST_OFF:
case HTML_UNORDERLIST_OFF: EndPara( sal_False );
break;
case HTML_TABLEROW_ON:
case HTML_TABLEROW_OFF: // Nur nach einem CELL ein RETURN, fuer Calc
case HTML_COL_ON:
case HTML_COLGROUP_ON:
case HTML_COLGROUP_OFF: break;
case HTML_FONT_ON: // ...
break;
case HTML_FONT_OFF: // ...
break;
// #58335# kein SkipGroup on/off auf inline markup etc.
case HTML_TITLE_ON:
bInTitle = sal_True;
break;
case HTML_TITLE_OFF:
bInTitle = sal_False;
break;
// globals
case HTML_HTML_ON:
case HTML_HTML_OFF:
case HTML_BODY_ON:
case HTML_BODY_OFF:
case HTML_HEAD_ON:
case HTML_HEAD_OFF:
case HTML_FORM_ON:
case HTML_FORM_OFF:
case HTML_THEAD_ON:
case HTML_THEAD_OFF:
case HTML_TBODY_ON:
case HTML_TBODY_OFF:
// inline elements, structural markup
// HTML 3.0
case HTML_BANNER_ON:
case HTML_BANNER_OFF:
case HTML_DIVISION_ON:
case HTML_DIVISION_OFF:
// case HTML_LISTHEADER_ON: //! special handling
// case HTML_LISTHEADER_OFF:
case HTML_NOTE_ON:
case HTML_NOTE_OFF:
// inline elements, logical markup
// HTML 2.0
case HTML_ADDRESS_ON:
case HTML_ADDRESS_OFF:
// case HTML_BLOCKQUOTE_ON: //! extra Behandlung
// case HTML_BLOCKQUOTE_OFF:
case HTML_CITIATION_ON:
case HTML_CITIATION_OFF:
case HTML_CODE_ON:
case HTML_CODE_OFF:
case HTML_DEFINSTANCE_ON:
case HTML_DEFINSTANCE_OFF:
case HTML_EMPHASIS_ON:
case HTML_EMPHASIS_OFF:
case HTML_KEYBOARD_ON:
case HTML_KEYBOARD_OFF:
case HTML_SAMPLE_ON:
case HTML_SAMPLE_OFF:
case HTML_STRIKE_ON:
case HTML_STRIKE_OFF:
case HTML_STRONG_ON:
case HTML_STRONG_OFF:
case HTML_VARIABLE_ON:
case HTML_VARIABLE_OFF:
// HTML 3.0
case HTML_ABBREVIATION_ON:
case HTML_ABBREVIATION_OFF:
case HTML_ACRONYM_ON:
case HTML_ACRONYM_OFF:
case HTML_AUTHOR_ON:
case HTML_AUTHOR_OFF:
// case HTML_BLOCKQUOTE30_ON: //! extra Behandlung
// case HTML_BLOCKQUOTE30_OFF:
case HTML_DELETEDTEXT_ON:
case HTML_DELETEDTEXT_OFF:
case HTML_INSERTEDTEXT_ON:
case HTML_INSERTEDTEXT_OFF:
case HTML_LANGUAGE_ON:
case HTML_LANGUAGE_OFF:
case HTML_PERSON_ON:
case HTML_PERSON_OFF:
case HTML_SHORTQUOTE_ON:
case HTML_SHORTQUOTE_OFF:
case HTML_SUBSCRIPT_ON:
case HTML_SUBSCRIPT_OFF:
case HTML_SUPERSCRIPT_ON:
case HTML_SUPERSCRIPT_OFF:
// inline elements, visual markup
// HTML 2.0
case HTML_BOLD_ON:
case HTML_BOLD_OFF:
case HTML_ITALIC_ON:
case HTML_ITALIC_OFF:
case HTML_TELETYPE_ON:
case HTML_TELETYPE_OFF:
case HTML_UNDERLINE_ON:
case HTML_UNDERLINE_OFF:
// HTML 3.0
case HTML_BIGPRINT_ON:
case HTML_BIGPRINT_OFF:
case HTML_STRIKETHROUGH_ON:
case HTML_STRIKETHROUGH_OFF:
case HTML_SMALLPRINT_ON:
case HTML_SMALLPRINT_OFF:
// figures
case HTML_FIGURE_ON:
case HTML_FIGURE_OFF:
case HTML_CAPTION_ON:
case HTML_CAPTION_OFF:
case HTML_CREDIT_ON:
case HTML_CREDIT_OFF:
// misc
case HTML_DIRLIST_ON:
case HTML_DIRLIST_OFF:
case HTML_FOOTNOTE_ON: //! landen so im Text
case HTML_FOOTNOTE_OFF:
case HTML_MENULIST_ON:
case HTML_MENULIST_OFF:
// case HTML_PLAINTEXT_ON: //! extra Behandlung
// case HTML_PLAINTEXT_OFF:
// case HTML_PREFORMTXT_ON: //! extra Behandlung
// case HTML_PREFORMTXT_OFF:
case HTML_SPAN_ON:
case HTML_SPAN_OFF:
// obsolete
// case HTML_XMP_ON: //! extra Behandlung
// case HTML_XMP_OFF:
// case HTML_LISTING_ON: //! extra Behandlung
// case HTML_LISTING_OFF:
// Netscape
case HTML_BLINK_ON:
case HTML_BLINK_OFF:
case HTML_NOBR_ON:
case HTML_NOBR_OFF:
case HTML_NOEMBED_ON:
case HTML_NOEMBED_OFF:
case HTML_NOFRAMES_ON:
case HTML_NOFRAMES_OFF:
// Internet Explorer
case HTML_MARQUEE_ON:
case HTML_MARQUEE_OFF:
// case HTML_PLAINTEXT2_ON: //! extra Behandlung
// case HTML_PLAINTEXT2_OFF:
break;
default:
{
if ( nToken & HTML_TOKEN_ONOFF )
{
if ( ( nToken == HTML_UNKNOWNCONTROL_ON ) || ( nToken == HTML_UNKNOWNCONTROL_OFF ) )
{
;
}
else if ( !(nToken & 1) )
{
DBG_ASSERT( !( nToken & 1 ), "Kein Start-Token ?!" );
SkipGroup( nToken + 1 );
}
}
}
} // SWITCH
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_NEXTTOKEN, this, pImpEditEngine->CreateESel( aCurSel ) );
aImportInfo.nToken = nToken;
aImportInfo.nTokenValue = (short)nTokenValue;
if ( nToken == HTML_TEXTTOKEN )
aImportInfo.aText = aToken;
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
}
void EditHTMLParser::ImpInsertParaBreak()
{
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_INSERTPARA, this, pImpEditEngine->CreateESel( aCurSel ) );
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
nLastAction = ACTION_INSERTPARABRK;
}
void EditHTMLParser::ImpSetAttribs( const SfxItemSet& rItems, EditSelection* pSel )
{
// pSel, wenn Zeichenattribute, sonst Absatzattribute fuer den
// aktuellen Absatz.
DBG_ASSERT( pSel || ( aCurSel.Min().GetNode() == aCurSel.Max().GetNode() ), "ImpInsertAttribs: Selektion?" );
EditPaM aStartPaM( pSel ? pSel->Min() : aCurSel.Min() );
EditPaM aEndPaM( pSel ? pSel->Max() : aCurSel.Max() );
if ( !pSel )
{
aStartPaM.SetIndex( 0 );
aEndPaM.SetIndex( aEndPaM.GetNode()->Len() );
}
if ( pImpEditEngine->aImportHdl.IsSet() )
{
EditSelection aSel( aStartPaM, aEndPaM );
ImportInfo aImportInfo( HTMLIMP_SETATTR, this, pImpEditEngine->CreateESel( aSel ) );
aImportInfo.pAttrs = (void*)&rItems;
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
ContentNode* pSN = aStartPaM.GetNode();
sal_uInt16 nStartNode = pImpEditEngine->GetEditDoc().GetPos( pSN );
// Wenn ein Attribut von 0 bis aktuelle Absatzlaenge geht,
// soll es ein Absatz-Attribut sein!
// Achtung: Selektion kann ueber mehrere Absaetze gehen.
// Alle vollstaendigen Absaetze sind Absatzattribute...
// HTML eigentlich nicht:
#ifdef DBG_UTIL
ContentNode* pEN = aEndPaM.GetNode();
sal_uInt16 nEndNode = pImpEditEngine->GetEditDoc().GetPos( pEN );
DBG_ASSERT( nStartNode == nEndNode, "ImpSetAttribs: Mehrere Absaetze?" );
#endif
/*
for ( sal_uInt16 z = nStartNode+1; z < nEndNode; z++ )
{
DBG_ASSERT( pImpEditEngine->GetEditDoc().SaveGetObject( z ), "Node existiert noch nicht(RTF)" );
pImpEditEngine->SetParaAttribs( z, rSet.GetAttrSet() );
}
if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
{
// Den Rest des StartNodes...
if ( aStartPaM.GetIndex() == 0 )
pImpEditEngine->SetParaAttribs( nStartNode, rSet.GetAttrSet() );
else
pImpEditEngine->SetAttribs( EditSelection( aStartPaM, EditPaM( aStartPaM.GetNode(), aStartPaM.GetNode()->Len() ) ), rSet.GetAttrSet() );
// Den Anfang des EndNodes....
if ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() )
pImpEditEngine->SetParaAttribs( nEndNode, rSet.GetAttrSet() );
else
pImpEditEngine->SetAttribs( EditSelection( EditPaM( aEndPaM.GetNode(), 0 ), aEndPaM ), rSet.GetAttrSet() );
}
else
*/
{
if ( ( aStartPaM.GetIndex() == 0 ) && ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() ) )
{
// Muesse gemergt werden:
SfxItemSet aItems( pImpEditEngine->GetParaAttribs( nStartNode ) );
aItems.Put( rItems );
pImpEditEngine->SetParaAttribs( nStartNode, aItems );
}
else
pImpEditEngine->SetAttribs( EditSelection( aStartPaM, aEndPaM ), rItems );
}
}
void EditHTMLParser::ImpSetStyleSheet( sal_uInt16 nHLevel )
{
/*
nHLevel: 0: Ausschalten
1-6: Heading
STYLE_PRE: Preformatted
*/
// if ( pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
// {
// SvxRTFStyleType* pS = GetStyleTbl().Get( rSet.StyleNo() );
// DBG_ASSERT( pS, "Vorlage in RTF nicht definiert!" );
// if ( pS )
// pImpEditEngine->SetStyleSheet( EditSelection( aStartPaM, aEndPaM ), pS->sName, SFX_STYLE_FAMILY_ALL );
// }
// else
{
// Harte Attribute erzeugen...
// Reicht fuer Calc, bei StyleSheets muesste noch geklaert werden,
// dass diese auch in der App liegen sollten, damit sie beim
// fuettern in eine andere Engine auch noch da sind...
sal_uInt16 nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
// SfxItemSet aItems( pImpEditEngine->GetEmptyItemSet() );
SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
aItems.ClearItem( EE_PARA_ULSPACE );
aItems.ClearItem( EE_CHAR_FONTHEIGHT );
aItems.ClearItem( EE_CHAR_FONTINFO );
aItems.ClearItem( EE_CHAR_WEIGHT );
// Fett in den ersten 3 Headings
if ( ( nHLevel >= 1 ) && ( nHLevel <= 3 ) )
{
SvxWeightItem aWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT );
aItems.Put( aWeightItem );
}
// Fonthoehe und Abstaende, wenn LogicToLogic moeglich:
MapUnit eUnit = pImpEditEngine->GetRefMapMode().GetMapUnit();
if ( ( eUnit != MAP_PIXEL ) && ( eUnit != MAP_SYSFONT ) &&
( eUnit != MAP_APPFONT ) && ( eUnit != MAP_RELATIVE ) )
{
long nPoints = 10;
if ( nHLevel == 1 )
nPoints = 22;
else if ( nHLevel == 2 )
nPoints = 16;
else if ( nHLevel == 3 )
nPoints = 12;
else if ( nHLevel == 4 )
nPoints = 11;
nPoints = OutputDevice::LogicToLogic( nPoints, MAP_POINT, eUnit );
SvxFontHeightItem aHeightItem( nPoints, 100, EE_CHAR_FONTHEIGHT );
aItems.Put( aHeightItem );
// Absatzabstaende, wenn Heading:
if ( !nHLevel || ((nHLevel >= 1) && (nHLevel <= 6)) )
{
SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
aULSpaceItem.SetUpper( (sal_uInt16)OutputDevice::LogicToLogic( 42, MAP_10TH_MM, eUnit ) );
aULSpaceItem.SetLower( (sal_uInt16)OutputDevice::LogicToLogic( 35, MAP_10TH_MM, eUnit ) );
aItems.Put( aULSpaceItem );
}
}
// Bei Pre einen proportionalen Font waehlen
if ( nHLevel == STYLE_PRE )
{
Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_SYSTEM, 0 );
SvxFontItem aFontItem( aFont.GetFamily(), aFont.GetName(), XubString(), aFont.GetPitch(), aFont.GetCharSet(), EE_CHAR_FONTINFO );
aItems.Put( aFontItem );
}
pImpEditEngine->SetParaAttribs( nNode, aItems );
}
}
void EditHTMLParser::ImpInsertText( const String& rText )
{
String aText( rText );
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_INSERTTEXT, this, pImpEditEngine->CreateESel( aCurSel ) );
aImportInfo.aText = aText;
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
aCurSel = pImpEditEngine->ImpInsertText( aCurSel, aText );
nLastAction = ACTION_INSERTTEXT;
}
void EditHTMLParser::SkipGroup( int nEndToken )
{
// #69109# groups in cells are closed upon leaving the cell, because those
// ******* web authors don't know their job
// for example: <td><form></td> lacks a closing </form>
sal_uInt8 nCellLevel = nInCell;
int nToken;
while( nCellLevel <= nInCell && ( (nToken = GetNextToken() ) != nEndToken ) && nToken )
{
switch ( nToken )
{
case HTML_TABLEHEADER_ON:
case HTML_TABLEDATA_ON:
nInCell++;
break;
case HTML_TABLEHEADER_OFF:
case HTML_TABLEDATA_OFF:
if ( nInCell )
nInCell--;
break;
}
}
}
void EditHTMLParser::StartPara( sal_Bool bReal )
{
if ( bReal )
{
const HTMLOptions *_pOptions = GetOptions();
sal_uInt16 nArrLen = _pOptions->Count();
SvxAdjust eAdjust = SVX_ADJUST_LEFT;
for ( sal_uInt16 i = 0; i < nArrLen; i++ )
{
const HTMLOption *pOption = (*_pOptions)[i];
switch( pOption->GetToken() )
{
case HTML_O_ALIGN:
{
if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) == COMPARE_EQUAL )
eAdjust = SVX_ADJUST_RIGHT;
else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_middle ) == COMPARE_EQUAL )
eAdjust = SVX_ADJUST_CENTER;
else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) == COMPARE_EQUAL )
eAdjust = SVX_ADJUST_CENTER;
else
eAdjust = SVX_ADJUST_LEFT;
}
break;
}
}
SfxItemSet aItemSet( pImpEditEngine->GetEmptyItemSet() );
aItemSet.Put( SvxAdjustItem( eAdjust, EE_PARA_JUST ) );
ImpSetAttribs( aItemSet );
}
bInPara = sal_True;
}
void EditHTMLParser::EndPara( sal_Bool )
{
if ( bInPara )
{
sal_Bool bHasText = HasTextInCurrentPara();
if ( bHasText )
ImpInsertParaBreak();
// Nur, wenn ohne Absatzabstaende gearbeitet wird...
// if ( !nInTable && bReal && (nNumberingLevel<=1) && (nBulletLevel<=1) )
// ImpInsertParaBreak();
}
bInPara = sal_False;
}
sal_Bool EditHTMLParser::ThrowAwayBlank()
{
// Ein Blank muss weggeschmissen werden, wenn der neue Text mit einem
// Blank beginnt und der aktuelle Absatz leer ist oder mit einem
// Blank endet...
ContentNode* pNode = aCurSel.Max().GetNode();
if ( pNode->Len() && ( pNode->GetChar( pNode->Len()-1 ) != ' ' ) )
return sal_False;
return sal_True;
}
sal_Bool EditHTMLParser::HasTextInCurrentPara()
{
return aCurSel.Max().GetNode()->Len() ? sal_True : sal_False;
}
void EditHTMLParser::AnchorStart()
{
// Anker im Anker ignoriern
if ( !pCurAnchor )
{
const HTMLOptions* _pOptions = GetOptions();
sal_uInt16 nArrLen = _pOptions->Count();
String aRef;
for ( sal_uInt16 i = 0; i < nArrLen; i++ )
{
const HTMLOption* pOption = (*_pOptions)[i];
switch( pOption->GetToken() )
{
case HTML_O_HREF:
aRef = pOption->GetString();
break;
}
}
if ( aRef.Len() )
{
String aURL = aRef;
if ( aURL.Len() && ( aURL.GetChar( 0 ) != '#' ) )
{
INetURLObject aTargetURL;
INetURLObject aRootURL( aBaseURL );
aRootURL.GetNewAbsURL( aRef, &aTargetURL );
aURL = aTargetURL.GetMainURL( INetURLObject::DECODE_TO_IURI );
}
pCurAnchor = new AnchorInfo;
pCurAnchor->aHRef = aURL;
}
}
}
void EditHTMLParser::AnchorEnd()
{
if ( pCurAnchor )
{
// Als URL-Feld einfuegen...
SvxFieldItem aFld( SvxURLField( pCurAnchor->aHRef, pCurAnchor->aText, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD );
aCurSel = pImpEditEngine->InsertField( aCurSel, aFld );
bFieldsInserted = sal_True;
delete pCurAnchor;
pCurAnchor = 0;
if ( pImpEditEngine->aImportHdl.IsSet() )
{
ImportInfo aImportInfo( HTMLIMP_INSERTFIELD, this, pImpEditEngine->CreateESel( aCurSel ) );
pImpEditEngine->aImportHdl.Call( &aImportInfo );
}
}
}
void EditHTMLParser::HeadingStart( int nToken )
{
bWasInPara = bInPara;
StartPara( sal_False );
if ( bWasInPara && HasTextInCurrentPara() )
ImpInsertParaBreak();
sal_uInt16 nId = sal::static_int_cast< sal_uInt16 >(
1 + ( ( nToken - HTML_HEAD1_ON ) / 2 ) );
DBG_ASSERT( (nId >= 1) && (nId <= 9), "HeadingStart: ID kann nicht stimmen!" );
ImpSetStyleSheet( nId );
}
void EditHTMLParser::HeadingEnd( int )
{
EndPara( sal_False );
ImpSetStyleSheet( 0 );
if ( bWasInPara )
{
bInPara = sal_True;
bWasInPara = sal_False;
}
}