merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / ww8 / wrtw8num.cxx
blob9f30ac7f2b22c416b21531ae284e0543ab63343d
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 $
10 * $Revision: 1.47 $
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>
40 #include <doc.hxx>
41 #include <docary.hxx>
42 #include <numrule.hxx>
43 #include <paratr.hxx>
44 #include <charfmt.hxx>
45 #include <ndtxt.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"
53 #include "wrtww8.hxx"
54 #include "ww8par.hxx"
56 //#define DUMPSYMBOLS
57 #ifdef DUMPSYMBOLS
58 #include <fstream>
59 #endif
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 );
74 // <--
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;
92 return nNumId;
95 USHORT MSWordExportBase::GetId( const SwNumRule& rNumRule )
97 if ( !pUsedNumTbl )
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() );
123 // <--
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();
132 do {
133 aResult = aRuleDuplicates.find(nRet);
134 if ( aResult != aRuleDuplicates.end() )
136 nRet = (*aResult).second;
138 } while ( aResult != aRuleDuplicates.end() );
139 // <--
141 return nRet;
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();
154 else
155 nFirstLineOffset = rFmt.GetFirstLineOffset();
156 return nFirstLineOffset;
159 void WW8Export::WriteNumbering()
161 if ( !pUsedNumTbl )
162 return; // no numbering is used
164 // list formats - LSTF
165 pFib->fcPlcfLst = pTableStrm->Tell();
166 SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->Count() );
167 NumberingDefinitions();
168 // set len to FIB
169 pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
171 // list formats - LVLF
172 AbstractNumberingDefinitions();
174 // list formats - LFO
175 OutOverrideListTab();
177 // list formats - ListNames
178 OutListNamesTab();
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() )
192 nFlags |= 0x1;
194 *m_rWW8Export.pTableStrm << nFlags << nDummy;
197 void MSWordExportBase::NumberingDefinitions()
199 if ( !pUsedNumTbl )
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*/,
214 USHORT nStart,
215 USHORT nNumberingType,
216 SvxAdjust eAdjust,
217 const BYTE *pNumLvlPos,
218 BYTE nFollow,
219 const wwFont *pFont,
220 const SfxItemSet *pOutSet,
221 sal_Int16 nIndentAt,
222 sal_Int16 nFirstLineIndex,
223 sal_Int16 nListTabPos,
224 const String &rNumberingString
227 // Start value
228 SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
230 // Type
231 *m_rWW8Export.pTableStrm << WW8Export::GetNumId( nNumberingType );
233 // Justification
234 BYTE nAlign;
235 switch ( eAdjust )
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 );
253 // cbGrpprlChpx
254 WW8Bytes aCharAtrs;
255 if ( pOutSet )
257 WW8Bytes* pOldpO = m_rWW8Export.pO;
258 m_rWW8Export.pO = &aCharAtrs;
259 if ( pFont )
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 );
269 else
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() );
280 // cbGrpprlPapx
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 ) );
288 // reserved
289 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
291 // pap sprms
292 BYTE* pData = aPapSprms + 2;
293 Set_UInt16( pData, nIndentAt );
294 pData += 2;
295 Set_UInt16( pData, nFirstLineIndex );
296 pData += 5;
297 Set_UInt16( pData, nListTabPos );
299 m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
301 // write Chpx
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();
313 USHORT n;
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 );
326 BYTE nLvl;
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 );
336 BYTE nFollow = 0;
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;
351 break;
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;
357 break;
358 case SvxNumberFormat::NOTHING:
360 nFollow = 2;
362 break;
363 default:
365 nFollow = 0;
366 ASSERT( false,
367 "unknown GetLabelFollowedBy() return value" );
371 // <--
373 // Build the NumString for this Level
374 String sNumStr;
375 String sFontName;
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();
384 bWriteBullet = true;
386 pBulletFont = rFmt.GetBulletFont();
387 if (!pBulletFont)
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
409 // <--
411 // <--
413 else
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);
421 // <--
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 );
431 ++pLvlPos;
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
445 // <--
447 // <--
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;
459 // cbGrpprlChpx
460 SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
461 RES_CHRATR_END );
462 if ( rFmt.GetCharFmt() || bWriteBullet )
464 if ( bWriteBullet )
466 pOutSet = &aSet;
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() );
479 else
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,
502 rFmt.GetStart(),
503 rFmt.GetNumberingType(),
504 rFmt.GetNumAdjust(),
505 aNumLvlPos,
506 nFollow,
507 pPseudoFont, pOutSet,
508 nIndentAt, nFirstLineIndex, nListTabPos,
509 sNumStr );
511 delete pPseudoFont;
513 AttrOutput().EndAbstractNumbering();
515 delete pConvert;
518 void WW8Export::OutOverrideListTab()
520 if( !pUsedNumTbl )
521 return ; // no numbering is used
523 // write the "list format override" - LFO
524 USHORT nCount = pUsedNumTbl->Count();
525 USHORT n;
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
538 // set len to FIB
539 pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
542 void WW8Export::OutListNamesTab()
544 if( !pUsedNumTbl )
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 );
557 String sNm;
558 if( !rRule.IsAutoRule() )
559 sNm = rRule.GetName();
561 SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
562 if (sNm.Len())
563 SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
566 SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
567 // set len to FIB
568 pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
571 /* \f */
573 // old WW95-Code
575 void WW8Export::OutputOlst( const SwNumRule& rRule )
577 if ( bWrtWW8 )
578 return;
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() );
588 WW8_OLST aOlst;
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 );
599 if( pFmt )
600 BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
601 *pFmt, (BYTE)j );
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?");
619 // <--
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:
632 nb = 2;
633 break;
634 case SVX_ADJUST_CENTER:
635 nb = 1;
636 break;
637 case SVX_ADJUST_BLOCK:
638 case SVX_ADJUST_BLOCKLINE:
639 nb = 3;
640 break;
641 case SVX_ADJUST_LEFT:
642 case SVX_ADJUST_END:
643 break;
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
652 // <--
653 ByteToSVBT8(nb, rAnlv.aBits1);
655 if (1 < rCharLen)
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();
663 // <--
664 String sNumStr = rFmt.GetBulletChar();
665 rtl_TextEncoding eChrSet = rFont.GetCharSet();
666 String sFontName = rFont.GetName();
668 USHORT nFontId;
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(),
678 eChrSet, bWrtWW8);
679 nFontId = maFontHelper.GetId(aPseudoFont);
680 *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
682 else
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) && (
695 cChar <= 0xF0FF) )
697 *rpCh = static_cast< BYTE >(cChar - 0xF000);
699 else
700 *rpCh = ByteString::ConvertFromUnicode(cChar, eChrSet);
702 rpCh++;
703 rCharLen--;
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 );
713 else
715 ShortToSVBT16( 0, rAnlv.dxaIndent );
716 ShortToSVBT16( 0, rAnlv.dxaSpace );
718 // <--
721 void MSWordExportBase::SubstituteBullet( String& rNumStr,
722 rtl_TextEncoding& rChrSet, String& rFontName ) const
724 StarSymbolToMSMultiFont *pConvert = 0;
725 FontFamily eFamily = FAMILY_DECORATIVE;
727 if (!pConvert)
729 pConvert = CreateStarSymbolToMSMultiFont();
730 #ifdef DUMPSYMBOLS
731 ::std::ofstream output("fontdebug");
732 for (sal_Unicode i=0xE000;i<0xF8FF;i++)
734 String sFont = pConvert->ConvertChar(i);
735 if (sFont.Len())
736 output << ::std::hex << i << std::endl;
738 #endif
740 sal_Unicode cChar = rNumStr.GetChar(0);
741 String sFont = pConvert->ConvertChar(cChar);
743 if (sFont.Len())
745 rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
746 rFontName = sFont;
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);
762 else
765 Well we don't have an available substition, and we're
766 in our private area, so give up and show a standard
767 bullet symbol
769 rFontName.ASSIGN_CONST_ASC("Wingdings");
770 rNumStr = static_cast< sal_Unicode >(0x6C);
772 delete pConvert;
775 static void SwWw8_InsertAnlText( const String& rStr, BYTE*& rpCh,
776 USHORT& rCharLen, SVBT8& r8Len )
778 BYTE nb = 0;
779 WW8Bytes aO;
780 SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
782 USHORT nCnt = aO.Count();
783 if( nCnt && nCnt < rCharLen )
785 nb = (BYTE)nCnt;
786 memcpy( rpCh, aO.GetData(), nCnt );
787 rpCh += 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,
795 BYTE nSwLevel)
797 ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc);
799 BYTE nb = 0;
800 switch (rFmt.GetNumAdjust())
802 case SVX_ADJUST_RIGHT:
803 nb = 2;
804 break;
805 case SVX_ADJUST_CENTER:
806 nb = 1;
807 break;
808 case SVX_ADJUST_BLOCK:
809 case SVX_ADJUST_BLOCKLINE:
810 nb = 3;
811 break;
812 case SVX_ADJUST_LEFT:
813 case SVX_ADJUST_END:
814 break;
817 bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
818 if( bInclUpper )
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 );
842 else
844 SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
845 rAnlv.cbTextBefore );
846 SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
847 rAnlv.cbTextAfter );
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 );
857 else
859 ShortToSVBT16( 0, rAnlv.dxaIndent );
860 ShortToSVBT16( 0, rAnlv.dxaSpace );
862 // <--
865 void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
866 BYTE nSwLevel )
868 static BYTE __READONLY_DATA aSprmAnldDefault[54] = {
869 12, 52,
870 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
871 0,0,0,
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 };
874 BYTE aSprmAnld[54];
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;
882 if( nSwLevel == 11 )
883 BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
884 else
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");
901 return false;
904 BYTE nSwLevel = static_cast< BYTE >(nLevel);
906 const SwNumRule* pRul = pNd->GetNumRule();
907 if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
908 return false;
910 bool bRet = true;
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()));
920 if (
921 aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
922 aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
923 aFmt.GetNumberingType() == SVX_NUM_BITMAP
926 // Aufzaehlung
927 // --> OD 2008-04-02 #refactorlists#
928 // Out_WwNumLvl(bNoNum ? 12 : 11);
929 Out_WwNumLvl(11);
930 // <--
931 Out_NumRuleAnld(*pRul, aFmt, 11);
932 bRet = false;
934 else if (
935 pRul->IsContinusNum() ||
936 (pRul->Get(1).GetIncludeUpperLevels() <= 1)
939 // Nummerierung
940 // --> OD 2008-04-02 #refactorlists#
941 // Out_WwNumLvl(bNoNum ? 12 : 10);
942 Out_WwNumLvl(10);
943 // <--
944 Out_NumRuleAnld(*pRul, aFmt, 10);
945 bRet = false;
947 else
949 // Gliederung
950 // --> OD 2008-04-02 #refactorlists#
951 // Out_SwNumLvl(bNoNum ? 12 : nSwLevel);
952 Out_SwNumLvl(nSwLevel);
953 // <--
954 Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
956 return bRet;
959 /* vi:set tabstop=4 shiftwidth=4 expandtab: */