1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
27 #include <numrule.hxx>
29 #include <charfmt.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"
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
;
73 sal_uInt16
MSWordExportBase::GetId( const SwNumRule
& rNumRule
)
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();
109 aResult
= aRuleDuplicates
.find(nRet
);
110 if ( aResult
!= aRuleDuplicates
.end() )
112 nRet
= (*aResult
).second
;
114 } while ( aResult
!= aRuleDuplicates
.end() );
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();
130 nFirstLineOffset
= rFmt
.GetFirstLineOffset();
131 return nFirstLineOffset
;
134 void WW8Export::WriteNumbering()
137 return; // no numbering is used
139 // list formats - LSTF
140 pFib
->fcPlcfLst
= pTableStrm
->Tell();
141 SwWW8Writer::WriteShort( *pTableStrm
, pUsedNumTbl
->size() );
142 NumberingDefinitions();
144 pFib
->lcbPlcfLst
= pTableStrm
->Tell() - pFib
->fcPlcfLst
;
146 // list formats - LVLF
147 AbstractNumberingDefinitions();
149 // list formats - LFO
150 OutOverrideListTab();
152 // list formats - ListNames
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() )
169 *m_rWW8Export
.pTableStrm
<< nFlags
<< nDummy
;
172 void MSWordExportBase::NumberingDefinitions()
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*/,
190 sal_uInt16 nNumberingType
,
192 const sal_uInt8
*pNumLvlPos
,
195 const SfxItemSet
*pOutSet
,
197 sal_Int16 nFirstLineIndex
,
198 sal_Int16 nListTabPos
,
199 const String
&rNumberingString
,
200 const SvxBrushItem
* pBrush
//For i120928,to transfer graphic of bullet
204 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, nStart
);
207 *m_rWW8Export
.pTableStrm
<< WW8Export::GetNumId( nNumberingType
);
213 case SVX_ADJUST_CENTER
:
216 case SVX_ADJUST_RIGHT
:
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 );
240 ww::bytes
* pOldpO
= m_rWW8Export
.pO
;
241 m_rWW8Export
.pO
= &aCharAtrs
;
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
);
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
);
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() );
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
) );
284 SwWW8Writer::WriteShort( *m_rWW8Export
.pTableStrm
, 0 );
287 sal_uInt8
* pData
= aPapSprms
+ 2;
288 Set_UInt16( pData
, nIndentAt
);
290 Set_UInt16( pData
, nFirstLineIndex
);
292 Set_UInt16( pData
, nListTabPos
);
294 m_rWW8Export
.pTableStrm
->Write( aPapSprms
, sizeof( aPapSprms
));
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();
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
];
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;
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;
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;
352 case SvxNumberFormat::NOTHING
:
360 OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
365 // Build the NumString for this Level
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();
378 pBulletFont
= rFmt
.GetBulletFont();
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
);
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
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 );
420 sNumStr
.SetChar( nFnd
, (char)i
);
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
;
445 SfxItemSet
aSet( pDoc
->GetAttrPool(), RES_CHRATR_BEGIN
,
447 if ( rFmt
.GetCharFmt() || bWriteBullet
)
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() );
465 pOutSet
= &rFmt
.GetCharFmt()->GetAttrSet();
468 sal_Int16 nIndentAt
= 0;
469 sal_Int16 nFirstLineIndex
= 0;
470 sal_Int16 nListTabPos
= 0;
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
,
488 rFmt
.GetNumberingType(),
492 pPseudoFont
, pOutSet
,
493 nIndentAt
, nFirstLineIndex
, nListTabPos
,
495 rFmt
.GetNumberingType()==SVX_NUM_BITMAP
? rFmt
.GetBrush():0);
499 AttrOutput().EndAbstractNumbering();
503 void WW8Export::OutOverrideListTab()
506 return ; // no numbering is used
508 // write the "list format override" - LFO
509 sal_uInt16 nCount
= pUsedNumTbl
->size();
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
524 pFib
->lcbPlfLfo
= pTableStrm
->Tell() - pFib
->fcPlfLfo
;
527 void WW8Export::OutListNamesTab()
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
];
543 if( !rRule
.IsAutoRule() )
544 sNm
= rRule
.GetName();
546 SwWW8Writer::WriteShort( *pTableStrm
, sNm
.Len() );
548 SwWW8Writer::WriteString16(*pTableStrm
, sNm
, false);
551 SwWW8Writer::WriteLong( *pTableStrm
, pFib
->fcSttbListNames
+ 2, nNms
);
553 pFib
->lcbSttbListNames
= pTableStrm
->Tell() - pFib
->fcSttbListNames
;
559 void WW8Export::OutputOlst( const SwNumRule
& rRule
)
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
) );
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
);
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
)
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
:
615 case SVX_ADJUST_CENTER
:
618 case SVX_ADJUST_BLOCK
:
619 case SVX_ADJUST_BLOCKLINE
:
622 case SVX_ADJUST_LEFT
:
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
);
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();
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(),
655 nFontId
= maFontHelper
.GetId(aPseudoFont
);
656 *rpCh
= static_cast<sal_uInt8
>(sNumStr
.GetChar(0));
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) && (
673 *rpCh
= static_cast< sal_uInt8
>(cChar
- 0xF000);
676 *rpCh
= OUStringToOString(OUString(cChar
), eChrSet
).toChar();
680 ShortToSVBT16(nFontId
, rAnlv
.ftc
);
681 ByteToSVBT8( 1, rAnlv
.cbTextBefore
);
684 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
686 ShortToSVBT16( -GetWordFirstLineOffset(rFmt
), rAnlv
.dxaIndent
);
687 ShortToSVBT16( rFmt
.GetCharTextDistance(), rAnlv
.dxaSpace
);
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
)
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
)
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
);
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
,
729 ByteToSVBT8(WW8Export::GetNumId(rFmt
.GetNumberingType()), rAnlv
.nfc
);
732 switch (rFmt
.GetNumAdjust())
734 case SVX_ADJUST_RIGHT
:
737 case SVX_ADJUST_CENTER
:
740 case SVX_ADJUST_BLOCK
:
741 case SVX_ADJUST_BLOCKLINE
:
744 case SVX_ADJUST_LEFT
:
749 bool bInclUpper
= rFmt
.GetIncludeUpperLevels() > 0;
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
);
776 SwWw8_InsertAnlText( rFmt
.GetPrefix(), rpCh
, rCharLen
,
777 rAnlv
.cbTextBefore
);
778 SwWw8_InsertAnlText( rFmt
.GetSuffix(), rpCh
, rCharLen
,
782 ShortToSVBT16( rFmt
.GetStart(), rAnlv
.iStartAt
);
784 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
786 ShortToSVBT16( -GetWordFirstLineOffset(rFmt
), rAnlv
.dxaIndent
);
787 ShortToSVBT16( rFmt
.GetCharTextDistance(), rAnlv
.dxaSpace
);
791 ShortToSVBT16( 0, rAnlv
.dxaIndent
);
792 ShortToSVBT16( 0, rAnlv
.dxaSpace
);
796 void WW8Export::Out_NumRuleAnld( const SwNumRule
& rRul
, const SwNumFmt
& rFmt
,
799 static sal_uInt8 aSprmAnldDefault
[54] = {
801 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
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;
814 BuildAnlvBulletBase( pA
->eAnlv
, pChars
, nCharLen
, rFmt
);
816 BuildAnlvBase( pA
->eAnlv
, pChars
, nCharLen
, rRul
, rFmt
, nSwLevel
);
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");
835 sal_uInt8 nSwLevel
= static_cast< sal_uInt8
>(nLevel
);
837 const SwNumRule
* pRul
= pNd
->GetNumRule();
838 if( !pRul
|| nSwLevel
== WW8ListManager::nMaxLevel
)
843 SwNumFmt
aFmt(pRul
->Get(nSwLevel
));
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()));
852 aFmt
.GetNumberingType() == SVX_NUM_NUMBER_NONE
||
853 aFmt
.GetNumberingType() == SVX_NUM_CHAR_SPECIAL
||
854 aFmt
.GetNumberingType() == SVX_NUM_BITMAP
858 Out_NumRuleAnld(*pRul
, aFmt
, 11);
862 pRul
->IsContinusNum() ||
863 (pRul
->Get(1).GetIncludeUpperLevels() <= 1)
867 Out_NumRuleAnld(*pRul
, aFmt
, 10);
872 Out_SwNumLvl(nSwLevel
);
873 Out_NumRuleAnld(*pRul
, aFmt
, nSwLevel
);
878 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */