summaryrefslogtreecommitdiff
path: root/sw/source/filter/html/htmlnum.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/html/htmlnum.cxx')
-rw-r--r--sw/source/filter/html/htmlnum.cxx990
1 files changed, 990 insertions, 0 deletions
diff --git a/sw/source/filter/html/htmlnum.cxx b/sw/source/filter/html/htmlnum.cxx
new file mode 100644
index 000000000000..4a438fd43bb6
--- /dev/null
+++ b/sw/source/filter/html/htmlnum.cxx
@@ -0,0 +1,990 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: htmlnum.cxx,v $
+ * $Revision: 1.29 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <com/sun/star/style/NumberingType.hpp>
+#include <hintids.hxx>
+#include <svtools/htmltokn.h>
+#include <svtools/htmlkywd.hxx>
+#include <svtools/htmlout.hxx>
+#include <svl/urihelper.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <numrule.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <poolfmt.hxx>
+#include <ndtxt.hxx>
+#include <paratr.hxx>
+
+#include "htmlnum.hxx"
+#include "swcss1.hxx"
+#include "swhtml.hxx"
+#include "wrthtml.hxx"
+
+#include <SwNodeNum.hxx>
+
+using namespace ::com::sun::star;
+
+// TODO: Unicode: Are these characters the correct ones?
+#define HTML_BULLETCHAR_DISC (0xe008)
+#define HTML_BULLETCHAR_CIRCLE (0xe009)
+#define HTML_BULLETCHAR_SQUARE (0xe00b)
+
+
+// <UL TYPE=...>
+static HTMLOptionEnum __FAR_DATA aHTMLULTypeTable[] =
+{
+ { OOO_STRING_SVTOOLS_HTML_ULTYPE_disc, HTML_BULLETCHAR_DISC },
+ { OOO_STRING_SVTOOLS_HTML_ULTYPE_circle, HTML_BULLETCHAR_CIRCLE },
+ { OOO_STRING_SVTOOLS_HTML_ULTYPE_square, HTML_BULLETCHAR_SQUARE },
+ { 0, 0 }
+};
+
+/* */
+
+void SwHTMLNumRuleInfo::Set( const SwTxtNode& rTxtNd )
+{
+ // --> OD 2006-06-12 #b6435904#
+ // export all numberings, except the outline numbering.
+// if( rTxtNd.GetNumRule() && ! rTxtNd.IsOutline())
+ const SwNumRule* pTxtNdNumRule( rTxtNd.GetNumRule() );
+ if ( pTxtNdNumRule &&
+ pTxtNdNumRule != rTxtNd.GetDoc()->GetOutlineNumRule() )
+ {
+ pNumRule = const_cast<SwNumRule*>(pTxtNdNumRule);
+ nDeep = static_cast< sal_uInt16 >(pNumRule ? rTxtNd.GetActualListLevel() + 1 : 0);
+ bNumbered = rTxtNd.IsCountedInList();
+ // --> OD 2008-02-27 #refactorlists#
+ // --> OD 2005-11-16 #i57919#
+ // correction of refactoring done by cws swnumtree:
+ // <bRestart> has to be set to <true>, if numbering is restarted at this
+ // text node and the start value equals <USHRT_MAX>.
+ // Start value <USHRT_MAX> indicates, that at this text node the numbering
+ // is restarted with the value given at the corresponding level.
+// bRestart = rTxtNd.IsListRestart() &&
+// GetNum() && rTxtNd.GetNum()->GetStartValue() == USHRT_MAX;
+ bRestart = rTxtNd.IsListRestart() && !rTxtNd.HasAttrListRestartValue();
+ // <--
+ }
+ // <--
+ else
+ {
+ pNumRule = 0;
+ nDeep = 0;
+ bNumbered = bRestart = sal_False;
+ }
+}
+
+/* */
+
+void SwHTMLParser::NewNumBulList( int nToken )
+{
+ SwHTMLNumRuleInfo& rInfo = GetNumInfo();
+
+ // Erstmal einen neuen Absatz aufmachen
+ sal_Bool bSpace = (rInfo.GetDepth() + nDefListDeep) == 0;
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( bSpace ? AM_SPACE : AM_NOSPACE, sal_False );
+ else if( bSpace )
+ AddParSpace();
+
+ // Die Numerierung-Ebene erhoehen
+ rInfo.IncDepth();
+ sal_uInt8 nLevel = (sal_uInt8)( (rInfo.GetDepth() <= MAXLEVEL ? rInfo.GetDepth()
+ : MAXLEVEL) - 1 );
+
+ // ggf. ein Regelwerk anlegen
+ if( !rInfo.GetNumRule() )
+ {
+ sal_uInt16 nPos = pDoc->MakeNumRule( pDoc->GetUniqueNumRuleName() );
+ rInfo.SetNumRule( pDoc->GetNumRuleTbl()[nPos] );
+ }
+
+ // das Format anpassen, falls es fuer den Level noch nicht
+ // geschehen ist!
+ sal_Bool bNewNumFmt = rInfo.GetNumRule()->GetNumFmt( nLevel ) == 0;
+ sal_Bool bChangeNumFmt = sal_False;
+
+ // das default Numerierungsformat erstellen
+ SwNumFmt aNumFmt( rInfo.GetNumRule()->Get(nLevel) );
+ rInfo.SetNodeStartValue( nLevel );
+ if( bNewNumFmt )
+ {
+ sal_uInt16 nChrFmtPoolId = 0;
+ if( HTML_ORDERLIST_ON == nToken )
+ {
+ aNumFmt.SetNumberingType(SVX_NUM_ARABIC);
+ nChrFmtPoolId = RES_POOLCHR_NUM_LEVEL;
+ }
+ else
+ {
+ // Wir setzen hier eine Zeichenvorlage, weil die UI das auch
+ // so macht. Dadurch wurd immer auch eine 9pt-Schrift
+ // eingestellt, was in Netscape nicht der Fall ist. Bisher hat
+ // das noch niemanden gestoert.
+ // --> OD 2008-06-03 #i63395#
+ // Only apply user defined default bullet font
+ if ( numfunc::IsDefBulletFontUserDefined() )
+ {
+ aNumFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ }
+ // <--
+ aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aNumFmt.SetBulletChar( cBulletChar ); // das Bulletzeichen !!
+ nChrFmtPoolId = RES_POOLCHR_BUL_LEVEL;
+ }
+
+ sal_uInt16 nAbsLSpace = HTML_NUMBUL_MARGINLEFT;
+
+ short nFirstLineIndent = HTML_NUMBUL_INDENT;
+ if( nLevel > 0 )
+ {
+ const SwNumFmt& rPrevNumFmt = rInfo.GetNumRule()->Get( nLevel-1 );
+ nAbsLSpace = nAbsLSpace + rPrevNumFmt.GetAbsLSpace();
+ nFirstLineIndent = rPrevNumFmt.GetFirstLineOffset();
+ }
+ aNumFmt.SetAbsLSpace( nAbsLSpace );
+ aNumFmt.SetFirstLineOffset( nFirstLineIndent );
+ aNumFmt.SetCharFmt( pCSS1Parser->GetCharFmtFromPool(nChrFmtPoolId) );
+
+ bChangeNumFmt = sal_True;
+ }
+ else if( 1 != aNumFmt.GetStart() )
+ {
+ // Wenn die Ebene schon mal benutzt wurde, muss der Start-Wert
+ // ggf. hart am Absatz gesetzt werden.
+ rInfo.SetNodeStartValue( nLevel, 1 );
+ }
+
+ // und es ggf. durch die Optionen veraendern
+ String aId, aStyle, aClass, aBulletSrc, aLang, aDir;
+ sal_Int16 eVertOri = text::VertOrientation::NONE;
+ sal_uInt16 nWidth=USHRT_MAX, nHeight=USHRT_MAX;
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_ID:
+ aId = pOption->GetString();
+ break;
+ case HTML_O_TYPE:
+ if( bNewNumFmt && pOption->GetString().Len() )
+ {
+ switch( nToken )
+ {
+ case HTML_ORDERLIST_ON:
+ bChangeNumFmt = sal_True;
+ switch( pOption->GetString().GetChar(0) )
+ {
+ case 'A': aNumFmt.SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER); break;
+ case 'a': aNumFmt.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER); break;
+ case 'I': aNumFmt.SetNumberingType(SVX_NUM_ROMAN_UPPER); break;
+ case 'i': aNumFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER); break;
+ default: bChangeNumFmt = sal_False;
+ }
+ break;
+
+ case HTML_UNORDERLIST_ON:
+ aNumFmt.SetBulletChar( (sal_Unicode)pOption->GetEnum(
+ aHTMLULTypeTable,aNumFmt.GetBulletChar() ) );
+ bChangeNumFmt = sal_True;
+ break;
+ }
+ }
+ break;
+ case HTML_O_START:
+ {
+ sal_uInt16 nStart = (sal_uInt16)pOption->GetNumber();
+ if( bNewNumFmt )
+ {
+ aNumFmt.SetStart( nStart );
+ bChangeNumFmt = sal_True;
+ }
+ else
+ {
+ rInfo.SetNodeStartValue( nLevel, nStart );
+ }
+ }
+ break;
+ case HTML_O_STYLE:
+ aStyle = pOption->GetString();
+ break;
+ case HTML_O_CLASS:
+ aClass = pOption->GetString();
+ break;
+ case HTML_O_LANG:
+ aLang = pOption->GetString();
+ break;
+ case HTML_O_DIR:
+ aDir = pOption->GetString();
+ break;
+ case HTML_O_SRC:
+ if( bNewNumFmt )
+ {
+ aBulletSrc = pOption->GetString();
+ if( !InternalImgToPrivateURL(aBulletSrc) )
+ aBulletSrc = URIHelper::SmartRel2Abs( INetURLObject( sBaseURL ), aBulletSrc, Link(), false );
+ }
+ break;
+ case HTML_O_WIDTH:
+ nWidth = (sal_uInt16)pOption->GetNumber();
+ break;
+ case HTML_O_HEIGHT:
+ nHeight = (sal_uInt16)pOption->GetNumber();
+ break;
+ case HTML_O_ALIGN:
+ eVertOri =
+ (sal_Int16)pOption->GetEnum( aHTMLImgVAlignTable,
+ static_cast< sal_uInt16 >(eVertOri) );
+ break;
+ }
+ }
+
+ if( aBulletSrc.Len() )
+ {
+ // Eine Bullet-Liste mit Grafiken
+ aNumFmt.SetNumberingType(SVX_NUM_BITMAP);
+
+ // Die Grafik als Brush anlegen
+ SvxBrushItem aBrushItem( RES_BACKGROUND );
+ aBrushItem.SetGraphicLink( aBulletSrc );
+ aBrushItem.SetGraphicPos( GPOS_AREA );
+
+ // Die Groesse nur beachten, wenn Breite und Hoehe vorhanden sind
+ Size aTwipSz( nWidth, nHeight), *pTwipSz=0;
+ if( nWidth!=USHRT_MAX && nHeight!=USHRT_MAX )
+ {
+ aTwipSz =
+ Application::GetDefaultDevice()->PixelToLogic( aTwipSz,
+ MapMode(MAP_TWIP) );
+ pTwipSz = &aTwipSz;
+ }
+
+ // Die Ausrichtung auch nur beachten, wenn eine Ausrichtung
+ // angegeben wurde
+ aNumFmt.SetGraphicBrush( &aBrushItem, pTwipSz,
+ text::VertOrientation::NONE!=eVertOri ? &eVertOri : 0);
+
+ // Und noch die Grafik merken, um sie in den Absaetzen nicht
+ // einzufuegen
+ aBulletGrfs[nLevel] = aBulletSrc;
+ bChangeNumFmt = sal_True;
+ }
+ else
+ aBulletGrfs[nLevel].Erase();
+
+ // den aktuellen Absatz erst einmal nicht numerieren
+ {
+ BYTE nLvl = nLevel;
+ // --> OD 2008-04-02 #refactorlists#
+// SetNoNum(&nLvl, TRUE); // #115962#
+// SetNodeNum( nLvl );
+ SetNodeNum( nLvl, false );
+ // <--
+ }
+
+ // einen neuen Kontext anlegen
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ if( bNewNumFmt )
+ {
+ if( aPropInfo.bLeftMargin )
+ {
+ // Der Der Default-Einzug wurde schon eingefuegt.
+ sal_uInt16 nAbsLSpace =
+ aNumFmt.GetAbsLSpace() - HTML_NUMBUL_MARGINLEFT;
+ if( aPropInfo.nLeftMargin < 0 &&
+ nAbsLSpace < -aPropInfo.nLeftMargin )
+ nAbsLSpace = 0U;
+ else if( aPropInfo.nLeftMargin > USHRT_MAX ||
+ (long)nAbsLSpace +
+ aPropInfo.nLeftMargin > USHRT_MAX )
+ nAbsLSpace = USHRT_MAX;
+ else
+ nAbsLSpace = nAbsLSpace + (sal_uInt16)aPropInfo.nLeftMargin;
+
+ aNumFmt.SetAbsLSpace( nAbsLSpace );
+ bChangeNumFmt = sal_True;
+ }
+ if( aPropInfo.bTextIndent )
+ {
+ short nTextIndent =
+ ((const SvxLRSpaceItem &)aItemSet.Get( RES_LR_SPACE ))
+ .GetTxtFirstLineOfst();
+ aNumFmt.SetFirstLineOffset( nTextIndent );
+ bChangeNumFmt = sal_True;
+ }
+ }
+ aPropInfo.bLeftMargin = aPropInfo.bTextIndent = sal_False;
+ if( !aPropInfo.bRightMargin )
+ aItemSet.ClearItem( RES_LR_SPACE );
+
+ // --> OD 2008-06-26 #i89812#
+ // Perform change to list style before calling <DoPositioning(..)>,
+ // because <DoPositioning(..)> may open a new context and thus may
+ // clear the <SwHTMLNumRuleInfo> instance hold by local variable <rInfo>.
+ if( bChangeNumFmt )
+ {
+ rInfo.GetNumRule()->Set( nLevel, aNumFmt );
+ pDoc->ChgNumRuleFmts( *rInfo.GetNumRule() );
+ bChangeNumFmt = sal_False;
+ }
+ // <--
+
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ if( bChangeNumFmt )
+ {
+ rInfo.GetNumRule()->Set( nLevel, aNumFmt );
+ pDoc->ChgNumRuleFmts( *rInfo.GetNumRule() );
+ }
+
+ PushContext( pCntxt );
+
+ // die Attribute der neuen Vorlage setzen
+ SetTxtCollAttrs( pCntxt );
+}
+
+void SwHTMLParser::EndNumBulList( int nToken )
+{
+ SwHTMLNumRuleInfo& rInfo = GetNumInfo();
+
+ // Ein neuer Absatz muss aufgemacht werden, wenn
+ // - der aktuelle nicht leer ist, also Text oder absatzgebundene Objekte
+ // enthaelt.
+ // - der aktuelle Absatz numeriert ist.
+ sal_Bool bAppend = pPam->GetPoint()->nContent.GetIndex() > 0;
+ if( !bAppend )
+ {
+ SwTxtNode* pTxtNode = pPam->GetNode()->GetTxtNode();
+
+ bAppend = (pTxtNode && ! pTxtNode->IsOutline() && pTxtNode->IsCountedInList()) ||
+
+ HasCurrentParaFlys();
+ }
+
+ sal_Bool bSpace = (rInfo.GetDepth() + nDefListDeep) == 1;
+ if( bAppend )
+ AppendTxtNode( bSpace ? AM_SPACE : AM_NOSPACE, sal_False );
+ else if( bSpace )
+ AddParSpace();
+
+ // den aktuellen Kontext vom Stack holen
+ _HTMLAttrContext *pCntxt = nToken!=0 ? PopContext( static_cast< sal_uInt16 >(nToken & ~1) ) : 0;
+
+ // Keine Liste aufgrund eines Tokens beenden, wenn der Kontext
+ // nie angelgt wurde oder nicht beendet werden darf.
+ if( rInfo.GetDepth()>0 && (!nToken || pCntxt) )
+ {
+ rInfo.DecDepth();
+ if( !rInfo.GetDepth() ) // wars der letze Level ?
+ {
+ // Die noch nicht angepassten Formate werden jetzt noch
+ // angepasst, damit es sich besser Editieren laesst.
+ const SwNumFmt *pRefNumFmt = 0;
+ sal_Bool bChanged = sal_False;
+ for( sal_uInt16 i=0; i<MAXLEVEL; i++ )
+ {
+ const SwNumFmt *pNumFmt = rInfo.GetNumRule()->GetNumFmt(i);
+ if( pNumFmt )
+ {
+ pRefNumFmt = pNumFmt;
+ }
+ else if( pRefNumFmt )
+ {
+ SwNumFmt aNumFmt( rInfo.GetNumRule()->Get(i) );
+ aNumFmt.SetNumberingType(pRefNumFmt->GetNumberingType() != SVX_NUM_BITMAP
+ ? pRefNumFmt->GetNumberingType() : style::NumberingType::CHAR_SPECIAL);
+ if( SVX_NUM_CHAR_SPECIAL == aNumFmt.GetNumberingType() )
+ {
+ // --> OD 2008-06-03 #i63395#
+ // Only apply user defined default bullet font
+ if ( numfunc::IsDefBulletFontUserDefined() )
+ {
+ aNumFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ }
+ // <--
+ aNumFmt.SetBulletChar( cBulletChar );
+ }
+ aNumFmt.SetAbsLSpace( (i+1) * HTML_NUMBUL_MARGINLEFT );
+ aNumFmt.SetFirstLineOffset( HTML_NUMBUL_INDENT );
+ aNumFmt.SetCharFmt( pRefNumFmt->GetCharFmt() );
+ rInfo.GetNumRule()->Set( i, aNumFmt );
+ bChanged = sal_True;
+ }
+ }
+ if( bChanged )
+ pDoc->ChgNumRuleFmts( *rInfo.GetNumRule() );
+
+ // Beim letzen Append wurde das NumRule-Item und das
+ // NodeNum-Objekt mit kopiert. Beides muessen wir noch
+ // loeschen. Das ResetAttr loescht das NodeNum-Objekt mit!
+ pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
+
+ rInfo.Clear();
+ }
+ else
+ {
+ // den naechsten Absatz erstmal nicht numerieren
+ // --> OD 2008-04-02 #refactorlists#
+// SetNodeNum( rInfo.GetLevel() | NO_NUMLEVEL );
+ SetNodeNum( rInfo.GetLevel(), false );
+ // <--
+ }
+ }
+
+ // und noch Attribute beenden
+ sal_Bool bSetAttrs = sal_False;
+ if( pCntxt )
+ {
+ EndContext( pCntxt );
+ delete pCntxt;
+ bSetAttrs = sal_True;
+ }
+
+ if( nToken )
+ SetTxtCollAttrs();
+
+ if( bSetAttrs )
+ SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
+
+}
+
+/* */
+
+void SwHTMLParser::NewNumBulListItem( int nToken )
+{
+ sal_uInt8 nLevel = GetNumInfo().GetLevel();
+ String aId, aStyle, aClass, aLang, aDir;
+ sal_uInt16 nStart = HTML_LISTHEADER_ON != nToken
+ ? GetNumInfo().GetNodeStartValue( nLevel )
+ : USHRT_MAX;
+ if( USHRT_MAX != nStart )
+ GetNumInfo().SetNodeStartValue( nLevel );
+
+ const HTMLOptions *pHTMLOptions = GetOptions();
+ for( sal_uInt16 i = pHTMLOptions->Count(); i; )
+ {
+ const HTMLOption *pOption = (*pHTMLOptions)[--i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_VALUE:
+ nStart = (sal_uInt16)pOption->GetNumber();
+ break;
+ case HTML_O_ID:
+ aId = pOption->GetString();
+ break;
+ case HTML_O_STYLE:
+ aStyle = pOption->GetString();
+ break;
+ case HTML_O_CLASS:
+ aClass = pOption->GetString();
+ break;
+ case HTML_O_LANG:
+ aLang = pOption->GetString();
+ break;
+ case HTML_O_DIR:
+ aDir = pOption->GetString();
+ break;
+ }
+ }
+
+ // einen neuen Absatz aufmachen
+ if( pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_NOSPACE, sal_False );
+ bNoParSpace = sal_False; // In <LI> wird kein Abstand eingefuegt!
+
+ // --> OD 2008-04-02 #refactorlists#
+// if( HTML_LISTHEADER_ON==nToken )
+// SetNoNum(&nLevel, TRUE);
+ const bool bCountedInList( HTML_LISTHEADER_ON==nToken ? false : true );
+ // <--
+
+ _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
+
+ String aNumRuleName;
+ if( GetNumInfo().GetNumRule() )
+ {
+ aNumRuleName = GetNumInfo().GetNumRule()->GetName();
+ }
+ else
+ {
+ aNumRuleName = pDoc->GetUniqueNumRuleName();
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ SwNumRule aNumRule( aNumRuleName,
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
+ // <--
+ SwNumFmt aNumFmt( aNumRule.Get( 0 ) );
+ // --> OD 2008-06-03 #i63395#
+ // Only apply user defined default bullet font
+ if ( numfunc::IsDefBulletFontUserDefined() )
+ {
+ aNumFmt.SetBulletFont( &numfunc::GetDefBulletFont() );
+ }
+ // <--
+ aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+ aNumFmt.SetBulletChar( cBulletChar ); // das Bulletzeichen !!
+ aNumFmt.SetCharFmt( pCSS1Parser->GetCharFmtFromPool(RES_POOLCHR_BUL_LEVEL) );
+ aNumFmt.SetLSpace( (sal_uInt16)(-HTML_NUMBUL_INDENT) );
+ aNumFmt.SetFirstLineOffset( HTML_NUMBUL_INDENT );
+ aNumRule.Set( 0, aNumFmt );
+
+ pDoc->MakeNumRule( aNumRuleName, &aNumRule );
+
+ ASSERT( !nOpenParaToken,
+ "Jetzt geht ein offenes Absatz-Element verloren" );
+ // Wir tun so, als ob wir in einem Absatz sind. Dann wird
+ // beim naechsten Absatz wenigstens die Numerierung
+ // weggeschmissen, die nach dem naechsten AppendTxtNode uebernommen
+ // wird.
+ nOpenParaToken = static_cast< sal_uInt16 >(nToken);
+ }
+
+ SwTxtNode* pTxtNode = pPam->GetNode()->GetTxtNode();
+ ((SwCntntNode *)pTxtNode)->SetAttr( SwNumRuleItem(aNumRuleName) );
+ pTxtNode->SetAttrListLevel(nLevel);
+ // --> OD 2005-11-14 #i57656#
+ // <IsCounted()> state of text node has to be adjusted accordingly.
+ if ( /*nLevel >= 0 &&*/ nLevel < MAXLEVEL )
+ {
+ // --> OD 2008-04-02 #refactorlists#
+ pTxtNode->SetCountedInList( bCountedInList );
+ // <--
+ }
+ // <--
+ // --> OD 2005-11-15 #i57919#
+ // correction of refactoring done by cws swnumtree
+ // - <nStart> contains the start value, if the numbering has to be restarted
+ // at this text node. Value <USHRT_MAX> indicates, that numbering isn't
+ // restarted at this text node
+ if ( nStart != USHRT_MAX )
+ {
+ pTxtNode->SetListRestart( true );
+ pTxtNode->SetAttrListRestartValue( nStart );
+ }
+ // <--
+
+ if( GetNumInfo().GetNumRule() )
+ GetNumInfo().GetNumRule()->SetInvalidRule( sal_True );
+
+ // Styles parsen
+ if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
+ {
+ SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
+ SvxCSS1PropertyInfo aPropInfo;
+
+ if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
+ {
+ DoPositioning( aItemSet, aPropInfo, pCntxt );
+ InsertAttrs( aItemSet, aPropInfo, pCntxt );
+ }
+ }
+
+ PushContext( pCntxt );
+
+ // die neue Vorlage setzen
+ SetTxtCollAttrs( pCntxt );
+
+ // Laufbalkenanzeige aktualisieren
+ ShowStatline();
+}
+
+void SwHTMLParser::EndNumBulListItem( int nToken, sal_Bool bSetColl,
+ sal_Bool /*bLastPara*/ )
+{
+ // einen neuen Absatz aufmachen
+ if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
+ AppendTxtNode( AM_NOSPACE );
+
+ // Kontext zu dem Token suchen und vom Stack holen
+ _HTMLAttrContext *pCntxt = 0;
+ sal_uInt16 nPos = aContexts.Count();
+ nToken &= ~1;
+ while( !pCntxt && nPos>nContextStMin )
+ {
+ sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
+ switch( nCntxtToken )
+ {
+ case HTML_LI_ON:
+ case HTML_LISTHEADER_ON:
+ if( !nToken || nToken == nCntxtToken )
+ {
+ pCntxt = aContexts[nPos];
+ aContexts.Remove( nPos, 1 );
+ }
+ break;
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ case HTML_MENULIST_ON:
+ case HTML_DIRLIST_ON:
+ // keine LI/LH ausserhalb der aktuellen Liste betrachten
+ 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();
+}
+
+/* */
+
+// --> OD 2008-04-02 #refactorlists#
+void SwHTMLParser::SetNodeNum( sal_uInt8 nLevel, bool bCountedInList )
+{
+ SwTxtNode* pTxtNode = pPam->GetNode()->GetTxtNode();
+ ASSERT( pTxtNode, "Kein Text-Node an PaM-Position" );
+
+ ASSERT( GetNumInfo().GetNumRule(), "Kein Numerierungs-Regel" );
+ const String& rName = GetNumInfo().GetNumRule()->GetName();
+ ((SwCntntNode *)pTxtNode)->SetAttr( SwNumRuleItem(rName) );
+
+ // --> OD 2008-04-02 #refactorlists#
+// // --> OD 2005-11-14 #i57656#
+// // consider usage of NO_NUMLEVEL - see implementation of <SwTxtNode::SetLevel(..)>
+// if ( /*nLevel >= 0 &&*/ ( nLevel & NO_NUMLEVEL ) )
+// {
+// pTxtNode->SetAttrListLevel( nLevel & ~NO_NUMLEVEL );
+// pTxtNode->SetCountedInList( false );
+// }
+// else
+// {
+// pTxtNode->SetAttrListLevel( nLevel );
+// pTxtNode->SetCountedInList( true );
+// }
+ pTxtNode->SetAttrListLevel( nLevel );
+ pTxtNode->SetCountedInList( bCountedInList );
+ // <--
+
+ // NumRule invalidieren, weil sie durch ein EndAction bereits
+ // auf valid geschaltet worden sein kann.
+ GetNumInfo().GetNumRule()->SetInvalidRule( sal_False );
+}
+
+
+/* */
+
+void SwHTMLWriter::FillNextNumInfo()
+{
+ pNextNumRuleInfo = 0;
+
+ ULONG nPos = pCurPam->GetPoint()->nNode.GetIndex() + 1;
+
+ sal_Bool bTable = sal_False;
+ do
+ {
+ const SwNode* pNd = pDoc->GetNodes()[nPos];
+ if( pNd->IsTxtNode() )
+ {
+ // Der naechste wird als naechstes ausgegeben.
+ pNextNumRuleInfo = new SwHTMLNumRuleInfo( *pNd->GetTxtNode() );
+
+ // Vor einer Tabelle behalten wir erst einmal die alte Ebene bei,
+ // wenn die gleiche Numerierung hinter der Tabelle
+ // fortgesetzt wird und dort nicht von vorne numeriert
+ // wird. Die Tabelle wird ann beim Import so weit eingeruckt,
+ // wie es der Num-Ebene entspricht.
+ if( bTable &&
+ pNextNumRuleInfo->GetNumRule()==GetNumInfo().GetNumRule() &&
+ !pNextNumRuleInfo->IsRestart() )
+ {
+ pNextNumRuleInfo->SetDepth( GetNumInfo().GetDepth() );
+ }
+ }
+ else if( pNd->IsTableNode() )
+ {
+ // Eine Tabelle wird uebersprungen, also den Node
+ // hinter der Tabelle betrachten.
+ nPos = pNd->EndOfSectionIndex() + 1;
+ bTable = sal_True;
+ }
+ else
+ {
+ // In allen anderen Faellen ist die Numerierung erstmal
+ // zu Ende.
+ pNextNumRuleInfo = new SwHTMLNumRuleInfo;
+ }
+ }
+ while( !pNextNumRuleInfo );
+}
+
+void SwHTMLWriter::ClearNextNumInfo()
+{
+ delete pNextNumRuleInfo;
+ pNextNumRuleInfo = 0;
+}
+
+Writer& OutHTML_NumBulListStart( SwHTMLWriter& rWrt,
+ const SwHTMLNumRuleInfo& rInfo )
+{
+ SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo();
+ sal_Bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule();
+ if( bSameRule && rPrevInfo.GetDepth() >= rInfo.GetDepth() &&
+ !rInfo.IsRestart() )
+ {
+ return rWrt;
+ }
+
+ sal_Bool bStartValue = sal_False;
+ if( !bSameRule && rInfo.GetDepth() )
+ {
+ String aName( rInfo.GetNumRule()->GetName() );
+ if( rWrt.aNumRuleNames.Seek_Entry( &aName ) )
+ {
+ // The rule has been applied before
+ sal_Int16 eType = rInfo.GetNumRule()
+ ->Get( rInfo.GetDepth()-1 ).GetNumberingType();
+ if( SVX_NUM_CHAR_SPECIAL != eType && SVX_NUM_BITMAP != eType )
+ {
+ // If its a numbering rule, the current number should be
+ // exported as start value, but only if there are no nodes
+ // within the numbering that have a lower level
+ bStartValue = sal_True;
+ if( rInfo.GetDepth() > 1 )
+ {
+ ULONG nPos =
+ rWrt.pCurPam->GetPoint()->nNode.GetIndex() + 1;
+ do
+ {
+ const SwNode* pNd = rWrt.pDoc->GetNodes()[nPos];
+ if( pNd->IsTxtNode() )
+ {
+ const SwTxtNode *pTxtNd = pNd->GetTxtNode();
+ if( !pTxtNd->GetNumRule() )
+ {
+ // node isn't numbered => check completed
+ break;
+ }
+
+ ASSERT(! pTxtNd->IsOutline(),
+ "outline not expected");
+
+ if( pTxtNd->GetActualListLevel() + 1 <
+ rInfo.GetDepth() )
+ {
+ // node is numbered, but level is lower
+ // => check completed
+ bStartValue = sal_False;
+ break;
+ }
+ nPos++;
+ }
+ else if( pNd->IsTableNode() )
+ {
+ // skip table
+ nPos = pNd->EndOfSectionIndex() + 1;
+ }
+ else
+ {
+ // end node or sections start node -> check
+ // completed
+ break;
+ }
+ }
+ while( sal_True );
+ }
+ }
+ }
+ else
+ {
+ rWrt.aNumRuleNames.Insert( new String( aName ) );
+ }
+ }
+
+
+ DBG_ASSERT( rWrt.nLastParaToken == 0,
+ "<PRE> wurde nicht vor <OL> beendet." );
+ sal_uInt16 nPrevDepth =
+ (bSameRule && !rInfo.IsRestart()) ? rPrevInfo.GetDepth() : 0;
+
+ for( sal_uInt16 i=nPrevDepth; i<rInfo.GetDepth(); i++ )
+ {
+ rWrt.OutNewLine(); // <OL>/<UL> in eine neue Zeile
+
+ rWrt.aBulletGrfs[i].Erase();
+ ByteString sOut( '<' );
+ const SwNumFmt& rNumFmt = rInfo.GetNumRule()->Get( i );
+ sal_Int16 eType = rNumFmt.GetNumberingType();
+ if( SVX_NUM_CHAR_SPECIAL == eType )
+ {
+ // Aufzaehlungs-Liste: <OL>
+ sOut += OOO_STRING_SVTOOLS_HTML_unorderlist;
+
+ // den Typ ueber das Bullet-Zeichen bestimmen
+ const sal_Char *pStr = 0;
+ switch( rNumFmt.GetBulletChar() )
+ {
+ case HTML_BULLETCHAR_DISC:
+ pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_disc;
+ break;
+ case HTML_BULLETCHAR_CIRCLE:
+ pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_circle;
+ break;
+ case HTML_BULLETCHAR_SQUARE:
+ pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_square;
+ break;
+ }
+
+ if( pStr )
+ (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += pStr;
+ }
+ else if( SVX_NUM_BITMAP == eType )
+ {
+ // Aufzaehlungs-Liste: <OL>
+ sOut += OOO_STRING_SVTOOLS_HTML_unorderlist;
+ rWrt.Strm() << sOut.GetBuffer();
+ sOut.Erase();
+
+ OutHTML_BulletImage( rWrt,
+ 0,
+ rNumFmt.GetBrush(),
+ rWrt.aBulletGrfs[i],
+ rNumFmt.GetGraphicSize(),
+ rNumFmt.GetGraphicOrientation() );
+ }
+ else
+ {
+ // Numerierungs-Liste: <UL>
+ sOut += OOO_STRING_SVTOOLS_HTML_orderlist;
+
+ // den Typ ueber das Format bestimmen
+ sal_Char cType = 0;
+ switch( eType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER: cType = 'A'; break;
+ case SVX_NUM_CHARS_LOWER_LETTER: cType = 'a'; break;
+ case SVX_NUM_ROMAN_UPPER: cType = 'I'; break;
+ case SVX_NUM_ROMAN_LOWER: cType = 'i'; break;
+ }
+ if( cType )
+ (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += cType;
+
+ sal_uInt16 nStartVal = rNumFmt.GetStart();
+ if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 )
+ {
+ // --> OD 2005-11-02 #i51089 - TUNING#
+ if ( rWrt.pCurPam->GetNode()->GetTxtNode()->GetNum() )
+ {
+ nStartVal = static_cast< sal_uInt16 >( rWrt.pCurPam->GetNode()
+ ->GetTxtNode()->GetNumberVector()[i] );
+ }
+ else
+ {
+ ASSERT( false,
+ "<OutHTML_NumBulListStart(..) - text node has no number." );
+ }
+ }
+ if( nStartVal != 1 )
+ {
+ (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_start) += '=')
+ += ByteString::CreateFromInt32( nStartVal );
+ }
+ }
+
+ if( sOut.Len() )
+ rWrt.Strm() << sOut.GetBuffer();
+
+ if( rWrt.bCfgOutStyles )
+ OutCSS1_NumBulListStyleOpt( rWrt, *rInfo.GetNumRule(), (BYTE)i );
+
+ rWrt.Strm() << '>';
+
+ rWrt.IncIndentLevel(); // Inhalt von <OL> einruecken
+ }
+
+ return rWrt;
+}
+
+Writer& OutHTML_NumBulListEnd( SwHTMLWriter& rWrt,
+ const SwHTMLNumRuleInfo& rNextInfo )
+{
+ SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo();
+ sal_Bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
+ if( bSameRule && rNextInfo.GetDepth() >= rInfo.GetDepth() &&
+ !rNextInfo.IsRestart() )
+ {
+ return rWrt;
+ }
+
+ DBG_ASSERT( rWrt.nLastParaToken == 0,
+ "<PRE> wurde nicht vor </OL> beendet." );
+ sal_uInt16 nNextDepth =
+ (bSameRule && !rNextInfo.IsRestart()) ? rNextInfo.GetDepth() : 0;
+
+ // MIB 23.7.97: Die Schleife muss doch rueckwaerts durchlaufen
+ // werden, weil die Reihenfolge von </OL>/</UL> stimmen muss
+ for( sal_uInt16 i=rInfo.GetDepth(); i>nNextDepth; i-- )
+ {
+ rWrt.DecIndentLevel(); // Inhalt von <OL> einruecken
+ if( rWrt.bLFPossible )
+ rWrt.OutNewLine(); // </OL>/</UL> in eine neue Zeile
+
+ // es wird also eine Liste angefangen oder beendet:
+ sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType();
+ const sal_Char *pStr;
+ if( SVX_NUM_CHAR_SPECIAL == eType || SVX_NUM_BITMAP == eType)
+ pStr = OOO_STRING_SVTOOLS_HTML_unorderlist;
+ else
+ pStr = OOO_STRING_SVTOOLS_HTML_orderlist;
+ HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, sal_False );
+ rWrt.bLFPossible = sal_True;
+ }
+
+ return rWrt;
+}