update credits
[LibreOffice.git] / sw / source / filter / ww8 / wrtw8num.cxx
blob82c54c19f778b2f9dac41099029c089498d13cba
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 .
21 #include <hintids.hxx>
22 #include <vcl/font.hxx>
23 #include <editeng/fontitem.hxx>
24 #include <editeng/lrspitem.hxx>
25 #include <doc.hxx>
26 #include <docary.hxx>
27 #include <numrule.hxx>
28 #include <paratr.hxx>
29 #include <charfmt.hxx>
30 #include <ndtxt.hxx>
31 #include <com/sun/star/i18n/ScriptType.hpp>
33 #include <doctok/sprmids.hxx>
35 #include "ww8attributeoutput.hxx"
36 #include "writerhelper.hxx"
37 #include "writerwordglue.hxx"
38 #include "wrtww8.hxx"
39 #include "ww8par.hxx"
41 using namespace ::com::sun::star;
42 using namespace sw::types;
43 using namespace sw::util;
45 sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
47 sal_uInt16 nNumId = USHRT_MAX;
48 String sPrefix(OUString("WW8TempExport"));
49 sPrefix += OUString::number( nUniqueList++ );
50 SwNumRule* pMyNumRule =
51 new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ),
52 SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
53 pUsedNumTbl->push_back( pMyNumRule );
55 for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
57 const SwNumFmt& rSubRule = pRule->Get(i);
58 pMyNumRule->Set( i, rSubRule );
61 SwNumFmt aNumFmt( pMyNumRule->Get( nLevel ) );
62 aNumFmt.SetStart( nVal );
63 pMyNumRule->Set( nLevel, aNumFmt );
65 nNumId = GetId( *pMyNumRule );
67 // Map the old list to our new list
68 aRuleDuplicates[GetId( *pRule )] = nNumId;
70 return nNumId;
73 sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule )
75 if ( !pUsedNumTbl )
77 pUsedNumTbl = new SwNumRuleTbl;
78 pUsedNumTbl->insert( pUsedNumTbl->begin(), pDoc->GetNumRuleTbl().begin(), pDoc->GetNumRuleTbl().end() );
79 // Check, if the outline rule is already inserted into <pUsedNumTbl>.
80 // If yes, do not insert it again.
81 bool bOutlineRuleAdded( false );
82 for ( sal_uInt16 n = pUsedNumTbl->size(); n; )
84 const SwNumRule& rRule = *(*pUsedNumTbl)[ --n ];
85 if ( !pDoc->IsUsed( rRule ) )
87 pUsedNumTbl->erase( pUsedNumTbl->begin() + n );
89 else if ( &rRule == pDoc->GetOutlineNumRule() )
91 bOutlineRuleAdded = true;
95 if ( !bOutlineRuleAdded )
97 // still need to paste the OutlineRule
98 SwNumRule* pR = (SwNumRule*)pDoc->GetOutlineNumRule();
99 pUsedNumTbl->push_back( pR );
102 SwNumRule* p = (SwNumRule*)&rNumRule;
103 sal_uInt16 nRet = pUsedNumTbl->GetPos(p);
105 // Is this list now duplicated into a new list which we should use
106 // #i77812# - perform 'deep' search in duplication map
107 ::std::map<sal_uInt16,sal_uInt16>::const_iterator aResult = aRuleDuplicates.end();
108 do {
109 aResult = aRuleDuplicates.find(nRet);
110 if ( aResult != aRuleDuplicates.end() )
112 nRet = (*aResult).second;
114 } while ( aResult != aRuleDuplicates.end() );
116 return nRet;
119 // GetFirstLineOffset should problem never appear unadorned apart from
120 // here in the ww export filter
121 sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt)
123 OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
124 "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
126 short nFirstLineOffset;
127 if (rFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
128 nFirstLineOffset = -rFmt.GetCharTextDistance();
129 else
130 nFirstLineOffset = rFmt.GetFirstLineOffset();
131 return nFirstLineOffset;
134 void WW8Export::WriteNumbering()
136 if ( !pUsedNumTbl )
137 return; // no numbering is used
139 // list formats - LSTF
140 pFib->fcPlcfLst = pTableStrm->Tell();
141 SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->size() );
142 NumberingDefinitions();
143 // set len to FIB
144 pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
146 // list formats - LVLF
147 AbstractNumberingDefinitions();
149 // list formats - LFO
150 OutOverrideListTab();
152 // list formats - ListNames
153 OutListNamesTab();
156 void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
158 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
159 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
161 // not associated with a Style
162 for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
163 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0xFFF );
165 sal_uInt8 nFlags = 0, nDummy = 0;
166 if ( rRule.IsContinusNum() )
167 nFlags |= 0x1;
169 *m_rWW8Export.pTableStrm << nFlags << nDummy;
172 void MSWordExportBase::NumberingDefinitions()
174 if ( !pUsedNumTbl )
175 return; // no numbering is used
177 sal_uInt16 nCount = pUsedNumTbl->size();
179 // Write static data of SwNumRule - LSTF
180 for ( sal_uInt16 n = 0; n < nCount; ++n )
182 const SwNumRule& rRule = *(*pUsedNumTbl)[ n ];
184 AttrOutput().NumberingDefinition( n + 1, rRule );
188 void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
189 sal_uInt16 nStart,
190 sal_uInt16 nNumberingType,
191 SvxAdjust eAdjust,
192 const sal_uInt8 *pNumLvlPos,
193 sal_uInt8 nFollow,
194 const wwFont *pFont,
195 const SfxItemSet *pOutSet,
196 sal_Int16 nIndentAt,
197 sal_Int16 nFirstLineIndex,
198 sal_Int16 nListTabPos,
199 const String &rNumberingString,
200 const SvxBrushItem* pBrush //For i120928,to transfer graphic of bullet
203 // Start value
204 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
206 // Type
207 *m_rWW8Export.pTableStrm << WW8Export::GetNumId( nNumberingType );
209 // Justification
210 sal_uInt8 nAlign;
211 switch ( eAdjust )
213 case SVX_ADJUST_CENTER:
214 nAlign = 1;
215 break;
216 case SVX_ADJUST_RIGHT:
217 nAlign = 2;
218 break;
219 default:
220 nAlign = 0;
221 break;
223 *m_rWW8Export.pTableStrm << nAlign;
225 // Write the rgbxchNums[9], positions of placeholders for paragraph
226 // numbers in the text
227 m_rWW8Export.pTableStrm->Write( pNumLvlPos, WW8ListManager::nMaxLevel );
229 // Type of the character between the bullet and the text
230 *m_rWW8Export.pTableStrm << nFollow;
232 // dxaSoace/dxaIndent (Word 6 compatibility)
233 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
234 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
236 // cbGrpprlChpx
237 ww::bytes aCharAtrs;
238 if ( pOutSet )
240 ww::bytes* pOldpO = m_rWW8Export.pO;
241 m_rWW8Export.pO = &aCharAtrs;
242 if ( pFont )
244 sal_uInt16 nFontID = m_rWW8Export.maFontHelper.GetId( *pFont );
246 if ( m_rWW8Export.bWrtWW8 )
248 m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
249 m_rWW8Export.InsUInt16( nFontID );
250 m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
252 else
253 m_rWW8Export.pO->push_back( 93 );
254 m_rWW8Export.InsUInt16( nFontID );
257 m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.mbExportModeRTF );
258 //For i120928,achieve graphic's index of bullet from the bullet bookmark
259 if (SVX_NUM_BITMAP == nNumberingType && pBrush)
261 int nIndex = m_rWW8Export.GetGrfIndex(*pBrush);
262 if ( nIndex != -1 )
264 m_rWW8Export.InsUInt16(0x6887);
265 m_rWW8Export.InsUInt32(nIndex);
266 m_rWW8Export.InsUInt16(0x4888);
267 m_rWW8Export.InsUInt16(1);
271 m_rWW8Export.pO = pOldpO;
273 *m_rWW8Export.pTableStrm << sal_uInt8( aCharAtrs.size() );
275 // cbGrpprlPapx
276 sal_uInt8 aPapSprms [] = {
277 0x5e, 0x84, 0, 0, // sprmPDxaLeft
278 0x60, 0x84, 0, 0, // sprmPDxaLeft1
279 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
281 *m_rWW8Export.pTableStrm << sal_uInt8( sizeof( aPapSprms ) );
283 // reserved
284 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
286 // pap sprms
287 sal_uInt8* pData = aPapSprms + 2;
288 Set_UInt16( pData, nIndentAt );
289 pData += 2;
290 Set_UInt16( pData, nFirstLineIndex );
291 pData += 5;
292 Set_UInt16( pData, nListTabPos );
294 m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
296 // write Chpx
297 if( !aCharAtrs.empty() )
298 m_rWW8Export.pTableStrm->Write( aCharAtrs.data(), aCharAtrs.size() );
300 // write the num string
301 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, rNumberingString.Len() );
302 SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
305 void MSWordExportBase::AbstractNumberingDefinitions()
307 sal_uInt16 nCount = pUsedNumTbl->size();
308 sal_uInt16 n;
310 // prepare the NodeNum to generate the NumString
311 SwNumberTree::tNumberVector aNumVector;
312 for ( n = 0; n < WW8ListManager::nMaxLevel; ++n )
313 aNumVector.push_back( n );
315 for( n = 0; n < nCount; ++n )
317 AttrOutput().StartAbstractNumbering( n + 1 );
319 const SwNumRule& rRule = *(*pUsedNumTbl)[ n ];
320 sal_uInt8 nLvl;
321 sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
322 WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
323 for( nLvl = 0; nLvl < nLevels; ++nLvl )
325 // write the static data of the SwNumFmt of this level
326 sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
328 const SwNumFmt& rFmt = rRule.Get( nLvl );
330 sal_uInt8 nFollow = 0;
331 // #i86652#
332 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
334 nFollow = 2; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
336 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
338 switch ( rFmt.GetLabelFollowedBy() )
340 case SvxNumberFormat::LISTTAB:
342 // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
343 nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 0 : 2;
345 break;
346 case SvxNumberFormat::SPACE:
348 // 1 (space) unless there would be no content before the space in which case 2 (nothing)
349 nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 1 : 2;
351 break;
352 case SvxNumberFormat::NOTHING:
354 nFollow = 2;
356 break;
357 default:
359 nFollow = 0;
360 OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
365 // Build the NumString for this Level
366 String sNumStr;
367 String sFontName;
368 bool bWriteBullet = false;
369 const Font* pBulletFont=0;
370 rtl_TextEncoding eChrSet=0;
371 FontFamily eFamily=FAMILY_DECORATIVE;
372 if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() ||
373 SVX_NUM_BITMAP == rFmt.GetNumberingType() )
375 sNumStr = rFmt.GetBulletChar();
376 bWriteBullet = true;
378 pBulletFont = rFmt.GetBulletFont();
379 if (!pBulletFont)
381 pBulletFont = &numfunc::GetDefBulletFont();
384 eChrSet = pBulletFont->GetCharSet();
385 sFontName = pBulletFont->GetName();
386 eFamily = pBulletFont->GetFamily();
388 if ( sw::util::IsStarSymbol( sFontName ) )
389 SubstituteBullet( sNumStr, eChrSet, sFontName );
391 // #i86652#
392 if ( rFmt.GetPositionAndSpaceMode() ==
393 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
395 // <nFollow = 2>, if minimum label width equals 0 and
396 // minimum distance between label and text equals 0
397 nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
398 rFmt.GetCharTextDistance() == 0 )
399 ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
402 else
404 if (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType())
406 sal_uInt8* pLvlPos = aNumLvlPos;
407 // the numbering string has to be restrict
408 // to the level currently working on.
409 sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
411 // now search the nums in the string
412 for( sal_uInt8 i = 0; i <= nLvl; ++i )
414 String sSrch( OUString::number( i ));
415 xub_StrLen nFnd = sNumStr.Search( sSrch );
416 if( STRING_NOTFOUND != nFnd )
418 *pLvlPos = (sal_uInt8)(nFnd + rFmt.GetPrefix().getLength() + 1 );
419 ++pLvlPos;
420 sNumStr.SetChar( nFnd, (char)i );
423 // #i86652#
424 if ( rFmt.GetPositionAndSpaceMode() ==
425 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
427 // <nFollow = 2>, if minimum label width equals 0 and
428 // minimum distance between label and text equals 0
429 nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
430 rFmt.GetCharTextDistance() == 0 )
431 ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
435 if( !rFmt.GetPrefix().isEmpty() )
436 sNumStr.Insert( rFmt.GetPrefix(), 0 );
437 sNumStr += rFmt.GetSuffix();
440 // Attributes of the numbering
441 wwFont *pPseudoFont = NULL;
442 const SfxItemSet* pOutSet = NULL;
444 // cbGrpprlChpx
445 SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
446 RES_CHRATR_END );
447 if ( rFmt.GetCharFmt() || bWriteBullet )
449 if ( bWriteBullet )
451 pOutSet = &aSet;
453 if ( rFmt.GetCharFmt() )
454 aSet.Put( rFmt.GetCharFmt()->GetAttrSet() );
455 aSet.ClearItem( RES_CHRATR_CJK_FONT );
456 aSet.ClearItem( RES_CHRATR_FONT );
458 if ( !sFontName.Len() )
459 sFontName = pBulletFont->GetName();
461 pPseudoFont = new wwFont( sFontName, pBulletFont->GetPitch(),
462 eFamily, eChrSet, SupportsUnicode() );
464 else
465 pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
468 sal_Int16 nIndentAt = 0;
469 sal_Int16 nFirstLineIndex = 0;
470 sal_Int16 nListTabPos = 0;
472 // #i86652#
473 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
475 nIndentAt = nListTabPos = rFmt.GetAbsLSpace();
476 nFirstLineIndex = GetWordFirstLineOffset(rFmt);
478 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
480 nIndentAt = static_cast<sal_Int16>(rFmt.GetIndentAt());
481 nFirstLineIndex = static_cast<sal_Int16>(rFmt.GetFirstLineIndent());
482 nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
483 static_cast<sal_Int16>( rFmt.GetListtabPos() ) : 0;
486 AttrOutput().NumberingLevel( nLvl,
487 rFmt.GetStart(),
488 rFmt.GetNumberingType(),
489 rFmt.GetNumAdjust(),
490 aNumLvlPos,
491 nFollow,
492 pPseudoFont, pOutSet,
493 nIndentAt, nFirstLineIndex, nListTabPos,
494 sNumStr,
495 rFmt.GetNumberingType()==SVX_NUM_BITMAP ? rFmt.GetBrush():0);
497 delete pPseudoFont;
499 AttrOutput().EndAbstractNumbering();
503 void WW8Export::OutOverrideListTab()
505 if( !pUsedNumTbl )
506 return ; // no numbering is used
508 // write the "list format override" - LFO
509 sal_uInt16 nCount = pUsedNumTbl->size();
510 sal_uInt16 n;
512 pFib->fcPlfLfo = pTableStrm->Tell();
513 SwWW8Writer::WriteLong( *pTableStrm, nCount );
515 for( n = 0; n < nCount; ++n )
517 SwWW8Writer::WriteLong( *pTableStrm, n + 1 );
518 SwWW8Writer::FillCount( *pTableStrm, 12 );
520 for( n = 0; n < nCount; ++n )
521 SwWW8Writer::WriteLong( *pTableStrm, -1 ); // no overwrite
523 // set len to FIB
524 pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
527 void WW8Export::OutListNamesTab()
529 if( !pUsedNumTbl )
530 return ; // no numbering is used
532 // write the "list format override" - LFO
533 sal_uInt16 nNms = 0, nCount = pUsedNumTbl->size();
535 pFib->fcSttbListNames = pTableStrm->Tell();
536 SwWW8Writer::WriteShort( *pTableStrm, -1 );
537 SwWW8Writer::WriteLong( *pTableStrm, nCount );
539 for( ; nNms < nCount; ++nNms )
541 const SwNumRule& rRule = *(*pUsedNumTbl)[ nNms ];
542 String sNm;
543 if( !rRule.IsAutoRule() )
544 sNm = rRule.GetName();
546 SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
547 if (sNm.Len())
548 SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
551 SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
552 // set len to FIB
553 pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
557 // old WW95-Code
559 void WW8Export::OutputOlst( const SwNumRule& rRule )
561 if ( bWrtWW8 )
562 return;
564 static sal_uInt8 aAnlvBase[] = { // Defaults
565 1,0,0, // Upper Roman
566 0x0C, // Hanging Indent, fPrev
567 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
569 static sal_uInt8 aSprmOlstHdr[] = { 133, 212 };
571 pO->insert( pO->end(), aSprmOlstHdr, aSprmOlstHdr+sizeof( aSprmOlstHdr ) );
572 WW8_OLST aOlst;
573 memset( &aOlst, 0, sizeof(aOlst) );
574 sal_uInt8* pC = aOlst.rgch;
575 sal_uInt8* pChars = (sal_uInt8*)pC;
576 sal_uInt16 nCharLen = 64;
578 for (sal_uInt16 j = 0; j < WW8ListManager::nMaxLevel; j++ ) // 9 variable ANLVs
580 memcpy( &aOlst.rganlv[j], aAnlvBase, sizeof( WW8_ANLV ) ); // Defaults
582 const SwNumFmt* pFmt = rRule.GetNumFmt( j );
583 if( pFmt )
584 BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
585 *pFmt, (sal_uInt8)j );
588 pO->insert( pO->end(), (sal_uInt8*)&aOlst, (sal_uInt8*)&aOlst+sizeof( aOlst ) );
592 void WW8Export::Out_WwNumLvl( sal_uInt8 nWwLevel )
594 pO->push_back( 13 );
595 pO->push_back( nWwLevel );
598 void WW8Export::Out_SwNumLvl( sal_uInt8 nSwLevel )
600 OSL_ENSURE( nSwLevel < MAXLEVEL, "numbered?");
601 Out_WwNumLvl( nSwLevel + 1 );
604 void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
605 sal_uInt16& rCharLen, const SwNumFmt& rFmt)
607 ByteToSVBT8(11, rAnlv.nfc);
609 sal_uInt8 nb = 0; // type of number
610 switch (rFmt.GetNumAdjust())
612 case SVX_ADJUST_RIGHT:
613 nb = 2;
614 break;
615 case SVX_ADJUST_CENTER:
616 nb = 1;
617 break;
618 case SVX_ADJUST_BLOCK:
619 case SVX_ADJUST_BLOCKLINE:
620 nb = 3;
621 break;
622 case SVX_ADJUST_LEFT:
623 case SVX_ADJUST_END:
624 break;
627 // #i86652#
628 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
630 if (GetWordFirstLineOffset(rFmt) < 0)
631 nb |= 0x8; // number will be displayed using a hanging indent
633 ByteToSVBT8(nb, rAnlv.aBits1);
635 if (1 < rCharLen)
637 const Font& rFont = rFmt.GetBulletFont()
638 ? *rFmt.GetBulletFont()
639 : numfunc::GetDefBulletFont();
640 String sNumStr = OUString(rFmt.GetBulletChar());
641 rtl_TextEncoding eChrSet = rFont.GetCharSet();
642 String sFontName = rFont.GetName();
644 sal_uInt16 nFontId;
645 if (sw::util::IsStarSymbol(sFontName))
648 If we are starsymbol then in ww7- mode we will always convert to a
649 windows 8bit symbol font and an index into it, to conversion to
650 8 bit is complete at this stage.
652 SubstituteBullet(sNumStr, eChrSet, sFontName);
653 wwFont aPseudoFont(sFontName, rFont.GetPitch(), rFont.GetFamily(),
654 eChrSet, bWrtWW8);
655 nFontId = maFontHelper.GetId(aPseudoFont);
656 *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
658 else
661 Otherwise we are a unicode char and need to be converted back to
662 an 8 bit format. We happen to know that if the font is already an
663 8 bit windows font currently, staroffice promotes the char into
664 the F000->F0FF range, so we can undo this, and we'll be back to
665 the equivalent 8bit location, otherwise we have to convert from
666 true unicode to an 8bit charset
668 nFontId = maFontHelper.GetId(rFont);
669 sal_Unicode cChar = sNumStr.GetChar(0);
670 if ( (eChrSet == RTL_TEXTENCODING_SYMBOL) && (cChar >= 0xF000) && (
671 cChar <= 0xF0FF) )
673 *rpCh = static_cast< sal_uInt8 >(cChar - 0xF000);
675 else
676 *rpCh = OUStringToOString(OUString(cChar), eChrSet).toChar();
678 rpCh++;
679 rCharLen--;
680 ShortToSVBT16(nFontId, rAnlv.ftc);
681 ByteToSVBT8( 1, rAnlv.cbTextBefore );
683 // #i86652#
684 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
686 ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
687 ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
689 else
691 ShortToSVBT16( 0, rAnlv.dxaIndent );
692 ShortToSVBT16( 0, rAnlv.dxaSpace );
696 void MSWordExportBase::SubstituteBullet( String& rNumStr,
697 rtl_TextEncoding& rChrSet, String& rFontName ) const
699 if (!bSubstituteBullets)
700 return;
701 OUString sFontName = rFontName;
702 rNumStr.SetChar(0, msfilter::util::bestFitOpenSymbolToMSFont(rNumStr.GetChar(0),
703 rChrSet, sFontName, !SupportsUnicode()));
704 rFontName = sFontName;
707 static void SwWw8_InsertAnlText( const String& rStr, sal_uInt8*& rpCh,
708 sal_uInt16& rCharLen, SVBT8& r8Len )
710 sal_uInt8 nb = 0;
711 ww::bytes aO;
712 SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
714 sal_uInt16 nCnt = aO.size();
715 if( nCnt && nCnt < rCharLen )
717 nb = (sal_uInt8)nCnt;
718 std::copy( aO.begin(), aO.end(), rpCh );
719 rpCh += nCnt;
720 rCharLen = rCharLen - nCnt;
722 ByteToSVBT8( nb, r8Len );
725 void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
726 sal_uInt16& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt,
727 sal_uInt8 nSwLevel)
729 ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc);
731 sal_uInt8 nb = 0;
732 switch (rFmt.GetNumAdjust())
734 case SVX_ADJUST_RIGHT:
735 nb = 2;
736 break;
737 case SVX_ADJUST_CENTER:
738 nb = 1;
739 break;
740 case SVX_ADJUST_BLOCK:
741 case SVX_ADJUST_BLOCKLINE:
742 nb = 3;
743 break;
744 case SVX_ADJUST_LEFT:
745 case SVX_ADJUST_END:
746 break;
749 bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
750 if( bInclUpper )
751 nb |= 0x4; // include previous levels
753 if (GetWordFirstLineOffset(rFmt) < 0)
754 nb |= 0x8; // number will be displayed using a hanging indent
755 ByteToSVBT8( nb, rAnlv.aBits1 );
757 if( bInclUpper && !rRul.IsContinusNum() )
759 if( (nSwLevel >= WW8ListManager::nMinLevel )
760 && (nSwLevel<= WW8ListManager::nMaxLevel )
761 && (rFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // UEberhaupt Nummerierung ?
762 { // -> suche, ob noch Zahlen davor
763 sal_uInt8 nUpper = rFmt.GetIncludeUpperLevels();
764 if( (nUpper <= WW8ListManager::nMaxLevel) &&
765 (rRul.Get(nUpper).GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // Nummerierung drueber ?
767 // dann Punkt einfuegen
768 SwWw8_InsertAnlText( aDotStr, rpCh, rCharLen,
769 rAnlv.cbTextBefore );
774 else
776 SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
777 rAnlv.cbTextBefore );
778 SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
779 rAnlv.cbTextAfter );
782 ShortToSVBT16( rFmt.GetStart(), rAnlv.iStartAt );
783 // #i86652#
784 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
786 ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
787 ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
789 else
791 ShortToSVBT16( 0, rAnlv.dxaIndent );
792 ShortToSVBT16( 0, rAnlv.dxaSpace );
796 void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
797 sal_uInt8 nSwLevel )
799 static sal_uInt8 aSprmAnldDefault[54] = {
800 12, 52,
801 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
802 0,0,0,
803 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
804 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
805 sal_uInt8 aSprmAnld[54];
807 memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) );
808 WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2); // handy pointer
810 sal_uInt8* pChars = (sal_uInt8*)(pA->rgchAnld);
811 sal_uInt16 nCharLen = 31;
813 if( nSwLevel == 11 )
814 BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
815 else
816 BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel );
818 // ... spit it out
819 OutSprmBytes( (sal_uInt8*)&aSprmAnld, sizeof( aSprmAnld ) );
823 // Return: is it an outline?
824 bool WW8Export::Out_SwNum(const SwTxtNode* pNd)
826 int nLevel = pNd->GetActualListLevel();
828 if (nLevel < 0 || nLevel >= MAXLEVEL)
830 OSL_FAIL("Invalid level");
832 return false;
835 sal_uInt8 nSwLevel = static_cast< sal_uInt8 >(nLevel);
837 const SwNumRule* pRul = pNd->GetNumRule();
838 if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
839 return false;
841 bool bRet = true;
843 SwNumFmt aFmt(pRul->Get(nSwLevel));
844 // #i86652#
845 if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
847 const SvxLRSpaceItem& rLR = ItemGet<SvxLRSpaceItem>(*pNd, RES_LR_SPACE);
848 aFmt.SetAbsLSpace(writer_cast<short>(aFmt.GetAbsLSpace() + rLR.GetLeft()));
851 if (
852 aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
853 aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
854 aFmt.GetNumberingType() == SVX_NUM_BITMAP
857 Out_WwNumLvl(11);
858 Out_NumRuleAnld(*pRul, aFmt, 11);
859 bRet = false;
861 else if (
862 pRul->IsContinusNum() ||
863 (pRul->Get(1).GetIncludeUpperLevels() <= 1)
866 Out_WwNumLvl(10);
867 Out_NumRuleAnld(*pRul, aFmt, 10);
868 bRet = false;
870 else
872 Out_SwNumLvl(nSwLevel);
873 Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
875 return bRet;
878 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */