summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/wrtw8num.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/wrtw8num.cxx')
-rw-r--r--sw/source/filter/ww8/wrtw8num.cxx959
1 files changed, 959 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
new file mode 100644
index 000000000000..6c74beb82a7b
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -0,0 +1,959 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wrtw8num.cxx,v $
+ * $Revision: 1.47 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+
+#include <hintids.hxx>
+#include <vcl/font.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <numrule.hxx>
+#include <paratr.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "ww8attributeoutput.hxx"
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+
+//#define DUMPSYMBOLS
+#ifdef DUMPSYMBOLS
+#include <fstream>
+#endif
+
+using namespace ::com::sun::star;
+using namespace sw::types;
+using namespace sw::util;
+
+USHORT MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, BYTE nLevel, USHORT nVal )
+{
+ USHORT nNumId = USHRT_MAX;
+ String sPrefix( CREATE_CONST_ASC( "WW8TempExport" ) );
+ sPrefix += String::CreateFromInt32( nUniqueList++ );
+ // --> OD 2008-02-11 #newlistlevelattrs#
+ SwNumRule* pMyNumRule =
+ new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ),
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
+ // <--
+ pUsedNumTbl->Insert( pMyNumRule, pUsedNumTbl->Count() );
+
+ for ( USHORT i = 0; i < MAXLEVEL; i++ )
+ {
+ const SwNumFmt& rSubRule = pRule->Get(i);
+ pMyNumRule->Set( i, rSubRule );
+ }
+
+ SwNumFmt aNumFmt( pMyNumRule->Get( nLevel ) );
+ aNumFmt.SetStart( nVal );
+ pMyNumRule->Set( nLevel, aNumFmt );
+
+ nNumId = GetId( *pMyNumRule );
+
+ //Map the old list to our new list
+ aRuleDuplicates[GetId( *pRule )] = nNumId;
+
+ return nNumId;
+}
+
+USHORT MSWordExportBase::GetId( const SwNumRule& rNumRule )
+{
+ if ( !pUsedNumTbl )
+ {
+ pUsedNumTbl = new SwNumRuleTbl;
+ pUsedNumTbl->Insert( &pDoc->GetNumRuleTbl(), 0 );
+ // --> OD 2005-10-17 #126238# - Check, if the outline rule is
+ // already inserted into <pUsedNumTbl>. If yes, do not insert it again.
+ bool bOutlineRuleAdded( false );
+ for ( USHORT n = pUsedNumTbl->Count(); n; )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( --n );
+ if ( !pDoc->IsUsed( rRule ) )
+ {
+ pUsedNumTbl->Remove( n );
+ }
+ else if ( &rRule == pDoc->GetOutlineNumRule() )
+ {
+ bOutlineRuleAdded = true;
+ }
+ }
+
+ if ( !bOutlineRuleAdded )
+ {
+ // jetzt noch die OutlineRule einfuegen
+ SwNumRule* pR = (SwNumRule*)pDoc->GetOutlineNumRule();
+ pUsedNumTbl->Insert( pR, pUsedNumTbl->Count() );
+ }
+ // <--
+ }
+ SwNumRule* p = (SwNumRule*)&rNumRule;
+ USHORT nRet = pUsedNumTbl->GetPos(p);
+
+ //Is this list now duplicated into a new list which we should use
+ // --> OD 2007-05-30 #i77812#
+ // perform 'deep' search in duplication map
+ ::std::map<USHORT,USHORT>::const_iterator aResult = aRuleDuplicates.end();
+ do {
+ aResult = aRuleDuplicates.find(nRet);
+ if ( aResult != aRuleDuplicates.end() )
+ {
+ nRet = (*aResult).second;
+ }
+ } while ( aResult != aRuleDuplicates.end() );
+ // <--
+
+ return nRet;
+}
+
+//GetFirstLineOffset should problem never appear unadorned apart from
+//here in the ww export filter
+sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt)
+{
+ ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
+
+ short nFirstLineOffset;
+ if (rFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
+ nFirstLineOffset = -rFmt.GetCharTextDistance();
+ else
+ nFirstLineOffset = rFmt.GetFirstLineOffset();
+ return nFirstLineOffset;
+}
+
+void WW8Export::WriteNumbering()
+{
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ // list formats - LSTF
+ pFib->fcPlcfLst = pTableStrm->Tell();
+ SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->Count() );
+ NumberingDefinitions();
+ // set len to FIB
+ pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
+
+ // list formats - LVLF
+ AbstractNumberingDefinitions();
+
+ // list formats - LFO
+ OutOverrideListTab();
+
+ // list formats - ListNames
+ OutListNamesTab();
+}
+
+void WW8AttributeOutput::NumberingDefinition( USHORT nId, const SwNumRule &rRule )
+{
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
+
+ // mit keinen Styles verbunden
+ for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0xFFF );
+
+ BYTE nFlags = 0, nDummy = 0;
+ if ( rRule.IsContinusNum() )
+ nFlags |= 0x1;
+
+ *m_rWW8Export.pTableStrm << nFlags << nDummy;
+}
+
+void MSWordExportBase::NumberingDefinitions()
+{
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ USHORT nCount = pUsedNumTbl->Count();
+
+ // Write static data of SwNumRule - LSTF
+ for ( USHORT n = 0; n < nCount; ++n )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
+
+ AttrOutput().NumberingDefinition( n + 1, rRule );
+ }
+}
+
+void WW8AttributeOutput::NumberingLevel( BYTE /*nLevel*/,
+ USHORT nStart,
+ USHORT nNumberingType,
+ SvxAdjust eAdjust,
+ const BYTE *pNumLvlPos,
+ BYTE nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString
+ )
+{
+ // Start value
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
+
+ // Type
+ *m_rWW8Export.pTableStrm << WW8Export::GetNumId( nNumberingType );
+
+ // Justification
+ BYTE nAlign;
+ switch ( eAdjust )
+ {
+ case SVX_ADJUST_CENTER: nAlign = 1; break;
+ default: nAlign = 0; break;
+ }
+ *m_rWW8Export.pTableStrm << nAlign;
+
+ // Write the rgbxchNums[9], positions of placeholders for paragraph
+ // numbers in the text
+ m_rWW8Export.pTableStrm->Write( pNumLvlPos, WW8ListManager::nMaxLevel );
+
+ // Type of the character between the bullet and the text
+ *m_rWW8Export.pTableStrm << nFollow;
+
+ // dxaSoace/dxaIndent (Word 6 compatibility)
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
+
+ // cbGrpprlChpx
+ WW8Bytes aCharAtrs;
+ if ( pOutSet )
+ {
+ WW8Bytes* pOldpO = m_rWW8Export.pO;
+ m_rWW8Export.pO = &aCharAtrs;
+ if ( pFont )
+ {
+ USHORT nFontID = m_rWW8Export.maFontHelper.GetId( *pFont );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
+ m_rWW8Export.InsUInt16( nFontID );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
+ }
+ else
+ m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nFontID );
+ }
+
+ m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN );
+
+ m_rWW8Export.pO = pOldpO;
+ }
+ *m_rWW8Export.pTableStrm << BYTE( aCharAtrs.Count() );
+
+ // cbGrpprlPapx
+ BYTE aPapSprms [] = {
+ 0x5e, 0x84, 0, 0, // sprmPDxaLeft
+ 0x60, 0x84, 0, 0, // sprmPDxaLeft1
+ 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
+ };
+ *m_rWW8Export.pTableStrm << BYTE( sizeof( aPapSprms ) );
+
+ // reserved
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
+
+ // pap sprms
+ BYTE* pData = aPapSprms + 2;
+ Set_UInt16( pData, nIndentAt );
+ pData += 2;
+ Set_UInt16( pData, nFirstLineIndex );
+ pData += 5;
+ Set_UInt16( pData, nListTabPos );
+
+ m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
+
+ // write Chpx
+ if( aCharAtrs.Count() )
+ m_rWW8Export.pTableStrm->Write( aCharAtrs.GetData(), aCharAtrs.Count() );
+
+ // write the num string
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, rNumberingString.Len() );
+ SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
+}
+
+void MSWordExportBase::AbstractNumberingDefinitions()
+{
+ USHORT nCount = pUsedNumTbl->Count();
+ USHORT n;
+
+ // prepare the NodeNum to generate the NumString
+ SwNumberTree::tNumberVector aNumVector;
+ for ( n = 0; n < WW8ListManager::nMaxLevel; ++n )
+ aNumVector.push_back( n );
+
+ StarSymbolToMSMultiFont *pConvert = 0;
+ for( n = 0; n < nCount; ++n )
+ {
+ AttrOutput().StartAbstractNumbering( n + 1 );
+
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
+ BYTE nLvl;
+ BYTE nLevels = static_cast< BYTE >(rRule.IsContinusNum() ?
+ WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
+ for( nLvl = 0; nLvl < nLevels; ++nLvl )
+ {
+ // write the static data of the SwNumFmt of this level
+ BYTE aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
+
+ const SwNumFmt& rFmt = rRule.Get( nLvl );
+
+ BYTE nFollow = 0;
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nFollow = 2; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ switch ( rFmt.GetLabelFollowedBy() )
+ {
+ case SvxNumberFormat::LISTTAB:
+ {
+ // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
+ nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 0 : 2;
+ }
+ break;
+ case SvxNumberFormat::SPACE:
+ {
+ // 1 (space) unless there would be no content before the space in which case 2 (nothing)
+ nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 1 : 2;
+ }
+ break;
+ case SvxNumberFormat::NOTHING:
+ {
+ nFollow = 2;
+ }
+ break;
+ default:
+ {
+ nFollow = 0;
+ ASSERT( false,
+ "unknown GetLabelFollowedBy() return value" );
+ }
+ }
+ }
+ // <--
+
+ // Build the NumString for this Level
+ String sNumStr;
+ String sFontName;
+ bool bWriteBullet = false;
+ const Font* pBulletFont=0;
+ rtl_TextEncoding eChrSet=0;
+ FontFamily eFamily=FAMILY_DECORATIVE;
+ if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() ||
+ SVX_NUM_BITMAP == rFmt.GetNumberingType() )
+ {
+ sNumStr = rFmt.GetBulletChar();
+ bWriteBullet = true;
+
+ pBulletFont = rFmt.GetBulletFont();
+ if (!pBulletFont)
+ {
+ pBulletFont = &numfunc::GetDefBulletFont();
+ }
+
+ eChrSet = pBulletFont->GetCharSet();
+ sFontName = pBulletFont->GetName();
+ eFamily = pBulletFont->GetFamily();
+
+ if ( sw::util::IsStarSymbol( sFontName ) )
+ SubstituteBullet( sNumStr, eChrSet, sFontName );
+
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ // --> OD 2007-07-23 #148661#
+ // <nFollow = 2>, if minimum label width equals 0 and
+ // minimum distance between label and text equals 0
+ nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
+ rFmt.GetCharTextDistance() == 0 )
+ ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ // <--
+ }
+ // <--
+ }
+ else
+ {
+ if (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType())
+ {
+ BYTE* pLvlPos = aNumLvlPos;
+ // --> OD 2005-10-17 #126238# - the numbering string
+ // has to be restrict to the level currently working on.
+ sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
+ // <--
+
+ // now search the nums in the string
+ for( BYTE i = 0; i <= nLvl; ++i )
+ {
+ String sSrch( String::CreateFromInt32( i ));
+ xub_StrLen nFnd = sNumStr.Search( sSrch );
+ if( STRING_NOTFOUND != nFnd )
+ {
+ *pLvlPos = (BYTE)(nFnd + rFmt.GetPrefix().Len() + 1 );
+ ++pLvlPos;
+ sNumStr.SetChar( nFnd, (char)i );
+ }
+ }
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ // --> OD 2007-07-23 #148661#
+ // <nFollow = 2>, if minimum label width equals 0 and
+ // minimum distance between label and text equals 0
+ nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
+ rFmt.GetCharTextDistance() == 0 )
+ ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ // <--
+ }
+ // <--
+ }
+
+ if( rFmt.GetPrefix().Len() )
+ sNumStr.Insert( rFmt.GetPrefix(), 0 );
+ sNumStr += rFmt.GetSuffix();
+ }
+
+ // Attributes of the numbering
+ wwFont *pPseudoFont = NULL;
+ const SfxItemSet* pOutSet = NULL;
+
+ // cbGrpprlChpx
+ SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
+ RES_CHRATR_END );
+ if ( rFmt.GetCharFmt() || bWriteBullet )
+ {
+ if ( bWriteBullet )
+ {
+ pOutSet = &aSet;
+
+ if ( rFmt.GetCharFmt() )
+ aSet.Put( rFmt.GetCharFmt()->GetAttrSet() );
+ aSet.ClearItem( RES_CHRATR_CJK_FONT );
+ aSet.ClearItem( RES_CHRATR_FONT );
+
+ if ( !sFontName.Len() )
+ sFontName = pBulletFont->GetName();
+
+ pPseudoFont = new wwFont( sFontName, pBulletFont->GetPitch(),
+ eFamily, eChrSet, HackIsWW8OrHigher() );
+ }
+ else
+ pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
+ }
+
+ sal_Int16 nIndentAt = 0;
+ sal_Int16 nFirstLineIndex = 0;
+ sal_Int16 nListTabPos = 0;
+
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nIndentAt = nListTabPos = rFmt.GetAbsLSpace();
+ nFirstLineIndex = GetWordFirstLineOffset(rFmt);
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nIndentAt = static_cast<sal_Int16>(rFmt.GetIndentAt());
+ nFirstLineIndex = static_cast<sal_Int16>(rFmt.GetFirstLineIndent());
+ nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
+ static_cast<sal_Int16>( rFmt.GetListtabPos() ) : 0;
+ }
+
+ AttrOutput().NumberingLevel( nLvl,
+ rFmt.GetStart(),
+ rFmt.GetNumberingType(),
+ rFmt.GetNumAdjust(),
+ aNumLvlPos,
+ nFollow,
+ pPseudoFont, pOutSet,
+ nIndentAt, nFirstLineIndex, nListTabPos,
+ sNumStr );
+
+ delete pPseudoFont;
+ }
+ AttrOutput().EndAbstractNumbering();
+ }
+ delete pConvert;
+}
+
+void WW8Export::OutOverrideListTab()
+{
+ if( !pUsedNumTbl )
+ return ; // no numbering is used
+
+ // write the "list format override" - LFO
+ USHORT nCount = pUsedNumTbl->Count();
+ USHORT n;
+
+ pFib->fcPlfLfo = pTableStrm->Tell();
+ SwWW8Writer::WriteLong( *pTableStrm, nCount );
+
+ for( n = 0; n < nCount; ++n )
+ {
+ SwWW8Writer::WriteLong( *pTableStrm, n + 1 );
+ SwWW8Writer::FillCount( *pTableStrm, 12 );
+ }
+ for( n = 0; n < nCount; ++n )
+ SwWW8Writer::WriteLong( *pTableStrm, -1 ); // no overwrite
+
+ // set len to FIB
+ pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
+}
+
+void WW8Export::OutListNamesTab()
+{
+ if( !pUsedNumTbl )
+ return ; // no numbering is used
+
+ // write the "list format override" - LFO
+ USHORT nNms = 0, nCount = pUsedNumTbl->Count();
+
+ pFib->fcSttbListNames = pTableStrm->Tell();
+ SwWW8Writer::WriteShort( *pTableStrm, -1 );
+ SwWW8Writer::WriteLong( *pTableStrm, nCount );
+
+ for( ; nNms < nCount; ++nNms )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( nNms );
+ String sNm;
+ if( !rRule.IsAutoRule() )
+ sNm = rRule.GetName();
+
+ SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
+ if (sNm.Len())
+ SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
+ }
+
+ SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
+ // set len to FIB
+ pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
+}
+
+/* */
+
+// old WW95-Code
+
+void WW8Export::OutputOlst( const SwNumRule& rRule )
+{
+ if ( bWrtWW8 )
+ return;
+
+ static BYTE __READONLY_DATA aAnlvBase[] = { // Defaults
+ 1,0,0, // Upper Roman
+ 0x0C, // Hanging Indent, fPrev
+ 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
+
+ static BYTE __READONLY_DATA aSprmOlstHdr[] = { 133, 212 };
+
+ pO->Insert( aSprmOlstHdr, sizeof( aSprmOlstHdr ), pO->Count() );
+ WW8_OLST aOlst;
+ memset( &aOlst, 0, sizeof(aOlst) );
+ BYTE* pC = aOlst.rgch;
+ BYTE* pChars = (BYTE*)pC;
+ USHORT nCharLen = 64;
+
+ for (USHORT j = 0; j < WW8ListManager::nMaxLevel; j++ ) // 9 variable ANLVs
+ {
+ memcpy( &aOlst.rganlv[j], aAnlvBase, sizeof( WW8_ANLV ) ); // Defaults
+
+ const SwNumFmt* pFmt = rRule.GetNumFmt( j );
+ if( pFmt )
+ BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
+ *pFmt, (BYTE)j );
+ }
+
+ pO->Insert( (BYTE*)&aOlst, sizeof( aOlst ), pO->Count() );
+}
+
+
+void WW8Export::Out_WwNumLvl( BYTE nWwLevel )
+{
+ pO->Insert( 13, pO->Count() );
+ pO->Insert( nWwLevel, pO->Count() );
+}
+
+void WW8Export::Out_SwNumLvl( BYTE nSwLevel )
+{
+ // --> OD 2008-04-02 #refactorlists#
+// ASSERT(IsNum(nSwLevel), "numbered?");
+ ASSERT( nSwLevel < MAXLEVEL, "numbered?");
+ // <--
+ Out_WwNumLvl( nSwLevel + 1 );
+}
+
+void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, BYTE*& rpCh,
+ USHORT& rCharLen, const SwNumFmt& rFmt)
+{
+ ByteToSVBT8(11, rAnlv.nfc);
+
+ BYTE nb = 0; // Zahlentyp
+ switch (rFmt.GetNumAdjust())
+ {
+ case SVX_ADJUST_RIGHT:
+ nb = 2;
+ break;
+ case SVX_ADJUST_CENTER:
+ nb = 1;
+ break;
+ case SVX_ADJUST_BLOCK:
+ case SVX_ADJUST_BLOCKLINE:
+ nb = 3;
+ break;
+ case SVX_ADJUST_LEFT:
+ case SVX_ADJUST_END:
+ break;
+ }
+
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if (GetWordFirstLineOffset(rFmt) < 0)
+ nb |= 0x8; // number will be displayed using a hanging indent
+ }
+ // <--
+ ByteToSVBT8(nb, rAnlv.aBits1);
+
+ if (1 < rCharLen)
+ {
+ // --> OD 2006-06-27 #b6440955#
+// const Font& rFont = rFmt.GetBulletFont() ? *rFmt.GetBulletFont()
+// : SwNumRule::GetDefBulletFont();
+ const Font& rFont = rFmt.GetBulletFont()
+ ? *rFmt.GetBulletFont()
+ : numfunc::GetDefBulletFont();
+ // <--
+ String sNumStr = rFmt.GetBulletChar();
+ rtl_TextEncoding eChrSet = rFont.GetCharSet();
+ String sFontName = rFont.GetName();
+
+ USHORT nFontId;
+ if (sw::util::IsStarSymbol(sFontName))
+ {
+ /*
+ If we are starsymbol then in ww7- mode we will always convert to a
+ windows 8bit symbol font and an index into it, to conversion to
+ 8 bit is complete at this stage.
+ */
+ SubstituteBullet(sNumStr, eChrSet, sFontName);
+ wwFont aPseudoFont(sFontName, rFont.GetPitch(), rFont.GetFamily(),
+ eChrSet, bWrtWW8);
+ nFontId = maFontHelper.GetId(aPseudoFont);
+ *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
+ }
+ else
+ {
+ /*
+ Otherwise we are a unicode char and need to be converted back to
+ an 8 bit format. We happen to know that if the font is already an
+ 8 bit windows font currently, staroffice promotes the char into
+ the F000->F0FF range, so we can undo this, and we'll be back to
+ the equivalent 8bit location, otherwise we have to convert from
+ true unicode to an 8bit charset
+ */
+ nFontId = maFontHelper.GetId(rFont);
+ sal_Unicode cChar = sNumStr.GetChar(0);
+ if ( (eChrSet == RTL_TEXTENCODING_SYMBOL) && (cChar >= 0xF000) && (
+ cChar <= 0xF0FF) )
+ {
+ *rpCh = static_cast< BYTE >(cChar - 0xF000);
+ }
+ else
+ *rpCh = ByteString::ConvertFromUnicode(cChar, eChrSet);
+ }
+ rpCh++;
+ rCharLen--;
+ ShortToSVBT16(nFontId, rAnlv.ftc);
+ ByteToSVBT8( 1, rAnlv.cbTextBefore );
+ }
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
+ ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
+ }
+ else
+ {
+ ShortToSVBT16( 0, rAnlv.dxaIndent );
+ ShortToSVBT16( 0, rAnlv.dxaSpace );
+ }
+ // <--
+}
+
+void MSWordExportBase::SubstituteBullet( String& rNumStr,
+ rtl_TextEncoding& rChrSet, String& rFontName ) const
+{
+ StarSymbolToMSMultiFont *pConvert = 0;
+ FontFamily eFamily = FAMILY_DECORATIVE;
+
+ if (!pConvert)
+ {
+ pConvert = CreateStarSymbolToMSMultiFont();
+#ifdef DUMPSYMBOLS
+ ::std::ofstream output("fontdebug");
+ for (sal_Unicode i=0xE000;i<0xF8FF;i++)
+ {
+ String sFont = pConvert->ConvertChar(i);
+ if (sFont.Len())
+ output << ::std::hex << i << std::endl;
+ }
+#endif
+ }
+ sal_Unicode cChar = rNumStr.GetChar(0);
+ String sFont = pConvert->ConvertChar(cChar);
+
+ if (sFont.Len())
+ {
+ rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
+ rFontName = sFont;
+ rChrSet = RTL_TEXTENCODING_SYMBOL;
+ }
+ else if ( HackIsWW8OrHigher() &&
+ (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) )
+ {
+ /*
+ Ok we can't fit into a known windows unicode font, but
+ we are not in the private area, so we are a
+ standardized symbol, so turn off the symbol bit and
+ let words own font substitution kick in
+ */
+ rChrSet = RTL_TEXTENCODING_UNICODE;
+ eFamily = FAMILY_SWISS;
+ rFontName = ::GetFontToken(rFontName, 0);
+ }
+ else
+ {
+ /*
+ Well we don't have an available substition, and we're
+ in our private area, so give up and show a standard
+ bullet symbol
+ */
+ rFontName.ASSIGN_CONST_ASC("Wingdings");
+ rNumStr = static_cast< sal_Unicode >(0x6C);
+ }
+ delete pConvert;
+}
+
+static void SwWw8_InsertAnlText( const String& rStr, BYTE*& rpCh,
+ USHORT& rCharLen, SVBT8& r8Len )
+{
+ BYTE nb = 0;
+ WW8Bytes aO;
+ SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
+
+ USHORT nCnt = aO.Count();
+ if( nCnt && nCnt < rCharLen )
+ {
+ nb = (BYTE)nCnt;
+ memcpy( rpCh, aO.GetData(), nCnt );
+ rpCh += nCnt;
+ rCharLen = rCharLen - nCnt;
+ }
+ ByteToSVBT8( nb, r8Len );
+}
+
+void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, BYTE*& rpCh,
+ USHORT& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt,
+ BYTE nSwLevel)
+{
+ ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc);
+
+ BYTE nb = 0;
+ switch (rFmt.GetNumAdjust())
+ {
+ case SVX_ADJUST_RIGHT:
+ nb = 2;
+ break;
+ case SVX_ADJUST_CENTER:
+ nb = 1;
+ break;
+ case SVX_ADJUST_BLOCK:
+ case SVX_ADJUST_BLOCKLINE:
+ nb = 3;
+ break;
+ case SVX_ADJUST_LEFT:
+ case SVX_ADJUST_END:
+ break;
+ }
+
+ bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
+ if( bInclUpper )
+ nb |= 0x4; // include previous levels
+
+ if (GetWordFirstLineOffset(rFmt) < 0)
+ nb |= 0x8; // number will be displayed using a hanging indent
+ ByteToSVBT8( nb, rAnlv.aBits1 );
+
+ if( bInclUpper && !rRul.IsContinusNum() )
+ {
+ if( (nSwLevel >= WW8ListManager::nMinLevel )
+ && (nSwLevel<= WW8ListManager::nMaxLevel )
+ && (rFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // UEberhaupt Nummerierung ?
+ { // -> suche, ob noch Zahlen davor
+ BYTE nUpper = rFmt.GetIncludeUpperLevels();
+ if( (nUpper <= WW8ListManager::nMaxLevel) &&
+ (rRul.Get(nUpper).GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // Nummerierung drueber ?
+ {
+ // dann Punkt einfuegen
+ SwWw8_InsertAnlText( aDotStr, rpCh, rCharLen,
+ rAnlv.cbTextBefore );
+ }
+
+ }
+ }
+ else
+ {
+ SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
+ rAnlv.cbTextBefore );
+ SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
+ rAnlv.cbTextAfter );
+ }
+
+ ShortToSVBT16( rFmt.GetStart(), rAnlv.iStartAt );
+ // --> OD 2008-06-03 #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
+ ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
+ }
+ else
+ {
+ ShortToSVBT16( 0, rAnlv.dxaIndent );
+ ShortToSVBT16( 0, rAnlv.dxaSpace );
+ }
+ // <--
+}
+
+void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
+ BYTE nSwLevel )
+{
+ static BYTE __READONLY_DATA aSprmAnldDefault[54] = {
+ 12, 52,
+ 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
+ 0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+ BYTE aSprmAnld[54];
+
+ memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) );
+ WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2); // handlicher Pointer
+
+ BYTE* pChars = (BYTE*)(pA->rgchAnld);
+ USHORT nCharLen = 31;
+
+ if( nSwLevel == 11 )
+ BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
+ else
+ BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel );
+
+ // ... und raus damit
+ OutSprmBytes( (BYTE*)&aSprmAnld, sizeof( aSprmAnld ) );
+}
+
+
+// Return: ist es eine Gliederung ?
+bool WW8Export::Out_SwNum(const SwTxtNode* pNd)
+{
+ int nLevel = pNd->GetActualListLevel();
+
+ if (nLevel < 0 || nLevel >= MAXLEVEL)
+ {
+ ASSERT(FALSE, "Invalid level");
+
+ return false;
+ }
+
+ BYTE nSwLevel = static_cast< BYTE >(nLevel);
+
+ const SwNumRule* pRul = pNd->GetNumRule();
+ if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
+ return false;
+
+ bool bRet = true;
+
+ SwNumFmt aFmt(pRul->Get(nSwLevel));
+ // --> OD 2008-06-03 #i86652#
+ if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ const SvxLRSpaceItem& rLR = ItemGet<SvxLRSpaceItem>(*pNd, RES_LR_SPACE);
+ aFmt.SetAbsLSpace(writer_cast<short>(aFmt.GetAbsLSpace() + rLR.GetLeft()));
+ }
+
+ if (
+ aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
+ aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
+ aFmt.GetNumberingType() == SVX_NUM_BITMAP
+ )
+ {
+ // Aufzaehlung
+ // --> OD 2008-04-02 #refactorlists#
+// Out_WwNumLvl(bNoNum ? 12 : 11);
+ Out_WwNumLvl(11);
+ // <--
+ Out_NumRuleAnld(*pRul, aFmt, 11);
+ bRet = false;
+ }
+ else if (
+ pRul->IsContinusNum() ||
+ (pRul->Get(1).GetIncludeUpperLevels() <= 1)
+ )
+ {
+ // Nummerierung
+ // --> OD 2008-04-02 #refactorlists#
+// Out_WwNumLvl(bNoNum ? 12 : 10);
+ Out_WwNumLvl(10);
+ // <--
+ Out_NumRuleAnld(*pRul, aFmt, 10);
+ bRet = false;
+ }
+ else
+ {
+ // Gliederung
+ // --> OD 2008-04-02 #refactorlists#
+// Out_SwNumLvl(bNoNum ? 12 : nSwLevel);
+ Out_SwNumLvl(nSwLevel);
+ // <--
+ Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
+ }
+ return bRet;
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */