new ODF numbered list parameter loext:num-list-format
[LibreOffice.git] / sw / source / filter / ww8 / wrtw8num.cxx
blob1313c79c031f721e2330553c2161d73dc8e27f16
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
21 #include <vcl/font.hxx>
22 #include <editeng/langitem.hxx>
23 #include <doc.hxx>
24 #include <docary.hxx>
25 #include <numrule.hxx>
26 #include <charfmt.hxx>
27 #include <com/sun/star/i18n/ScriptType.hpp>
29 #include "sprmids.hxx"
31 #include "ww8attributeoutput.hxx"
32 #include "writerhelper.hxx"
33 #include "writerwordglue.hxx"
34 #include "wrtww8.hxx"
35 #include "ww8par.hxx"
37 #include <numeric>
39 using namespace ::com::sun::star;
40 using namespace sw::types;
41 using namespace sw::util;
43 SwNumRule* MSWordExportBase::DuplicateNumRuleImpl(const SwNumRule *pRule)
45 const OUString sPrefix("WW8TempExport" + OUString::number( m_nUniqueList++ ));
46 SwNumRule* pMyNumRule =
47 new SwNumRule( m_rDoc.GetUniqueNumRuleName( &sPrefix ),
48 SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
49 m_pUsedNumTable->push_back( pMyNumRule );
51 for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
53 const SwNumFormat& rSubRule = pRule->Get(i);
54 pMyNumRule->Set( i, rSubRule );
56 return pMyNumRule;
59 sal_uInt16 MSWordExportBase::DuplicateNumRule(const SwNumRule* pRule, sal_uInt8 nLevel, sal_uInt16 nVal)
61 SwNumRule* const pMyNumRule = DuplicateNumRuleImpl(pRule);
63 SwNumFormat aNumFormat(pMyNumRule->Get(nLevel));
64 aNumFormat.SetStart(nVal);
65 pMyNumRule->Set(nLevel, aNumFormat);
67 return GetNumberingId(*pMyNumRule);
70 // multiple SwList can be based on the same SwNumRule; ensure one w:abstractNum
71 // per SwList
72 sal_uInt16 MSWordExportBase::DuplicateAbsNum(OUString const& rListId,
73 SwNumRule const& rAbstractRule)
75 auto const it(m_Lists.find(rListId));
76 if (it != m_Lists.end())
78 return it->second;
80 else
82 auto const pNewAbstractRule = DuplicateNumRuleImpl(&rAbstractRule);
83 assert(GetNumberingId(*pNewAbstractRule) == m_pUsedNumTable->size() - 1);
84 (void) pNewAbstractRule;
85 m_Lists.insert(std::make_pair(rListId, m_pUsedNumTable->size() - 1));
86 return m_pUsedNumTable->size() - 1;
90 // Ideally we want to map SwList to w:abstractNum and SwNumRule to w:num
91 // The current approach is to keep exporting every SwNumRule to
92 // 1 w:abstractNum and 1 w:num, and then add extra w:num via this function
93 // that reference an existing w:abstractNum and may override its formatting;
94 // of course this will end up exporting some w:num that aren't actually used.
95 sal_uInt16 MSWordExportBase::OverrideNumRule(
96 SwNumRule const& rExistingRule,
97 OUString const& rListId,
98 SwNumRule const& rAbstractRule)
100 const sal_uInt16 numdef = GetNumberingId(rExistingRule);
102 const sal_uInt16 absnumdef = rListId == rAbstractRule.GetDefaultListId()
103 ? GetNumberingId(rAbstractRule)
104 : DuplicateAbsNum(rListId, rAbstractRule);
105 assert(numdef != USHRT_MAX);
106 assert(absnumdef != USHRT_MAX);
107 auto const mapping = std::make_pair(numdef, absnumdef);
109 auto it = m_OverridingNums.insert(std::make_pair(m_pUsedNumTable->size(), mapping));
111 m_pUsedNumTable->push_back(nullptr); // dummy, it's unique_ptr...
112 ++m_nUniqueList; // counter for DuplicateNumRule...
114 return it.first->first;
117 void MSWordExportBase::AddListLevelOverride(sal_uInt16 nListId,
118 sal_uInt16 nLevelNum,
119 sal_uInt16 nStartAt)
121 m_ListLevelOverrides[nListId][nLevelNum] = nStartAt;
124 sal_uInt16 MSWordExportBase::GetNumberingId( const SwNumRule& rNumRule )
126 if ( !m_pUsedNumTable )
128 m_pUsedNumTable.reset(new SwNumRuleTable);
129 m_pUsedNumTable->insert( m_pUsedNumTable->begin(), m_rDoc.GetNumRuleTable().begin(), m_rDoc.GetNumRuleTable().end() );
130 // Check, if the outline rule is already inserted into <pUsedNumTable>.
131 // If yes, do not insert it again.
132 bool bOutlineRuleAdded( false );
133 for ( sal_uInt16 n = m_pUsedNumTable->size(); n; )
135 const SwNumRule& rRule = *(*m_pUsedNumTable)[ --n ];
136 if (!m_rDoc.IsUsed(rRule))
138 m_pUsedNumTable->erase( m_pUsedNumTable->begin() + n );
140 else if ( &rRule == m_rDoc.GetOutlineNumRule() )
142 bOutlineRuleAdded = true;
146 if ( !bOutlineRuleAdded )
148 // still need to paste the OutlineRule
149 SwNumRule* pR = m_rDoc.GetOutlineNumRule();
150 m_pUsedNumTable->push_back( pR );
153 SwNumRule* p = const_cast<SwNumRule*>(&rNumRule);
154 sal_uInt16 nRet = o3tl::narrowing<sal_uInt16>(m_pUsedNumTable->GetPos(p));
156 return nRet;
159 // GetFirstLineOffset should problem never appear unadorned apart from
160 // here in the ww export filter
161 sal_Int16 GetWordFirstLineOffset(const SwNumFormat &rFormat)
163 OSL_ENSURE( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
164 "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
166 short nFirstLineOffset;
167 if (rFormat.GetNumAdjust() == SvxAdjust::Right)
168 nFirstLineOffset = -rFormat.GetCharTextDistance();
169 else
170 nFirstLineOffset = rFormat.GetFirstLineOffset(); //TODO: overflow
171 return nFirstLineOffset;
174 void WW8Export::WriteNumbering()
176 if ( !m_pUsedNumTable )
177 return; // no numbering is used
179 // list formats - LSTF
180 pFib->m_fcPlcfLst = pTableStrm->Tell();
181 pTableStrm->WriteUInt16( m_pUsedNumTable->size() );
182 NumberingDefinitions();
183 // set len to FIB
184 pFib->m_lcbPlcfLst = pTableStrm->Tell() - pFib->m_fcPlcfLst;
186 // list formats - LVLF
187 AbstractNumberingDefinitions();
189 // list formats - LFO
190 OutOverrideListTab();
192 // list formats - ListNames
193 OutListNamesTab();
196 void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
198 m_rWW8Export.pTableStrm->WriteUInt32( nId );
199 m_rWW8Export.pTableStrm->WriteUInt32( nId );
201 // not associated with a Style
202 for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
203 m_rWW8Export.pTableStrm->WriteUInt16( 0xFFF );
205 sal_uInt8 nFlags = 0;
206 if ( rRule.IsContinusNum() )
207 nFlags |= 0x1;
209 m_rWW8Export.pTableStrm->WriteUChar( nFlags ).WriteUChar( 0/*nDummy*/ );
212 void MSWordExportBase::NumberingDefinitions()
214 if ( !m_pUsedNumTable )
215 return; // no numbering is used
217 sal_uInt16 nCount = m_pUsedNumTable->size();
219 // Write static data of SwNumRule - LSTF
220 for ( sal_uInt16 n = 0; n < nCount; ++n )
222 const SwNumRule * pRule = (*m_pUsedNumTable)[ n ];
223 if (pRule)
225 AttrOutput().NumberingDefinition(n + 1, *pRule);
227 else
229 auto it = m_OverridingNums.find(n);
230 assert(it != m_OverridingNums.end());
231 pRule = (*m_pUsedNumTable)[it->second.first];
232 assert(pRule);
233 AttrOutput().OverrideNumberingDefinition(*pRule, n + 1, it->second.second + 1, m_ListLevelOverrides[n]);
239 * Converts the SVX numbering type to MSONFC.
241 * This is used for special paragraph numbering considerations.
243 static sal_uInt8 GetLevelNFC(sal_uInt16 eNumType, const SfxItemSet* pOutSet, sal_uInt8 nDefault)
245 sal_uInt8 nRet = nDefault;
246 switch( eNumType )
248 case SVX_NUM_NUMBER_LOWER_ZH:
249 nRet = 35;
250 if ( pOutSet ) {
251 const SvxLanguageItem& rLang = pOutSet->Get( RES_CHRATR_CJK_LANGUAGE);
252 const LanguageType eLang = rLang.GetLanguage();
253 if (LANGUAGE_CHINESE_SIMPLIFIED ==eLang) {
254 nRet = 39;
257 break;
259 // LVLF can't contain 0x08, msonfcHex.
260 case style::NumberingType::SYMBOL_CHICAGO:
261 // No SVX_NUM_SYMBOL_CHICAGO here: LVLF can't contain 0x09, msonfcChiManSty.
262 nRet = 0;
263 break;
264 // LVLF can't contain 0x0F / 15, msonfcSbChar / decimalHalfWidth.
265 // LVLF can't contain 0x13 / 19, msonfcDArabic / decimalFullWidth2
267 return nRet;
271 void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
272 sal_uInt16 nStart,
273 sal_uInt16 nNumberingType,
274 SvxAdjust eAdjust,
275 const sal_uInt8 *pNumLvlPos,
276 sal_uInt8 nFollow,
277 const wwFont *pFont,
278 const SfxItemSet *pOutSet,
279 sal_Int16 nIndentAt,
280 sal_Int16 nFirstLineIndex,
281 sal_Int16 nListTabPos,
282 const OUString &rNumberingString,
283 const SvxBrushItem* pBrush //For i120928,to transfer graphic of bullet
286 // Start value
287 m_rWW8Export.pTableStrm->WriteUInt32( nStart );
289 // Type
290 sal_uInt8 nNumId = GetLevelNFC(nNumberingType, pOutSet, WW8Export::GetNumId(nNumberingType));
291 m_rWW8Export.pTableStrm->WriteUChar(nNumId);
293 // Justification
294 sal_uInt8 nAlign;
295 switch ( eAdjust )
297 case SvxAdjust::Center:
298 nAlign = 1;
299 break;
300 case SvxAdjust::Right:
301 nAlign = 2;
302 break;
303 default:
304 nAlign = 0;
305 break;
307 m_rWW8Export.pTableStrm->WriteUChar( nAlign );
309 // Write the rgbxchNums[9], positions of placeholders for paragraph
310 // numbers in the text
311 m_rWW8Export.pTableStrm->WriteBytes(pNumLvlPos, WW8ListManager::nMaxLevel);
313 // Type of the character between the bullet and the text
314 m_rWW8Export.pTableStrm->WriteUChar( nFollow );
316 // dxaSoace/dxaIndent (Word 6 compatibility)
317 m_rWW8Export.pTableStrm->WriteUInt32( 0 );
318 m_rWW8Export.pTableStrm->WriteUInt32( 0 );
320 // cbGrpprlChpx
321 std::unique_ptr<ww::bytes> pCharAtrs;
322 if ( pOutSet )
324 std::unique_ptr<ww::bytes> pOldpO = std::move(m_rWW8Export.pO);
325 m_rWW8Export.pO.reset(new ww::bytes);
326 if ( pFont )
328 sal_uInt16 nFontID = m_rWW8Export.m_aFontHelper.GetId( *pFont );
330 m_rWW8Export.InsUInt16( NS_sprm::CRgFtc0::val );
331 m_rWW8Export.InsUInt16( nFontID );
332 m_rWW8Export.InsUInt16( NS_sprm::CRgFtc2::val );
333 m_rWW8Export.InsUInt16( nFontID );
336 m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.m_bExportModeRTF );
337 //For i120928,achieve graphic's index of bullet from the bullet bookmark
338 if (SVX_NUM_BITMAP == nNumberingType && pBrush)
340 int nIndex = m_rWW8Export.GetGrfIndex(*pBrush);
341 if ( nIndex != -1 )
343 m_rWW8Export.InsUInt16(NS_sprm::CPbiIBullet::val);
344 m_rWW8Export.InsUInt32(nIndex);
345 m_rWW8Export.InsUInt16(NS_sprm::CPbiGrf::val);
346 m_rWW8Export.InsUInt16(1);
350 pCharAtrs = std::move(m_rWW8Export.pO);
351 m_rWW8Export.pO = std::move(pOldpO);
353 m_rWW8Export.pTableStrm->WriteUChar(sal_uInt8(pCharAtrs ? pCharAtrs->size() : 0));
355 // cbGrpprlPapx
356 sal_uInt8 aPapSprms [] = {
357 0x5e, 0x84, 0, 0, // sprmPDxaLeft
358 0x60, 0x84, 0, 0, // sprmPDxaLeft1
359 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
361 m_rWW8Export.pTableStrm->WriteUChar( sal_uInt8( sizeof( aPapSprms ) ) );
363 // reserved
364 m_rWW8Export.pTableStrm->WriteUInt16( 0 );
366 // pap sprms
367 sal_uInt8* pData = aPapSprms + 2;
368 Set_UInt16( pData, nIndentAt );
369 pData += 2;
370 Set_UInt16( pData, nFirstLineIndex );
371 pData += 5;
372 Set_UInt16( pData, nListTabPos );
374 m_rWW8Export.pTableStrm->WriteBytes(aPapSprms, sizeof(aPapSprms));
376 // write Chpx
377 if (pCharAtrs && !pCharAtrs->empty())
378 m_rWW8Export.pTableStrm->WriteBytes(pCharAtrs->data(), pCharAtrs->size());
380 // write the num string
381 m_rWW8Export.pTableStrm->WriteUInt16( rNumberingString.getLength() );
382 SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
385 void MSWordExportBase::AbstractNumberingDefinitions()
387 sal_uInt16 nCount = m_pUsedNumTable->size();
388 sal_uInt16 n;
390 for( n = 0; n < nCount; ++n )
392 if (nullptr == (*m_pUsedNumTable)[ n ])
394 continue;
397 AttrOutput().StartAbstractNumbering( n + 1 );
399 const SwNumRule& rRule = *(*m_pUsedNumTable)[ n ];
400 sal_uInt8 nLvl;
401 sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
402 WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
403 for( nLvl = 0; nLvl < nLevels; ++nLvl )
405 NumberingLevel(rRule, nLvl);
408 AttrOutput().EndAbstractNumbering();
412 void MSWordExportBase::NumberingLevel(
413 SwNumRule const& rRule, sal_uInt8 const nLvl)
415 // prepare the NodeNum to generate the NumString
416 static const SwNumberTree::tNumberVector aNumVector = [] {
417 SwNumberTree::tNumberVector vec(WW8ListManager::nMaxLevel);
418 std::iota(vec.begin(), vec.end(), 0);
419 return vec;
420 }();
422 // write the static data of the SwNumFormat of this level
423 sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
425 const SwNumFormat& rFormat = rRule.Get( nLvl );
427 sal_uInt8 nFollow = 0;
428 // #i86652#
429 if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
431 // <nFollow = 2>, if minimum label width equals 0 and
432 // minimum distance between label and text equals 0
433 nFollow = (rFormat.GetFirstLineOffset() == 0 &&
434 rFormat.GetCharTextDistance() == 0)
435 ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
437 else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
439 switch (rFormat.GetLabelFollowedBy())
441 case SvxNumberFormat::LISTTAB:
443 // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
444 nFollow = (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType()) ? 0 : 2;
446 break;
447 case SvxNumberFormat::SPACE:
449 // 1 (space) unless there would be no content before the space in which case 2 (nothing)
450 nFollow = (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType()) ? 1 : 2;
452 break;
453 case SvxNumberFormat::NOTHING:
455 nFollow = 2;
457 break;
458 default:
460 nFollow = 0;
461 OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
466 // Build the NumString for this Level
467 OUString sNumStr;
468 OUString sFontName;
469 bool bWriteBullet = false;
470 const vcl::Font* pBulletFont=nullptr;
471 rtl_TextEncoding eChrSet=0;
472 FontFamily eFamily=FAMILY_DECORATIVE;
473 if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
474 SVX_NUM_BITMAP == rFormat.GetNumberingType())
476 // Use bullet
477 sal_UCS4 cBullet = rFormat.GetBulletChar();
478 sNumStr = OUString(&cBullet, 1);
480 else
482 // Create level string
483 // For docx it is not the best way: we can just take it from rRule.Get(nLvl).GetListFormat()
484 // But for compatibility with doc we follow same routine
485 if (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType())
487 sal_uInt8* pLvlPos = aNumLvlPos;
488 // the numbering string has to be restrict
489 // to the level currently working on.
490 sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
492 // now search the nums in the string
493 for (sal_uInt8 i = 0; i <= nLvl; ++i)
495 OUString sSrch(OUString::number(i));
496 sal_Int32 nFnd = sNumStr.indexOf(sSrch);
497 if (-1 != nFnd)
499 *pLvlPos = static_cast<sal_uInt8>(nFnd + 1);
500 ++pLvlPos;
501 sNumStr = sNumStr.replaceAt(nFnd, 1, OUString(static_cast<char>(i)));
506 if (!rRule.Get(nLvl).HasListFormat())
508 if (!rFormat.GetPrefix().isEmpty())
509 sNumStr = rFormat.GetPrefix() + sNumStr;
510 sNumStr += rFormat.GetSuffix();
514 if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
515 SVX_NUM_BITMAP == rFormat.GetNumberingType())
517 bWriteBullet = true;
519 pBulletFont = rFormat.GetBulletFont();
520 if (!pBulletFont)
522 pBulletFont = &numfunc::GetDefBulletFont();
525 eChrSet = pBulletFont->GetCharSet();
526 sFontName = pBulletFont->GetFamilyName();
527 eFamily = pBulletFont->GetFamilyType();
529 if (IsStarSymbol(sFontName))
530 SubstituteBullet(sNumStr, eChrSet, sFontName);
533 // Attributes of the numbering
534 std::unique_ptr<wwFont> pPseudoFont;
535 const SfxItemSet* pOutSet = nullptr;
537 // cbGrpprlChpx
538 SfxItemSet aSet( m_rDoc.GetAttrPool(), svl::Items<RES_CHRATR_BEGIN,
539 RES_CHRATR_END>{} );
540 if (rFormat.GetCharFormat() || bWriteBullet)
542 if (bWriteBullet)
544 pOutSet = &aSet;
546 if (rFormat.GetCharFormat())
547 aSet.Put( rFormat.GetCharFormat()->GetAttrSet() );
548 aSet.ClearItem( RES_CHRATR_CJK_FONT );
549 aSet.ClearItem( RES_CHRATR_FONT );
551 if (sFontName.isEmpty())
552 sFontName = pBulletFont->GetFamilyName();
554 pPseudoFont.reset(new wwFont( sFontName, pBulletFont->GetPitch(),
555 eFamily, eChrSet));
557 else
558 pOutSet = &rFormat.GetCharFormat()->GetAttrSet();
561 sal_Int16 nIndentAt = 0;
562 sal_Int16 nFirstLineIndex = 0;
563 sal_Int16 nListTabPos = -1;
565 // #i86652#
566 if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
568 nIndentAt = nListTabPos = rFormat.GetAbsLSpace(); //TODO: overflow
569 nFirstLineIndex = GetWordFirstLineOffset(rFormat);
571 else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
573 nIndentAt = static_cast<sal_Int16>(rFormat.GetIndentAt());
574 nFirstLineIndex = static_cast<sal_Int16>(rFormat.GetFirstLineIndent());
575 nListTabPos = rFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
576 static_cast<sal_Int16>( rFormat.GetListtabPos() ) : 0;
579 AttrOutput().NumberingLevel( nLvl,
580 rFormat.GetStart(),
581 rFormat.GetNumberingType(),
582 rFormat.GetNumAdjust(),
583 aNumLvlPos,
584 nFollow,
585 pPseudoFont.get(), pOutSet,
586 nIndentAt, nFirstLineIndex, nListTabPos,
587 sNumStr,
588 rFormat.GetNumberingType()==SVX_NUM_BITMAP ? rFormat.GetBrush() : nullptr);
591 void WW8Export::OutOverrideListTab()
593 if( !m_pUsedNumTable )
594 return ; // no numbering is used
596 // write the "list format override" - LFO
597 sal_uInt16 nCount = m_pUsedNumTable->size();
598 sal_uInt16 n;
600 pFib->m_fcPlfLfo = pTableStrm->Tell();
601 pTableStrm->WriteUInt32( nCount );
603 // LFO ([MS-DOC] 2.9.131)
604 for( n = 0; n < nCount; ++n )
606 pTableStrm->WriteUInt32( n + 1 );
607 SwWW8Writer::FillCount( *pTableStrm, 12 );
609 // LFOData ([MS-DOC] 2.9.132)
610 for( n = 0; n < nCount; ++n )
611 pTableStrm->WriteInt32( -1 ); // no overwrite
613 // set len to FIB
614 pFib->m_lcbPlfLfo = pTableStrm->Tell() - pFib->m_fcPlfLfo;
617 void WW8Export::OutListNamesTab()
619 if( !m_pUsedNumTable )
620 return ; // no numbering is used
622 // write the "list format override" - LFO
623 sal_uInt16 nNms = 0, nCount = m_pUsedNumTable->size();
625 pFib->m_fcSttbListNames = pTableStrm->Tell();
626 pTableStrm->WriteInt16( -1 );
627 pTableStrm->WriteUInt32( nCount );
629 for( ; nNms < nCount; ++nNms )
631 const SwNumRule& rRule = *(*m_pUsedNumTable)[ nNms ];
632 OUString sNm;
633 if( !rRule.IsAutoRule() )
634 sNm = rRule.GetName();
636 pTableStrm->WriteUInt16( sNm.getLength() );
637 if (!sNm.isEmpty())
638 SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
641 SwWW8Writer::WriteLong( *pTableStrm, pFib->m_fcSttbListNames + 2, nNms );
642 // set len to FIB
643 pFib->m_lcbSttbListNames = pTableStrm->Tell() - pFib->m_fcSttbListNames;
646 void MSWordExportBase::SubstituteBullet( OUString& rNumStr,
647 rtl_TextEncoding& rChrSet, OUString& rFontName ) const
649 if (!m_bSubstituteBullets)
650 return;
651 OUString sFontName = rFontName;
653 // If Bullet char is "", don't change
654 if (rNumStr[0] != u'\0')
656 rNumStr = rNumStr.replaceAt(0, 1, OUString(
657 msfilter::util::bestFitOpenSymbolToMSFont(rNumStr[0], rChrSet, sFontName)));
660 rFontName = sFontName;
663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */