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: wrtw8num.cxx,v $
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"
34 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <hintids.hxx>
37 #include <vcl/font.hxx>
38 #include <svx/fontitem.hxx>
39 #include <svx/lrspitem.hxx>
42 #include <numrule.hxx>
44 #include <charfmt.hxx>
46 #include <com/sun/star/i18n/ScriptType.hdl>
48 #include <writerfilter/doctok/sprmids.hxx>
50 #include "ww8attributeoutput.hxx"
51 #include "writerhelper.hxx"
52 #include "writerwordglue.hxx"
61 using namespace ::com::sun::star
;
62 using namespace sw::types
;
63 using namespace sw::util
;
65 USHORT
MSWordExportBase::DuplicateNumRule( const SwNumRule
*pRule
, BYTE nLevel
, USHORT nVal
)
67 USHORT nNumId
= USHRT_MAX
;
68 String
sPrefix( CREATE_CONST_ASC( "WW8TempExport" ) );
69 sPrefix
+= String::CreateFromInt32( nUniqueList
++ );
70 // --> OD 2008-02-11 #newlistlevelattrs#
71 SwNumRule
* pMyNumRule
=
72 new SwNumRule( pDoc
->GetUniqueNumRuleName( &sPrefix
),
73 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
);
75 pUsedNumTbl
->Insert( pMyNumRule
, pUsedNumTbl
->Count() );
77 for ( USHORT i
= 0; i
< MAXLEVEL
; i
++ )
79 const SwNumFmt
& rSubRule
= pRule
->Get(i
);
80 pMyNumRule
->Set( i
, rSubRule
);
83 SwNumFmt
aNumFmt( pMyNumRule
->Get( nLevel
) );
84 aNumFmt
.SetStart( nVal
);
85 pMyNumRule
->Set( nLevel
, aNumFmt
);
87 nNumId
= GetId( *pMyNumRule
);
89 //Map the old list to our new list
90 aRuleDuplicates
[GetId( *pRule
)] = nNumId
;
95 USHORT
MSWordExportBase::GetId( const SwNumRule
& rNumRule
)
99 pUsedNumTbl
= new SwNumRuleTbl
;
100 pUsedNumTbl
->Insert( &pDoc
->GetNumRuleTbl(), 0 );
101 // --> OD 2005-10-17 #126238# - Check, if the outline rule is
102 // already inserted into <pUsedNumTbl>. If yes, do not insert it again.
103 bool bOutlineRuleAdded( false );
104 for ( USHORT n
= pUsedNumTbl
->Count(); n
; )
106 const SwNumRule
& rRule
= *pUsedNumTbl
->GetObject( --n
);
107 if ( !pDoc
->IsUsed( rRule
) )
109 pUsedNumTbl
->Remove( n
);
111 else if ( &rRule
== pDoc
->GetOutlineNumRule() )
113 bOutlineRuleAdded
= true;
117 if ( !bOutlineRuleAdded
)
119 // jetzt noch die OutlineRule einfuegen
120 SwNumRule
* pR
= (SwNumRule
*)pDoc
->GetOutlineNumRule();
121 pUsedNumTbl
->Insert( pR
, pUsedNumTbl
->Count() );
125 SwNumRule
* p
= (SwNumRule
*)&rNumRule
;
126 USHORT nRet
= pUsedNumTbl
->GetPos(p
);
128 //Is this list now duplicated into a new list which we should use
129 // --> OD 2007-05-30 #i77812#
130 // perform 'deep' search in duplication map
131 ::std::map
<USHORT
,USHORT
>::const_iterator aResult
= aRuleDuplicates
.end();
133 aResult
= aRuleDuplicates
.find(nRet
);
134 if ( aResult
!= aRuleDuplicates
.end() )
136 nRet
= (*aResult
).second
;
138 } while ( aResult
!= aRuleDuplicates
.end() );
144 //GetFirstLineOffset should problem never appear unadorned apart from
145 //here in the ww export filter
146 sal_Int16
GetWordFirstLineOffset(const SwNumFmt
&rFmt
)
148 ASSERT( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
149 "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
151 short nFirstLineOffset
;
152 if (rFmt
.GetNumAdjust() == SVX_ADJUST_RIGHT
)
153 nFirstLineOffset
= -rFmt
.GetCharTextDistance();
155 nFirstLineOffset
= rFmt
.GetFirstLineOffset();
156 return nFirstLineOffset
;
159 void WW8Export::WriteNumbering()
162 return; // no numbering is used
164 // list formats - LSTF
165 pFib
->fcPlcfLst
= pTableStrm
->Tell();
166 SwWW8Writer::WriteShort( *pTableStrm
, pUsedNumTbl
->Count() );
167 NumberingDefinitions();
169 pFib
->lcbPlcfLst
= pTableStrm
->Tell() - pFib
->fcPlcfLst
;
171 // list formats - LVLF
172 AbstractNumberingDefinitions();
174 // list formats - LFO
175 OutOverrideListTab();
177 // list formats - ListNames
181 void WW8AttributeOutput::NumberingDefinition( USHORT nId
, const SwNumRule
&rRule
)
183 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, nId
);
184 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, nId
);
186 // mit keinen Styles verbunden
187 for ( int i
= 0; i
< WW8ListManager::nMaxLevel
; ++i
)
188 SwWW8Writer::WriteShort( *m_rWW8Export
.pTableStrm
, 0xFFF );
190 BYTE nFlags
= 0, nDummy
= 0;
191 if ( rRule
.IsContinusNum() )
194 *m_rWW8Export
.pTableStrm
<< nFlags
<< nDummy
;
197 void MSWordExportBase::NumberingDefinitions()
200 return; // no numbering is used
202 USHORT nCount
= pUsedNumTbl
->Count();
204 // Write static data of SwNumRule - LSTF
205 for ( USHORT n
= 0; n
< nCount
; ++n
)
207 const SwNumRule
& rRule
= *pUsedNumTbl
->GetObject( n
);
209 AttrOutput().NumberingDefinition( n
+ 1, rRule
);
213 void WW8AttributeOutput::NumberingLevel( BYTE
/*nLevel*/,
215 USHORT nNumberingType
,
217 const BYTE
*pNumLvlPos
,
220 const SfxItemSet
*pOutSet
,
222 sal_Int16 nFirstLineIndex
,
223 sal_Int16 nListTabPos
,
224 const String
&rNumberingString
228 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, nStart
);
231 *m_rWW8Export
.pTableStrm
<< WW8Export::GetNumId( nNumberingType
);
237 case SVX_ADJUST_CENTER
: nAlign
= 1; break;
238 default: nAlign
= 0; break;
240 *m_rWW8Export
.pTableStrm
<< nAlign
;
242 // Write the rgbxchNums[9], positions of placeholders for paragraph
243 // numbers in the text
244 m_rWW8Export
.pTableStrm
->Write( pNumLvlPos
, WW8ListManager::nMaxLevel
);
246 // Type of the character between the bullet and the text
247 *m_rWW8Export
.pTableStrm
<< nFollow
;
249 // dxaSoace/dxaIndent (Word 6 compatibility)
250 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, 0 );
251 SwWW8Writer::WriteLong( *m_rWW8Export
.pTableStrm
, 0 );
257 WW8Bytes
* pOldpO
= m_rWW8Export
.pO
;
258 m_rWW8Export
.pO
= &aCharAtrs
;
261 USHORT nFontID
= m_rWW8Export
.maFontHelper
.GetId( *pFont
);
263 if ( m_rWW8Export
.bWrtWW8
)
265 m_rWW8Export
.InsUInt16( NS_sprm::LN_CRgFtc0
);
266 m_rWW8Export
.InsUInt16( nFontID
);
267 m_rWW8Export
.InsUInt16( NS_sprm::LN_CRgFtc2
);
270 m_rWW8Export
.pO
->Insert( 93, m_rWW8Export
.pO
->Count() );
271 m_rWW8Export
.InsUInt16( nFontID
);
274 m_rWW8Export
.OutputItemSet( *pOutSet
, false, true, i18n::ScriptType::LATIN
);
276 m_rWW8Export
.pO
= pOldpO
;
278 *m_rWW8Export
.pTableStrm
<< BYTE( aCharAtrs
.Count() );
281 BYTE aPapSprms
[] = {
282 0x5e, 0x84, 0, 0, // sprmPDxaLeft
283 0x60, 0x84, 0, 0, // sprmPDxaLeft1
284 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
286 *m_rWW8Export
.pTableStrm
<< BYTE( sizeof( aPapSprms
) );
289 SwWW8Writer::WriteShort( *m_rWW8Export
.pTableStrm
, 0 );
292 BYTE
* pData
= aPapSprms
+ 2;
293 Set_UInt16( pData
, nIndentAt
);
295 Set_UInt16( pData
, nFirstLineIndex
);
297 Set_UInt16( pData
, nListTabPos
);
299 m_rWW8Export
.pTableStrm
->Write( aPapSprms
, sizeof( aPapSprms
));
302 if( aCharAtrs
.Count() )
303 m_rWW8Export
.pTableStrm
->Write( aCharAtrs
.GetData(), aCharAtrs
.Count() );
305 // write the num string
306 SwWW8Writer::WriteShort( *m_rWW8Export
.pTableStrm
, rNumberingString
.Len() );
307 SwWW8Writer::WriteString16( *m_rWW8Export
.pTableStrm
, rNumberingString
, false );
310 void MSWordExportBase::AbstractNumberingDefinitions()
312 USHORT nCount
= pUsedNumTbl
->Count();
315 // prepare the NodeNum to generate the NumString
316 SwNumberTree::tNumberVector aNumVector
;
317 for ( n
= 0; n
< WW8ListManager::nMaxLevel
; ++n
)
318 aNumVector
.push_back( n
);
320 StarSymbolToMSMultiFont
*pConvert
= 0;
321 for( n
= 0; n
< nCount
; ++n
)
323 AttrOutput().StartAbstractNumbering( n
+ 1 );
325 const SwNumRule
& rRule
= *pUsedNumTbl
->GetObject( n
);
327 BYTE nLevels
= static_cast< BYTE
>(rRule
.IsContinusNum() ?
328 WW8ListManager::nMinLevel
: WW8ListManager::nMaxLevel
);
329 for( nLvl
= 0; nLvl
< nLevels
; ++nLvl
)
331 // write the static data of the SwNumFmt of this level
332 BYTE aNumLvlPos
[WW8ListManager::nMaxLevel
] = { 0,0,0,0,0,0,0,0,0 };
334 const SwNumFmt
& rFmt
= rRule
.Get( nLvl
);
337 // --> OD 2008-06-03 #i86652#
338 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
340 nFollow
= 2; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
342 else if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
344 switch ( rFmt
.GetLabelFollowedBy() )
346 case SvxNumberFormat::LISTTAB
:
348 // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
349 nFollow
= (SVX_NUM_NUMBER_NONE
!= rFmt
.GetNumberingType()) ? 0 : 2;
352 case SvxNumberFormat::SPACE
:
354 // 1 (space) unless there would be no content before the space in which case 2 (nothing)
355 nFollow
= (SVX_NUM_NUMBER_NONE
!= rFmt
.GetNumberingType()) ? 1 : 2;
358 case SvxNumberFormat::NOTHING
:
367 "unknown GetLabelFollowedBy() return value" );
373 // Build the NumString for this Level
376 bool bWriteBullet
= false;
377 const Font
* pBulletFont
=0;
378 rtl_TextEncoding eChrSet
=0;
379 FontFamily eFamily
=FAMILY_DECORATIVE
;
380 if( SVX_NUM_CHAR_SPECIAL
== rFmt
.GetNumberingType() ||
381 SVX_NUM_BITMAP
== rFmt
.GetNumberingType() )
383 sNumStr
= rFmt
.GetBulletChar();
386 pBulletFont
= rFmt
.GetBulletFont();
389 pBulletFont
= &numfunc::GetDefBulletFont();
392 eChrSet
= pBulletFont
->GetCharSet();
393 sFontName
= pBulletFont
->GetName();
394 eFamily
= pBulletFont
->GetFamily();
396 if ( sw::util::IsStarSymbol( sFontName
) )
397 SubstituteBullet( sNumStr
, eChrSet
, sFontName
);
399 // --> OD 2008-06-03 #i86652#
400 if ( rFmt
.GetPositionAndSpaceMode() ==
401 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
403 // --> OD 2007-07-23 #148661#
404 // <nFollow = 2>, if minimum label width equals 0 and
405 // minimum distance between label and text equals 0
406 nFollow
= ( rFmt
.GetFirstLineOffset() == 0 &&
407 rFmt
.GetCharTextDistance() == 0 )
408 ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
415 if (SVX_NUM_NUMBER_NONE
!= rFmt
.GetNumberingType())
417 BYTE
* pLvlPos
= aNumLvlPos
;
418 // --> OD 2005-10-17 #126238# - the numbering string
419 // has to be restrict to the level currently working on.
420 sNumStr
= rRule
.MakeNumString(aNumVector
, false, true, nLvl
);
423 // now search the nums in the string
424 for( BYTE i
= 0; i
<= nLvl
; ++i
)
426 String
sSrch( String::CreateFromInt32( i
));
427 xub_StrLen nFnd
= sNumStr
.Search( sSrch
);
428 if( STRING_NOTFOUND
!= nFnd
)
430 *pLvlPos
= (BYTE
)(nFnd
+ rFmt
.GetPrefix().Len() + 1 );
432 sNumStr
.SetChar( nFnd
, (char)i
);
435 // --> OD 2008-06-03 #i86652#
436 if ( rFmt
.GetPositionAndSpaceMode() ==
437 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
439 // --> OD 2007-07-23 #148661#
440 // <nFollow = 2>, if minimum label width equals 0 and
441 // minimum distance between label and text equals 0
442 nFollow
= ( rFmt
.GetFirstLineOffset() == 0 &&
443 rFmt
.GetCharTextDistance() == 0 )
444 ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
450 if( rFmt
.GetPrefix().Len() )
451 sNumStr
.Insert( rFmt
.GetPrefix(), 0 );
452 sNumStr
+= rFmt
.GetSuffix();
455 // Attributes of the numbering
456 wwFont
*pPseudoFont
= NULL
;
457 const SfxItemSet
* pOutSet
= NULL
;
460 SfxItemSet
aSet( pDoc
->GetAttrPool(), RES_CHRATR_BEGIN
,
462 if ( rFmt
.GetCharFmt() || bWriteBullet
)
468 if ( rFmt
.GetCharFmt() )
469 aSet
.Put( rFmt
.GetCharFmt()->GetAttrSet() );
470 aSet
.ClearItem( RES_CHRATR_CJK_FONT
);
471 aSet
.ClearItem( RES_CHRATR_FONT
);
473 if ( !sFontName
.Len() )
474 sFontName
= pBulletFont
->GetName();
476 pPseudoFont
= new wwFont( sFontName
, pBulletFont
->GetPitch(),
477 eFamily
, eChrSet
, HackIsWW8OrHigher() );
480 pOutSet
= &rFmt
.GetCharFmt()->GetAttrSet();
483 sal_Int16 nIndentAt
= 0;
484 sal_Int16 nFirstLineIndex
= 0;
485 sal_Int16 nListTabPos
= 0;
487 // --> OD 2008-06-03 #i86652#
488 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
490 nIndentAt
= nListTabPos
= rFmt
.GetAbsLSpace();
491 nFirstLineIndex
= GetWordFirstLineOffset(rFmt
);
493 else if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
495 nIndentAt
= static_cast<sal_Int16
>(rFmt
.GetIndentAt());
496 nFirstLineIndex
= static_cast<sal_Int16
>(rFmt
.GetFirstLineIndent());
497 nListTabPos
= rFmt
.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB
?
498 static_cast<sal_Int16
>( rFmt
.GetListtabPos() ) : 0;
501 AttrOutput().NumberingLevel( nLvl
,
503 rFmt
.GetNumberingType(),
507 pPseudoFont
, pOutSet
,
508 nIndentAt
, nFirstLineIndex
, nListTabPos
,
513 AttrOutput().EndAbstractNumbering();
518 void WW8Export::OutOverrideListTab()
521 return ; // no numbering is used
523 // write the "list format override" - LFO
524 USHORT nCount
= pUsedNumTbl
->Count();
527 pFib
->fcPlfLfo
= pTableStrm
->Tell();
528 SwWW8Writer::WriteLong( *pTableStrm
, nCount
);
530 for( n
= 0; n
< nCount
; ++n
)
532 SwWW8Writer::WriteLong( *pTableStrm
, n
+ 1 );
533 SwWW8Writer::FillCount( *pTableStrm
, 12 );
535 for( n
= 0; n
< nCount
; ++n
)
536 SwWW8Writer::WriteLong( *pTableStrm
, -1 ); // no overwrite
539 pFib
->lcbPlfLfo
= pTableStrm
->Tell() - pFib
->fcPlfLfo
;
542 void WW8Export::OutListNamesTab()
545 return ; // no numbering is used
547 // write the "list format override" - LFO
548 USHORT nNms
= 0, nCount
= pUsedNumTbl
->Count();
550 pFib
->fcSttbListNames
= pTableStrm
->Tell();
551 SwWW8Writer::WriteShort( *pTableStrm
, -1 );
552 SwWW8Writer::WriteLong( *pTableStrm
, nCount
);
554 for( ; nNms
< nCount
; ++nNms
)
556 const SwNumRule
& rRule
= *pUsedNumTbl
->GetObject( nNms
);
558 if( !rRule
.IsAutoRule() )
559 sNm
= rRule
.GetName();
561 SwWW8Writer::WriteShort( *pTableStrm
, sNm
.Len() );
563 SwWW8Writer::WriteString16(*pTableStrm
, sNm
, false);
566 SwWW8Writer::WriteLong( *pTableStrm
, pFib
->fcSttbListNames
+ 2, nNms
);
568 pFib
->lcbSttbListNames
= pTableStrm
->Tell() - pFib
->fcSttbListNames
;
575 void WW8Export::OutputOlst( const SwNumRule
& rRule
)
580 static BYTE __READONLY_DATA aAnlvBase
[] = { // Defaults
581 1,0,0, // Upper Roman
582 0x0C, // Hanging Indent, fPrev
583 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
585 static BYTE __READONLY_DATA aSprmOlstHdr
[] = { 133, 212 };
587 pO
->Insert( aSprmOlstHdr
, sizeof( aSprmOlstHdr
), pO
->Count() );
589 memset( &aOlst
, 0, sizeof(aOlst
) );
590 BYTE
* pC
= aOlst
.rgch
;
591 BYTE
* pChars
= (BYTE
*)pC
;
592 USHORT nCharLen
= 64;
594 for (USHORT j
= 0; j
< WW8ListManager::nMaxLevel
; j
++ ) // 9 variable ANLVs
596 memcpy( &aOlst
.rganlv
[j
], aAnlvBase
, sizeof( WW8_ANLV
) ); // Defaults
598 const SwNumFmt
* pFmt
= rRule
.GetNumFmt( j
);
600 BuildAnlvBase( aOlst
.rganlv
[j
], pChars
, nCharLen
, rRule
,
604 pO
->Insert( (BYTE
*)&aOlst
, sizeof( aOlst
), pO
->Count() );
608 void WW8Export::Out_WwNumLvl( BYTE nWwLevel
)
610 pO
->Insert( 13, pO
->Count() );
611 pO
->Insert( nWwLevel
, pO
->Count() );
614 void WW8Export::Out_SwNumLvl( BYTE nSwLevel
)
616 // --> OD 2008-04-02 #refactorlists#
617 // ASSERT(IsNum(nSwLevel), "numbered?");
618 ASSERT( nSwLevel
< MAXLEVEL
, "numbered?");
620 Out_WwNumLvl( nSwLevel
+ 1 );
623 void WW8Export::BuildAnlvBulletBase(WW8_ANLV
& rAnlv
, BYTE
*& rpCh
,
624 USHORT
& rCharLen
, const SwNumFmt
& rFmt
)
626 ByteToSVBT8(11, rAnlv
.nfc
);
628 BYTE nb
= 0; // Zahlentyp
629 switch (rFmt
.GetNumAdjust())
631 case SVX_ADJUST_RIGHT
:
634 case SVX_ADJUST_CENTER
:
637 case SVX_ADJUST_BLOCK
:
638 case SVX_ADJUST_BLOCKLINE
:
641 case SVX_ADJUST_LEFT
:
646 // --> OD 2008-06-03 #i86652#
647 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
649 if (GetWordFirstLineOffset(rFmt
) < 0)
650 nb
|= 0x8; // number will be displayed using a hanging indent
653 ByteToSVBT8(nb
, rAnlv
.aBits1
);
657 // --> OD 2006-06-27 #b6440955#
658 // const Font& rFont = rFmt.GetBulletFont() ? *rFmt.GetBulletFont()
659 // : SwNumRule::GetDefBulletFont();
660 const Font
& rFont
= rFmt
.GetBulletFont()
661 ? *rFmt
.GetBulletFont()
662 : numfunc::GetDefBulletFont();
664 String sNumStr
= rFmt
.GetBulletChar();
665 rtl_TextEncoding eChrSet
= rFont
.GetCharSet();
666 String sFontName
= rFont
.GetName();
669 if (sw::util::IsStarSymbol(sFontName
))
672 If we are starsymbol then in ww7- mode we will always convert to a
673 windows 8bit symbol font and an index into it, to conversion to
674 8 bit is complete at this stage.
676 SubstituteBullet(sNumStr
, eChrSet
, sFontName
);
677 wwFont
aPseudoFont(sFontName
, rFont
.GetPitch(), rFont
.GetFamily(),
679 nFontId
= maFontHelper
.GetId(aPseudoFont
);
680 *rpCh
= static_cast<sal_uInt8
>(sNumStr
.GetChar(0));
685 Otherwise we are a unicode char and need to be converted back to
686 an 8 bit format. We happen to know that if the font is already an
687 8 bit windows font currently, staroffice promotes the char into
688 the F000->F0FF range, so we can undo this, and we'll be back to
689 the equivalent 8bit location, otherwise we have to convert from
690 true unicode to an 8bit charset
692 nFontId
= maFontHelper
.GetId(rFont
);
693 sal_Unicode cChar
= sNumStr
.GetChar(0);
694 if ( (eChrSet
== RTL_TEXTENCODING_SYMBOL
) && (cChar
>= 0xF000) && (
697 *rpCh
= static_cast< BYTE
>(cChar
- 0xF000);
700 *rpCh
= ByteString::ConvertFromUnicode(cChar
, eChrSet
);
704 ShortToSVBT16(nFontId
, rAnlv
.ftc
);
705 ByteToSVBT8( 1, rAnlv
.cbTextBefore
);
707 // --> OD 2008-06-03 #i86652#
708 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
710 ShortToSVBT16( -GetWordFirstLineOffset(rFmt
), rAnlv
.dxaIndent
);
711 ShortToSVBT16( rFmt
.GetCharTextDistance(), rAnlv
.dxaSpace
);
715 ShortToSVBT16( 0, rAnlv
.dxaIndent
);
716 ShortToSVBT16( 0, rAnlv
.dxaSpace
);
721 void MSWordExportBase::SubstituteBullet( String
& rNumStr
,
722 rtl_TextEncoding
& rChrSet
, String
& rFontName
) const
724 StarSymbolToMSMultiFont
*pConvert
= 0;
725 FontFamily eFamily
= FAMILY_DECORATIVE
;
729 pConvert
= CreateStarSymbolToMSMultiFont();
731 ::std::ofstream
output("fontdebug");
732 for (sal_Unicode i
=0xE000;i
<0xF8FF;i
++)
734 String sFont
= pConvert
->ConvertChar(i
);
736 output
<< ::std::hex
<< i
<< std::endl
;
740 sal_Unicode cChar
= rNumStr
.GetChar(0);
741 String sFont
= pConvert
->ConvertChar(cChar
);
745 rNumStr
= static_cast< sal_Unicode
>(cChar
| 0xF000);
747 rChrSet
= RTL_TEXTENCODING_SYMBOL
;
749 else if ( HackIsWW8OrHigher() &&
750 (rNumStr
.GetChar(0) < 0xE000 || rNumStr
.GetChar(0) > 0xF8FF) )
753 Ok we can't fit into a known windows unicode font, but
754 we are not in the private area, so we are a
755 standardized symbol, so turn off the symbol bit and
756 let words own font substitution kick in
758 rChrSet
= RTL_TEXTENCODING_UNICODE
;
759 eFamily
= FAMILY_SWISS
;
760 rFontName
= ::GetFontToken(rFontName
, 0);
765 Well we don't have an available substition, and we're
766 in our private area, so give up and show a standard
769 rFontName
.ASSIGN_CONST_ASC("Wingdings");
770 rNumStr
= static_cast< sal_Unicode
>(0x6C);
775 static void SwWw8_InsertAnlText( const String
& rStr
, BYTE
*& rpCh
,
776 USHORT
& rCharLen
, SVBT8
& r8Len
)
780 SwWW8Writer::InsAsString8( aO
, rStr
, RTL_TEXTENCODING_MS_1252
);
782 USHORT nCnt
= aO
.Count();
783 if( nCnt
&& nCnt
< rCharLen
)
786 memcpy( rpCh
, aO
.GetData(), nCnt
);
788 rCharLen
= rCharLen
- nCnt
;
790 ByteToSVBT8( nb
, r8Len
);
793 void WW8Export::BuildAnlvBase(WW8_ANLV
& rAnlv
, BYTE
*& rpCh
,
794 USHORT
& rCharLen
, const SwNumRule
& rRul
, const SwNumFmt
& rFmt
,
797 ByteToSVBT8(WW8Export::GetNumId(rFmt
.GetNumberingType()), rAnlv
.nfc
);
800 switch (rFmt
.GetNumAdjust())
802 case SVX_ADJUST_RIGHT
:
805 case SVX_ADJUST_CENTER
:
808 case SVX_ADJUST_BLOCK
:
809 case SVX_ADJUST_BLOCKLINE
:
812 case SVX_ADJUST_LEFT
:
817 bool bInclUpper
= rFmt
.GetIncludeUpperLevels() > 0;
819 nb
|= 0x4; // include previous levels
821 if (GetWordFirstLineOffset(rFmt
) < 0)
822 nb
|= 0x8; // number will be displayed using a hanging indent
823 ByteToSVBT8( nb
, rAnlv
.aBits1
);
825 if( bInclUpper
&& !rRul
.IsContinusNum() )
827 if( (nSwLevel
>= WW8ListManager::nMinLevel
)
828 && (nSwLevel
<= WW8ListManager::nMaxLevel
)
829 && (rFmt
.GetNumberingType() != SVX_NUM_NUMBER_NONE
) ) // UEberhaupt Nummerierung ?
830 { // -> suche, ob noch Zahlen davor
831 BYTE nUpper
= rFmt
.GetIncludeUpperLevels();
832 if( (nUpper
<= WW8ListManager::nMaxLevel
) &&
833 (rRul
.Get(nUpper
).GetNumberingType() != SVX_NUM_NUMBER_NONE
) ) // Nummerierung drueber ?
835 // dann Punkt einfuegen
836 SwWw8_InsertAnlText( aDotStr
, rpCh
, rCharLen
,
837 rAnlv
.cbTextBefore
);
844 SwWw8_InsertAnlText( rFmt
.GetPrefix(), rpCh
, rCharLen
,
845 rAnlv
.cbTextBefore
);
846 SwWw8_InsertAnlText( rFmt
.GetSuffix(), rpCh
, rCharLen
,
850 ShortToSVBT16( rFmt
.GetStart(), rAnlv
.iStartAt
);
851 // --> OD 2008-06-03 #i86652#
852 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
854 ShortToSVBT16( -GetWordFirstLineOffset(rFmt
), rAnlv
.dxaIndent
);
855 ShortToSVBT16( rFmt
.GetCharTextDistance(), rAnlv
.dxaSpace
);
859 ShortToSVBT16( 0, rAnlv
.dxaIndent
);
860 ShortToSVBT16( 0, rAnlv
.dxaSpace
);
865 void WW8Export::Out_NumRuleAnld( const SwNumRule
& rRul
, const SwNumFmt
& rFmt
,
868 static BYTE __READONLY_DATA aSprmAnldDefault
[54] = {
870 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
872 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
873 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
876 memcpy( aSprmAnld
, aSprmAnldDefault
, sizeof( aSprmAnld
) );
877 WW8_ANLD
* pA
= (WW8_ANLD
*)(aSprmAnld
+ 2); // handlicher Pointer
879 BYTE
* pChars
= (BYTE
*)(pA
->rgchAnld
);
880 USHORT nCharLen
= 31;
883 BuildAnlvBulletBase( pA
->eAnlv
, pChars
, nCharLen
, rFmt
);
885 BuildAnlvBase( pA
->eAnlv
, pChars
, nCharLen
, rRul
, rFmt
, nSwLevel
);
887 // ... und raus damit
888 OutSprmBytes( (BYTE
*)&aSprmAnld
, sizeof( aSprmAnld
) );
892 // Return: ist es eine Gliederung ?
893 bool WW8Export::Out_SwNum(const SwTxtNode
* pNd
)
895 int nLevel
= pNd
->GetActualListLevel();
897 if (nLevel
< 0 || nLevel
>= MAXLEVEL
)
899 ASSERT(FALSE
, "Invalid level");
904 BYTE nSwLevel
= static_cast< BYTE
>(nLevel
);
906 const SwNumRule
* pRul
= pNd
->GetNumRule();
907 if( !pRul
|| nSwLevel
== WW8ListManager::nMaxLevel
)
912 SwNumFmt
aFmt(pRul
->Get(nSwLevel
));
913 // --> OD 2008-06-03 #i86652#
914 if ( aFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
916 const SvxLRSpaceItem
& rLR
= ItemGet
<SvxLRSpaceItem
>(*pNd
, RES_LR_SPACE
);
917 aFmt
.SetAbsLSpace(writer_cast
<short>(aFmt
.GetAbsLSpace() + rLR
.GetLeft()));
921 aFmt
.GetNumberingType() == SVX_NUM_NUMBER_NONE
||
922 aFmt
.GetNumberingType() == SVX_NUM_CHAR_SPECIAL
||
923 aFmt
.GetNumberingType() == SVX_NUM_BITMAP
927 // --> OD 2008-04-02 #refactorlists#
928 // Out_WwNumLvl(bNoNum ? 12 : 11);
931 Out_NumRuleAnld(*pRul
, aFmt
, 11);
935 pRul
->IsContinusNum() ||
936 (pRul
->Get(1).GetIncludeUpperLevels() <= 1)
940 // --> OD 2008-04-02 #refactorlists#
941 // Out_WwNumLvl(bNoNum ? 12 : 10);
944 Out_NumRuleAnld(*pRul
, aFmt
, 10);
950 // --> OD 2008-04-02 #refactorlists#
951 // Out_SwNumLvl(bNoNum ? 12 : nSwLevel);
952 Out_SwNumLvl(nSwLevel
);
954 Out_NumRuleAnld(*pRul
, aFmt
, nSwLevel
);
959 /* vi:set tabstop=4 shiftwidth=4 expandtab: */