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