1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <com/sun/star/text/VertOrientation.hpp>
21 #include <com/sun/star/style/NumberingType.hpp>
22 #include <hintids.hxx>
23 #include <svtools/htmltokn.h>
24 #include <svtools/htmlkywd.hxx>
25 #include <svtools/htmlout.hxx>
26 #include <svl/urihelper.hxx>
27 #include <editeng/brushitem.hxx>
28 #include <editeng/lrspitem.hxx>
29 #include <vcl/svapp.hxx>
30 #include <sal/log.hxx>
31 #include <osl/diagnose.h>
32 #include <numrule.hxx>
33 #include <doc.hxx>
34 #include <docary.hxx>
35 #include <poolfmt.hxx>
36 #include <ndtxt.hxx>
37 #include <paratr.hxx>
38
39 #include "htmlnum.hxx"
40 #include "swcss1.hxx"
41 #include "swhtml.hxx"
42
43 #include <SwNodeNum.hxx>
44
45 using namespace css;
46
47 // <UL TYPE=...>
48 static HTMLOptionEnum<sal_Unicode> const aHTMLULTypeTable[] =
49 {
50 { OOO_STRING_SVTOOLS_HTML_ULTYPE_disc, HTML_BULLETCHAR_DISC },
51 { OOO_STRING_SVTOOLS_HTML_ULTYPE_circle, HTML_BULLETCHAR_CIRCLE },
52 { OOO_STRING_SVTOOLS_HTML_ULTYPE_square, HTML_BULLETCHAR_SQUARE },
53 { nullptr, 0 }
54 };
55
56
NewNumBulList(HtmlTokenId nToken)57 void SwHTMLParser::NewNumBulList( HtmlTokenId nToken )
58 {
59 SwHTMLNumRuleInfo& rInfo = GetNumInfo();
60
61 // Create a new paragraph
62 bool bSpace = (rInfo.GetDepth() + m_nDefListDeep) == 0;
63 if( m_pPam->GetPoint()->nContent.GetIndex() )
64 AppendTextNode( bSpace ? AM_SPACE : AM_NOSPACE, false );
65 else if( bSpace )
66 AddParSpace();
67
68 // Increment the numbering depth
69 rInfo.IncDepth();
70 sal_uInt8 nLevel = static_cast<sal_uInt8>( (rInfo.GetDepth() <= MAXLEVEL ? rInfo.GetDepth()
71 : MAXLEVEL) - 1 );
72
73 // Create rules if needed
74 if( !rInfo.GetNumRule() )
75 {
76 sal_uInt16 nPos = m_xDoc->MakeNumRule( m_xDoc->GetUniqueNumRuleName() );
77 rInfo.SetNumRule( m_xDoc->GetNumRuleTable()[nPos] );
78 }
79
80 // Change the format for this level if that hasn't happened yet for this level
81 bool bNewNumFormat = rInfo.GetNumRule()->GetNumFormat( nLevel ) == nullptr;
82 bool bChangeNumFormat = false;
83
84 // Create the default numbering format
85 SwNumFormat aNumFormat( rInfo.GetNumRule()->Get(nLevel) );
86 rInfo.SetNodeStartValue( nLevel );
87 if( bNewNumFormat )
88 {
89 sal_uInt16 nChrFormatPoolId = 0;
90 if( HtmlTokenId::ORDERLIST_ON == nToken )
91 {
92 aNumFormat.SetNumberingType(SVX_NUM_ARABIC);
93 nChrFormatPoolId = RES_POOLCHR_NUM_LEVEL;
94 }
95 else
96 {
97 // We'll set a default style because the UI does the same. This meant a 9pt font, which
98 // was not the case in Netscape. That didn't bother anyone so far
99 // #i63395# - Only apply user defined default bullet font
100 if ( numfunc::IsDefBulletFontUserDefined() )
101 {
102 aNumFormat.SetBulletFont( &numfunc::GetDefBulletFont() );
103 }
104 aNumFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
105 aNumFormat.SetBulletChar( cBulletChar );
106 nChrFormatPoolId = RES_POOLCHR_BUL_LEVEL;
107 }
108
109 sal_Int32 nAbsLSpace = HTML_NUMBUL_MARGINLEFT;
110
111 sal_Int32 nFirstLineIndent = HTML_NUMBUL_INDENT;
112 if( nLevel > 0 )
113 {
114 const SwNumFormat& rPrevNumFormat = rInfo.GetNumRule()->Get( nLevel-1 );
115 nAbsLSpace = nAbsLSpace + rPrevNumFormat.GetAbsLSpace();
116 nFirstLineIndent = rPrevNumFormat.GetFirstLineOffset();
117 }
118 aNumFormat.SetAbsLSpace( nAbsLSpace );
119 aNumFormat.SetFirstLineOffset( nFirstLineIndent );
120 aNumFormat.SetCharFormat( m_pCSS1Parser->GetCharFormatFromPool(nChrFormatPoolId) );
121
122 bChangeNumFormat = true;
123 }
124 else if( 1 != aNumFormat.GetStart() )
125 {
126 // If the layer has already been used, the start value may need to be set hard to the paragraph.
127 rInfo.SetNodeStartValue( nLevel, 1 );
128 }
129
130 // and set that in the options
131 OUString aId, aStyle, aClass, aLang, aDir;
132 OUString aBulletSrc;
133 sal_Int16 eVertOri = text::VertOrientation::NONE;
134 sal_uInt16 nWidth=USHRT_MAX, nHeight=USHRT_MAX;
135 const HTMLOptions& rHTMLOptions = GetOptions();
136 for (size_t i = rHTMLOptions.size(); i; )
137 {
138 const HTMLOption& rOption = rHTMLOptions[--i];
139 switch( rOption.GetToken() )
140 {
141 case HtmlOptionId::ID:
142 aId = rOption.GetString();
143 break;
144 case HtmlOptionId::TYPE:
145 if( bNewNumFormat && !rOption.GetString().isEmpty() )
146 {
147 switch( nToken )
148 {
149 case HtmlTokenId::ORDERLIST_ON:
150 bChangeNumFormat = true;
151 switch( rOption.GetString()[0] )
152 {
153 case 'A': aNumFormat.SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER); break;
154 case 'a': aNumFormat.SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER); break;
155 case 'I': aNumFormat.SetNumberingType(SVX_NUM_ROMAN_UPPER); break;
156 case 'i': aNumFormat.SetNumberingType(SVX_NUM_ROMAN_LOWER); break;
157 default: bChangeNumFormat = false;
158 }
159 break;
160
161 case HtmlTokenId::UNORDERLIST_ON:
162 aNumFormat.SetBulletChar( rOption.GetEnum(
163 aHTMLULTypeTable,aNumFormat.GetBulletChar() ) );
164 bChangeNumFormat = true;
165 break;
166 default: break;
167 }
168 }
169 break;
170 case HtmlOptionId::START:
171 {
172 sal_uInt16 nStart = static_cast<sal_uInt16>(rOption.GetNumber());
173 if( bNewNumFormat )
174 {
175 aNumFormat.SetStart( nStart );
176 bChangeNumFormat = true;
177 }
178 else
179 {
180 rInfo.SetNodeStartValue( nLevel, nStart );
181 }
182 }
183 break;
184 case HtmlOptionId::STYLE:
185 aStyle = rOption.GetString();
186 break;
187 case HtmlOptionId::CLASS:
188 aClass = rOption.GetString();
189 break;
190 case HtmlOptionId::LANG:
191 aLang = rOption.GetString();
192 break;
193 case HtmlOptionId::DIR:
194 aDir = rOption.GetString();
195 break;
196 case HtmlOptionId::SRC:
197 if( bNewNumFormat )
198 {
199 aBulletSrc = rOption.GetString();
200 if( !InternalImgToPrivateURL(aBulletSrc) )
201 aBulletSrc = URIHelper::SmartRel2Abs( INetURLObject( m_sBaseURL ), aBulletSrc, Link<OUString *, bool>(), false );
202 }
203 break;
204 case HtmlOptionId::WIDTH:
205 nWidth = static_cast<sal_uInt16>(rOption.GetNumber());
206 break;
207 case HtmlOptionId::HEIGHT:
208 nHeight = static_cast<sal_uInt16>(rOption.GetNumber());
209 break;
210 case HtmlOptionId::ALIGN:
211 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
212 break;
213 default: break;
214 }
215 }
216
217 if( !aBulletSrc.isEmpty() )
218 {
219 // A bullet list with graphics
220 aNumFormat.SetNumberingType(SVX_NUM_BITMAP);
221
222 // Create the graphic as a brush
223 SvxBrushItem aBrushItem( RES_BACKGROUND );
224 aBrushItem.SetGraphicLink( aBulletSrc );
225 aBrushItem.SetGraphicPos( GPOS_AREA );
226
227 // Only set size if given a width and a height
228 Size aTwipSz( nWidth, nHeight), *pTwipSz=nullptr;
229 if( nWidth!=USHRT_MAX && nHeight!=USHRT_MAX )
230 {
231 aTwipSz =
232 Application::GetDefaultDevice()->PixelToLogic( aTwipSz,
233 MapMode(MapUnit::MapTwip) );
234 pTwipSz = &aTwipSz;
235 }
236
237 // Only set orientation if given one
238 aNumFormat.SetGraphicBrush( &aBrushItem, pTwipSz,
239 text::VertOrientation::NONE!=eVertOri ? &eVertOri : nullptr);
240
241 // Remember the graphic to not put it into the paragraph
242 m_aBulletGrfs[nLevel] = aBulletSrc;
243 bChangeNumFormat = true;
244 }
245 else
246 m_aBulletGrfs[nLevel].clear();
247
248 // don't number the current paragraph (for now)
249 {
250 sal_uInt8 nLvl = nLevel;
251 SetNodeNum( nLvl );
252 }
253
254 // create a new context
255 std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(nToken));
256
257 // Parse styles
258 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
259 {
260 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
261 SvxCSS1PropertyInfo aPropInfo;
262
263 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
264 {
265 if( bNewNumFormat )
266 {
267 if( aPropInfo.m_bLeftMargin )
268 {
269 // Default indent has already been added
270 long nAbsLSpace =
271 aNumFormat.GetAbsLSpace() - HTML_NUMBUL_MARGINLEFT;
272 if( aPropInfo.m_nLeftMargin < 0 &&
273 nAbsLSpace < -aPropInfo.m_nLeftMargin )
274 nAbsLSpace = 0U;
275 else if( aPropInfo.m_nLeftMargin > SHRT_MAX ||
276 nAbsLSpace + aPropInfo.m_nLeftMargin > SHRT_MAX )
277 nAbsLSpace = SHRT_MAX;
278 else
279 nAbsLSpace = nAbsLSpace + aPropInfo.m_nLeftMargin;
280
281 aNumFormat.SetAbsLSpace( nAbsLSpace );
282 bChangeNumFormat = true;
283 }
284 if( aPropInfo.m_bTextIndent )
285 {
286 short nTextIndent =
287 aItemSet.Get( RES_LR_SPACE ).GetTextFirstLineOfst();
288 aNumFormat.SetFirstLineOffset( nTextIndent );
289 bChangeNumFormat = true;
290 }
291 if( aPropInfo.m_bNumbering )
292 {
293 aNumFormat.SetNumberingType(aPropInfo.m_nNumberingType);
294 bChangeNumFormat = true;
295 }
296 if( aPropInfo.m_bBullet )
297 {
298 aNumFormat.SetBulletChar( aPropInfo.m_cBulletChar );
299 bChangeNumFormat = true;
300 }
301 }
302 aPropInfo.m_bLeftMargin = aPropInfo.m_bTextIndent = false;
303 if( !aPropInfo.m_bRightMargin )
304 aItemSet.ClearItem( RES_LR_SPACE );
305
306 // #i89812# - Perform change to list style before calling <DoPositioning(..)>,
307 // because <DoPositioning(..)> may open a new context and thus may
308 // clear the <SwHTMLNumRuleInfo> instance hold by local variable <rInfo>.
309 if( bChangeNumFormat )
310 {
311 rInfo.GetNumRule()->Set( nLevel, aNumFormat );
312 m_xDoc->ChgNumRuleFormats( *rInfo.GetNumRule() );
313 bChangeNumFormat = false;
314 }
315
316 DoPositioning(aItemSet, aPropInfo, xCntxt.get());
317
318 InsertAttrs(aItemSet, aPropInfo, xCntxt.get());
319 }
320 }
321
322 if( bChangeNumFormat )
323 {
324 rInfo.GetNumRule()->Set( nLevel, aNumFormat );
325 m_xDoc->ChgNumRuleFormats( *rInfo.GetNumRule() );
326 }
327
328 PushContext(xCntxt);
329
330 // set attributes to the current template
331 SetTextCollAttrs(m_aContexts.back().get());
332 }
333
EndNumBulList(HtmlTokenId nToken)334 void SwHTMLParser::EndNumBulList( HtmlTokenId nToken )
335 {
336 SwHTMLNumRuleInfo& rInfo = GetNumInfo();
337
338 // A new paragraph needs to be created, when
339 // - the current one isn't empty (it contains text or paragraph-bound objects)
340 // - the current one is numbered
341 bool bAppend = m_pPam->GetPoint()->nContent.GetIndex() > 0;
342 if( !bAppend )
343 {
344 SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode();
345
346 bAppend = (pTextNode && ! pTextNode->IsOutline() && pTextNode->IsCountedInList()) ||
347
348 HasCurrentParaFlys();
349 }
350
351 bool bSpace = (rInfo.GetDepth() + m_nDefListDeep) == 1;
352 if( bAppend )
353 AppendTextNode( bSpace ? AM_SPACE : AM_NOSPACE, false );
354 else if( bSpace )
355 AddParSpace();
356
357 // get current context from stack
358 std::unique_ptr<HTMLAttrContext> xCntxt(nToken != HtmlTokenId::NONE ? PopContext(getOnToken(nToken)) : nullptr);
359
360 // Don't end a list because of a token, if the context wasn't created or mustn't be ended
361 if( rInfo.GetDepth()>0 && (nToken == HtmlTokenId::NONE || xCntxt) )
362 {
363 rInfo.DecDepth();
364 if( !rInfo.GetDepth() ) // was that the last level?
365 {
366 // The formats not yet modified are now modified, to ease editing
367 const SwNumFormat *pRefNumFormat = nullptr;
368 bool bChanged = false;
369 for( sal_uInt16 i=0; i<MAXLEVEL; i++ )
370 {
371 const SwNumFormat *pNumFormat = rInfo.GetNumRule()->GetNumFormat(i);
372 if( pNumFormat )
373 {
374 pRefNumFormat = pNumFormat;
375 }
376 else if( pRefNumFormat )
377 {
378 SwNumFormat aNumFormat( rInfo.GetNumRule()->Get(i) );
379 aNumFormat.SetNumberingType(pRefNumFormat->GetNumberingType() != SVX_NUM_BITMAP
380 ? pRefNumFormat->GetNumberingType() : SVX_NUM_CHAR_SPECIAL);
381 if( SVX_NUM_CHAR_SPECIAL == aNumFormat.GetNumberingType() )
382 {
383 // #i63395# - Only apply user defined default bullet font
384 if ( numfunc::IsDefBulletFontUserDefined() )
385 {
386 aNumFormat.SetBulletFont( &numfunc::GetDefBulletFont() );
387 }
388 aNumFormat.SetBulletChar( cBulletChar );
389 }
390 aNumFormat.SetAbsLSpace( (i+1) * HTML_NUMBUL_MARGINLEFT );
391 aNumFormat.SetFirstLineOffset( HTML_NUMBUL_INDENT );
392 aNumFormat.SetCharFormat( pRefNumFormat->GetCharFormat() );
393 rInfo.GetNumRule()->Set( i, aNumFormat );
394 bChanged = true;
395 }
396 }
397 if( bChanged )
398 m_xDoc->ChgNumRuleFormats( *rInfo.GetNumRule() );
399
400 // On the last append, the NumRule item and NodeNum object were copied.
401 // Now we need to delete them. ResetAttr deletes the NodeNum object as well
402 if (SwTextNode *pTextNode = m_pPam->GetNode().GetTextNode())
403 pTextNode->ResetAttr(RES_PARATR_NUMRULE);
404
405 rInfo.Clear();
406 }
407 else
408 {
409 // the next paragraph not numbered first
410 SetNodeNum( rInfo.GetLevel() );
411 }
412 }
413
414 // end attributes
415 bool bSetAttrs = false;
416 if (xCntxt)
417 {
418 EndContext(xCntxt.get());
419 xCntxt.reset();
420 bSetAttrs = true;
421 }
422
423 if( nToken != HtmlTokenId::NONE )
424 SetTextCollAttrs();
425
426 if( bSetAttrs )
427 SetAttr(); // Set paragraph attributes asap because of Javascript
428
429 }
430
NewNumBulListItem(HtmlTokenId nToken)431 void SwHTMLParser::NewNumBulListItem( HtmlTokenId nToken )
432 {
433 sal_uInt8 nLevel = GetNumInfo().GetLevel();
434 OUString aId, aStyle, aClass, aLang, aDir;
435 sal_uInt16 nStart = HtmlTokenId::LISTHEADER_ON != nToken
436 ? GetNumInfo().GetNodeStartValue( nLevel )
437 : USHRT_MAX;
438 if( USHRT_MAX != nStart )
439 GetNumInfo().SetNodeStartValue( nLevel );
440
441 const HTMLOptions& rHTMLOptions = GetOptions();
442 for (size_t i = rHTMLOptions.size(); i; )
443 {
444 const HTMLOption& rOption = rHTMLOptions[--i];
445 switch( rOption.GetToken() )
446 {
447 case HtmlOptionId::VALUE:
448 nStart = static_cast<sal_uInt16>(rOption.GetNumber());
449 break;
450 case HtmlOptionId::ID:
451 aId = rOption.GetString();
452 break;
453 case HtmlOptionId::STYLE:
454 aStyle = rOption.GetString();
455 break;
456 case HtmlOptionId::CLASS:
457 aClass = rOption.GetString();
458 break;
459 case HtmlOptionId::LANG:
460 aLang = rOption.GetString();
461 break;
462 case HtmlOptionId::DIR:
463 aDir = rOption.GetString();
464 break;
465 default: break;
466 }
467 }
468
469 // create a new paragraph
470 if( m_pPam->GetPoint()->nContent.GetIndex() )
471 AppendTextNode( AM_NOSPACE, false );
472 m_bNoParSpace = false; // no space in <LI>!
473
474 SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode();
475 if (!pTextNode)
476 {
477 SAL_WARN("sw.html", "No Text-Node at PaM-Position");
478 return;
479 }
480
481 const bool bCountedInList = nToken != HtmlTokenId::LISTHEADER_ON;
482
483 std::unique_ptr<HTMLAttrContext> xCntxt(new HTMLAttrContext(nToken));
484
485 OUString aNumRuleName;
486 if( GetNumInfo().GetNumRule() )
487 {
488 aNumRuleName = GetNumInfo().GetNumRule()->GetName();
489 }
490 else
491 {
492 aNumRuleName = m_xDoc->GetUniqueNumRuleName();
493 SwNumRule aNumRule( aNumRuleName,
494 SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
495 SwNumFormat aNumFormat( aNumRule.Get( 0 ) );
496 // #i63395# - Only apply user defined default bullet font
497 if ( numfunc::IsDefBulletFontUserDefined() )
498 {
499 aNumFormat.SetBulletFont( &numfunc::GetDefBulletFont() );
500 }
501 aNumFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
502 aNumFormat.SetBulletChar( cBulletChar ); // the bullet character !!
503 aNumFormat.SetCharFormat( m_pCSS1Parser->GetCharFormatFromPool(RES_POOLCHR_BUL_LEVEL) );
504 aNumFormat.SetFirstLineOffset( HTML_NUMBUL_INDENT );
505 aNumRule.Set( 0, aNumFormat );
506
507 m_xDoc->MakeNumRule( aNumRuleName, &aNumRule );
508
509 OSL_ENSURE( m_nOpenParaToken == HtmlTokenId::NONE,
510 "Now an open paragraph element is lost" );
511 // We'll act like we're in a paragraph. On the next paragraph, at least numbering is gone,
512 // that's gonna be taken over by the next AppendTextNode
513 m_nOpenParaToken = nToken;
514 }
515
516 static_cast<SwContentNode *>(pTextNode)->SetAttr( SwNumRuleItem(aNumRuleName) );
517 pTextNode->SetAttrListLevel(nLevel);
518 // #i57656# - <IsCounted()> state of text node has to be adjusted accordingly.
519 if ( nLevel < MAXLEVEL )
520 {
521 pTextNode->SetCountedInList( bCountedInList );
522 }
523 // #i57919#
524 // correction of refactoring done by cws swnumtree
525 // - <nStart> contains the start value, if the numbering has to be restarted
526 // at this text node. Value <USHRT_MAX> indicates, that numbering isn't
527 // restarted at this text node
528 if ( nStart != USHRT_MAX )
529 {
530 pTextNode->SetListRestart( true );
531 pTextNode->SetAttrListRestartValue( nStart );
532 }
533
534 if( GetNumInfo().GetNumRule() )
535 GetNumInfo().GetNumRule()->SetInvalidRule( true );
536
537 // parse styles
538 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
539 {
540 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
541 SvxCSS1PropertyInfo aPropInfo;
542
543 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
544 {
545 DoPositioning(aItemSet, aPropInfo, xCntxt.get());
546 InsertAttrs(aItemSet, aPropInfo, xCntxt.get());
547 }
548 }
549
550 PushContext(xCntxt);
551
552 // set the new template
553 SetTextCollAttrs(m_aContexts.back().get());
554
555 // Refresh scroll bar
556 ShowStatline();
557 }
558
EndNumBulListItem(HtmlTokenId nToken,bool bSetColl)559 void SwHTMLParser::EndNumBulListItem( HtmlTokenId nToken, bool bSetColl )
560 {
561 // Create a new paragraph
562 if( nToken == HtmlTokenId::NONE && m_pPam->GetPoint()->nContent.GetIndex() )
563 AppendTextNode( AM_NOSPACE );
564
565 // Get context to that token and pop it from stack
566 std::unique_ptr<HTMLAttrContext> xCntxt;
567 auto nPos = m_aContexts.size();
568 nToken = getOnToken(nToken);
569 while (!xCntxt && nPos>m_nContextStMin)
570 {
571 HtmlTokenId nCntxtToken = m_aContexts[--nPos]->GetToken();
572 switch( nCntxtToken )
573 {
574 case HtmlTokenId::LI_ON:
575 case HtmlTokenId::LISTHEADER_ON:
576 if( nToken == HtmlTokenId::NONE || nToken == nCntxtToken )
577 {
578 xCntxt = std::move(m_aContexts[nPos]);
579 m_aContexts.erase( m_aContexts.begin() + nPos );
580 }
581 break;
582 case HtmlTokenId::ORDERLIST_ON:
583 case HtmlTokenId::UNORDERLIST_ON:
584 case HtmlTokenId::MENULIST_ON:
585 case HtmlTokenId::DIRLIST_ON:
586 // Don't care about LI/LH outside the current list
587 nPos = m_nContextStMin;
588 break;
589 default: break;
590 }
591 }
592
593 // end attributes
594 if (xCntxt)
595 {
596 EndContext(xCntxt.get());
597 SetAttr(); // set paragraph attributes asap because of Javascript
598 xCntxt.reset();
599 }
600
601 // set current template
602 if( bSetColl )
603 SetTextCollAttrs();
604 }
605
SetNodeNum(sal_uInt8 nLevel)606 void SwHTMLParser::SetNodeNum( sal_uInt8 nLevel )
607 {
608 SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode();
609 if (!pTextNode)
610 {
611 SAL_WARN("sw.html", "No Text-Node at PaM-Position");
612 return;
613 }
614
615 OSL_ENSURE( GetNumInfo().GetNumRule(), "No numbering rule" );
616 const OUString& rName = GetNumInfo().GetNumRule()->GetName();
617 static_cast<SwContentNode *>(pTextNode)->SetAttr( SwNumRuleItem(rName) );
618
619 pTextNode->SetAttrListLevel( nLevel );
620 pTextNode->SetCountedInList( false );
621
622 // Invalidate NumRule, it may have been set valid because of an EndAction
623 GetNumInfo().GetNumRule()->SetInvalidRule( false );
624 }
625
626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
627