/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include "ww8attributeoutput.hxx" #include "writerhelper.hxx" #include "writerwordglue.hxx" #include "wrtww8.hxx" #include "ww8par.hxx" using namespace ::com::sun::star; using namespace sw::types; using namespace sw::util; sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal ) { sal_uInt16 nNumId = USHRT_MAX; String sPrefix( CREATE_CONST_ASC( "WW8TempExport" ) ); sPrefix += String::CreateFromInt32( nUniqueList++ ); SwNumRule* pMyNumRule = new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ), SvxNumberFormat::LABEL_WIDTH_AND_POSITION ); pUsedNumTbl->Insert( pMyNumRule, pUsedNumTbl->Count() ); for ( sal_uInt16 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; } sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule ) { if ( !pUsedNumTbl ) { pUsedNumTbl = new SwNumRuleTbl; pUsedNumTbl->Insert( &pDoc->GetNumRuleTbl(), 0 ); // Check, if the outline rule is already inserted into . // If yes, do not insert it again. bool bOutlineRuleAdded( false ); for ( sal_uInt16 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; sal_uInt16 nRet = pUsedNumTbl->GetPos(p); //Is this list now duplicated into a new list which we should use // #i77812# - perform 'deep' search in duplication map ::std::map::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) { OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION, " - 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( sal_uInt16 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 ); sal_uInt8 nFlags = 0, nDummy = 0; if ( rRule.IsContinusNum() ) nFlags |= 0x1; *m_rWW8Export.pTableStrm << nFlags << nDummy; } void MSWordExportBase::NumberingDefinitions() { if ( !pUsedNumTbl ) return; // no numbering is used sal_uInt16 nCount = pUsedNumTbl->Count(); // Write static data of SwNumRule - LSTF for ( sal_uInt16 n = 0; n < nCount; ++n ) { const SwNumRule& rRule = *pUsedNumTbl->GetObject( n ); AttrOutput().NumberingDefinition( n + 1, rRule ); } } void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/, sal_uInt16 nStart, sal_uInt16 nNumberingType, SvxAdjust eAdjust, const sal_uInt8 *pNumLvlPos, sal_uInt8 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 sal_uInt8 nAlign; switch ( eAdjust ) { case SVX_ADJUST_CENTER: nAlign = 1; break; case SVX_ADJUST_RIGHT: nAlign = 2; 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 ) { sal_uInt16 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.mbExportModeRTF ); m_rWW8Export.pO = pOldpO; } *m_rWW8Export.pTableStrm << sal_uInt8( aCharAtrs.Count() ); // cbGrpprlPapx sal_uInt8 aPapSprms [] = { 0x5e, 0x84, 0, 0, // sprmPDxaLeft 0x60, 0x84, 0, 0, // sprmPDxaLeft1 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06 }; *m_rWW8Export.pTableStrm << sal_uInt8( sizeof( aPapSprms ) ); // reserved SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 ); // pap sprms sal_uInt8* 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() { sal_uInt16 nCount = pUsedNumTbl->Count(); sal_uInt16 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 ); sal_uInt8 nLvl; sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ? WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel); for( nLvl = 0; nLvl < nLevels; ++nLvl ) { // write the static data of the SwNumFmt of this level sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 }; const SwNumFmt& rFmt = rRule.Get( nLvl ); sal_uInt8 nFollow = 0; // #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; OSL_FAIL( "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 ); // #i86652# if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) { // , 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()) { sal_uInt8* pLvlPos = aNumLvlPos; // 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( sal_uInt8 i = 0; i <= nLvl; ++i ) { String sSrch( String::CreateFromInt32( i )); xub_StrLen nFnd = sNumStr.Search( sSrch ); if( STRING_NOTFOUND != nFnd ) { *pLvlPos = (sal_uInt8)(nFnd + rFmt.GetPrefix().Len() + 1 ); ++pLvlPos; sNumStr.SetChar( nFnd, (char)i ); } } // #i86652# if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) { // , 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, SupportsUnicode() ); } else pOutSet = &rFmt.GetCharFmt()->GetAttrSet(); } sal_Int16 nIndentAt = 0; sal_Int16 nFirstLineIndex = 0; sal_Int16 nListTabPos = 0; // #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(rFmt.GetIndentAt()); nFirstLineIndex = static_cast(rFmt.GetFirstLineIndent()); nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB? static_cast( 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 sal_uInt16 nCount = pUsedNumTbl->Count(); sal_uInt16 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 sal_uInt16 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 sal_uInt8 aAnlvBase[] = { // Defaults 1,0,0, // Upper Roman 0x0C, // Hanging Indent, fPrev 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 }; static sal_uInt8 aSprmOlstHdr[] = { 133, 212 }; pO->Insert( aSprmOlstHdr, sizeof( aSprmOlstHdr ), pO->Count() ); WW8_OLST aOlst; memset( &aOlst, 0, sizeof(aOlst) ); sal_uInt8* pC = aOlst.rgch; sal_uInt8* pChars = (sal_uInt8*)pC; sal_uInt16 nCharLen = 64; for (sal_uInt16 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, (sal_uInt8)j ); } pO->Insert( (sal_uInt8*)&aOlst, sizeof( aOlst ), pO->Count() ); } void WW8Export::Out_WwNumLvl( sal_uInt8 nWwLevel ) { pO->Insert( 13, pO->Count() ); pO->Insert( nWwLevel, pO->Count() ); } void WW8Export::Out_SwNumLvl( sal_uInt8 nSwLevel ) { OSL_ENSURE( nSwLevel < MAXLEVEL, "numbered?"); Out_WwNumLvl( nSwLevel + 1 ); } void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh, sal_uInt16& rCharLen, const SwNumFmt& rFmt) { ByteToSVBT8(11, rAnlv.nfc); sal_uInt8 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; } // #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) { const Font& rFont = rFmt.GetBulletFont() ? *rFmt.GetBulletFont() : numfunc::GetDefBulletFont(); String sNumStr = rFmt.GetBulletChar(); rtl_TextEncoding eChrSet = rFont.GetCharSet(); String sFontName = rFont.GetName(); sal_uInt16 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(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< sal_uInt8 >(cChar - 0xF000); } else *rpCh = rtl::OUStringToOString(rtl::OUString(cChar), eChrSet).toChar(); } rpCh++; rCharLen--; ShortToSVBT16(nFontId, rAnlv.ftc); ByteToSVBT8( 1, rAnlv.cbTextBefore ); } // #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; if (!bSubstituteBullets) return; if (!bSubstituteBullets) return; if (!pConvert) { pConvert = CreateStarSymbolToMSMultiFont(); } 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 ( SupportsUnicode() && (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; 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, sal_uInt8*& rpCh, sal_uInt16& rCharLen, SVBT8& r8Len ) { sal_uInt8 nb = 0; WW8Bytes aO; SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 ); sal_uInt16 nCnt = aO.Count(); if( nCnt && nCnt < rCharLen ) { nb = (sal_uInt8)nCnt; memcpy( rpCh, aO.GetData(), nCnt ); rpCh += nCnt; rCharLen = rCharLen - nCnt; } ByteToSVBT8( nb, r8Len ); } void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh, sal_uInt16& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt, sal_uInt8 nSwLevel) { ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc); sal_uInt8 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 sal_uInt8 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 ); // #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, sal_uInt8 nSwLevel ) { static sal_uInt8 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 }; sal_uInt8 aSprmAnld[54]; memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) ); WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2); // handlicher Pointer sal_uInt8* pChars = (sal_uInt8*)(pA->rgchAnld); sal_uInt16 nCharLen = 31; if( nSwLevel == 11 ) BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt ); else BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel ); // ... und raus damit OutSprmBytes( (sal_uInt8*)&aSprmAnld, sizeof( aSprmAnld ) ); } // Return: ist es eine Gliederung ? bool WW8Export::Out_SwNum(const SwTxtNode* pNd) { int nLevel = pNd->GetActualListLevel(); if (nLevel < 0 || nLevel >= MAXLEVEL) { OSL_FAIL("Invalid level"); return false; } sal_uInt8 nSwLevel = static_cast< sal_uInt8 >(nLevel); const SwNumRule* pRul = pNd->GetNumRule(); if( !pRul || nSwLevel == WW8ListManager::nMaxLevel) return false; bool bRet = true; SwNumFmt aFmt(pRul->Get(nSwLevel)); // #i86652# if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) { const SvxLRSpaceItem& rLR = ItemGet(*pNd, RES_LR_SPACE); aFmt.SetAbsLSpace(writer_cast(aFmt.GetAbsLSpace() + rLR.GetLeft())); } if ( aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE || aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL || aFmt.GetNumberingType() == SVX_NUM_BITMAP ) { Out_WwNumLvl(11); Out_NumRuleAnld(*pRul, aFmt, 11); bRet = false; } else if ( pRul->IsContinusNum() || (pRul->Get(1).GetIncludeUpperLevels() <= 1) ) { Out_WwNumLvl(10); Out_NumRuleAnld(*pRul, aFmt, 10); bRet = false; } else { Out_SwNumLvl(nSwLevel); Out_NumRuleAnld(*pRul, aFmt, nSwLevel); } return bRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */