xref: /trunk/main/sw/source/filter/ww8/wrtw8num.cxx (revision 91568915)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28 
29 #include <hintids.hxx>
30 #include <vcl/font.hxx>
31 #include <editeng/fontitem.hxx>
32 #include <editeng/lrspitem.hxx>
33 #include <doc.hxx>
34 #include <docary.hxx>
35 #include <numrule.hxx>
36 #include <paratr.hxx>
37 #include <charfmt.hxx>
38 #include <ndtxt.hxx>
39 #include <com/sun/star/i18n/ScriptType.hdl>
40 
41 #include <writerfilter/doctok/sprmids.hxx>
42 
43 #include "ww8attributeoutput.hxx"
44 #include "writerhelper.hxx"
45 #include "writerwordglue.hxx"
46 #include "wrtww8.hxx"
47 #include "ww8par.hxx"
48 #include <editeng/langitem.hxx>
49 
50 //#define DUMPSYMBOLS
51 #ifdef DUMPSYMBOLS
52 #include <fstream>
53 #endif
54 
55 using namespace ::com::sun::star;
56 using namespace sw::types;
57 using namespace sw::util;
58 
DuplicateNumRule(const SwNumRule * pRule,sal_uInt8 nLevel,sal_uInt16 nVal)59 sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
60 {
61     sal_uInt16 nNumId = USHRT_MAX;
62     String sPrefix( CREATE_CONST_ASC( "WW8TempExport" ) );
63     sPrefix += String::CreateFromInt32( nUniqueList++ );
64     // --> OD 2008-02-11 #newlistlevelattrs#
65     SwNumRule* pMyNumRule =
66             new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ),
67                            SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
68     // <--
69     pUsedNumTbl->Insert( pMyNumRule, pUsedNumTbl->Count() );
70 
71     for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
72     {
73         const SwNumFmt& rSubRule = pRule->Get(i);
74         pMyNumRule->Set( i, rSubRule );
75     }
76 
77     SwNumFmt aNumFmt( pMyNumRule->Get( nLevel ) );
78     aNumFmt.SetStart( nVal );
79     pMyNumRule->Set( nLevel, aNumFmt );
80 
81     nNumId = GetId( *pMyNumRule );
82 
83     //Map the old list to our new list
84     aRuleDuplicates[GetId( *pRule )] = nNumId;
85 
86     return nNumId;
87 }
88 
GetId(const SwNumRule & rNumRule)89 sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule )
90 {
91     if ( !pUsedNumTbl )
92     {
93         pUsedNumTbl = new SwNumRuleTbl;
94         pUsedNumTbl->Insert( &pDoc->GetNumRuleTbl(), 0 );
95         // --> OD 2005-10-17 #126238# - Check, if the outline rule is
96         // already inserted into <pUsedNumTbl>. If yes, do not insert it again.
97         bool bOutlineRuleAdded( false );
98         for ( sal_uInt16 n = pUsedNumTbl->Count(); n; )
99         {
100             const SwNumRule& rRule = *pUsedNumTbl->GetObject( --n );
101             if ( !pDoc->IsUsed( rRule ) )
102             {
103                 pUsedNumTbl->Remove( n );
104             }
105             else if ( &rRule == pDoc->GetOutlineNumRule() )
106             {
107                 bOutlineRuleAdded = true;
108             }
109         }
110 
111         if ( !bOutlineRuleAdded )
112         {
113             // jetzt noch die OutlineRule einfuegen
114             SwNumRule* pR = (SwNumRule*)pDoc->GetOutlineNumRule();
115             pUsedNumTbl->Insert( pR, pUsedNumTbl->Count() );
116         }
117         // <--
118     }
119     SwNumRule* p = (SwNumRule*)&rNumRule;
120     sal_uInt16 nRet = pUsedNumTbl->GetPos(p);
121 
122     //Is this list now duplicated into a new list which we should use
123     // --> OD 2007-05-30 #i77812#
124     // perform 'deep' search in duplication map
125     ::std::map<sal_uInt16,sal_uInt16>::const_iterator aResult = aRuleDuplicates.end();
126     do {
127         aResult = aRuleDuplicates.find(nRet);
128         if ( aResult != aRuleDuplicates.end() )
129         {
130             nRet = (*aResult).second;
131         }
132     } while ( aResult != aRuleDuplicates.end() );
133     // <--
134 
135     return nRet;
136 }
137 
138 //GetFirstLineOffset should problem never appear unadorned apart from
139 //here in the ww export filter
GetWordFirstLineOffset(const SwNumFmt & rFmt)140 sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt)
141 {
142     ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
143             "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
144 
145     short nFirstLineOffset;
146     if (rFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
147         nFirstLineOffset = -rFmt.GetCharTextDistance();
148     else
149         nFirstLineOffset = rFmt.GetFirstLineOffset();
150     return nFirstLineOffset;
151 }
152 
WriteNumbering()153 void WW8Export::WriteNumbering()
154 {
155     if ( !pUsedNumTbl )
156         return; // no numbering is used
157 
158     // list formats - LSTF
159     pFib->fcPlcfLst = pTableStrm->Tell();
160     SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->Count() );
161     NumberingDefinitions();
162     // set len to FIB
163     pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
164 
165     // list formats - LVLF
166     AbstractNumberingDefinitions();
167 
168     // list formats - LFO
169     OutOverrideListTab();
170 
171     // list formats - ListNames
172     OutListNamesTab();
173 }
174 
NumberingDefinition(sal_uInt16 nId,const SwNumRule & rRule)175 void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
176 {
177     SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
178     SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
179 
180     // mit keinen Styles verbunden
181     for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
182         SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0xFFF );
183 
184     sal_uInt8 nFlags = 0, nDummy = 0;
185     if ( rRule.IsContinusNum() )
186         nFlags |= 0x1;
187 
188     *m_rWW8Export.pTableStrm << nFlags << nDummy;
189 }
190 
NumberingDefinitions()191 void MSWordExportBase::NumberingDefinitions()
192 {
193     if ( !pUsedNumTbl )
194         return; // no numbering is used
195 
196     sal_uInt16 nCount = pUsedNumTbl->Count();
197 
198     // Write static data of SwNumRule - LSTF
199     for ( sal_uInt16 n = 0; n < nCount; ++n )
200     {
201         const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
202 
203         AttrOutput().NumberingDefinition( n + 1, rRule );
204     }
205 }
206 
GetLevelNFC(sal_uInt16 eNumType,const SfxItemSet * pOutSet)207 static sal_uInt8 GetLevelNFC(  sal_uInt16 eNumType, const SfxItemSet *pOutSet)
208 {
209     sal_uInt8 nRet = 0;
210     switch( eNumType )
211     {
212     case SVX_NUM_CHARS_UPPER_LETTER:
213     case SVX_NUM_CHARS_UPPER_LETTER_N:  nRet = 3;       break;
214     case SVX_NUM_CHARS_LOWER_LETTER:
215     case SVX_NUM_CHARS_LOWER_LETTER_N:  nRet = 4;       break;
216     case SVX_NUM_ROMAN_UPPER:           nRet = 1;       break;
217     case SVX_NUM_ROMAN_LOWER:           nRet = 2;       break;
218 
219     case SVX_NUM_BITMAP:
220     case SVX_NUM_CHAR_SPECIAL:         nRet = 23;      break;
221     case SVX_NUM_FULL_WIDTH_ARABIC: nRet = 14; break;
222     case SVX_NUM_CIRCLE_NUMBER: nRet = 18;break;
223     case SVX_NUM_NUMBER_LOWER_ZH:
224         nRet = 35;
225         if ( pOutSet ) {
226             const SvxLanguageItem rLang = (const SvxLanguageItem&) pOutSet->Get( RES_CHRATR_CJK_LANGUAGE,true);
227             const LanguageType eLang = rLang.GetLanguage();
228             if (LANGUAGE_CHINESE_SIMPLIFIED ==eLang) {
229                 nRet = 39;
230             }
231         }
232         break;
233     case SVX_NUM_NUMBER_UPPER_ZH: nRet = 38; break;
234     case SVX_NUM_NUMBER_UPPER_ZH_TW: nRet = 34;break;
235     case SVX_NUM_TIAN_GAN_ZH: nRet = 30; break;
236     case SVX_NUM_DI_ZI_ZH: nRet = 31; break;
237     case SVX_NUM_NUMBER_TRADITIONAL_JA: nRet = 16; break;
238     case SVX_NUM_AIU_FULLWIDTH_JA: nRet = 20; break;
239     case SVX_NUM_AIU_HALFWIDTH_JA: nRet = 12; break;
240     case SVX_NUM_IROHA_FULLWIDTH_JA: nRet = 21; break;
241     case SVX_NUM_IROHA_HALFWIDTH_JA: nRet = 13; break;
242     case style::NumberingType::HANGUL_SYLLABLE_KO: nRet = 24; break;// ganada
243     case style::NumberingType::HANGUL_JAMO_KO: nRet = 25; break;// chosung
244     case style::NumberingType::HANGUL_CIRCLED_SYLLABLE_KO: nRet = 24; break;
245     case style::NumberingType::HANGUL_CIRCLED_JAMO_KO: nRet = 25; break;
246     case style::NumberingType::NUMBER_HANGUL_KO: nRet = 41; break;
247     case style::NumberingType::NUMBER_UPPER_KO: nRet = 44; break;
248     case SVX_NUM_NUMBER_NONE:           nRet = 0xff;    break;
249     }
250     return nRet;
251 }
252 
NumberingLevel(sal_uInt8,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)253 void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
254         sal_uInt16 nStart,
255         sal_uInt16 nNumberingType,
256         SvxAdjust eAdjust,
257         const sal_uInt8 *pNumLvlPos,
258         sal_uInt8 nFollow,
259         const wwFont *pFont,
260         const SfxItemSet *pOutSet,
261         sal_Int16 nIndentAt,
262         sal_Int16 nFirstLineIndex,
263         sal_Int16 nListTabPos,
264         const String &rNumberingString,
265         const SvxBrushItem* pBrush //For i120928,to transfer graphic of bullet
266     )
267 {
268     // Start value
269     SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
270 
271     // Type
272     *m_rWW8Export.pTableStrm << GetLevelNFC( nNumberingType ,pOutSet);
273 
274     // Justification
275     sal_uInt8 nAlign;
276     switch ( eAdjust )
277     {
278     case SVX_ADJUST_CENTER:
279         nAlign = 1;
280         break;
281     case SVX_ADJUST_RIGHT:
282         nAlign = 2;
283         break;
284     default:
285         nAlign = 0;
286         break;
287     }
288     *m_rWW8Export.pTableStrm << nAlign;
289 
290     // Write the rgbxchNums[9], positions of placeholders for paragraph
291     // numbers in the text
292     m_rWW8Export.pTableStrm->Write( pNumLvlPos, WW8ListManager::nMaxLevel );
293 
294     // Type of the character between the bullet and the text
295     *m_rWW8Export.pTableStrm << nFollow;
296 
297     // dxaSoace/dxaIndent (Word 6 compatibility)
298     SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
299     SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
300 
301     // cbGrpprlChpx
302     WW8Bytes aCharAtrs;
303     if ( pOutSet )
304     {
305         WW8Bytes* pOldpO = m_rWW8Export.pO;
306         m_rWW8Export.pO = &aCharAtrs;
307         if ( pFont )
308         {
309             sal_uInt16 nFontID = m_rWW8Export.maFontHelper.GetId( *pFont );
310 
311             if ( m_rWW8Export.bWrtWW8 )
312             {
313                 m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
314                 m_rWW8Export.InsUInt16( nFontID );
315                 m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
316             }
317             else
318                 m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
319             m_rWW8Export.InsUInt16( nFontID );
320         }
321 
322         m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.mbExportModeRTF );
323 	//For i120928,achieve graphic's index of bullet from the bullet bookmark
324 	if (SVX_NUM_BITMAP == nNumberingType && pBrush)
325 	{
326 		int nIndex = m_rWW8Export.GetGrfIndex(*pBrush);
327 		if ( nIndex != -1 )
328 		{
329 			m_rWW8Export.InsUInt16(0x6887);
330 			m_rWW8Export.InsUInt32(nIndex);
331 			m_rWW8Export.InsUInt16(0x4888);
332 			m_rWW8Export.InsUInt16(1);
333 		}
334 	}
335 
336         m_rWW8Export.pO = pOldpO;
337     }
338     *m_rWW8Export.pTableStrm << sal_uInt8( aCharAtrs.Count() );
339 
340     // cbGrpprlPapx
341     sal_uInt8 aPapSprms [] = {
342         0x5e, 0x84, 0, 0,               // sprmPDxaLeft
343         0x60, 0x84, 0, 0,               // sprmPDxaLeft1
344         0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
345     };
346     *m_rWW8Export.pTableStrm << sal_uInt8( sizeof( aPapSprms ) );
347 
348     // reserved
349     SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
350 
351     // pap sprms
352     sal_uInt8* pData = aPapSprms + 2;
353     Set_UInt16( pData, nIndentAt );
354     pData += 2;
355     Set_UInt16( pData, nFirstLineIndex );
356     pData += 5;
357     Set_UInt16( pData, nListTabPos );
358 
359     m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
360 
361     // write Chpx
362     if( aCharAtrs.Count() )
363         m_rWW8Export.pTableStrm->Write( aCharAtrs.GetData(), aCharAtrs.Count() );
364 
365     // write the num string
366     SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, rNumberingString.Len() );
367     SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
368 }
369 
AbstractNumberingDefinitions()370 void MSWordExportBase::AbstractNumberingDefinitions()
371 {
372     sal_uInt16 nCount = pUsedNumTbl->Count();
373     sal_uInt16 n;
374 
375     // prepare the NodeNum to generate the NumString
376     SwNumberTree::tNumberVector aNumVector;
377     for ( n = 0; n < WW8ListManager::nMaxLevel; ++n )
378         aNumVector.push_back( n );
379 
380     StarSymbolToMSMultiFont *pConvert = 0;
381     for( n = 0; n < nCount; ++n )
382     {
383         AttrOutput().StartAbstractNumbering( n + 1 );
384 
385         const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
386         sal_uInt8 nLvl;
387         sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
388             WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
389         for( nLvl = 0; nLvl < nLevels; ++nLvl )
390         {
391             // write the static data of the SwNumFmt of this level
392             sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
393 
394             const SwNumFmt& rFmt = rRule.Get( nLvl );
395 
396             sal_uInt8 nFollow = 0;
397             // --> OD 2008-06-03 #i86652#
398             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
399             {
400                 nFollow = 2;     // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
401             }
402             else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
403             {
404                 switch ( rFmt.GetLabelFollowedBy() )
405                 {
406                     case SvxNumberFormat::LISTTAB:
407                     {
408 			// 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
409 			nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 0 : 2;
410                     }
411                     break;
412                     case SvxNumberFormat::SPACE:
413                     {
414 			// 1 (space) unless there would be no content before the space in which case 2 (nothing)
415 			nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 1 : 2;
416                     }
417                     break;
418                     case SvxNumberFormat::NOTHING:
419                     {
420                         nFollow = 2;
421                     }
422                     break;
423                     default:
424                     {
425                         nFollow = 0;
426                         ASSERT( false,
427                                 "unknown GetLabelFollowedBy() return value" );
428                     }
429                 }
430             }
431             // <--
432 
433             // Build the NumString for this Level
434             String sNumStr;
435             String sFontName;
436             bool bWriteBullet = false;
437             const Font* pBulletFont=0;
438             rtl_TextEncoding eChrSet=0;
439             FontFamily eFamily=FAMILY_DECORATIVE;
440             if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() ||
441                 SVX_NUM_BITMAP == rFmt.GetNumberingType() )
442             {
443                 sNumStr = rFmt.GetBulletChar();
444                 bWriteBullet = true;
445 
446                 pBulletFont = rFmt.GetBulletFont();
447                 if (!pBulletFont)
448                 {
449                     pBulletFont = &numfunc::GetDefBulletFont();
450                 }
451 
452                 eChrSet = pBulletFont->GetCharSet();
453                 sFontName = pBulletFont->GetName();
454                 eFamily = pBulletFont->GetFamily();
455 
456                 if ( sw::util::IsStarSymbol( sFontName ) )
457                     SubstituteBullet( sNumStr, eChrSet, sFontName );
458 
459                 // --> OD 2008-06-03 #i86652#
460                 if ( rFmt.GetPositionAndSpaceMode() ==
461                                         SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
462                 {
463                     // --> OD 2007-07-23 #148661#
464                     // <nFollow = 2>, if minimum label width equals 0 and
465                     // minimum distance between label and text equals 0
466                     nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
467                                 rFmt.GetCharTextDistance() == 0 )
468                               ? 2 : 0;     // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
469                     // <--
470                 }
471                 // <--
472             }
473             else
474             {
475                 if (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType())
476                 {
477                     sal_uInt8* pLvlPos = aNumLvlPos;
478                     // --> OD 2005-10-17 #126238# - the numbering string
479                     // has to be restrict to the level currently working on.
480                     sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
481                     // <--
482 
483                     // now search the nums in the string
484                     for( sal_uInt8 i = 0; i <= nLvl; ++i )
485                     {
486                         String sSrch( String::CreateFromInt32( i ));
487                         xub_StrLen nFnd = sNumStr.Search( sSrch );
488                         if( STRING_NOTFOUND != nFnd )
489                         {
490                             *pLvlPos = (sal_uInt8)(nFnd + rFmt.GetPrefix().Len() + 1 );
491                             ++pLvlPos;
492                             sNumStr.SetChar( nFnd, (char)i );
493                         }
494                     }
495                     // --> OD 2008-06-03 #i86652#
496                     if ( rFmt.GetPositionAndSpaceMode() ==
497                                             SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
498                     {
499                         // --> OD 2007-07-23 #148661#
500                         // <nFollow = 2>, if minimum label width equals 0 and
501                         // minimum distance between label and text equals 0
502                         nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
503                                     rFmt.GetCharTextDistance() == 0 )
504                                   ? 2 : 0;     // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
505                         // <--
506                     }
507                     // <--
508                 }
509 
510                 if( rFmt.GetPrefix().Len() )
511                     sNumStr.Insert( rFmt.GetPrefix(), 0 );
512                 sNumStr += rFmt.GetSuffix();
513             }
514 
515             // Attributes of the numbering
516             wwFont *pPseudoFont = NULL;
517             const SfxItemSet* pOutSet = NULL;
518 
519             // cbGrpprlChpx
520             SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
521                                                   RES_CHRATR_END );
522             if ( rFmt.GetCharFmt() || bWriteBullet )
523             {
524                 if ( bWriteBullet )
525                 {
526                     pOutSet = &aSet;
527 
528                     if ( rFmt.GetCharFmt() )
529                         aSet.Put( rFmt.GetCharFmt()->GetAttrSet() );
530                     aSet.ClearItem( RES_CHRATR_CJK_FONT );
531                     aSet.ClearItem( RES_CHRATR_FONT );
532 
533                     if ( !sFontName.Len() )
534                         sFontName = pBulletFont->GetName();
535 
536                     pPseudoFont = new wwFont( sFontName, pBulletFont->GetPitch(),
537                         eFamily, eChrSet, HackIsWW8OrHigher() );
538                 }
539                 else
540                     pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
541             }
542 
543             sal_Int16 nIndentAt = 0;
544             sal_Int16 nFirstLineIndex = 0;
545             sal_Int16 nListTabPos = 0;
546 
547             // --> OD 2008-06-03 #i86652#
548             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
549             {
550                 nIndentAt = nListTabPos = rFmt.GetAbsLSpace();
551                 nFirstLineIndex = GetWordFirstLineOffset(rFmt);
552             }
553             else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
554             {
555                 nIndentAt = static_cast<sal_Int16>(rFmt.GetIndentAt());
556                 nFirstLineIndex = static_cast<sal_Int16>(rFmt.GetFirstLineIndent());
557                 nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
558                               static_cast<sal_Int16>( rFmt.GetListtabPos() ) : 0;
559             }
560 
561             AttrOutput().NumberingLevel( nLvl,
562                     rFmt.GetStart(),
563                     rFmt.GetNumberingType(),
564                     rFmt.GetNumAdjust(),
565                     aNumLvlPos,
566                     nFollow,
567                     pPseudoFont, pOutSet,
568                     nIndentAt, nFirstLineIndex, nListTabPos,
569                     sNumStr,
570                     rFmt.GetNumberingType()==SVX_NUM_BITMAP ? rFmt.GetBrush():0);//Start for i120928,export graphic bullet,2012.9.25
571 
572             delete pPseudoFont;
573         }
574         AttrOutput().EndAbstractNumbering();
575     }
576     delete pConvert;
577 }
578 
OutOverrideListTab()579 void WW8Export::OutOverrideListTab()
580 {
581     if( !pUsedNumTbl )
582         return ;            // no numbering is used
583 
584     // write the "list format override" - LFO
585     sal_uInt16 nCount = pUsedNumTbl->Count();
586     sal_uInt16 n;
587 
588     pFib->fcPlfLfo = pTableStrm->Tell();
589     SwWW8Writer::WriteLong( *pTableStrm, nCount );
590 
591     for( n = 0; n < nCount; ++n )
592     {
593         SwWW8Writer::WriteLong( *pTableStrm, n + 1 );
594         SwWW8Writer::FillCount( *pTableStrm, 12 );
595     }
596     for( n = 0; n < nCount; ++n )
597         SwWW8Writer::WriteLong( *pTableStrm, -1 );  // no overwrite
598 
599     // set len to FIB
600     pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
601 }
602 
OutListNamesTab()603 void WW8Export::OutListNamesTab()
604 {
605     if( !pUsedNumTbl )
606         return ;            // no numbering is used
607 
608     // write the "list format override" - LFO
609     sal_uInt16 nNms = 0, nCount = pUsedNumTbl->Count();
610 
611     pFib->fcSttbListNames = pTableStrm->Tell();
612     SwWW8Writer::WriteShort( *pTableStrm, -1 );
613     SwWW8Writer::WriteLong( *pTableStrm, nCount );
614 
615     for( ; nNms < nCount; ++nNms )
616     {
617         const SwNumRule& rRule = *pUsedNumTbl->GetObject( nNms );
618         String sNm;
619         if( !rRule.IsAutoRule() )
620             sNm = rRule.GetName();
621 
622         SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
623         if (sNm.Len())
624             SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
625     }
626 
627     SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
628     // set len to FIB
629     pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
630 }
631 
632 /*  */
633 
634 // old WW95-Code
635 
OutputOlst(const SwNumRule & rRule)636 void WW8Export::OutputOlst( const SwNumRule& rRule )
637 {
638     if ( bWrtWW8 )
639         return;
640 
641     static sal_uInt8 __READONLY_DATA aAnlvBase[] = { // Defaults
642                                 1,0,0,          // Upper Roman
643                                 0x0C,           // Hanging Indent, fPrev
644                                 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
645 
646     static sal_uInt8 __READONLY_DATA aSprmOlstHdr[] = { 133, 212 };
647 
648     pO->Insert( aSprmOlstHdr, sizeof( aSprmOlstHdr ), pO->Count() );
649     WW8_OLST aOlst;
650     memset( &aOlst, 0, sizeof(aOlst) );
651     sal_uInt8* pC = aOlst.rgch;
652     sal_uInt8* pChars = (sal_uInt8*)pC;
653     sal_uInt16 nCharLen = 64;
654 
655     for (sal_uInt16 j = 0; j < WW8ListManager::nMaxLevel; j++ ) // 9 variable ANLVs
656     {
657         memcpy( &aOlst.rganlv[j], aAnlvBase, sizeof( WW8_ANLV ) );  // Defaults
658 
659         const SwNumFmt* pFmt = rRule.GetNumFmt( j );
660         if( pFmt )
661             BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
662                             *pFmt, (sal_uInt8)j );
663     }
664 
665     pO->Insert( (sal_uInt8*)&aOlst, sizeof( aOlst ), pO->Count() );
666 }
667 
668 
Out_WwNumLvl(sal_uInt8 nWwLevel)669 void WW8Export::Out_WwNumLvl( sal_uInt8 nWwLevel )
670 {
671     pO->Insert( 13, pO->Count() );
672     pO->Insert( nWwLevel, pO->Count() );
673 }
674 
Out_SwNumLvl(sal_uInt8 nSwLevel)675 void WW8Export::Out_SwNumLvl( sal_uInt8 nSwLevel )
676 {
677     // --> OD 2008-04-02 #refactorlists#
678 //    ASSERT(IsNum(nSwLevel), "numbered?");
679     ASSERT( nSwLevel < MAXLEVEL, "numbered?");
680     // <--
681 	Out_WwNumLvl( nSwLevel + 1 );
682 }
683 
BuildAnlvBulletBase(WW8_ANLV & rAnlv,sal_uInt8 * & rpCh,sal_uInt16 & rCharLen,const SwNumFmt & rFmt)684 void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
685     sal_uInt16& rCharLen, const SwNumFmt& rFmt)
686 {
687     ByteToSVBT8(11, rAnlv.nfc);
688 
689     sal_uInt8 nb = 0;                                // Zahlentyp
690     switch (rFmt.GetNumAdjust())
691     {
692         case SVX_ADJUST_RIGHT:
693             nb = 2;
694             break;
695         case SVX_ADJUST_CENTER:
696             nb = 1;
697             break;
698         case SVX_ADJUST_BLOCK:
699         case SVX_ADJUST_BLOCKLINE:
700             nb = 3;
701             break;
702         case SVX_ADJUST_LEFT:
703         case SVX_ADJUST_END:
704             break;
705     }
706 
707     // --> OD 2008-06-03 #i86652#
708     if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
709     {
710         if (GetWordFirstLineOffset(rFmt) < 0)
711             nb |= 0x8;          // number will be displayed using a hanging indent
712     }
713     // <--
714     ByteToSVBT8(nb, rAnlv.aBits1);
715 
716     if (1 < rCharLen)
717     {
718         // --> OD 2006-06-27 #b6440955#
719 //        const Font& rFont = rFmt.GetBulletFont() ? *rFmt.GetBulletFont()
720 //            : SwNumRule::GetDefBulletFont();
721         const Font& rFont = rFmt.GetBulletFont()
722                             ? *rFmt.GetBulletFont()
723                             : numfunc::GetDefBulletFont();
724         // <--
725         String sNumStr = rFmt.GetBulletChar();
726         rtl_TextEncoding eChrSet = rFont.GetCharSet();
727         String sFontName = rFont.GetName();
728 
729         sal_uInt16 nFontId;
730         if (sw::util::IsStarSymbol(sFontName))
731         {
732             /*
733             If we are starsymbol then in ww7- mode we will always convert to a
734             windows 8bit symbol font and an index into it, to conversion to
735             8 bit is complete at this stage.
736             */
737             SubstituteBullet(sNumStr, eChrSet, sFontName);
738             wwFont aPseudoFont(sFontName, rFont.GetPitch(), rFont.GetFamily(),
739                 eChrSet, bWrtWW8);
740             nFontId = maFontHelper.GetId(aPseudoFont);
741             *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
742         }
743         else
744         {
745             /*
746             Otherwise we are a unicode char and need to be converted back to
747             an 8 bit format. We happen to know that if the font is already an
748             8 bit windows font currently, staroffice promotes the char into
749             the F000->F0FF range, so we can undo this, and we'll be back to
750             the equivalent 8bit location, otherwise we have to convert from
751             true unicode to an 8bit charset
752             */
753             nFontId = maFontHelper.GetId(rFont);
754             sal_Unicode cChar = sNumStr.GetChar(0);
755             if ( (eChrSet == RTL_TEXTENCODING_SYMBOL) && (cChar >= 0xF000) && (
756                 cChar <= 0xF0FF) )
757             {
758                 *rpCh = static_cast< sal_uInt8 >(cChar - 0xF000);
759             }
760             else
761                 *rpCh =  ByteString::ConvertFromUnicode(cChar, eChrSet);
762         }
763         rpCh++;
764         rCharLen--;
765         ShortToSVBT16(nFontId, rAnlv.ftc);
766         ByteToSVBT8( 1, rAnlv.cbTextBefore );
767     }
768     // --> OD 2008-06-03 #i86652#
769     if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
770     {
771         ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
772         ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
773     }
774     else
775     {
776         ShortToSVBT16( 0, rAnlv.dxaIndent );
777         ShortToSVBT16( 0, rAnlv.dxaSpace );
778     }
779     // <--
780 }
781 
SubstituteBullet(String & rNumStr,rtl_TextEncoding & rChrSet,String & rFontName) const782 void MSWordExportBase::SubstituteBullet( String& rNumStr,
783     rtl_TextEncoding& rChrSet, String& rFontName ) const
784 {
785     StarSymbolToMSMultiFont *pConvert = 0;
786     FontFamily eFamily = FAMILY_DECORATIVE;
787 
788     if (!bSubstituteBullets)
789         return;
790 
791     if (!pConvert)
792     {
793         pConvert = CreateStarSymbolToMSMultiFont();
794 #ifdef DUMPSYMBOLS
795         ::std::ofstream output("fontdebug");
796         for (sal_Unicode i=0xE000;i<0xF8FF;i++)
797         {
798             String sFont = pConvert->ConvertChar(i);
799             if (sFont.Len())
800                  output << ::std::hex << i << std::endl;
801         }
802 #endif
803     }
804     sal_Unicode cChar = rNumStr.GetChar(0);
805     String sFont = pConvert->ConvertChar(cChar);
806 
807     if (sFont.Len())
808     {
809         rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
810         rFontName = sFont;
811         rChrSet = RTL_TEXTENCODING_SYMBOL;
812     }
813     else if ( HackIsWW8OrHigher() &&
814         (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) )
815     {
816         /*
817         Ok we can't fit into a known windows unicode font, but
818         we are not in the private area, so we are a
819         standardized symbol, so turn off the symbol bit and
820         let words own font substitution kick in
821         */
822         rChrSet = RTL_TEXTENCODING_UNICODE;
823         eFamily = FAMILY_SWISS;
824         rFontName = ::GetFontToken(rFontName, 0);
825      }
826      else
827      {
828         /*
829         Well we don't have an available substition, and we're
830         in our private area, so give up and show a standard
831         bullet symbol
832         */
833         rFontName.ASSIGN_CONST_ASC("Wingdings");
834         rNumStr = static_cast< sal_Unicode >(0x6C);
835      }
836      delete pConvert;
837 }
838 
SwWw8_InsertAnlText(const String & rStr,sal_uInt8 * & rpCh,sal_uInt16 & rCharLen,SVBT8 & r8Len)839 static void SwWw8_InsertAnlText( const String& rStr, sal_uInt8*& rpCh,
840                                  sal_uInt16& rCharLen, SVBT8& r8Len )
841 {
842     sal_uInt8 nb = 0;
843     WW8Bytes aO;
844     SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
845 
846     sal_uInt16 nCnt = aO.Count();
847     if( nCnt && nCnt < rCharLen )
848     {
849         nb = (sal_uInt8)nCnt;
850         memcpy( rpCh, aO.GetData(), nCnt );
851         rpCh += nCnt;
852         rCharLen = rCharLen - nCnt;
853     }
854     ByteToSVBT8( nb, r8Len );
855 }
856 
BuildAnlvBase(WW8_ANLV & rAnlv,sal_uInt8 * & rpCh,sal_uInt16 & rCharLen,const SwNumRule & rRul,const SwNumFmt & rFmt,sal_uInt8 nSwLevel)857 void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
858     sal_uInt16& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt,
859     sal_uInt8 nSwLevel)
860 {
861     const SfxItemSet *pOutSet = NULL;
862     if (rFmt.GetCharFmt())
863         pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
864 
865     ByteToSVBT8(GetLevelNFC(rFmt.GetNumberingType(),pOutSet ), rAnlv.nfc);
866 
867     sal_uInt8 nb = 0;
868     switch (rFmt.GetNumAdjust())
869     {
870         case SVX_ADJUST_RIGHT:
871             nb = 2;
872             break;
873         case SVX_ADJUST_CENTER:
874             nb = 1;
875             break;
876         case SVX_ADJUST_BLOCK:
877         case SVX_ADJUST_BLOCKLINE:
878             nb = 3;
879             break;
880         case SVX_ADJUST_LEFT:
881         case SVX_ADJUST_END:
882             break;
883     }
884 
885     bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
886     if( bInclUpper )
887         nb |= 0x4;          // include previous levels
888 
889     if (GetWordFirstLineOffset(rFmt) < 0)
890         nb |= 0x8;          // number will be displayed using a hanging indent
891     ByteToSVBT8( nb, rAnlv.aBits1 );
892 
893     if( bInclUpper && !rRul.IsContinusNum() )
894     {
895         if( (nSwLevel >= WW8ListManager::nMinLevel )
896             && (nSwLevel<= WW8ListManager::nMaxLevel )
897             && (rFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE ) )  // UEberhaupt Nummerierung ?
898         {                                               // -> suche, ob noch Zahlen davor
899             sal_uInt8 nUpper = rFmt.GetIncludeUpperLevels();
900             if( (nUpper <= WW8ListManager::nMaxLevel) &&
901                 (rRul.Get(nUpper).GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // Nummerierung drueber ?
902             {
903                                                     // dann Punkt einfuegen
904                 SwWw8_InsertAnlText( aDotStr, rpCh, rCharLen,
905                                     rAnlv.cbTextBefore );
906             }
907 
908         }
909     }
910     else
911     {
912         SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
913                              rAnlv.cbTextBefore );
914         SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
915                              rAnlv.cbTextAfter );
916     }
917 
918     ShortToSVBT16( rFmt.GetStart(), rAnlv.iStartAt );
919     // --> OD 2008-06-03 #i86652#
920     if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
921     {
922         ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
923         ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
924     }
925     else
926     {
927         ShortToSVBT16( 0, rAnlv.dxaIndent );
928         ShortToSVBT16( 0, rAnlv.dxaSpace );
929     }
930     // <--
931 }
932 
Out_NumRuleAnld(const SwNumRule & rRul,const SwNumFmt & rFmt,sal_uInt8 nSwLevel)933 void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
934                                    sal_uInt8 nSwLevel )
935 {
936     static sal_uInt8 __READONLY_DATA aSprmAnldDefault[54] = {
937                          12, 52,
938                          1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
939                          0,0,0,
940                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
941                          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
942     sal_uInt8 aSprmAnld[54];
943 
944     memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) );
945     WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2);  // handlicher Pointer
946 
947     sal_uInt8* pChars = (sal_uInt8*)(pA->rgchAnld);
948     sal_uInt16 nCharLen = 31;
949 
950     if( nSwLevel == 11 )
951         BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
952     else
953         BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel );
954 
955     // ... und raus damit
956     OutSprmBytes( (sal_uInt8*)&aSprmAnld, sizeof( aSprmAnld ) );
957 }
958 
959 
960 // Return: ist es eine Gliederung ?
Out_SwNum(const SwTxtNode * pNd)961 bool WW8Export::Out_SwNum(const SwTxtNode* pNd)
962 {
963     int nLevel = pNd->GetActualListLevel();
964 
965     if (nLevel < 0 || nLevel >= MAXLEVEL)
966     {
967         ASSERT(sal_False, "Invalid level");
968 
969         return false;
970     }
971 
972     sal_uInt8 nSwLevel = static_cast< sal_uInt8 >(nLevel);
973 
974 	const SwNumRule* pRul = pNd->GetNumRule();
975 	if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
976 		return false;
977 
978 	bool bRet = true;
979 
980     SwNumFmt aFmt(pRul->Get(nSwLevel));
981     // --> OD 2008-06-03 #i86652#
982     if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
983     {
984         const SvxLRSpaceItem& rLR = ItemGet<SvxLRSpaceItem>(*pNd, RES_LR_SPACE);
985         aFmt.SetAbsLSpace(writer_cast<short>(aFmt.GetAbsLSpace() + rLR.GetLeft()));
986     }
987 
988     if (
989          aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
990          aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
991          aFmt.GetNumberingType() == SVX_NUM_BITMAP
992        )
993     {
994         // Aufzaehlung
995         // --> OD 2008-04-02 #refactorlists#
996 //        Out_WwNumLvl(bNoNum ? 12 : 11);
997         Out_WwNumLvl(11);
998         // <--
999         Out_NumRuleAnld(*pRul, aFmt, 11);
1000         bRet = false;
1001     }
1002     else if (
1003               pRul->IsContinusNum() ||
1004               (pRul->Get(1).GetIncludeUpperLevels() <= 1)
1005             )
1006     {
1007         // Nummerierung
1008         // --> OD 2008-04-02 #refactorlists#
1009 //        Out_WwNumLvl(bNoNum ? 12 : 10);
1010         Out_WwNumLvl(10);
1011         // <--
1012         Out_NumRuleAnld(*pRul, aFmt, 10);
1013         bRet = false;
1014     }
1015     else
1016     {
1017         // Gliederung
1018         // --> OD 2008-04-02 #refactorlists#
1019 //        Out_SwNumLvl(bNoNum ? 12 : nSwLevel);
1020         Out_SwNumLvl(nSwLevel);
1021         // <--
1022         Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
1023     }
1024     return bRet;
1025 }
1026 
1027 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
1028