Update ooo320-m1
[ooovba.git] / sw / source / filter / html / htmlnum.cxx
blob0499cfd8636701ebbccc5eccc4444d67342350df
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 $
10 * $Revision: 1.29 $
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>
46 #include <doc.hxx>
47 #include <docary.hxx>
48 #include <poolfmt.hxx>
49 #include <ndtxt.hxx>
50 #include <paratr.hxx>
52 #include "htmlnum.hxx"
53 #include "swcss1.hxx"
54 #include "swhtml.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)
67 // <UL TYPE=...>
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 },
73 { 0, 0 }
76 /* \f */
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() );
84 if ( pTxtNdNumRule &&
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();
100 // <--
102 // <--
103 else
105 pNumRule = 0;
106 nDeep = 0;
107 bNumbered = bRestart = sal_False;
111 /* \f */
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 );
121 else if( bSpace )
122 AddParSpace();
124 // Die Numerierung-Ebene erhoehen
125 rInfo.IncDepth();
126 sal_uInt8 nLevel = (sal_uInt8)( (rInfo.GetDepth() <= MAXLEVEL ? rInfo.GetDepth()
127 : MAXLEVEL) - 1 );
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
137 // geschehen ist!
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 );
144 if( bNewNumFmt )
146 sal_uInt16 nChrFmtPoolId = 0;
147 if( HTML_ORDERLIST_ON == nToken )
149 aNumFmt.SetNumberingType(SVX_NUM_ARABIC);
150 nChrFmtPoolId = RES_POOLCHR_NUM_LEVEL;
152 else
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() );
164 // <--
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;
173 if( nLevel > 0 )
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() )
202 case HTML_O_ID:
203 aId = pOption->GetString();
204 break;
205 case HTML_O_TYPE:
206 if( bNewNumFmt && pOption->GetString().Len() )
208 switch( nToken )
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;
220 break;
222 case HTML_UNORDERLIST_ON:
223 aNumFmt.SetBulletChar( (sal_Unicode)pOption->GetEnum(
224 aHTMLULTypeTable,aNumFmt.GetBulletChar() ) );
225 bChangeNumFmt = sal_True;
226 break;
229 break;
230 case HTML_O_START:
232 sal_uInt16 nStart = (sal_uInt16)pOption->GetNumber();
233 if( bNewNumFmt )
235 aNumFmt.SetStart( nStart );
236 bChangeNumFmt = sal_True;
238 else
240 rInfo.SetNodeStartValue( nLevel, nStart );
243 break;
244 case HTML_O_STYLE:
245 aStyle = pOption->GetString();
246 break;
247 case HTML_O_CLASS:
248 aClass = pOption->GetString();
249 break;
250 case HTML_O_LANG:
251 aLang = pOption->GetString();
252 break;
253 case HTML_O_DIR:
254 aDir = pOption->GetString();
255 break;
256 case HTML_O_SRC:
257 if( bNewNumFmt )
259 aBulletSrc = pOption->GetString();
260 if( !InternalImgToPrivateURL(aBulletSrc) )
261 aBulletSrc = URIHelper::SmartRel2Abs( INetURLObject( sBaseURL ), aBulletSrc, Link(), false );
263 break;
264 case HTML_O_WIDTH:
265 nWidth = (sal_uInt16)pOption->GetNumber();
266 break;
267 case HTML_O_HEIGHT:
268 nHeight = (sal_uInt16)pOption->GetNumber();
269 break;
270 case HTML_O_ALIGN:
271 eVertOri =
272 (sal_Int16)pOption->GetEnum( aHTMLImgVAlignTable,
273 static_cast< sal_uInt16 >(eVertOri) );
274 break;
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 )
292 aTwipSz =
293 Application::GetDefaultDevice()->PixelToLogic( aTwipSz,
294 MapMode(MAP_TWIP) );
295 pTwipSz = &aTwipSz;
298 // Die Ausrichtung auch nur beachten, wenn eine Ausrichtung
299 // angegeben wurde
300 aNumFmt.SetGraphicBrush( &aBrushItem, pTwipSz,
301 text::VertOrientation::NONE!=eVertOri ? &eVertOri : 0);
303 // Und noch die Grafik merken, um sie in den Absaetzen nicht
304 // einzufuegen
305 aBulletGrfs[nLevel] = aBulletSrc;
306 bChangeNumFmt = sal_True;
308 else
309 aBulletGrfs[nLevel].Erase();
311 // den aktuellen Absatz erst einmal nicht numerieren
313 BYTE nLvl = nLevel;
314 // --> OD 2008-04-02 #refactorlists#
315 // SetNoNum(&nLvl, TRUE); // #115962#
316 // SetNodeNum( nLvl );
317 SetNodeNum( nLvl, false );
318 // <--
321 // einen neuen Kontext anlegen
322 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
324 // Styles parsen
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 ) )
332 if( bNewNumFmt )
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 )
341 nAbsLSpace = 0U;
342 else if( aPropInfo.nLeftMargin > USHRT_MAX ||
343 (long)nAbsLSpace +
344 aPropInfo.nLeftMargin > USHRT_MAX )
345 nAbsLSpace = USHRT_MAX;
346 else
347 nAbsLSpace = nAbsLSpace + (sal_uInt16)aPropInfo.nLeftMargin;
349 aNumFmt.SetAbsLSpace( nAbsLSpace );
350 bChangeNumFmt = sal_True;
352 if( aPropInfo.bTextIndent )
354 short nTextIndent =
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>.
369 if( bChangeNumFmt )
371 rInfo.GetNumRule()->Set( nLevel, aNumFmt );
372 pDoc->ChgNumRuleFmts( *rInfo.GetNumRule() );
373 bChangeNumFmt = sal_False;
375 // <--
377 DoPositioning( aItemSet, aPropInfo, pCntxt );
379 InsertAttrs( aItemSet, aPropInfo, pCntxt );
383 if( bChangeNumFmt )
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
401 // enthaelt.
402 // - der aktuelle Absatz numeriert ist.
403 sal_Bool bAppend = pPam->GetPoint()->nContent.GetIndex() > 0;
404 if( !bAppend )
406 SwTxtNode* pTxtNode = pPam->GetNode()->GetTxtNode();
408 bAppend = (pTxtNode && ! pTxtNode->IsOutline() && pTxtNode->IsCountedInList()) ||
410 HasCurrentParaFlys();
413 sal_Bool bSpace = (rInfo.GetDepth() + nDefListDeep) == 1;
414 if( bAppend )
415 AppendTxtNode( bSpace ? AM_SPACE : AM_NOSPACE, sal_False );
416 else if( bSpace )
417 AddParSpace();
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) )
426 rInfo.DecDepth();
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);
436 if( pNumFmt )
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() );
453 // <--
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 );
460 bChanged = sal_True;
463 if( bChanged )
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 );
471 rInfo.Clear();
473 else
475 // den naechsten Absatz erstmal nicht numerieren
476 // --> OD 2008-04-02 #refactorlists#
477 // SetNodeNum( rInfo.GetLevel() | NO_NUMLEVEL );
478 SetNodeNum( rInfo.GetLevel(), false );
479 // <--
483 // und noch Attribute beenden
484 sal_Bool bSetAttrs = sal_False;
485 if( pCntxt )
487 EndContext( pCntxt );
488 delete pCntxt;
489 bSetAttrs = sal_True;
492 if( nToken )
493 SetTxtCollAttrs();
495 if( bSetAttrs )
496 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
500 /* \f */
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 )
508 : USHRT_MAX;
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() )
518 case HTML_O_VALUE:
519 nStart = (sal_uInt16)pOption->GetNumber();
520 break;
521 case HTML_O_ID:
522 aId = pOption->GetString();
523 break;
524 case HTML_O_STYLE:
525 aStyle = pOption->GetString();
526 break;
527 case HTML_O_CLASS:
528 aClass = pOption->GetString();
529 break;
530 case HTML_O_LANG:
531 aLang = pOption->GetString();
532 break;
533 case HTML_O_DIR:
534 aDir = pOption->GetString();
535 break;
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 );
548 // <--
550 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
552 String aNumRuleName;
553 if( GetNumInfo().GetNumRule() )
555 aNumRuleName = GetNumInfo().GetNumRule()->GetName();
557 else
559 aNumRuleName = pDoc->GetUniqueNumRuleName();
560 // --> OD 2008-02-11 #newlistlevelattrs#
561 SwNumRule aNumRule( aNumRuleName,
562 SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
563 // <--
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() );
571 // <--
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
586 // wird.
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 );
599 // <--
601 // <--
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 );
612 // <--
614 if( GetNumInfo().GetNumRule() )
615 GetNumInfo().GetNumRule()->SetInvalidRule( sal_True );
617 // Styles parsen
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
636 ShowStatline();
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();
649 nToken &= ~1;
650 while( !pCntxt && nPos>nContextStMin )
652 sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
653 switch( nCntxtToken )
655 case HTML_LI_ON:
656 case HTML_LISTHEADER_ON:
657 if( !nToken || nToken == nCntxtToken )
659 pCntxt = aContexts[nPos];
660 aContexts.Remove( nPos, 1 );
662 break;
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;
669 break;
673 // und noch Attribute beenden
674 if( pCntxt )
676 EndContext( pCntxt );
677 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
678 delete pCntxt;
681 // und die bisherige Vorlage setzen
682 if( bSetColl )
683 SetTxtCollAttrs();
686 /* \f */
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 ) )
702 // {
703 // pTxtNode->SetAttrListLevel( nLevel & ~NO_NUMLEVEL );
704 // pTxtNode->SetCountedInList( false );
705 // }
706 // else
707 // {
708 // pTxtNode->SetAttrListLevel( nLevel );
709 // pTxtNode->SetCountedInList( true );
710 // }
711 pTxtNode->SetAttrListLevel( nLevel );
712 pTxtNode->SetCountedInList( bCountedInList );
713 // <--
715 // NumRule invalidieren, weil sie durch ein EndAction bereits
716 // auf valid geschaltet worden sein kann.
717 GetNumInfo().GetNumRule()->SetInvalidRule( sal_False );
721 /* \f */
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.
743 if( bTable &&
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;
755 bTable = sal_True;
757 else
759 // In allen anderen Faellen ist die Numerierung erstmal
760 // zu Ende.
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() &&
779 !rInfo.IsRestart() )
781 return rWrt;
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 )
801 ULONG nPos =
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
812 break;
815 ASSERT(! pTxtNd->IsOutline(),
816 "outline not expected");
818 if( pTxtNd->GetActualListLevel() + 1 <
819 rInfo.GetDepth() )
821 // node is numbered, but level is lower
822 // => check completed
823 bStartValue = sal_False;
824 break;
826 nPos++;
828 else if( pNd->IsTableNode() )
830 // skip table
831 nPos = pNd->EndOfSectionIndex() + 1;
833 else
835 // end node or sections start node -> check
836 // completed
837 break;
840 while( sal_True );
844 else
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;
875 break;
876 case HTML_BULLETCHAR_CIRCLE:
877 pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_circle;
878 break;
879 case HTML_BULLETCHAR_SQUARE:
880 pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_square;
881 break;
884 if( pStr )
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();
892 sOut.Erase();
894 OutHTML_BulletImage( rWrt,
896 rNumFmt.GetBrush(),
897 rWrt.aBulletGrfs[i],
898 rNumFmt.GetGraphicSize(),
899 rNumFmt.GetGraphicOrientation() );
901 else
903 // Numerierungs-Liste: <UL>
904 sOut += OOO_STRING_SVTOOLS_HTML_orderlist;
906 // den Typ ueber das Format bestimmen
907 sal_Char cType = 0;
908 switch( eType )
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;
915 if( cType )
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] );
927 else
929 ASSERT( false,
930 "<OutHTML_NumBulListStart(..) - text node has no number." );
933 if( nStartVal != 1 )
935 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_start) += '=')
936 += ByteString::CreateFromInt32( nStartVal );
940 if( sOut.Len() )
941 rWrt.Strm() << sOut.GetBuffer();
943 if( rWrt.bCfgOutStyles )
944 OutCSS1_NumBulListStyleOpt( rWrt, *rInfo.GetNumRule(), (BYTE)i );
946 rWrt.Strm() << '>';
948 rWrt.IncIndentLevel(); // Inhalt von <OL> einruecken
951 return rWrt;
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() )
962 return rWrt;
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;
983 else
984 pStr = OOO_STRING_SVTOOLS_HTML_orderlist;
985 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, sal_False );
986 rWrt.bLFPossible = sal_True;
989 return rWrt;