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