Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <hintids.hxx>
22 : #include <vcl/font.hxx>
23 : #include <editeng/fontitem.hxx>
24 : #include <editeng/lrspitem.hxx>
25 : #include <doc.hxx>
26 : #include <docary.hxx>
27 : #include <numrule.hxx>
28 : #include <paratr.hxx>
29 : #include <charfmt.hxx>
30 : #include <ndtxt.hxx>
31 : #include <com/sun/star/i18n/ScriptType.hpp>
32 :
33 : #include <writerfilter/doctok/sprmids.hxx>
34 :
35 : #include "ww8attributeoutput.hxx"
36 : #include "writerhelper.hxx"
37 : #include "writerwordglue.hxx"
38 : #include "wrtww8.hxx"
39 : #include "ww8par.hxx"
40 :
41 : using namespace ::com::sun::star;
42 : using namespace sw::types;
43 : using namespace sw::util;
44 :
45 0 : sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
46 : {
47 0 : sal_uInt16 nNumId = USHRT_MAX;
48 0 : String sPrefix(rtl::OUString("WW8TempExport"));
49 0 : sPrefix += String::CreateFromInt32( nUniqueList++ );
50 : SwNumRule* pMyNumRule =
51 : new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ),
52 0 : SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
53 0 : pUsedNumTbl->push_back( pMyNumRule );
54 :
55 0 : for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
56 : {
57 0 : const SwNumFmt& rSubRule = pRule->Get(i);
58 0 : pMyNumRule->Set( i, rSubRule );
59 : }
60 :
61 0 : SwNumFmt aNumFmt( pMyNumRule->Get( nLevel ) );
62 0 : aNumFmt.SetStart( nVal );
63 0 : pMyNumRule->Set( nLevel, aNumFmt );
64 :
65 0 : nNumId = GetId( *pMyNumRule );
66 :
67 : //Map the old list to our new list
68 0 : aRuleDuplicates[GetId( *pRule )] = nNumId;
69 :
70 0 : return nNumId;
71 : }
72 :
73 6 : sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule )
74 : {
75 6 : if ( !pUsedNumTbl )
76 : {
77 1 : pUsedNumTbl = new SwNumRuleTbl;
78 1 : pUsedNumTbl->insert( pUsedNumTbl->begin(), pDoc->GetNumRuleTbl().begin(), pDoc->GetNumRuleTbl().end() );
79 : // Check, if the outline rule is already inserted into <pUsedNumTbl>.
80 : // If yes, do not insert it again.
81 1 : bool bOutlineRuleAdded( false );
82 5 : for ( sal_uInt16 n = pUsedNumTbl->size(); n; )
83 : {
84 3 : const SwNumRule& rRule = *(*pUsedNumTbl)[ --n ];
85 3 : if ( !pDoc->IsUsed( rRule ) )
86 : {
87 2 : pUsedNumTbl->erase( pUsedNumTbl->begin() + n );
88 : }
89 1 : else if ( &rRule == pDoc->GetOutlineNumRule() )
90 : {
91 1 : bOutlineRuleAdded = true;
92 : }
93 : }
94 :
95 1 : if ( !bOutlineRuleAdded )
96 : {
97 : // jetzt noch die OutlineRule einfuegen
98 0 : SwNumRule* pR = (SwNumRule*)pDoc->GetOutlineNumRule();
99 0 : pUsedNumTbl->push_back( pR );
100 : }
101 : }
102 6 : SwNumRule* p = (SwNumRule*)&rNumRule;
103 6 : sal_uInt16 nRet = pUsedNumTbl->GetPos(p);
104 :
105 : //Is this list now duplicated into a new list which we should use
106 : // #i77812# - perform 'deep' search in duplication map
107 6 : ::std::map<sal_uInt16,sal_uInt16>::const_iterator aResult = aRuleDuplicates.end();
108 12 : do {
109 6 : aResult = aRuleDuplicates.find(nRet);
110 6 : if ( aResult != aRuleDuplicates.end() )
111 : {
112 0 : nRet = (*aResult).second;
113 : }
114 12 : } while ( aResult != aRuleDuplicates.end() );
115 :
116 6 : return nRet;
117 : }
118 :
119 : //GetFirstLineOffset should problem never appear unadorned apart from
120 : //here in the ww export filter
121 0 : sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt)
122 : {
123 : OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
124 : "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
125 :
126 : short nFirstLineOffset;
127 0 : if (rFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
128 0 : nFirstLineOffset = -rFmt.GetCharTextDistance();
129 : else
130 0 : nFirstLineOffset = rFmt.GetFirstLineOffset();
131 0 : return nFirstLineOffset;
132 : }
133 :
134 4 : void WW8Export::WriteNumbering()
135 : {
136 4 : if ( !pUsedNumTbl )
137 7 : return; // no numbering is used
138 :
139 : // list formats - LSTF
140 1 : pFib->fcPlcfLst = pTableStrm->Tell();
141 1 : SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->size() );
142 1 : NumberingDefinitions();
143 : // set len to FIB
144 1 : pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
145 :
146 : // list formats - LVLF
147 1 : AbstractNumberingDefinitions();
148 :
149 : // list formats - LFO
150 1 : OutOverrideListTab();
151 :
152 : // list formats - ListNames
153 1 : OutListNamesTab();
154 : }
155 :
156 1 : void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
157 : {
158 1 : SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
159 1 : SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
160 :
161 : // mit keinen Styles verbunden
162 10 : for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
163 9 : SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0xFFF );
164 :
165 1 : sal_uInt8 nFlags = 0, nDummy = 0;
166 1 : if ( rRule.IsContinusNum() )
167 0 : nFlags |= 0x1;
168 :
169 1 : *m_rWW8Export.pTableStrm << nFlags << nDummy;
170 1 : }
171 :
172 1 : void MSWordExportBase::NumberingDefinitions()
173 : {
174 1 : if ( !pUsedNumTbl )
175 1 : return; // no numbering is used
176 :
177 1 : sal_uInt16 nCount = pUsedNumTbl->size();
178 :
179 : // Write static data of SwNumRule - LSTF
180 2 : for ( sal_uInt16 n = 0; n < nCount; ++n )
181 : {
182 1 : const SwNumRule& rRule = *(*pUsedNumTbl)[ n ];
183 :
184 1 : AttrOutput().NumberingDefinition( n + 1, rRule );
185 : }
186 : }
187 :
188 9 : void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
189 : sal_uInt16 nStart,
190 : sal_uInt16 nNumberingType,
191 : SvxAdjust eAdjust,
192 : const sal_uInt8 *pNumLvlPos,
193 : sal_uInt8 nFollow,
194 : const wwFont *pFont,
195 : const SfxItemSet *pOutSet,
196 : sal_Int16 nIndentAt,
197 : sal_Int16 nFirstLineIndex,
198 : sal_Int16 nListTabPos,
199 : const String &rNumberingString
200 : )
201 : {
202 : // Start value
203 9 : SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
204 :
205 : // Type
206 9 : *m_rWW8Export.pTableStrm << WW8Export::GetNumId( nNumberingType );
207 :
208 : // Justification
209 : sal_uInt8 nAlign;
210 9 : switch ( eAdjust )
211 : {
212 : case SVX_ADJUST_CENTER:
213 0 : nAlign = 1;
214 0 : break;
215 : case SVX_ADJUST_RIGHT:
216 0 : nAlign = 2;
217 0 : break;
218 : default:
219 9 : nAlign = 0;
220 9 : break;
221 : }
222 9 : *m_rWW8Export.pTableStrm << nAlign;
223 :
224 : // Write the rgbxchNums[9], positions of placeholders for paragraph
225 : // numbers in the text
226 9 : m_rWW8Export.pTableStrm->Write( pNumLvlPos, WW8ListManager::nMaxLevel );
227 :
228 : // Type of the character between the bullet and the text
229 9 : *m_rWW8Export.pTableStrm << nFollow;
230 :
231 : // dxaSoace/dxaIndent (Word 6 compatibility)
232 9 : SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
233 9 : SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
234 :
235 : // cbGrpprlChpx
236 9 : ww::bytes aCharAtrs;
237 9 : if ( pOutSet )
238 : {
239 0 : ww::bytes* pOldpO = m_rWW8Export.pO;
240 0 : m_rWW8Export.pO = &aCharAtrs;
241 0 : if ( pFont )
242 : {
243 0 : sal_uInt16 nFontID = m_rWW8Export.maFontHelper.GetId( *pFont );
244 :
245 0 : if ( m_rWW8Export.bWrtWW8 )
246 : {
247 0 : m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
248 0 : m_rWW8Export.InsUInt16( nFontID );
249 0 : m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
250 : }
251 : else
252 0 : m_rWW8Export.pO->push_back( 93 );
253 0 : m_rWW8Export.InsUInt16( nFontID );
254 : }
255 :
256 0 : m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.mbExportModeRTF );
257 :
258 0 : m_rWW8Export.pO = pOldpO;
259 : }
260 9 : *m_rWW8Export.pTableStrm << sal_uInt8( aCharAtrs.size() );
261 :
262 : // cbGrpprlPapx
263 : sal_uInt8 aPapSprms [] = {
264 : 0x5e, 0x84, 0, 0, // sprmPDxaLeft
265 : 0x60, 0x84, 0, 0, // sprmPDxaLeft1
266 : 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
267 9 : };
268 9 : *m_rWW8Export.pTableStrm << sal_uInt8( sizeof( aPapSprms ) );
269 :
270 : // reserved
271 9 : SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
272 :
273 : // pap sprms
274 9 : sal_uInt8* pData = aPapSprms + 2;
275 9 : Set_UInt16( pData, nIndentAt );
276 9 : pData += 2;
277 9 : Set_UInt16( pData, nFirstLineIndex );
278 9 : pData += 5;
279 9 : Set_UInt16( pData, nListTabPos );
280 :
281 9 : m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
282 :
283 : // write Chpx
284 9 : if( !aCharAtrs.empty() )
285 0 : m_rWW8Export.pTableStrm->Write( aCharAtrs.data(), aCharAtrs.size() );
286 :
287 : // write the num string
288 9 : SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, rNumberingString.Len() );
289 9 : SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
290 9 : }
291 :
292 1 : void MSWordExportBase::AbstractNumberingDefinitions()
293 : {
294 1 : sal_uInt16 nCount = pUsedNumTbl->size();
295 : sal_uInt16 n;
296 :
297 : // prepare the NodeNum to generate the NumString
298 1 : SwNumberTree::tNumberVector aNumVector;
299 10 : for ( n = 0; n < WW8ListManager::nMaxLevel; ++n )
300 9 : aNumVector.push_back( n );
301 :
302 1 : StarSymbolToMSMultiFont *pConvert = 0;
303 2 : for( n = 0; n < nCount; ++n )
304 : {
305 1 : AttrOutput().StartAbstractNumbering( n + 1 );
306 :
307 1 : const SwNumRule& rRule = *(*pUsedNumTbl)[ n ];
308 : sal_uInt8 nLvl;
309 1 : sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
310 1 : WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
311 10 : for( nLvl = 0; nLvl < nLevels; ++nLvl )
312 : {
313 : // write the static data of the SwNumFmt of this level
314 9 : sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
315 :
316 9 : const SwNumFmt& rFmt = rRule.Get( nLvl );
317 :
318 9 : sal_uInt8 nFollow = 0;
319 : // #i86652#
320 9 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
321 : {
322 0 : nFollow = 2; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
323 : }
324 9 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
325 : {
326 9 : switch ( rFmt.GetLabelFollowedBy() )
327 : {
328 : case SvxNumberFormat::LISTTAB:
329 : {
330 : // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
331 0 : nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 0 : 2;
332 : }
333 0 : break;
334 : case SvxNumberFormat::SPACE:
335 : {
336 : // 1 (space) unless there would be no content before the space in which case 2 (nothing)
337 0 : nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 1 : 2;
338 : }
339 0 : break;
340 : case SvxNumberFormat::NOTHING:
341 : {
342 9 : nFollow = 2;
343 : }
344 9 : break;
345 : default:
346 : {
347 0 : nFollow = 0;
348 : OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
349 : }
350 : }
351 : }
352 :
353 : // Build the NumString for this Level
354 9 : String sNumStr;
355 9 : String sFontName;
356 9 : bool bWriteBullet = false;
357 9 : const Font* pBulletFont=0;
358 9 : rtl_TextEncoding eChrSet=0;
359 9 : FontFamily eFamily=FAMILY_DECORATIVE;
360 18 : if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() ||
361 9 : SVX_NUM_BITMAP == rFmt.GetNumberingType() )
362 : {
363 0 : sNumStr = rFmt.GetBulletChar();
364 0 : bWriteBullet = true;
365 :
366 0 : pBulletFont = rFmt.GetBulletFont();
367 0 : if (!pBulletFont)
368 : {
369 0 : pBulletFont = &numfunc::GetDefBulletFont();
370 : }
371 :
372 0 : eChrSet = pBulletFont->GetCharSet();
373 0 : sFontName = pBulletFont->GetName();
374 0 : eFamily = pBulletFont->GetFamily();
375 :
376 0 : if ( sw::util::IsStarSymbol( sFontName ) )
377 0 : SubstituteBullet( sNumStr, eChrSet, sFontName );
378 :
379 : // #i86652#
380 0 : if ( rFmt.GetPositionAndSpaceMode() ==
381 : SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
382 : {
383 : // <nFollow = 2>, if minimum label width equals 0 and
384 : // minimum distance between label and text equals 0
385 0 : nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
386 0 : rFmt.GetCharTextDistance() == 0 )
387 0 : ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
388 : }
389 : }
390 : else
391 : {
392 9 : if (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType())
393 : {
394 0 : sal_uInt8* pLvlPos = aNumLvlPos;
395 : // the numbering string has to be restrict
396 : // to the level currently working on.
397 0 : sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
398 :
399 : // now search the nums in the string
400 0 : for( sal_uInt8 i = 0; i <= nLvl; ++i )
401 : {
402 0 : String sSrch( String::CreateFromInt32( i ));
403 0 : xub_StrLen nFnd = sNumStr.Search( sSrch );
404 0 : if( STRING_NOTFOUND != nFnd )
405 : {
406 0 : *pLvlPos = (sal_uInt8)(nFnd + rFmt.GetPrefix().getLength() + 1 );
407 0 : ++pLvlPos;
408 0 : sNumStr.SetChar( nFnd, (char)i );
409 : }
410 0 : }
411 : // #i86652#
412 0 : if ( rFmt.GetPositionAndSpaceMode() ==
413 : SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
414 : {
415 : // <nFollow = 2>, if minimum label width equals 0 and
416 : // minimum distance between label and text equals 0
417 0 : nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
418 0 : rFmt.GetCharTextDistance() == 0 )
419 0 : ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
420 : }
421 : }
422 :
423 9 : if( !rFmt.GetPrefix().isEmpty() )
424 0 : sNumStr.Insert( rFmt.GetPrefix(), 0 );
425 9 : sNumStr += rFmt.GetSuffix();
426 : }
427 :
428 : // Attributes of the numbering
429 9 : wwFont *pPseudoFont = NULL;
430 9 : const SfxItemSet* pOutSet = NULL;
431 :
432 : // cbGrpprlChpx
433 9 : SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
434 9 : RES_CHRATR_END );
435 9 : if ( rFmt.GetCharFmt() || bWriteBullet )
436 : {
437 0 : if ( bWriteBullet )
438 : {
439 0 : pOutSet = &aSet;
440 :
441 0 : if ( rFmt.GetCharFmt() )
442 0 : aSet.Put( rFmt.GetCharFmt()->GetAttrSet() );
443 0 : aSet.ClearItem( RES_CHRATR_CJK_FONT );
444 0 : aSet.ClearItem( RES_CHRATR_FONT );
445 :
446 0 : if ( !sFontName.Len() )
447 0 : sFontName = pBulletFont->GetName();
448 :
449 : pPseudoFont = new wwFont( sFontName, pBulletFont->GetPitch(),
450 0 : eFamily, eChrSet, SupportsUnicode() );
451 : }
452 : else
453 0 : pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
454 : }
455 :
456 9 : sal_Int16 nIndentAt = 0;
457 9 : sal_Int16 nFirstLineIndex = 0;
458 9 : sal_Int16 nListTabPos = 0;
459 :
460 : // #i86652#
461 9 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
462 : {
463 0 : nIndentAt = nListTabPos = rFmt.GetAbsLSpace();
464 0 : nFirstLineIndex = GetWordFirstLineOffset(rFmt);
465 : }
466 9 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
467 : {
468 9 : nIndentAt = static_cast<sal_Int16>(rFmt.GetIndentAt());
469 9 : nFirstLineIndex = static_cast<sal_Int16>(rFmt.GetFirstLineIndent());
470 9 : nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
471 9 : static_cast<sal_Int16>( rFmt.GetListtabPos() ) : 0;
472 : }
473 :
474 9 : AttrOutput().NumberingLevel( nLvl,
475 9 : rFmt.GetStart(),
476 9 : rFmt.GetNumberingType(),
477 : rFmt.GetNumAdjust(),
478 : aNumLvlPos,
479 : nFollow,
480 : pPseudoFont, pOutSet,
481 : nIndentAt, nFirstLineIndex, nListTabPos,
482 27 : sNumStr );
483 :
484 9 : delete pPseudoFont;
485 9 : }
486 1 : AttrOutput().EndAbstractNumbering();
487 : }
488 1 : delete pConvert;
489 1 : }
490 :
491 1 : void WW8Export::OutOverrideListTab()
492 : {
493 1 : if( !pUsedNumTbl )
494 1 : return ; // no numbering is used
495 :
496 : // write the "list format override" - LFO
497 1 : sal_uInt16 nCount = pUsedNumTbl->size();
498 : sal_uInt16 n;
499 :
500 1 : pFib->fcPlfLfo = pTableStrm->Tell();
501 1 : SwWW8Writer::WriteLong( *pTableStrm, nCount );
502 :
503 2 : for( n = 0; n < nCount; ++n )
504 : {
505 1 : SwWW8Writer::WriteLong( *pTableStrm, n + 1 );
506 1 : SwWW8Writer::FillCount( *pTableStrm, 12 );
507 : }
508 2 : for( n = 0; n < nCount; ++n )
509 1 : SwWW8Writer::WriteLong( *pTableStrm, -1 ); // no overwrite
510 :
511 : // set len to FIB
512 1 : pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
513 : }
514 :
515 1 : void WW8Export::OutListNamesTab()
516 : {
517 1 : if( !pUsedNumTbl )
518 1 : return ; // no numbering is used
519 :
520 : // write the "list format override" - LFO
521 1 : sal_uInt16 nNms = 0, nCount = pUsedNumTbl->size();
522 :
523 1 : pFib->fcSttbListNames = pTableStrm->Tell();
524 1 : SwWW8Writer::WriteShort( *pTableStrm, -1 );
525 1 : SwWW8Writer::WriteLong( *pTableStrm, nCount );
526 :
527 2 : for( ; nNms < nCount; ++nNms )
528 : {
529 1 : const SwNumRule& rRule = *(*pUsedNumTbl)[ nNms ];
530 1 : String sNm;
531 1 : if( !rRule.IsAutoRule() )
532 0 : sNm = rRule.GetName();
533 :
534 1 : SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
535 1 : if (sNm.Len())
536 0 : SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
537 1 : }
538 :
539 1 : SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
540 : // set len to FIB
541 1 : pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
542 : }
543 :
544 :
545 : // old WW95-Code
546 :
547 0 : void WW8Export::OutputOlst( const SwNumRule& rRule )
548 : {
549 0 : if ( bWrtWW8 )
550 0 : return;
551 :
552 : static sal_uInt8 aAnlvBase[] = { // Defaults
553 : 1,0,0, // Upper Roman
554 : 0x0C, // Hanging Indent, fPrev
555 : 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
556 :
557 : static sal_uInt8 aSprmOlstHdr[] = { 133, 212 };
558 :
559 0 : pO->insert( pO->end(), aSprmOlstHdr, aSprmOlstHdr+sizeof( aSprmOlstHdr ) );
560 : WW8_OLST aOlst;
561 0 : memset( &aOlst, 0, sizeof(aOlst) );
562 0 : sal_uInt8* pC = aOlst.rgch;
563 0 : sal_uInt8* pChars = (sal_uInt8*)pC;
564 0 : sal_uInt16 nCharLen = 64;
565 :
566 0 : for (sal_uInt16 j = 0; j < WW8ListManager::nMaxLevel; j++ ) // 9 variable ANLVs
567 : {
568 0 : memcpy( &aOlst.rganlv[j], aAnlvBase, sizeof( WW8_ANLV ) ); // Defaults
569 :
570 0 : const SwNumFmt* pFmt = rRule.GetNumFmt( j );
571 0 : if( pFmt )
572 0 : BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
573 0 : *pFmt, (sal_uInt8)j );
574 : }
575 :
576 0 : pO->insert( pO->end(), (sal_uInt8*)&aOlst, (sal_uInt8*)&aOlst+sizeof( aOlst ) );
577 : }
578 :
579 :
580 0 : void WW8Export::Out_WwNumLvl( sal_uInt8 nWwLevel )
581 : {
582 0 : pO->push_back( 13 );
583 0 : pO->push_back( nWwLevel );
584 0 : }
585 :
586 0 : void WW8Export::Out_SwNumLvl( sal_uInt8 nSwLevel )
587 : {
588 : OSL_ENSURE( nSwLevel < MAXLEVEL, "numbered?");
589 0 : Out_WwNumLvl( nSwLevel + 1 );
590 0 : }
591 :
592 0 : void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
593 : sal_uInt16& rCharLen, const SwNumFmt& rFmt)
594 : {
595 0 : ByteToSVBT8(11, rAnlv.nfc);
596 :
597 0 : sal_uInt8 nb = 0; // Zahlentyp
598 0 : switch (rFmt.GetNumAdjust())
599 : {
600 : case SVX_ADJUST_RIGHT:
601 0 : nb = 2;
602 0 : break;
603 : case SVX_ADJUST_CENTER:
604 0 : nb = 1;
605 0 : break;
606 : case SVX_ADJUST_BLOCK:
607 : case SVX_ADJUST_BLOCKLINE:
608 0 : nb = 3;
609 0 : break;
610 : case SVX_ADJUST_LEFT:
611 : case SVX_ADJUST_END:
612 0 : break;
613 : }
614 :
615 : // #i86652#
616 0 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
617 : {
618 0 : if (GetWordFirstLineOffset(rFmt) < 0)
619 0 : nb |= 0x8; // number will be displayed using a hanging indent
620 : }
621 0 : ByteToSVBT8(nb, rAnlv.aBits1);
622 :
623 0 : if (1 < rCharLen)
624 : {
625 0 : const Font& rFont = rFmt.GetBulletFont()
626 0 : ? *rFmt.GetBulletFont()
627 0 : : numfunc::GetDefBulletFont();
628 0 : String sNumStr = rtl::OUString(rFmt.GetBulletChar());
629 0 : rtl_TextEncoding eChrSet = rFont.GetCharSet();
630 0 : String sFontName = rFont.GetName();
631 :
632 : sal_uInt16 nFontId;
633 0 : if (sw::util::IsStarSymbol(sFontName))
634 : {
635 : /*
636 : If we are starsymbol then in ww7- mode we will always convert to a
637 : windows 8bit symbol font and an index into it, to conversion to
638 : 8 bit is complete at this stage.
639 : */
640 0 : SubstituteBullet(sNumStr, eChrSet, sFontName);
641 : wwFont aPseudoFont(sFontName, rFont.GetPitch(), rFont.GetFamily(),
642 0 : eChrSet, bWrtWW8);
643 0 : nFontId = maFontHelper.GetId(aPseudoFont);
644 0 : *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
645 : }
646 : else
647 : {
648 : /*
649 : Otherwise we are a unicode char and need to be converted back to
650 : an 8 bit format. We happen to know that if the font is already an
651 : 8 bit windows font currently, staroffice promotes the char into
652 : the F000->F0FF range, so we can undo this, and we'll be back to
653 : the equivalent 8bit location, otherwise we have to convert from
654 : true unicode to an 8bit charset
655 : */
656 0 : nFontId = maFontHelper.GetId(rFont);
657 0 : sal_Unicode cChar = sNumStr.GetChar(0);
658 0 : if ( (eChrSet == RTL_TEXTENCODING_SYMBOL) && (cChar >= 0xF000) && (
659 : cChar <= 0xF0FF) )
660 : {
661 0 : *rpCh = static_cast< sal_uInt8 >(cChar - 0xF000);
662 : }
663 : else
664 0 : *rpCh = rtl::OUStringToOString(rtl::OUString(cChar), eChrSet).toChar();
665 : }
666 0 : rpCh++;
667 0 : rCharLen--;
668 0 : ShortToSVBT16(nFontId, rAnlv.ftc);
669 0 : ByteToSVBT8( 1, rAnlv.cbTextBefore );
670 : }
671 : // #i86652#
672 0 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
673 : {
674 0 : ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
675 0 : ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
676 : }
677 : else
678 : {
679 0 : ShortToSVBT16( 0, rAnlv.dxaIndent );
680 0 : ShortToSVBT16( 0, rAnlv.dxaSpace );
681 : }
682 0 : }
683 :
684 0 : void MSWordExportBase::SubstituteBullet( String& rNumStr,
685 : rtl_TextEncoding& rChrSet, String& rFontName ) const
686 : {
687 0 : if (!bSubstituteBullets)
688 0 : return;
689 0 : rtl::OUString sFontName = rFontName;
690 0 : rNumStr.SetChar(0, msfilter::util::bestFitOpenSymbolToMSFont(rNumStr.GetChar(0),
691 0 : rChrSet, sFontName, !SupportsUnicode()));
692 0 : rFontName = sFontName;
693 : }
694 :
695 0 : static void SwWw8_InsertAnlText( const String& rStr, sal_uInt8*& rpCh,
696 : sal_uInt16& rCharLen, SVBT8& r8Len )
697 : {
698 0 : sal_uInt8 nb = 0;
699 0 : ww::bytes aO;
700 0 : SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
701 :
702 0 : sal_uInt16 nCnt = aO.size();
703 0 : if( nCnt && nCnt < rCharLen )
704 : {
705 0 : nb = (sal_uInt8)nCnt;
706 0 : std::copy( aO.begin(), aO.end(), rpCh );
707 0 : rpCh += nCnt;
708 0 : rCharLen = rCharLen - nCnt;
709 : }
710 0 : ByteToSVBT8( nb, r8Len );
711 0 : }
712 :
713 0 : void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
714 : sal_uInt16& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt,
715 : sal_uInt8 nSwLevel)
716 : {
717 0 : ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc);
718 :
719 0 : sal_uInt8 nb = 0;
720 0 : switch (rFmt.GetNumAdjust())
721 : {
722 : case SVX_ADJUST_RIGHT:
723 0 : nb = 2;
724 0 : break;
725 : case SVX_ADJUST_CENTER:
726 0 : nb = 1;
727 0 : break;
728 : case SVX_ADJUST_BLOCK:
729 : case SVX_ADJUST_BLOCKLINE:
730 0 : nb = 3;
731 0 : break;
732 : case SVX_ADJUST_LEFT:
733 : case SVX_ADJUST_END:
734 0 : break;
735 : }
736 :
737 0 : bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
738 0 : if( bInclUpper )
739 0 : nb |= 0x4; // include previous levels
740 :
741 0 : if (GetWordFirstLineOffset(rFmt) < 0)
742 0 : nb |= 0x8; // number will be displayed using a hanging indent
743 0 : ByteToSVBT8( nb, rAnlv.aBits1 );
744 :
745 0 : if( bInclUpper && !rRul.IsContinusNum() )
746 : {
747 0 : if( (nSwLevel >= WW8ListManager::nMinLevel )
748 : && (nSwLevel<= WW8ListManager::nMaxLevel )
749 0 : && (rFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // UEberhaupt Nummerierung ?
750 : { // -> suche, ob noch Zahlen davor
751 0 : sal_uInt8 nUpper = rFmt.GetIncludeUpperLevels();
752 0 : if( (nUpper <= WW8ListManager::nMaxLevel) &&
753 0 : (rRul.Get(nUpper).GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // Nummerierung drueber ?
754 : {
755 : // dann Punkt einfuegen
756 : SwWw8_InsertAnlText( aDotStr, rpCh, rCharLen,
757 0 : rAnlv.cbTextBefore );
758 : }
759 :
760 : }
761 : }
762 : else
763 : {
764 0 : SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
765 0 : rAnlv.cbTextBefore );
766 0 : SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
767 0 : rAnlv.cbTextAfter );
768 : }
769 :
770 0 : ShortToSVBT16( rFmt.GetStart(), rAnlv.iStartAt );
771 : // #i86652#
772 0 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
773 : {
774 0 : ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
775 0 : ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
776 : }
777 : else
778 : {
779 0 : ShortToSVBT16( 0, rAnlv.dxaIndent );
780 0 : ShortToSVBT16( 0, rAnlv.dxaSpace );
781 : }
782 0 : }
783 :
784 0 : void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
785 : sal_uInt8 nSwLevel )
786 : {
787 : static sal_uInt8 aSprmAnldDefault[54] = {
788 : 12, 52,
789 : 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
790 : 0,0,0,
791 : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
792 : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
793 : sal_uInt8 aSprmAnld[54];
794 :
795 0 : memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) );
796 0 : WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2); // handlicher Pointer
797 :
798 0 : sal_uInt8* pChars = (sal_uInt8*)(pA->rgchAnld);
799 0 : sal_uInt16 nCharLen = 31;
800 :
801 0 : if( nSwLevel == 11 )
802 0 : BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
803 : else
804 0 : BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel );
805 :
806 : // ... und raus damit
807 0 : OutSprmBytes( (sal_uInt8*)&aSprmAnld, sizeof( aSprmAnld ) );
808 0 : }
809 :
810 :
811 : // Return: ist es eine Gliederung ?
812 0 : bool WW8Export::Out_SwNum(const SwTxtNode* pNd)
813 : {
814 0 : int nLevel = pNd->GetActualListLevel();
815 :
816 0 : if (nLevel < 0 || nLevel >= MAXLEVEL)
817 : {
818 : OSL_FAIL("Invalid level");
819 :
820 0 : return false;
821 : }
822 :
823 0 : sal_uInt8 nSwLevel = static_cast< sal_uInt8 >(nLevel);
824 :
825 0 : const SwNumRule* pRul = pNd->GetNumRule();
826 0 : if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
827 0 : return false;
828 :
829 0 : bool bRet = true;
830 :
831 0 : SwNumFmt aFmt(pRul->Get(nSwLevel));
832 : // #i86652#
833 0 : if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
834 : {
835 0 : const SvxLRSpaceItem& rLR = ItemGet<SvxLRSpaceItem>(*pNd, RES_LR_SPACE);
836 0 : aFmt.SetAbsLSpace(writer_cast<short>(aFmt.GetAbsLSpace() + rLR.GetLeft()));
837 : }
838 :
839 0 : if (
840 0 : aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
841 0 : aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
842 0 : aFmt.GetNumberingType() == SVX_NUM_BITMAP
843 : )
844 : {
845 0 : Out_WwNumLvl(11);
846 0 : Out_NumRuleAnld(*pRul, aFmt, 11);
847 0 : bRet = false;
848 : }
849 0 : else if (
850 0 : pRul->IsContinusNum() ||
851 0 : (pRul->Get(1).GetIncludeUpperLevels() <= 1)
852 : )
853 : {
854 0 : Out_WwNumLvl(10);
855 0 : Out_NumRuleAnld(*pRul, aFmt, 10);
856 0 : bRet = false;
857 : }
858 : else
859 : {
860 0 : Out_SwNumLvl(nSwLevel);
861 0 : Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
862 : }
863 0 : return bRet;
864 18 : }
865 :
866 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|