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