1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: htmlnum.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <com/sun/star/style/NumberingType.hpp>
36 #include <hintids.hxx>
37 #include <svtools/htmltokn.h>
38 #include <svtools/htmlkywd.hxx>
39 #include <svtools/htmlout.hxx>
40 #include <svtools/urihelper.hxx>
41 #include <svx/brshitem.hxx>
42 #include <svx/lrspitem.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vcl/wrkwin.hxx>
45 #include <numrule.hxx>
48 #include <poolfmt.hxx>
52 #include "htmlnum.hxx"
55 #include "wrthtml.hxx"
57 #include <SwNodeNum.hxx>
59 using namespace ::com::sun::star
;
61 // TODO: Unicode: Are these characters the correct ones?
62 #define HTML_BULLETCHAR_DISC (0xe008)
63 #define HTML_BULLETCHAR_CIRCLE (0xe009)
64 #define HTML_BULLETCHAR_SQUARE (0xe00b)
68 static HTMLOptionEnum __FAR_DATA aHTMLULTypeTable
[] =
70 { OOO_STRING_SVTOOLS_HTML_ULTYPE_disc
, HTML_BULLETCHAR_DISC
},
71 { OOO_STRING_SVTOOLS_HTML_ULTYPE_circle
, HTML_BULLETCHAR_CIRCLE
},
72 { OOO_STRING_SVTOOLS_HTML_ULTYPE_square
, HTML_BULLETCHAR_SQUARE
},
78 void SwHTMLNumRuleInfo::Set( const SwTxtNode
& rTxtNd
)
80 // --> OD 2006-06-12 #b6435904#
81 // export all numberings, except the outline numbering.
82 // if( rTxtNd.GetNumRule() && ! rTxtNd.IsOutline())
83 const SwNumRule
* pTxtNdNumRule( rTxtNd
.GetNumRule() );
85 pTxtNdNumRule
!= rTxtNd
.GetDoc()->GetOutlineNumRule() )
87 pNumRule
= const_cast<SwNumRule
*>(pTxtNdNumRule
);
88 nDeep
= static_cast< sal_uInt16
>(pNumRule
? rTxtNd
.GetActualListLevel() + 1 : 0);
89 bNumbered
= rTxtNd
.IsCountedInList();
90 // --> OD 2008-02-27 #refactorlists#
91 // --> OD 2005-11-16 #i57919#
92 // correction of refactoring done by cws swnumtree:
93 // <bRestart> has to be set to <true>, if numbering is restarted at this
94 // text node and the start value equals <USHRT_MAX>.
95 // Start value <USHRT_MAX> indicates, that at this text node the numbering
96 // is restarted with the value given at the corresponding level.
97 // bRestart = rTxtNd.IsListRestart() &&
98 // GetNum() && rTxtNd.GetNum()->GetStartValue() == USHRT_MAX;
99 bRestart
= rTxtNd
.IsListRestart() && !rTxtNd
.HasAttrListRestartValue();
107 bNumbered
= bRestart
= sal_False
;
113 void SwHTMLParser::NewNumBulList( int nToken
)
115 SwHTMLNumRuleInfo
& rInfo
= GetNumInfo();
117 // Erstmal einen neuen Absatz aufmachen
118 sal_Bool bSpace
= (rInfo
.GetDepth() + nDefListDeep
) == 0;
119 if( pPam
->GetPoint()->nContent
.GetIndex() )
120 AppendTxtNode( bSpace
? AM_SPACE
: AM_NOSPACE
, sal_False
);
124 // Die Numerierung-Ebene erhoehen
126 sal_uInt8 nLevel
= (sal_uInt8
)( (rInfo
.GetDepth() <= MAXLEVEL
? rInfo
.GetDepth()
129 // ggf. ein Regelwerk anlegen
130 if( !rInfo
.GetNumRule() )
132 sal_uInt16 nPos
= pDoc
->MakeNumRule( pDoc
->GetUniqueNumRuleName() );
133 rInfo
.SetNumRule( pDoc
->GetNumRuleTbl()[nPos
] );
136 // das Format anpassen, falls es fuer den Level noch nicht
138 sal_Bool bNewNumFmt
= rInfo
.GetNumRule()->GetNumFmt( nLevel
) == 0;
139 sal_Bool bChangeNumFmt
= sal_False
;
141 // das default Numerierungsformat erstellen
142 SwNumFmt
aNumFmt( rInfo
.GetNumRule()->Get(nLevel
) );
143 rInfo
.SetNodeStartValue( nLevel
);
146 sal_uInt16 nChrFmtPoolId
= 0;
147 if( HTML_ORDERLIST_ON
== nToken
)
149 aNumFmt
.SetNumberingType(SVX_NUM_ARABIC
);
150 nChrFmtPoolId
= RES_POOLCHR_NUM_LEVEL
;
154 // Wir setzen hier eine Zeichenvorlage, weil die UI das auch
155 // so macht. Dadurch wurd immer auch eine 9pt-Schrift
156 // eingestellt, was in Netscape nicht der Fall ist. Bisher hat
157 // das noch niemanden gestoert.
158 // --> OD 2008-06-03 #i63395#
159 // Only apply user defined default bullet font
160 if ( numfunc::IsDefBulletFontUserDefined() )
162 aNumFmt
.SetBulletFont( &numfunc::GetDefBulletFont() );
165 aNumFmt
.SetNumberingType(SVX_NUM_CHAR_SPECIAL
);
166 aNumFmt
.SetBulletChar( cBulletChar
); // das Bulletzeichen !!
167 nChrFmtPoolId
= RES_POOLCHR_BUL_LEVEL
;
170 sal_uInt16 nAbsLSpace
= HTML_NUMBUL_MARGINLEFT
;
172 short nFirstLineIndent
= HTML_NUMBUL_INDENT
;
175 const SwNumFmt
& rPrevNumFmt
= rInfo
.GetNumRule()->Get( nLevel
-1 );
176 nAbsLSpace
= nAbsLSpace
+ rPrevNumFmt
.GetAbsLSpace();
177 nFirstLineIndent
= rPrevNumFmt
.GetFirstLineOffset();
179 aNumFmt
.SetAbsLSpace( nAbsLSpace
);
180 aNumFmt
.SetFirstLineOffset( nFirstLineIndent
);
181 aNumFmt
.SetCharFmt( pCSS1Parser
->GetCharFmtFromPool(nChrFmtPoolId
) );
183 bChangeNumFmt
= sal_True
;
185 else if( 1 != aNumFmt
.GetStart() )
187 // Wenn die Ebene schon mal benutzt wurde, muss der Start-Wert
188 // ggf. hart am Absatz gesetzt werden.
189 rInfo
.SetNodeStartValue( nLevel
, 1 );
192 // und es ggf. durch die Optionen veraendern
193 String aId
, aStyle
, aClass
, aBulletSrc
, aLang
, aDir
;
194 sal_Int16 eVertOri
= text::VertOrientation::NONE
;
195 sal_uInt16 nWidth
=USHRT_MAX
, nHeight
=USHRT_MAX
;
196 const HTMLOptions
*pHTMLOptions
= GetOptions();
197 for( sal_uInt16 i
= pHTMLOptions
->Count(); i
; )
199 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
200 switch( pOption
->GetToken() )
203 aId
= pOption
->GetString();
206 if( bNewNumFmt
&& pOption
->GetString().Len() )
210 case HTML_ORDERLIST_ON
:
211 bChangeNumFmt
= sal_True
;
212 switch( pOption
->GetString().GetChar(0) )
214 case 'A': aNumFmt
.SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER
); break;
215 case 'a': aNumFmt
.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER
); break;
216 case 'I': aNumFmt
.SetNumberingType(SVX_NUM_ROMAN_UPPER
); break;
217 case 'i': aNumFmt
.SetNumberingType(SVX_NUM_ROMAN_LOWER
); break;
218 default: bChangeNumFmt
= sal_False
;
222 case HTML_UNORDERLIST_ON
:
223 aNumFmt
.SetBulletChar( (sal_Unicode
)pOption
->GetEnum(
224 aHTMLULTypeTable
,aNumFmt
.GetBulletChar() ) );
225 bChangeNumFmt
= sal_True
;
232 sal_uInt16 nStart
= (sal_uInt16
)pOption
->GetNumber();
235 aNumFmt
.SetStart( nStart
);
236 bChangeNumFmt
= sal_True
;
240 rInfo
.SetNodeStartValue( nLevel
, nStart
);
245 aStyle
= pOption
->GetString();
248 aClass
= pOption
->GetString();
251 aLang
= pOption
->GetString();
254 aDir
= pOption
->GetString();
259 aBulletSrc
= pOption
->GetString();
260 if( !InternalImgToPrivateURL(aBulletSrc
) )
261 aBulletSrc
= URIHelper::SmartRel2Abs( INetURLObject( sBaseURL
), aBulletSrc
, Link(), false );
265 nWidth
= (sal_uInt16
)pOption
->GetNumber();
268 nHeight
= (sal_uInt16
)pOption
->GetNumber();
272 (sal_Int16
)pOption
->GetEnum( aHTMLImgVAlignTable
,
273 static_cast< sal_uInt16
>(eVertOri
) );
278 if( aBulletSrc
.Len() )
280 // Eine Bullet-Liste mit Grafiken
281 aNumFmt
.SetNumberingType(SVX_NUM_BITMAP
);
283 // Die Grafik als Brush anlegen
284 SvxBrushItem
aBrushItem( RES_BACKGROUND
);
285 aBrushItem
.SetGraphicLink( aBulletSrc
);
286 aBrushItem
.SetGraphicPos( GPOS_AREA
);
288 // Die Groesse nur beachten, wenn Breite und Hoehe vorhanden sind
289 Size
aTwipSz( nWidth
, nHeight
), *pTwipSz
=0;
290 if( nWidth
!=USHRT_MAX
&& nHeight
!=USHRT_MAX
)
293 Application::GetDefaultDevice()->PixelToLogic( aTwipSz
,
298 // Die Ausrichtung auch nur beachten, wenn eine Ausrichtung
300 aNumFmt
.SetGraphicBrush( &aBrushItem
, pTwipSz
,
301 text::VertOrientation::NONE
!=eVertOri
? &eVertOri
: 0);
303 // Und noch die Grafik merken, um sie in den Absaetzen nicht
305 aBulletGrfs
[nLevel
] = aBulletSrc
;
306 bChangeNumFmt
= sal_True
;
309 aBulletGrfs
[nLevel
].Erase();
311 // den aktuellen Absatz erst einmal nicht numerieren
314 // --> OD 2008-04-02 #refactorlists#
315 // SetNoNum(&nLvl, TRUE); // #115962#
316 // SetNodeNum( nLvl );
317 SetNodeNum( nLvl
, false );
321 // einen neuen Kontext anlegen
322 _HTMLAttrContext
*pCntxt
= new _HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
325 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
327 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), pCSS1Parser
->GetWhichMap() );
328 SvxCSS1PropertyInfo aPropInfo
;
330 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
334 if( aPropInfo
.bLeftMargin
)
336 // Der Der Default-Einzug wurde schon eingefuegt.
337 sal_uInt16 nAbsLSpace
=
338 aNumFmt
.GetAbsLSpace() - HTML_NUMBUL_MARGINLEFT
;
339 if( aPropInfo
.nLeftMargin
< 0 &&
340 nAbsLSpace
< -aPropInfo
.nLeftMargin
)
342 else if( aPropInfo
.nLeftMargin
> USHRT_MAX
||
344 aPropInfo
.nLeftMargin
> USHRT_MAX
)
345 nAbsLSpace
= USHRT_MAX
;
347 nAbsLSpace
= nAbsLSpace
+ (sal_uInt16
)aPropInfo
.nLeftMargin
;
349 aNumFmt
.SetAbsLSpace( nAbsLSpace
);
350 bChangeNumFmt
= sal_True
;
352 if( aPropInfo
.bTextIndent
)
355 ((const SvxLRSpaceItem
&)aItemSet
.Get( RES_LR_SPACE
))
356 .GetTxtFirstLineOfst();
357 aNumFmt
.SetFirstLineOffset( nTextIndent
);
358 bChangeNumFmt
= sal_True
;
361 aPropInfo
.bLeftMargin
= aPropInfo
.bTextIndent
= sal_False
;
362 if( !aPropInfo
.bRightMargin
)
363 aItemSet
.ClearItem( RES_LR_SPACE
);
365 // --> OD 2008-06-26 #i89812#
366 // Perform change to list style before calling <DoPositioning(..)>,
367 // because <DoPositioning(..)> may open a new context and thus may
368 // clear the <SwHTMLNumRuleInfo> instance hold by local variable <rInfo>.
371 rInfo
.GetNumRule()->Set( nLevel
, aNumFmt
);
372 pDoc
->ChgNumRuleFmts( *rInfo
.GetNumRule() );
373 bChangeNumFmt
= sal_False
;
377 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
379 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
385 rInfo
.GetNumRule()->Set( nLevel
, aNumFmt
);
386 pDoc
->ChgNumRuleFmts( *rInfo
.GetNumRule() );
389 PushContext( pCntxt
);
391 // die Attribute der neuen Vorlage setzen
392 SetTxtCollAttrs( pCntxt
);
395 void SwHTMLParser::EndNumBulList( int nToken
)
397 SwHTMLNumRuleInfo
& rInfo
= GetNumInfo();
399 // Ein neuer Absatz muss aufgemacht werden, wenn
400 // - der aktuelle nicht leer ist, also Text oder absatzgebundene Objekte
402 // - der aktuelle Absatz numeriert ist.
403 sal_Bool bAppend
= pPam
->GetPoint()->nContent
.GetIndex() > 0;
406 SwTxtNode
* pTxtNode
= pPam
->GetNode()->GetTxtNode();
408 bAppend
= (pTxtNode
&& ! pTxtNode
->IsOutline() && pTxtNode
->IsCountedInList()) ||
410 HasCurrentParaFlys();
413 sal_Bool bSpace
= (rInfo
.GetDepth() + nDefListDeep
) == 1;
415 AppendTxtNode( bSpace
? AM_SPACE
: AM_NOSPACE
, sal_False
);
419 // den aktuellen Kontext vom Stack holen
420 _HTMLAttrContext
*pCntxt
= nToken
!=0 ? PopContext( static_cast< sal_uInt16
>(nToken
& ~1) ) : 0;
422 // Keine Liste aufgrund eines Tokens beenden, wenn der Kontext
423 // nie angelgt wurde oder nicht beendet werden darf.
424 if( rInfo
.GetDepth()>0 && (!nToken
|| pCntxt
) )
427 if( !rInfo
.GetDepth() ) // wars der letze Level ?
429 // Die noch nicht angepassten Formate werden jetzt noch
430 // angepasst, damit es sich besser Editieren laesst.
431 const SwNumFmt
*pRefNumFmt
= 0;
432 sal_Bool bChanged
= sal_False
;
433 for( sal_uInt16 i
=0; i
<MAXLEVEL
; i
++ )
435 const SwNumFmt
*pNumFmt
= rInfo
.GetNumRule()->GetNumFmt(i
);
438 pRefNumFmt
= pNumFmt
;
440 else if( pRefNumFmt
)
442 SwNumFmt
aNumFmt( rInfo
.GetNumRule()->Get(i
) );
443 aNumFmt
.SetNumberingType(pRefNumFmt
->GetNumberingType() != SVX_NUM_BITMAP
444 ? pRefNumFmt
->GetNumberingType() : style::NumberingType::CHAR_SPECIAL
);
445 if( SVX_NUM_CHAR_SPECIAL
== aNumFmt
.GetNumberingType() )
447 // --> OD 2008-06-03 #i63395#
448 // Only apply user defined default bullet font
449 if ( numfunc::IsDefBulletFontUserDefined() )
451 aNumFmt
.SetBulletFont( &numfunc::GetDefBulletFont() );
454 aNumFmt
.SetBulletChar( cBulletChar
);
456 aNumFmt
.SetAbsLSpace( (i
+1) * HTML_NUMBUL_MARGINLEFT
);
457 aNumFmt
.SetFirstLineOffset( HTML_NUMBUL_INDENT
);
458 aNumFmt
.SetCharFmt( pRefNumFmt
->GetCharFmt() );
459 rInfo
.GetNumRule()->Set( i
, aNumFmt
);
464 pDoc
->ChgNumRuleFmts( *rInfo
.GetNumRule() );
466 // Beim letzen Append wurde das NumRule-Item und das
467 // NodeNum-Objekt mit kopiert. Beides muessen wir noch
468 // loeschen. Das ResetAttr loescht das NodeNum-Objekt mit!
469 pPam
->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE
);
475 // den naechsten Absatz erstmal nicht numerieren
476 // --> OD 2008-04-02 #refactorlists#
477 // SetNodeNum( rInfo.GetLevel() | NO_NUMLEVEL );
478 SetNodeNum( rInfo
.GetLevel(), false );
483 // und noch Attribute beenden
484 sal_Bool bSetAttrs
= sal_False
;
487 EndContext( pCntxt
);
489 bSetAttrs
= sal_True
;
496 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
502 void SwHTMLParser::NewNumBulListItem( int nToken
)
504 sal_uInt8 nLevel
= GetNumInfo().GetLevel();
505 String aId
, aStyle
, aClass
, aLang
, aDir
;
506 sal_uInt16 nStart
= HTML_LISTHEADER_ON
!= nToken
507 ? GetNumInfo().GetNodeStartValue( nLevel
)
509 if( USHRT_MAX
!= nStart
)
510 GetNumInfo().SetNodeStartValue( nLevel
);
512 const HTMLOptions
*pHTMLOptions
= GetOptions();
513 for( sal_uInt16 i
= pHTMLOptions
->Count(); i
; )
515 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
516 switch( pOption
->GetToken() )
519 nStart
= (sal_uInt16
)pOption
->GetNumber();
522 aId
= pOption
->GetString();
525 aStyle
= pOption
->GetString();
528 aClass
= pOption
->GetString();
531 aLang
= pOption
->GetString();
534 aDir
= pOption
->GetString();
539 // einen neuen Absatz aufmachen
540 if( pPam
->GetPoint()->nContent
.GetIndex() )
541 AppendTxtNode( AM_NOSPACE
, sal_False
);
542 bNoParSpace
= sal_False
; // In <LI> wird kein Abstand eingefuegt!
544 // --> OD 2008-04-02 #refactorlists#
545 // if( HTML_LISTHEADER_ON==nToken )
546 // SetNoNum(&nLevel, TRUE);
547 const bool bCountedInList( HTML_LISTHEADER_ON
==nToken
? false : true );
550 _HTMLAttrContext
*pCntxt
= new _HTMLAttrContext( static_cast< sal_uInt16
>(nToken
) );
553 if( GetNumInfo().GetNumRule() )
555 aNumRuleName
= GetNumInfo().GetNumRule()->GetName();
559 aNumRuleName
= pDoc
->GetUniqueNumRuleName();
560 // --> OD 2008-02-11 #newlistlevelattrs#
561 SwNumRule
aNumRule( aNumRuleName
,
562 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
);
564 SwNumFmt
aNumFmt( aNumRule
.Get( 0 ) );
565 // --> OD 2008-06-03 #i63395#
566 // Only apply user defined default bullet font
567 if ( numfunc::IsDefBulletFontUserDefined() )
569 aNumFmt
.SetBulletFont( &numfunc::GetDefBulletFont() );
572 aNumFmt
.SetNumberingType(SVX_NUM_CHAR_SPECIAL
);
573 aNumFmt
.SetBulletChar( cBulletChar
); // das Bulletzeichen !!
574 aNumFmt
.SetCharFmt( pCSS1Parser
->GetCharFmtFromPool(RES_POOLCHR_BUL_LEVEL
) );
575 aNumFmt
.SetLSpace( (sal_uInt16
)(-HTML_NUMBUL_INDENT
) );
576 aNumFmt
.SetFirstLineOffset( HTML_NUMBUL_INDENT
);
577 aNumRule
.Set( 0, aNumFmt
);
579 pDoc
->MakeNumRule( aNumRuleName
, &aNumRule
);
581 ASSERT( !nOpenParaToken
,
582 "Jetzt geht ein offenes Absatz-Element verloren" );
583 // Wir tun so, als ob wir in einem Absatz sind. Dann wird
584 // beim naechsten Absatz wenigstens die Numerierung
585 // weggeschmissen, die nach dem naechsten AppendTxtNode uebernommen
587 nOpenParaToken
= static_cast< sal_uInt16
>(nToken
);
590 SwTxtNode
* pTxtNode
= pPam
->GetNode()->GetTxtNode();
591 ((SwCntntNode
*)pTxtNode
)->SetAttr( SwNumRuleItem(aNumRuleName
) );
592 pTxtNode
->SetAttrListLevel(nLevel
);
593 // --> OD 2005-11-14 #i57656#
594 // <IsCounted()> state of text node has to be adjusted accordingly.
595 if ( /*nLevel >= 0 &&*/ nLevel
< MAXLEVEL
)
597 // --> OD 2008-04-02 #refactorlists#
598 pTxtNode
->SetCountedInList( bCountedInList
);
602 // --> OD 2005-11-15 #i57919#
603 // correction of refactoring done by cws swnumtree
604 // - <nStart> contains the start value, if the numbering has to be restarted
605 // at this text node. Value <USHRT_MAX> indicates, that numbering isn't
606 // restarted at this text node
607 if ( nStart
!= USHRT_MAX
)
609 pTxtNode
->SetListRestart( true );
610 pTxtNode
->SetAttrListRestartValue( nStart
);
614 if( GetNumInfo().GetNumRule() )
615 GetNumInfo().GetNumRule()->SetInvalidRule( sal_True
);
618 if( HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
620 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), pCSS1Parser
->GetWhichMap() );
621 SvxCSS1PropertyInfo aPropInfo
;
623 if( ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
, aPropInfo
, &aLang
, &aDir
) )
625 DoPositioning( aItemSet
, aPropInfo
, pCntxt
);
626 InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
630 PushContext( pCntxt
);
632 // die neue Vorlage setzen
633 SetTxtCollAttrs( pCntxt
);
635 // Laufbalkenanzeige aktualisieren
639 void SwHTMLParser::EndNumBulListItem( int nToken
, sal_Bool bSetColl
,
640 sal_Bool
/*bLastPara*/ )
642 // einen neuen Absatz aufmachen
643 if( !nToken
&& pPam
->GetPoint()->nContent
.GetIndex() )
644 AppendTxtNode( AM_NOSPACE
);
646 // Kontext zu dem Token suchen und vom Stack holen
647 _HTMLAttrContext
*pCntxt
= 0;
648 sal_uInt16 nPos
= aContexts
.Count();
650 while( !pCntxt
&& nPos
>nContextStMin
)
652 sal_uInt16 nCntxtToken
= aContexts
[--nPos
]->GetToken();
653 switch( nCntxtToken
)
656 case HTML_LISTHEADER_ON
:
657 if( !nToken
|| nToken
== nCntxtToken
)
659 pCntxt
= aContexts
[nPos
];
660 aContexts
.Remove( nPos
, 1 );
663 case HTML_ORDERLIST_ON
:
664 case HTML_UNORDERLIST_ON
:
665 case HTML_MENULIST_ON
:
666 case HTML_DIRLIST_ON
:
667 // keine LI/LH ausserhalb der aktuellen Liste betrachten
668 nPos
= nContextStMin
;
673 // und noch Attribute beenden
676 EndContext( pCntxt
);
677 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
681 // und die bisherige Vorlage setzen
688 // --> OD 2008-04-02 #refactorlists#
689 void SwHTMLParser::SetNodeNum( sal_uInt8 nLevel
, bool bCountedInList
)
691 SwTxtNode
* pTxtNode
= pPam
->GetNode()->GetTxtNode();
692 ASSERT( pTxtNode
, "Kein Text-Node an PaM-Position" );
694 ASSERT( GetNumInfo().GetNumRule(), "Kein Numerierungs-Regel" );
695 const String
& rName
= GetNumInfo().GetNumRule()->GetName();
696 ((SwCntntNode
*)pTxtNode
)->SetAttr( SwNumRuleItem(rName
) );
698 // --> OD 2008-04-02 #refactorlists#
699 // // --> OD 2005-11-14 #i57656#
700 // // consider usage of NO_NUMLEVEL - see implementation of <SwTxtNode::SetLevel(..)>
701 // if ( /*nLevel >= 0 &&*/ ( nLevel & NO_NUMLEVEL ) )
703 // pTxtNode->SetAttrListLevel( nLevel & ~NO_NUMLEVEL );
704 // pTxtNode->SetCountedInList( false );
708 // pTxtNode->SetAttrListLevel( nLevel );
709 // pTxtNode->SetCountedInList( true );
711 pTxtNode
->SetAttrListLevel( nLevel
);
712 pTxtNode
->SetCountedInList( bCountedInList
);
715 // NumRule invalidieren, weil sie durch ein EndAction bereits
716 // auf valid geschaltet worden sein kann.
717 GetNumInfo().GetNumRule()->SetInvalidRule( sal_False
);
723 void SwHTMLWriter::FillNextNumInfo()
725 pNextNumRuleInfo
= 0;
727 ULONG nPos
= pCurPam
->GetPoint()->nNode
.GetIndex() + 1;
729 sal_Bool bTable
= sal_False
;
732 const SwNode
* pNd
= pDoc
->GetNodes()[nPos
];
733 if( pNd
->IsTxtNode() )
735 // Der naechste wird als naechstes ausgegeben.
736 pNextNumRuleInfo
= new SwHTMLNumRuleInfo( *pNd
->GetTxtNode() );
738 // Vor einer Tabelle behalten wir erst einmal die alte Ebene bei,
739 // wenn die gleiche Numerierung hinter der Tabelle
740 // fortgesetzt wird und dort nicht von vorne numeriert
741 // wird. Die Tabelle wird ann beim Import so weit eingeruckt,
742 // wie es der Num-Ebene entspricht.
744 pNextNumRuleInfo
->GetNumRule()==GetNumInfo().GetNumRule() &&
745 !pNextNumRuleInfo
->IsRestart() )
747 pNextNumRuleInfo
->SetDepth( GetNumInfo().GetDepth() );
750 else if( pNd
->IsTableNode() )
752 // Eine Tabelle wird uebersprungen, also den Node
753 // hinter der Tabelle betrachten.
754 nPos
= pNd
->EndOfSectionIndex() + 1;
759 // In allen anderen Faellen ist die Numerierung erstmal
761 pNextNumRuleInfo
= new SwHTMLNumRuleInfo
;
764 while( !pNextNumRuleInfo
);
767 void SwHTMLWriter::ClearNextNumInfo()
769 delete pNextNumRuleInfo
;
770 pNextNumRuleInfo
= 0;
773 Writer
& OutHTML_NumBulListStart( SwHTMLWriter
& rWrt
,
774 const SwHTMLNumRuleInfo
& rInfo
)
776 SwHTMLNumRuleInfo
& rPrevInfo
= rWrt
.GetNumInfo();
777 sal_Bool bSameRule
= rPrevInfo
.GetNumRule() == rInfo
.GetNumRule();
778 if( bSameRule
&& rPrevInfo
.GetDepth() >= rInfo
.GetDepth() &&
784 sal_Bool bStartValue
= sal_False
;
785 if( !bSameRule
&& rInfo
.GetDepth() )
787 String
aName( rInfo
.GetNumRule()->GetName() );
788 if( rWrt
.aNumRuleNames
.Seek_Entry( &aName
) )
790 // The rule has been applied before
791 sal_Int16 eType
= rInfo
.GetNumRule()
792 ->Get( rInfo
.GetDepth()-1 ).GetNumberingType();
793 if( SVX_NUM_CHAR_SPECIAL
!= eType
&& SVX_NUM_BITMAP
!= eType
)
795 // If its a numbering rule, the current number should be
796 // exported as start value, but only if there are no nodes
797 // within the numbering that have a lower level
798 bStartValue
= sal_True
;
799 if( rInfo
.GetDepth() > 1 )
802 rWrt
.pCurPam
->GetPoint()->nNode
.GetIndex() + 1;
805 const SwNode
* pNd
= rWrt
.pDoc
->GetNodes()[nPos
];
806 if( pNd
->IsTxtNode() )
808 const SwTxtNode
*pTxtNd
= pNd
->GetTxtNode();
809 if( !pTxtNd
->GetNumRule() )
811 // node isn't numbered => check completed
815 ASSERT(! pTxtNd
->IsOutline(),
816 "outline not expected");
818 if( pTxtNd
->GetActualListLevel() + 1 <
821 // node is numbered, but level is lower
822 // => check completed
823 bStartValue
= sal_False
;
828 else if( pNd
->IsTableNode() )
831 nPos
= pNd
->EndOfSectionIndex() + 1;
835 // end node or sections start node -> check
846 rWrt
.aNumRuleNames
.Insert( new String( aName
) );
851 DBG_ASSERT( rWrt
.nLastParaToken
== 0,
852 "<PRE> wurde nicht vor <OL> beendet." );
853 sal_uInt16 nPrevDepth
=
854 (bSameRule
&& !rInfo
.IsRestart()) ? rPrevInfo
.GetDepth() : 0;
856 for( sal_uInt16 i
=nPrevDepth
; i
<rInfo
.GetDepth(); i
++ )
858 rWrt
.OutNewLine(); // <OL>/<UL> in eine neue Zeile
860 rWrt
.aBulletGrfs
[i
].Erase();
861 ByteString
sOut( '<' );
862 const SwNumFmt
& rNumFmt
= rInfo
.GetNumRule()->Get( i
);
863 sal_Int16 eType
= rNumFmt
.GetNumberingType();
864 if( SVX_NUM_CHAR_SPECIAL
== eType
)
866 // Aufzaehlungs-Liste: <OL>
867 sOut
+= OOO_STRING_SVTOOLS_HTML_unorderlist
;
869 // den Typ ueber das Bullet-Zeichen bestimmen
870 const sal_Char
*pStr
= 0;
871 switch( rNumFmt
.GetBulletChar() )
873 case HTML_BULLETCHAR_DISC
:
874 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_disc
;
876 case HTML_BULLETCHAR_CIRCLE
:
877 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_circle
;
879 case HTML_BULLETCHAR_SQUARE
:
880 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_square
;
885 (((sOut
+= ' ') += OOO_STRING_SVTOOLS_HTML_O_type
) += '=') += pStr
;
887 else if( SVX_NUM_BITMAP
== eType
)
889 // Aufzaehlungs-Liste: <OL>
890 sOut
+= OOO_STRING_SVTOOLS_HTML_unorderlist
;
891 rWrt
.Strm() << sOut
.GetBuffer();
894 OutHTML_BulletImage( rWrt
,
898 rNumFmt
.GetGraphicSize(),
899 rNumFmt
.GetGraphicOrientation() );
903 // Numerierungs-Liste: <UL>
904 sOut
+= OOO_STRING_SVTOOLS_HTML_orderlist
;
906 // den Typ ueber das Format bestimmen
910 case SVX_NUM_CHARS_UPPER_LETTER
: cType
= 'A'; break;
911 case SVX_NUM_CHARS_LOWER_LETTER
: cType
= 'a'; break;
912 case SVX_NUM_ROMAN_UPPER
: cType
= 'I'; break;
913 case SVX_NUM_ROMAN_LOWER
: cType
= 'i'; break;
916 (((sOut
+= ' ') += OOO_STRING_SVTOOLS_HTML_O_type
) += '=') += cType
;
918 sal_uInt16 nStartVal
= rNumFmt
.GetStart();
919 if( bStartValue
&& 1 == nStartVal
&& i
== rInfo
.GetDepth()-1 )
921 // --> OD 2005-11-02 #i51089 - TUNING#
922 if ( rWrt
.pCurPam
->GetNode()->GetTxtNode()->GetNum() )
924 nStartVal
= static_cast< sal_uInt16
>( rWrt
.pCurPam
->GetNode()
925 ->GetTxtNode()->GetNumberVector()[i
] );
930 "<OutHTML_NumBulListStart(..) - text node has no number." );
935 (((sOut
+= ' ') += OOO_STRING_SVTOOLS_HTML_O_start
) += '=')
936 += ByteString::CreateFromInt32( nStartVal
);
941 rWrt
.Strm() << sOut
.GetBuffer();
943 if( rWrt
.bCfgOutStyles
)
944 OutCSS1_NumBulListStyleOpt( rWrt
, *rInfo
.GetNumRule(), (BYTE
)i
);
948 rWrt
.IncIndentLevel(); // Inhalt von <OL> einruecken
954 Writer
& OutHTML_NumBulListEnd( SwHTMLWriter
& rWrt
,
955 const SwHTMLNumRuleInfo
& rNextInfo
)
957 SwHTMLNumRuleInfo
& rInfo
= rWrt
.GetNumInfo();
958 sal_Bool bSameRule
= rNextInfo
.GetNumRule() == rInfo
.GetNumRule();
959 if( bSameRule
&& rNextInfo
.GetDepth() >= rInfo
.GetDepth() &&
960 !rNextInfo
.IsRestart() )
965 DBG_ASSERT( rWrt
.nLastParaToken
== 0,
966 "<PRE> wurde nicht vor </OL> beendet." );
967 sal_uInt16 nNextDepth
=
968 (bSameRule
&& !rNextInfo
.IsRestart()) ? rNextInfo
.GetDepth() : 0;
970 // MIB 23.7.97: Die Schleife muss doch rueckwaerts durchlaufen
971 // werden, weil die Reihenfolge von </OL>/</UL> stimmen muss
972 for( sal_uInt16 i
=rInfo
.GetDepth(); i
>nNextDepth
; i
-- )
974 rWrt
.DecIndentLevel(); // Inhalt von <OL> einruecken
975 if( rWrt
.bLFPossible
)
976 rWrt
.OutNewLine(); // </OL>/</UL> in eine neue Zeile
978 // es wird also eine Liste angefangen oder beendet:
979 sal_Int16 eType
= rInfo
.GetNumRule()->Get( i
-1 ).GetNumberingType();
980 const sal_Char
*pStr
;
981 if( SVX_NUM_CHAR_SPECIAL
== eType
|| SVX_NUM_BITMAP
== eType
)
982 pStr
= OOO_STRING_SVTOOLS_HTML_unorderlist
;
984 pStr
= OOO_STRING_SVTOOLS_HTML_orderlist
;
985 HTMLOutFuncs::Out_AsciiTag( rWrt
.Strm(), pStr
, sal_False
);
986 rWrt
.bLFPossible
= sal_True
;