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