/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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 #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" #include //#define DUMPSYMBOLS #ifdef DUMPSYMBOLS #include #endif 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++ ); // --> OD 2008-02-11 #newlistlevelattrs# 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 ); // --> OD 2005-10-17 #126238# - 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 // --> OD 2007-05-30 #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) { ASSERT( 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 ); } } static sal_uInt8 GetLevelNFC( sal_uInt16 eNumType, const SfxItemSet *pOutSet) { sal_uInt8 nRet = 0; switch( eNumType ) { case SVX_NUM_CHARS_UPPER_LETTER: case SVX_NUM_CHARS_UPPER_LETTER_N: nRet = 3; break; case SVX_NUM_CHARS_LOWER_LETTER: case SVX_NUM_CHARS_LOWER_LETTER_N: nRet = 4; break; case SVX_NUM_ROMAN_UPPER: nRet = 1; break; case SVX_NUM_ROMAN_LOWER: nRet = 2; break; case SVX_NUM_BITMAP: case SVX_NUM_CHAR_SPECIAL: nRet = 23; break; case SVX_NUM_FULL_WIDTH_ARABIC: nRet = 14; break; case SVX_NUM_CIRCLE_NUMBER: nRet = 18;break; case SVX_NUM_NUMBER_LOWER_ZH: nRet = 35; if ( pOutSet ) { const SvxLanguageItem rLang = (const SvxLanguageItem&) pOutSet->Get( RES_CHRATR_CJK_LANGUAGE,true); const LanguageType eLang = rLang.GetLanguage(); if (LANGUAGE_CHINESE_SIMPLIFIED ==eLang) { nRet = 39; } } break; case SVX_NUM_NUMBER_UPPER_ZH: nRet = 38; break; case SVX_NUM_NUMBER_UPPER_ZH_TW: nRet = 34;break; case SVX_NUM_TIAN_GAN_ZH: nRet = 30; break; case SVX_NUM_DI_ZI_ZH: nRet = 31; break; case SVX_NUM_NUMBER_TRADITIONAL_JA: nRet = 16; break; case SVX_NUM_AIU_FULLWIDTH_JA: nRet = 20; break; case SVX_NUM_AIU_HALFWIDTH_JA: nRet = 12; break; case SVX_NUM_IROHA_FULLWIDTH_JA: nRet = 21; break; case SVX_NUM_IROHA_HALFWIDTH_JA: nRet = 13; break; case style::NumberingType::HANGUL_SYLLABLE_KO: nRet = 24; break;// ganada case style::NumberingType::HANGUL_JAMO_KO: nRet = 25; break;// chosung case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO: nRet = 24; break; case style::NumberingType::HANGUL_CIRCLED_JAMO_KO: nRet = 25; break; case style::NumberingType::NUMBER_HANGUL_KO: nRet = 41; break; case style::NumberingType::NUMBER_UPPER_KO: nRet = 44; break; case SVX_NUM_NUMBER_NONE: nRet = 0xff; break; } return nRet; } 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, const SvxBrushItem* pBrush //For i120928,to transfer graphic of bullet ) { // Start value SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart ); // Type *m_rWW8Export.pTableStrm << GetLevelNFC( nNumberingType ,pOutSet); // 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 ); //For i120928,achieve graphic's index of bullet from the bullet bookmark if (SVX_NUM_BITMAP == nNumberingType && pBrush) { int nIndex = m_rWW8Export.GetGrfIndex(*pBrush); if ( nIndex != -1 ) { m_rWW8Export.InsUInt16(0x6887); m_rWW8Export.InsUInt32(nIndex); m_rWW8Export.InsUInt16(0x4888); m_rWW8Export.InsUInt16(1); } } 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; // --> 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# // , 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; // --> 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( 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 ); } } // --> OD 2008-06-03 #i86652# if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) { // --> OD 2007-07-23 #148661# // , 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(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, rFmt.GetNumberingType()==SVX_NUM_BITMAP ? rFmt.GetBrush():0);//Start for i120928,export graphic bullet,2012.9.25 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 __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 sal_uInt8 __READONLY_DATA 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 ) { // --> OD 2008-04-02 #refactorlists# // ASSERT(IsNum(nSwLevel), "numbered?"); ASSERT( 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; } // --> 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(); 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 = 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 (!bSubstituteBullets) return; 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, 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) { const SfxItemSet *pOutSet = NULL; if (rFmt.GetCharFmt()) pOutSet = &rFmt.GetCharFmt()->GetAttrSet(); ByteToSVBT8(GetLevelNFC(rFmt.GetNumberingType(),pOutSet ), 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 ); // --> 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, sal_uInt8 nSwLevel ) { static sal_uInt8 __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 }; 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) { ASSERT(sal_False, "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)); // --> OD 2008-06-03 #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 ) { // 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: */