LibreOffice Module sw (master): ww8atr.cxx Source File * This file incorporates work covered by ... For Combined Characters in docx, MS Word uses half the normal ... currently writing

Embed Size (px)

Citation preview

LibreOffice Module sw (master): ww8atr.cxx Source File

LibreOffice Module sw (master) 1

MainPageRelatedPagesModulesNamespacesClassesFilesExamples

FileListFileMembers

swsourcefilterww8

ww8atr.cxx

Go to the documentation of this file. 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 * This file contains methods for the WW8 output

22 * (nodes, attributes, formats and chars).

23 */

24

25#include

26

27#include

28#include

29#include

30

31#include

32#include

33#include

34#include

35#include

36#include

37#include

38#include

39#include

40#include

41#include

42#include

43#include

44#include

45#include

46#include

47#include

48#include

49#include

50#include

51#include

52#include

53#include

54#include

55#include

56#include

57#include

58#include

59#include

60#include

61#include

62#include

63#include

64#include

65#include

66#include

67#include

68#include

69#include

70#include

71#include

72#include

73#include

74#include

75#include

76#include

77#include

78#include

79#include

80#include

81#include

82#include

83#include

84#include

85#include

86#include

87#include

88#include

89#include

90#include

91#include

92#include

93#include

94#include

95#include

96#include

97#include

98#include

99#include

100#include

101#include

102#include

103#include

104#include

105#include

106#include

107#include

108#include

109#include

110#include

111#include

112#include

113#include

114#include

115#include

116#include

117#include

118#include

119#include

120#include

121#include

122#include

123#include

124#include

125#include

126#include

127

128#include "sprmids.hxx"

129

130#include

131#include "writerhelper.hxx"

132#include "writerwordglue.hxx"

133#include "wrtww8.hxx"

134#include "ww8par.hxx"

135#include "ww8attributeoutput.hxx"

136#include "fields.hxx"

137#include

138#include

139#include

140#include

141#include

142

143

144using ::editeng::SvxBorderLine;

145using namespace ::com::sun::star;

146using namespace nsSwDocInfoSubType;

147using namespace sw::util;

148using namespace sw::types;

149

150bool WW8Export::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )

151{

152 bool bRet = true;

153 if ( nScript == i18n::ScriptType::ASIAN )

154 {

155 //for asian in ww8, there is only one fontsize

156 //and one fontstyle (posture/weight) for ww6

157 //there is the additional problem that there

158 //is only one font setting for all three scripts

159 switch ( nWhich )

160 {

161 case RES_CHRATR_FONTSIZE:

162 case RES_CHRATR_POSTURE:

163 case RES_CHRATR_WEIGHT:

164 bRet = false;

165 break;

166 case RES_CHRATR_LANGUAGE:

167 case RES_CHRATR_CTL_FONT:

168 case RES_CHRATR_CTL_FONTSIZE:

169 case RES_CHRATR_CTL_LANGUAGE:

170 case RES_CHRATR_CTL_POSTURE:

171 case RES_CHRATR_CTL_WEIGHT:

172 default:

173 break;

174 }

175 }

176 else if ( nScript == i18n::ScriptType::COMPLEX )

177 {

178 //Complex is ok in ww8, but for ww6 there is only

179 //one font, one fontsize, one fontsize (weight/posture)

180 //and only one language

181 }

182 else

183 {

184 //for western in ww8, there is only one fontsize

185 //and one fontstyle (posture/weight) for ww6

186 //there is the additional problem that there

187 //is only one font setting for all three scripts

188 switch ( nWhich )

189 {

190 case RES_CHRATR_CJK_FONTSIZE:

191 case RES_CHRATR_CJK_POSTURE:

192 case RES_CHRATR_CJK_WEIGHT:

193 bRet = false;

194 break;

195 case RES_CHRATR_CJK_LANGUAGE:

196 case RES_CHRATR_CTL_FONT:

197 case RES_CHRATR_CTL_FONTSIZE:

198 case RES_CHRATR_CTL_LANGUAGE:

199 case RES_CHRATR_CTL_POSTURE:

200 case RES_CHRATR_CTL_WEIGHT:

201 default:

202 break;

203 }

204 }

205 return bRet;

206}

207

208

209void MSWordExportBase::ExportPoolItemsToCHP( ww8::PoolItems &rItems, sal_uInt16 nScript, const SvxFontItem *pFont, bool bWriteCombChars )

210{

211 ww8::cPoolItemIter aEnd = rItems.end();

212 for ( ww8::cPoolItemIter aI = rItems.begin(); aI != aEnd; ++aI )

213 {

214 const SfxPoolItem *pItem = aI->second;

215 sal_uInt16 nWhich = pItem->Which();

216 if ( ( isCHRATR( nWhich ) || isTXTATR( nWhich ) ) && CollapseScriptsforWordOk( nScript, nWhich ) )

217 {

218 //In the id definition, RES_TXTATR_INETFMT must precede RES_TXTATR_CHARFMT, so that link style can overwrite char style.

219 //and in #i24291# it describes "All we want to do is ensure for now is that if a charfmt exist in the character

220 //properties that it rises to the top and is exported first."

221 //In bug 119649, it is in such situation, so we need to ignore the link style when doing ms word filter exports and

222 //add the second judgement for #i24291# definition.

223 if ( nWhich == RES_TXTATR_INETFMT && ( rItems.begin()->second->Which() == RES_TXTATR_CHARFMT ) )

224 continue;

225

226 // tdf#38778 Fix output of the font in DOC run for fields

227 if (pFont &&

228 nWhich == RES_TXTATR_FIELD)

229 {

230 AttrOutput().OutputItem( *pFont );

231 }

232

233 // tdf#66401 For Combined Characters in docx, MS Word uses half the normal font-size for the field's

234 // font-size, but only for . Therefore, we check if we are currently writing a field of type

235 // Combined Characters and if so, we half the font size.

236 if (bWriteCombChars &&

237 nWhich == RES_CHRATR_FONTSIZE)

238 {

239 SvxFontHeightItem fontHeight(item_cast( *pItem ));

240 fontHeight.SetHeight( fontHeight.GetHeight() / 2 );

241

242 AttrOutput().OutputItem( fontHeight );

243 }

244 else

245 {

246 AttrOutput().OutputItem( *pItem );

247 }

248 }

249 }

250}

251

252/*

253 * Output format as follows:

254 * - output the attributes; without parents!

255 */

256

257void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript,

258 bool bExportParentItemSet )

259{

260 if( bExportParentItemSet || rSet.Count() )

261 {

262 const SfxPoolItem* pItem;

263 m_pISet = &rSet; // for double attributes

264

265 // If frame dir is set, but not adjust, then force adjust as well

266 if ( bPapFormat && SfxItemState::SET == rSet.GetItemState( RES_FRAMEDIR, bExportParentItemSet ) )

267 {

268 // No explicit adjust set ?

269 if ( SfxItemState::SET != rSet.GetItemState( RES_PARATR_ADJUST, bExportParentItemSet ) )

270 {

271 if ( nullptr != ( pItem = rSet.GetItem( RES_PARATR_ADJUST, bExportParentItemSet ) ) )

272 {

273 // then set the adjust used by the parent format

274 AttrOutput().OutputItem( *pItem );

275 }

276 }

277 }

278

279 if ( bPapFormat && SfxItemState::SET == rSet.GetItemState( RES_PARATR_NUMRULE, bExportParentItemSet, &pItem ) )

280 {

281 AttrOutput().OutputItem( *pItem );

282

283 // switch off the numbering?

284 if ( static_cast(pItem)->GetValue().isEmpty() &&

285 SfxItemState::SET != rSet.GetItemState( RES_LR_SPACE, false) &&

286 SfxItemState::SET == rSet.GetItemState( RES_LR_SPACE, true, &pItem ) )

287 {

288 // the set the LR-Space of the parentformat!

289 AttrOutput().OutputItem( *pItem );

290 }

291 }

292

293 ww8::PoolItems aItems;

294 GetPoolItems( rSet, aItems, bExportParentItemSet );

295 if ( bChpFormat )

296 ExportPoolItemsToCHP(aItems, nScript, nullptr);

297 if ( bPapFormat )

298 {

299 ww8::cPoolItemIter aEnd = aItems.end();

300 for ( ww8::cPoolItemIter aI = aItems.begin(); aI != aEnd; ++aI )

301 {

302 pItem = aI->second;

303 sal_uInt16 nWhich = pItem->Which();

304 // Handle fill attributes just like frame attributes for now.

305 if ( (nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END && nWhich != RES_PARATR_NUMRULE ) ||

306 (nWhich >= XATTR_FILL_FIRST && nWhich < XATTR_FILL_LAST))

307 AttrOutput().OutputItem( *pItem );

308 }

309

310 // Has to be called after RES_PARATR_GRABBAG is processed.

311 const XFillStyleItem* pXFillStyleItem(rSet.GetItem(XATTR_FILLSTYLE));

312 if (pXFillStyleItem && pXFillStyleItem->GetValue() == drawing::FillStyle_SOLID && !rSet.HasItem(RES_BACKGROUND))

313 {

314 // Construct an SvxBrushItem, as expected by the exporters.

315 AttrOutput().OutputItem(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND));

316 }

317 }

318 m_pISet = nullptr; // for double attributes

319 }

320}

321

322void MSWordExportBase::GatherChapterFields()

323{

324 //If the header/footer contains a chapter field

325 SwFieldType* pType = m_pDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter );

326 SwIterator aFormatFields( *pType );

327 for ( SwFormatField* pField = aFormatFields.First(); pField; pField = aFormatFields.Next() )

328 {

329 if (const SwTextField *pTextField = pField->GetTextField())

330 {

331 const SwTextNode &rTextNode = pTextField->GetTextNode();

332 m_aChapterFieldLocs.push_back(rTextNode.GetIndex());

333 }

334 }

335}

336

337bool MSWordExportBase::ContentContainsChapterField(const SwFormatContent &rContent) const

338{

339 bool bRet = false;

340 if ( const SwNodeIndex* pSttIdx = rContent.GetContentIdx() )

341 {

342 SwNodeIndex aIdx( *pSttIdx, 1 );

343 SwNodeIndex aEnd( *pSttIdx->GetNode().EndOfSectionNode() );

344 sal_uLong nStart = aIdx.GetIndex();

345 sal_uLong nEnd = aEnd.GetIndex();

346 //If the header/footer contains a chapter field

347 mycCFIter aIEnd = m_aChapterFieldLocs.end();

348 for ( mycCFIter aI = m_aChapterFieldLocs.begin(); aI != aIEnd; ++aI )

349 {

350 if ( ( nStart GetContent() );

373}

374

375bool MSWordExportBase::SetCurrentPageDescFromNode(const SwNode &rNd)

376{

377 bool bNewPageDesc = false;

378 const SwPageDesc* pCurrent = SwPageDesc::GetPageDescOfNode(rNd);

379 OSL_ENSURE(pCurrent && m_pCurrentPageDesc, "Not possible surely");

380 if (m_pCurrentPageDesc && pCurrent)

381 {

382 if (pCurrent != m_pCurrentPageDesc)

383 {

384 if (m_pCurrentPageDesc->GetFollow() != pCurrent)

385 bNewPageDesc = true;

386 else

387 {

388 const SwFrameFormat& rTitleFormat = m_pCurrentPageDesc->GetFirstMaster();

389 const SwFrameFormat& rFollowFormat = pCurrent->GetMaster();

390

391 bNewPageDesc = !IsPlausableSingleWordSection(rTitleFormat,

392 rFollowFormat);

393 }

394 m_pCurrentPageDesc = pCurrent;

395 }

396 else

397 {

398 const SwFrameFormat &rFormat = pCurrent->GetMaster();

399 bNewPageDesc = FormatHdFtContainsChapterField(rFormat);

400 }

401 }

402 return bNewPageDesc;

403}

404

415void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode& rNd, bool isCellOpen, bool isTextNodeEmpty)

416{

417 if ( m_bStyDef || m_bOutKF || m_bInWriteEscher || m_bOutPageDescs )

418 return;

419

420 m_bBreakBefore = true;

421 bool bNewPageDesc = false;

422 const SfxPoolItem* pItem=nullptr;

423 const SwFormatPageDesc *pPgDesc=nullptr;

424

425 //Output a sectionbreak if there's a new pagedescriptor. Otherwise output a

426 //pagebreak if there is a pagebreak here, unless the new page (follow

427 //style) is different to the current one, in which case plump for a

428 //section.

429 bool bBreakSet = false;

430

431 const SwPageDesc * pPageDesc = rNd.FindPageDesc();

432

433 // Even if pAktPageDesc != pPageDesc ,it might be because of the different header & footer types.

434 if (m_pCurrentPageDesc != pPageDesc)

435 {

436 if ( ( isCellOpen && ( m_pCurrentPageDesc->GetName() != pPageDesc->GetName() )) ||

437 ( isTextNodeEmpty || m_bPrevTextNodeIsEmpty ))

438 {

439 /* Do not output a section break in the following scenarios.

440 1) Table cell is open and page header types are different

441 2) PageBreak is present but text node has no string - it is an empty node.

442 3) If the previous node was an empty text node and current node is a non empty text node or vice versa.

443 4) If previous node and current node both are empty text nodes.

444 Converting a page break to section break would cause serious issues while importing

445 the RT files with different first page being set.

446 */

447 bNewPageDesc = false;

448

449 /*

450 * If Table cell is open and page header types are different

451 * set pSet to NULL as we don't want to add any section breaks.

452 */

453 if ( isCellOpen && ( m_pCurrentPageDesc->GetName() != pPageDesc->GetName() ) )

454 pSet = nullptr;

455 }

456 else if (!sw::util::IsPlausableSingleWordSection(m_pCurrentPageDesc->GetFirstMaster(), pPageDesc->GetMaster()))

457 {

458 bBreakSet = true;

459 bNewPageDesc = true;

460 m_pCurrentPageDesc = pPageDesc;

461 }

462 }

463

464 if ( pSet && pSet->Count() )

465 {

466 if ( SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem ) &&

467 static_cast(pItem)->GetRegisteredIn() != nullptr)

468 {

469 bBreakSet = true;

470 bNewPageDesc = true;

471 pPgDesc = static_cast(pItem);

472 m_pCurrentPageDesc = pPgDesc->GetPageDesc();

473 }

474 else if ( SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem ) )

475 {

476 // Word does not like hard break attributes in some table cells

477 bool bRemoveHardBreakInsideTable = false;

478 if ( m_bOutTable )

479 {

480 const SwTableNode* pTableNode = rNd.FindTableNode();

481 if ( pTableNode )

482 {

483 const SwTableBox* pBox = rNd.GetTableBox();

484 const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr;

485 // but only for non-complex tables

486 if ( pLine && !pLine->GetUpper() )

487 {

488 // check if box is not first in that line:

489 if ( 0 < pLine->GetBoxPos( pBox ) && pBox->GetSttNd() )

490 {

491 bRemoveHardBreakInsideTable = true;

492 }

493 }

494 }

495 }

496 bNewPageDesc = false; // if next node has RES_BREAK(page break) then bNewPageDesc value should be false.

497 bBreakSet = true;

498

499 if ( !bRemoveHardBreakInsideTable )

500 {

501 OSL_ENSURE(m_pCurrentPageDesc, "should not be possible");

502 /*

503 If because of this pagebreak the page desc following the page

504 break is the follow style of the current page desc then output a

505 section break using that style instead. At least in those cases

506 we end up with the same style in word and writer, nothing can be

507 done when it happens when we get a new pagedesc because we

508 overflow from the first page style.

509 */

510 if ( m_pCurrentPageDesc )

511 {

512 // #i76301# - assure that there is a page break before set at the node.

513 const SvxFormatBreakItem* pBreak = dynamic_cast(pItem);

514 if ( pBreak &&

515 pBreak->GetBreak() == SvxBreak::PageBefore )

516 {

517 bNewPageDesc |= SetCurrentPageDescFromNode( rNd );

518 }

519 if( isTextNodeEmpty )

520 bNewPageDesc = false;

521 }

522 if ( !bNewPageDesc )

523 AttrOutput().OutputItem( *pItem );

524 }

525 }

526 }

527

528 /*

529 #i9301#

530 No explicit page break, lets see if the style had one and we've moved to a

531 new page style because of it, if we have to then we take the opportunity to

532 set the equivalent word section here. We *could* do it for every paragraph

533 that moves onto a new page because of layout, but that would be insane.

534 */

535 bool bHackInBreak = false;

536 if ( !bBreakSet )

537 {

538 if ( const SwContentNode *pNd = rNd.GetContentNode() )

539 {

540 const SvxFormatBreakItem &rBreak =

541 ItemGet( *pNd, RES_BREAK );

542 if ( rBreak.GetBreak() == SvxBreak::PageBefore )

543 bHackInBreak = true;

544 else

545 { // Even a pagedesc item is set, the break item can be set 'NONE',

546 // but a pagedesc item is an implicit page break before...

547 const SwFormatPageDesc &rPageDesc =

548 ItemGet( *pNd, RES_PAGEDESC );

549 if ( rPageDesc.KnowsPageDesc() )

550 bHackInBreak = true;

551 }

552 }

553 }

554

555 if ( bHackInBreak )

556 {

557 OSL_ENSURE( m_pCurrentPageDesc, "should not be possible" );

558 if ( m_pCurrentPageDesc )

559 bNewPageDesc = SetCurrentPageDescFromNode( rNd );

560 }

561

562 if ( bNewPageDesc && m_pCurrentPageDesc )

563 {

564 PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc );

565 }

566 m_bBreakBefore = false;

567 m_bPrevTextNodeIsEmpty = isTextNodeEmpty ;

568}

569

570// #i76300#

571bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTextNode* pNd )

572{

573 bool bRet = false;

574

575 if ( pNd &&

576 m_pCurrentPageDesc &&

577 m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() )

578 {

579 PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() );

580 bRet = true;

581 }

582

583 return bRet;

584}

585

586const SwSectionFormat* MSWordExportBase::GetSectionFormat( const SwNode& rNd )

587{

588 const SwSectionFormat* pFormat = nullptr;

589 const SwSectionNode* pSect = rNd.FindSectionNode();

590 if ( pSect &&

591 CONTENT_SECTION == pSect->GetSection().GetType() )

592 {

593 pFormat = pSect->GetSection().GetFormat();

594 }

595

596 return pFormat;

597}

598

599sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNode& rNd )

600{

601 const SwFormatLineNumber* pNItem = nullptr;

602 if ( pSet )

603 {

604 pNItem = &( ItemGet( *pSet, RES_LINENUMBER ) );

605 }

606 else if ( const SwContentNode *pNd = rNd.GetContentNode() )

607 {

608 pNItem = &( ItemGet( *pNd, RES_LINENUMBER ) );

609 }

610

611 return pNItem? pNItem->GetStartValue() : 0;

612}

613

614void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,

615 const SwNode& rNd,

616 const SwFormatPageDesc* pNewPgDescFormat,

617 const SwPageDesc* pNewPgDesc )

618{

619 // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding

620 // position by the occurrences of PageDesc attributes. The construction and

621 // output of the attributes and header/footer of the PageDesc are done

622 // after the main text and its attributes.

623

624 sal_uLong nFcPos = ReplaceCr( msword::PageBreak ); // Page/Section-Break

625

626 // actually nothing is outputted here, rather the arrays aCps, aSects

627 // accordingly completed

628 if ( !nFcPos )

629 return;

630

631 const SwSectionFormat* pFormat = GetSectionFormat( rNd );

632 const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );

633

634 OSL_ENSURE( pNewPgDescFormat || pNewPgDesc, "Neither page desc format nor page desc provided." );

635

636 if ( pNewPgDescFormat )

637 {

638 pSepx->AppendSep( Fc2Cp( nFcPos ), *pNewPgDescFormat, rNd, pFormat, nLnNm );

639 }

640 else if ( pNewPgDesc )

641 {

642 pSepx->AppendSep( Fc2Cp( nFcPos ), pNewPgDesc, rNd, pFormat, nLnNm );

643 }

644}

645

646void MSWordExportBase::CorrectTabStopInSet( SfxItemSet& rSet, short nAbsLeft )

647{

648 if (const SvxTabStopItem *pItem = rSet.GetItem(RES_PARATR_TABSTOP))

649 {

650 // then it must be corrected for the output

651 SvxTabStopItem aTStop(*pItem);

652 for ( sal_uInt16 nCnt = 0; nCnt < aTStop.Count(); ++nCnt )

653 {

654 SvxTabStop& rTab = const_cast(aTStop[ nCnt ]);

655 if ( SvxTabAdjust::Default != rTab.GetAdjustment() &&

656 rTab.GetTabPos() >= nAbsLeft )

657 {

658 rTab.GetTabPos() -= nAbsLeft;

659 }

660 else

661 {

662 aTStop.Remove( nCnt );

663 --nCnt;

664 }

665 }

666 rSet.Put( aTStop );

667 }

668}

669

670sal_uInt8 WW8Export::GetNumId( sal_uInt16 eNumType )

671{

672 sal_uInt8 nRet = 0;

673 switch( eNumType )

674 {

675 case SVX_NUM_CHARS_UPPER_LETTER:

676 case SVX_NUM_CHARS_UPPER_LETTER_N: nRet = 3; break;

677 case SVX_NUM_CHARS_LOWER_LETTER:

678 case SVX_NUM_CHARS_LOWER_LETTER_N: nRet = 4; break;

679 case SVX_NUM_ROMAN_UPPER: nRet = 1; break;

680 case SVX_NUM_ROMAN_LOWER: nRet = 2; break;

681

682 case SVX_NUM_BITMAP:

683 case SVX_NUM_CHAR_SPECIAL: nRet = 23; break;

684

685 // nothing, WW does the same (undocumented)

686 case SVX_NUM_NUMBER_NONE: nRet = 0xff; break;

687 }

688 return nRet;

689}

690

691void WW8AttributeOutput::OutlineNumbering(sal_uInt8 nLvl)

692{

693 if ( nLvl >= WW8ListManager::nMaxLevel )

694 nLvl = WW8ListManager::nMaxLevel-1;

695

696 // write sprmPOutLvl sprmPIlvl and sprmPIlfo

697 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::sprmPOutLvl );

698 m_rWW8Export.pO->push_back( nLvl );

699 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::sprmPIlvl );

700 m_rWW8Export.pO->push_back( nLvl );

701 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::sprmPIlfo );

702 SwWW8Writer::InsUInt16( *m_rWW8Export.pO,

703 1 + m_rWW8Export.GetId( *m_rWW8Export.m_pDoc->GetOutlineNumRule() ) );

704}

705

706// #i77805#

707bool WW8Export::DisallowInheritingOutlineNumbering(const SwFormat &rFormat)

708{

709 bool bRet( false );

710

711 //If there is no numbering on this fmt, but its parent was outline

712 //numbered, then in writer this is no inheritied, but in word it would

713 //be, so we must export "no numbering" and "body level" to make word

714 //behave like writer (see #i25755)

715 if (SfxItemState::SET != rFormat.GetItemState(RES_PARATR_NUMRULE, false))

716 {

717 if (const SwFormat *pParent = rFormat.DerivedFrom())

718 {

719 if (static_cast(pParent)->IsAssignedToListLevelOfOutlineStyle())

720 {

721 SwWW8Writer::InsUInt16(*pO, NS_sprm::sprmPOutLvl);

722 pO->push_back(sal_uInt8(9));

723 SwWW8Writer::InsUInt16(*pO, NS_sprm::sprmPIlfo);

724 SwWW8Writer::InsUInt16(*pO, 0);

725

726 bRet = true;

727 }

728 }

729 }

730

731 return bRet;

732}

733

734void MSWordExportBase::OutputFormat( const SwFormat& rFormat, bool bPapFormat, bool bChpFormat, bool bFlyFormat )

735{

736 bool bCallOutSet = true;

737 const SwModify* pOldMod = m_pOutFormatNode;

738 m_pOutFormatNode = &rFormat;

739

740 switch( rFormat.Which() )

741 {

742 case RES_CONDTXTFMTCOLL:

743 case RES_TXTFMTCOLL:

744 if( bPapFormat )

745 {

746 int nLvl = MAXLEVEL;

747

748 if (static_cast(rFormat).IsAssignedToListLevelOfOutlineStyle())

749 nLvl = static_cast(rFormat).GetAssignedOutlineStyleLevel();

750

751 if (nLvl >= 0 && nLvl < MAXLEVEL)

752 {

753 //if outline numbered

754 // if Write StyleDefinition then write the OutlineRule

755 const SwNumFormat& rNFormat = m_pDoc->GetOutlineNumRule()->Get( static_cast( nLvl ) );

756 if ( m_bStyDef )

757 AttrOutput().OutlineNumbering(static_cast(nLvl));

758

759 if ( rNFormat.GetPositionAndSpaceMode() ==

760 SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&

761 rNFormat.GetAbsLSpace() )

762 {

763 SfxItemSet aSet( rFormat.GetAttrSet() );

764 SvxLRSpaceItem aLR(

765 ItemGet(aSet, RES_LR_SPACE));

766

767 aLR.SetTextLeft( aLR.GetTextLeft() + rNFormat.GetAbsLSpace() );

768 aLR.SetTextFirstLineOfst( GetWordFirstLineOffset(rNFormat));

769

770 aSet.Put( aLR );

771 CorrectTabStopInSet( aSet, rNFormat.GetAbsLSpace() );

772 OutputItemSet( aSet, bPapFormat, bChpFormat,

773 i18n::ScriptType::LATIN, m_bExportModeRTF);

774 bCallOutSet = false;

775 }

776 }

777 else

778 {

779 //otherwise we might have to remove outline numbering from

780 //what gets exported if the parent style was outline numbered

781 // #i77805#

782 // If inherited outline numbering is suppress, the left/right

783 // margins has to be exported explicitly.

784 if ( m_bStyDef && DisallowInheritingOutlineNumbering(rFormat) )

785 {

786 SfxItemSet aSet( rFormat.GetAttrSet() );

787 const SvxLRSpaceItem& aLR(

788 ItemGet(aSet, RES_LR_SPACE));

789 aSet.Put( aLR );

790 OutputItemSet( aSet, bPapFormat, bChpFormat,

791 css::i18n::ScriptType::LATIN, m_bExportModeRTF);

792 bCallOutSet = false;

793 }

794 }

795 }

796 break;

797

798 case RES_CHRFMT:

799 break;

800 case RES_FLYFRMFMT:

801 if (bFlyFormat)

802 {

803 OSL_ENSURE(m_pParentFrame, "No parent frame, all broken");

804

805 if (m_pParentFrame)

806 {

807 const SwFrameFormat &rFrameFormat = m_pParentFrame->GetFrameFormat();

808

809 SfxItemSet aSet(m_pDoc->GetAttrPool(), svl::Items{});

812 aSet.Set(rFrameFormat.GetAttrSet());

813

814 // Fly as character becomes a paragraph bound

815 // now set the distance to paragraph margin

816 if (m_pFlyOffset)

817 {

818 aSet.Put(SwFormatHoriOrient(m_pFlyOffset->X()));

819 aSet.Put(SwFormatVertOrient(m_pFlyOffset->Y()));

820 SwFormatAnchor aAnchor(rFrameFormat.GetAnchor());

821 aAnchor.SetType(m_eNewAnchorType);

822 aSet.Put(aAnchor);

823 }

824

825 if (SfxItemState::SET != aSet.GetItemState(RES_SURROUND))

826 aSet.Put(SwFormatSurround(css::text::WrapTextMode_NONE));

827

828 const XFillStyleItem* pXFillStyleItem(rFrameFormat.GetAttrSet().GetItem(XATTR_FILLSTYLE));

829 if (pXFillStyleItem)

830 {

831 switch (pXFillStyleItem->GetValue())

832 {

833 case drawing::FillStyle_NONE:

834 break;

835 case drawing::FillStyle_SOLID:

836 {

837 // Construct an SvxBrushItem, as expected by the exporters.

838 aSet.Put(getSvxBrushItemFromSourceSet(rFrameFormat.GetAttrSet(), RES_BACKGROUND));

839 break;

840 }

841 default:

842 break;

843 }

844 }

845

846 m_bOutFlyFrameAttrs = true;

847 //script doesn't matter if not exporting chp

848 OutputItemSet(aSet, true, false,

849 i18n::ScriptType::LATIN, m_bExportModeRTF);

850 m_bOutFlyFrameAttrs = false;

851

852 bCallOutSet = false;

853 }

854 }

855 break;

856 case RES_FRMFMT:

857 break;

858 default:

859 OSL_ENSURE( false, "Which format is exported here?" );

860 break;

861 }

862

863 if( bCallOutSet )

864 OutputItemSet( rFormat.GetAttrSet(), bPapFormat, bChpFormat,

865 i18n::ScriptType::LATIN, m_bExportModeRTF);

866 m_pOutFormatNode = pOldMod;

867}

868

869bool MSWordExportBase::HasRefToObject( sal_uInt16 nTyp, const OUString* pName, sal_uInt16 nSeqNo )

870{

871

872 SwFieldType* pType = m_pDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef );

873 SwIterator aFormatFields( *pType );

874 for ( SwFormatField* pFormatField = aFormatFields.First(); pFormatField; pFormatField = aFormatFields.Next() )

875 {

876 const SwTextNode* pNd;

877 if ( pFormatField->GetTextField() && nTyp == pFormatField->GetField()->GetSubType() &&

878 nullptr != ( pNd = pFormatField->GetTextField()->GetpTextNode() ) &&

879 pNd->GetNodes().IsDocNodes() )

880 {

881 const SwGetRefField& rRField = *static_cast< SwGetRefField* >( pFormatField->GetField() );

882 switch ( nTyp )

883 {

884 case REF_BOOKMARK:

885 case REF_SETREFATTR:

886 if ( pName && *pName == rRField.GetSetRefName() )

887 return true;

888 break;

889 case REF_FOOTNOTE:

890 case REF_ENDNOTE:

891 if ( nSeqNo == rRField.GetSeqNo() )

892 return true;

893 break;

894 case REF_SEQUENCEFLD:

895 break; // ???

896 case REF_OUTLINE:

897 break; // ???

898 }

899 }

900 }

901

902 return false;

903}

904

905OUString MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp, const OUString* pName, sal_uInt16 nSeqNo )

906{

907 OUString sRet;

908 switch ( nTyp )

909 {

910 case REF_SETREFATTR:

911 if ( pName )

912 {

913 sRet += "Ref_";

914 sRet += *pName;

915 }

916 break;

917 case REF_SEQUENCEFLD:

918 {

919 assert(pName);

920 sRet += "Ref_";

921 sRet += *pName;

922 break;

923 }

924 case REF_BOOKMARK:

925 if ( pName )

926 sRet = *pName;

927 break;

928 case REF_OUTLINE:

929 break; // ???

930 case REF_FOOTNOTE:

931 sRet += "_RefF";

932 sRet += OUString::number( nSeqNo );

933 break;

934 case REF_ENDNOTE:

935 sRet += "_RefE";

936 sRet += OUString::number( nSeqNo );

937 break;

938 }

939 return BookmarkToWord( sRet ); // #i43956# - encode bookmark accordingly

940}

941

942/* File CHRATR.HXX: */

943void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )

944{

945 if (bIsRTL)

946 {

947 if( m_rWW8Export.m_pDoc->GetDocumentType() != SwDoc::DOCTYPE_MSWORD )

948 {

949 m_rWW8Export.InsUInt16( NS_sprm::sprmCFBiDi );

950 m_rWW8Export.pO->push_back( sal_uInt8(1) );

951 }

952 }

953

954 // #i46087# patch from james_clark; complex texts needs the undocumented SPRM CComplexScript with param 0x81.

955 if (nScript == i18n::ScriptType::COMPLEX && !bIsRTL)

956 {

957 m_rWW8Export.InsUInt16( NS_sprm::sprmCFComplexScripts );

958 m_rWW8Export.pO->push_back( sal_uInt8(0x81) );

959 m_rWW8Export.pDop->bUseThaiLineBreakingRules = true;

960 }

961}

962

963void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )

964{

965 m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() - (mbOnTOXEnding?2:0), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );

966 mbOnTOXEnding = false;

967 m_rWW8Export.pO->clear();

968

969 if ( pTextNodeInfoInner.get() != nullptr )

970 {

971 if ( pTextNodeInfoInner->isEndOfLine() )

972 {

973 TableRowEnd( pTextNodeInfoInner->getDepth() );

974

975 SVBT16 nSty;

976 ShortToSVBT16( 0, nSty );

977 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // Style #

978 TableInfoRow( pTextNodeInfoInner );

979 m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data());

980 m_rWW8Export.pO->clear();

981 }

982 }

983

984 // Clear bookmarks of the current paragraph

985 m_aBookmarksOfParagraphStart.clear();

986 m_aBookmarksOfParagraphEnd.clear();

987}

988

989void WW8AttributeOutput::StartRunProperties()

990{

991 WW8_WrPlcField* pCurrentFields = m_rWW8Export.CurrentFieldPlc();

992 m_nFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;

993}

994

995void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool /*bSingleEmptyRun*/ )

996{

997 if (pRedlineData)

998 {

999 const OUString &rComment = pRedlineData->GetComment();

1000 //Only possible to export to main text

1001 if (!rComment.isEmpty() && (m_rWW8Export.m_nTextTyp == TXT_MAINTEXT))

1002 {

1003 if (m_rWW8Export.m_pAtn->IsNewRedlineComment(pRedlineData))

1004 {

1005 m_rWW8Export.m_pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pRedlineData );

1006 m_rWW8Export.WritePostItBegin( m_rWW8Export.pO );

1007 }

1008 }

1009 }

1010

1012 auto aRange = m_aBookmarksOfParagraphStart.equal_range(nPos);

1013 for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)

1014 {

1015 GetExport().AppendBookmark(BookmarkToWord(aIter->second));

1016 }

1017}

1018

1019void WW8AttributeOutput::OnTOXEnding()

1020{

1021 mbOnTOXEnding = true;

1022}

1023

1024void WW8AttributeOutput::EndRun( const SwTextNode* /*pNode*/, sal_Int32 nPos, bool bLastRun )

1025{

1027 auto aRange = m_aBookmarksOfParagraphEnd.equal_range(nPos);

1028 for( auto aIter = aRange.first; aIter != aRange.second; ++aIter)

1029 {

1030 if(bLastRun)

1031 GetExport().AppendBookmarkEndWithCorrection(BookmarkToWord(aIter->second));

1032 else

1033 GetExport().AppendBookmark(BookmarkToWord(aIter->second));

1034 }

1035}

1036

1037void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )

1038{

1039 Redline( pRedlineData );

1040

1041 WW8_WrPlcField* pCurrentFields = m_rWW8Export.CurrentFieldPlc();

1042 sal_uInt16 nNewFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;

1043

1044 bool bExportedFieldResult = ( m_nFieldResults != nNewFieldResults );

1045

1046 // If we have exported a field result, then we will have been forced to

1047 // split up the text into a 0x13, 0x14, 0x15 sequence with the

1048 // properties forced out at the end of the result, so the 0x15 itself

1049 // should remain clean of all other attributes to avoid #iXXXXX#

1050 if ( !bExportedFieldResult )

1051 {

1052 m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),

1053 m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );

1054 }

1055 m_rWW8Export.pO->clear();

1056}

1057

1058void WW8AttributeOutput::RunText( const OUString& rText, rtl_TextEncoding eCharSet )

1059{

1060 RawText(rText, eCharSet);

1061}

1062

1063void WW8AttributeOutput::RawText(const OUString& rText, rtl_TextEncoding)

1064{

1065 m_rWW8Export.OutSwString(rText, 0, rText.getLength());

1066}

1067

1068void WW8AttributeOutput::OutputFKP(bool bForce)

1069{

1070 if (!m_rWW8Export.pO->empty() || bForce)

1071 {

1072 m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),

1073 m_rWW8Export.pO->size(), m_rWW8Export.pO->data() );

1074 m_rWW8Export.pO->clear();

1075 }

1076}

1077

1078void WW8AttributeOutput::ParagraphStyle( sal_uInt16 nStyle )

1079{

1080 OSL_ENSURE( m_rWW8Export.pO->empty(), " pO is not empty at line end" );

1081

1082 SVBT16 nSty;

1083 ShortToSVBT16( nStyle, nSty );

1084 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // style #

1085}

1086

1087void WW8AttributeOutput::OutputWW8Attribute( sal_uInt8 nId, bool bVal )

1088{

1089 m_rWW8Export.InsUInt16( 8 == nId ? NS_sprm::sprmCFDStrike : NS_sprm::sprmCFBold + nId );

1090

1091 m_rWW8Export.pO->push_back( bVal ? 1 : 0 );

1092}

1093

1094void WW8AttributeOutput::OutputWW8AttributeCTL( sal_uInt8 nId, bool bVal )

1095{

1096 OSL_ENSURE( nId 1)

1098 return;

1099

1100 m_rWW8Export.InsUInt16( NS_sprm::sprmCFBoldBi + nId );

1101 m_rWW8Export.pO->push_back( bVal ? 1 : 0 );

1102}

1103

1104void WW8AttributeOutput::CharFont( const SvxFontItem& rFont )

1105{

1106 sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );

1107

1108 m_rWW8Export.InsUInt16( NS_sprm::sprmCRgFtc0 );

1109 m_rWW8Export.InsUInt16( nFontID );

1110 m_rWW8Export.InsUInt16( NS_sprm::sprmCRgFtc2 );

1111

1112 m_rWW8Export.InsUInt16( nFontID );

1113}

1114

1115void WW8AttributeOutput::CharFontCTL( const SvxFontItem& rFont )

1116{

1117 sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );

1118 m_rWW8Export.InsUInt16( NS_sprm::sprmCFtcBi );

1119 m_rWW8Export.InsUInt16( nFontID );

1120}

1121

1122void WW8AttributeOutput::CharFontCJK( const SvxFontItem& rFont )

1123{

1124 sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );

1125 m_rWW8Export.InsUInt16( NS_sprm::sprmCRgFtc1 );

1126 m_rWW8Export.InsUInt16( nFontID );

1127}

1128

1129void WW8AttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )

1130{

1131 OutputWW8AttributeCTL( 0, WEIGHT_BOLD == rWeight.GetWeight());

1132}

1133

1134void WW8AttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture )

1135{

1136 OutputWW8AttributeCTL( 1, ITALIC_NONE != rPosture.GetPosture() );

1137}

1138

1139void WW8AttributeOutput::CharPosture( const SvxPostureItem& rPosture )

1140{

1141 OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() );

1142}

1143

1144void WW8AttributeOutput::CharWeight( const SvxWeightItem& rWeight )

1145{

1146 OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight() );

1147}

1148

1149// Shadowed and Contour are not in WW-UI. JP: ??

1150void WW8AttributeOutput::CharContour( const SvxContourItem& rContour )

1151{

1152 OutputWW8Attribute( 3, rContour.GetValue() );

1153}

1154

1155void WW8AttributeOutput::CharShadow( const SvxShadowedItem& rShadow )

1156{

1157 OutputWW8Attribute( 4, rShadow.GetValue() );

1158}

1159

1160void WW8AttributeOutput::CharKerning( const SvxKerningItem& rKerning )

1161{

1162 m_rWW8Export.InsUInt16( NS_sprm::sprmCDxaSpace );

1163

1164 m_rWW8Export.InsUInt16( rKerning.GetValue() );

1165}

1166

1167void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern )

1168{

1169 m_rWW8Export.InsUInt16( NS_sprm::sprmCHpsKern );

1170

1171 m_rWW8Export.InsUInt16( rAutoKern.GetValue() ? 2 : 0 );

1172}

1173

1174void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )

1175{

1176 m_rWW8Export.InsUInt16( NS_sprm::sprmCSfxText );

1177 // At the moment the only animated text effect we support is blinking

1178 m_rWW8Export.pO->push_back( rBlink.GetValue() ? 2 : 0 );

1179}

1180

1181void WW8AttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossed )

1182{

1183 FontStrikeout eSt = rCrossed.GetStrikeout();

1184 if ( STRIKEOUT_DOUBLE == eSt )

1185 {

1186 OutputWW8Attribute( 8, true );

1187 return;

1188 }

1189 if ( STRIKEOUT_NONE != eSt )

1190 {

1191 OutputWW8Attribute( 2, true );

1192 return;

1193 }

1194

1195 // otherwise both off

1196 OutputWW8Attribute( 8, false );

1197 OutputWW8Attribute( 2, false );

1198}

1199

1200void WW8AttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )

1201{

1202 SvxCaseMap eSt = rCaseMap.GetValue();

1203 switch ( eSt )

1204 {

1205 case SvxCaseMap::SmallCaps:

1206 OutputWW8Attribute( 5, true );

1207 return;

1208 case SvxCaseMap::Uppercase:

1209 OutputWW8Attribute( 6, true );

1210 return;

1211 case SvxCaseMap::Capitalize:

1212 // no such feature in word

1213 break;

1214 default:

1215 // otherwise both off

1216 OutputWW8Attribute( 5, false );

1217 OutputWW8Attribute( 6, false );

1218 return;

1219 }

1220}

1221

1222void WW8AttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )

1223{

1224 OutputWW8Attribute( 7, rHidden.GetValue() );

1225}

1226

1227void WW8AttributeOutput::CharBorder( const SvxBorderLine* pAllBorder, const sal_uInt16 /*nDist*/, const bool bShadow )

1228{

1229 WW8Export::Out_BorderLine( *m_rWW8Export.pO, pAllBorder, 0, NS_sprm::sprmCBrc80, NS_sprm::sprmCBrc, bShadow );

1230}

1231

1232void WW8AttributeOutput::CharHighlight( const SvxBrushItem& rBrush )

1233{

1234 if (rBrush.GetColor() != COL_TRANSPARENT)

1235 {

1236 sal_uInt8 nColor = msfilter::util::TransColToIco( rBrush.GetColor() );

1237 // sprmCHighlight

1238 m_rWW8Export.InsUInt16( NS_sprm::sprmCHighlight );

1239 m_rWW8Export.pO->push_back( nColor );

1240 }

1241}

1242

1243void WW8AttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )

1244{

1245 m_rWW8Export.InsUInt16( NS_sprm::sprmCKul );

1246

1247 const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_CHRATR_WORDLINEMODE );

1248 bool bWord = false;

1249 if (pItem)

1250 bWord = static_cast(pItem)->GetValue();

1251

1252 // WW95 - parameters: 0 = none, 1 = single, 2 = by Word,

1253 // 3 = double, 4 = dotted, 5 = hidden

1254 // WW97 - additional parameters:

1255 // 6 = thick, 7 = dash, 8 = dot(not used)

1256 // 9 = dotdash 10 = dotdotdash, 11 = wave

1257 sal_uInt8 b = 0;

1258 switch ( rUnderline.GetLineStyle() )

1259 {

1260 case LINESTYLE_SINGLE:

1261 b = bWord ? 2 : 1;

1262 break;

1263 case LINESTYLE_BOLD:

1264 b = 6;

1265 break;

1266 case LINESTYLE_DOUBLE:

1267 b = 3;

1268 break;

1269 case LINESTYLE_DOTTED:

1270 b = 4;

1271 break;

1272 case LINESTYLE_DASH:

1273 b = 7;

1274 break;

1275 case LINESTYLE_DASHDOT:

1276 b = 9;

1277 break;

1278 case LINESTYLE_DASHDOTDOT:

1279 b = 10;

1280 break;

1281 case LINESTYLE_WAVE:

1282 b = 11;

1283 break;

1284 // new in WW2000

1285 case LINESTYLE_BOLDDOTTED:

1286 b = 20;

1287 break;

1288 case LINESTYLE_BOLDDASH:

1289 b = 23;

1290 break;

1291 case LINESTYLE_LONGDASH:

1292 b = 39;

1293 break;

1294 case LINESTYLE_BOLDLONGDASH:

1295 b = 55;

1296 break;

1297 case LINESTYLE_BOLDDASHDOT:

1298 b = 25;

1299 break;

1300 case LINESTYLE_BOLDDASHDOTDOT:

1301 b = 26;

1302 break;

1303 case LINESTYLE_BOLDWAVE:

1304 b = 27;

1305 break;

1306 case LINESTYLE_DOUBLEWAVE:

1307 b = 43;

1308 break;

1309 case LINESTYLE_NONE:

1310 b = 0;

1311 break;

1312 default:

1313 OSL_ENSURE( rUnderline.GetLineStyle() == LINESTYLE_NONE, "Unhandled underline type" );

1314 break;

1315 }

1316

1317 m_rWW8Export.pO->push_back( b );

1318 Color aColor = rUnderline.GetColor();

1319 if( aColor != COL_TRANSPARENT )

1320 {

1321 m_rWW8Export.InsUInt16( NS_sprm::sprmCCvUl );

1322

1323 m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( aColor ) );

1324 }

1325}

1326

1327void WW8AttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )

1328{

1329 sal_uInt16 nId = 0;

1330 switch ( rLanguage.Which() )

1331 {

1332 case RES_CHRATR_LANGUAGE:

1333 nId = NS_sprm::sprmCRgLid0_80;

1334 break;

1335 case RES_CHRATR_CJK_LANGUAGE:

1336 nId = NS_sprm::sprmCRgLid1_80;

1337 break;

1338 case RES_CHRATR_CTL_LANGUAGE:

1339 nId = NS_sprm::sprmCLidBi;

1340 break;

1341 }

1342

1343 if ( nId )

1344 {

1345 // use sprmCRgLid0_80 rather than sprmCLid

1346 m_rWW8Export.InsUInt16( nId );

1347 m_rWW8Export.InsUInt16( static_cast(rLanguage.GetLanguage()) );

1348

1349 // Word 2000 and above apparently require both old and new versions of

1350 // these sprms to be set, without it spellchecking doesn't work

1351 if ( nId == NS_sprm::sprmCRgLid0_80 )

1352 {

1353 m_rWW8Export.InsUInt16( NS_sprm::sprmCRgLid0 );

1354 m_rWW8Export.InsUInt16( static_cast(rLanguage.GetLanguage()) );

1355 }

1356 else if ( nId == NS_sprm::sprmCRgLid1_80 )

1357 {

1358 m_rWW8Export.InsUInt16( NS_sprm::sprmCRgLid1 );

1359 m_rWW8Export.InsUInt16( static_cast(rLanguage.GetLanguage()) );

1360 }

1361 }

1362}

1363

1364void WW8AttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )

1365{

1366 sal_uInt8 b = 0xFF;

1367 short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProportionalHeight();

1368 if ( !nEsc )

1369 {

1370 b = 0;

1371 nEsc = 0;

1372 nProp = 100;

1373 }

1374 else if ( DFLT_ESC_PROP == nProp )

1375 {

1376 if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )

1377 b = 2;

1378 else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )

1379 b = 1;

1380 }

1381

1382 if ( 0xFF != b )

1383 {

1384 m_rWW8Export.InsUInt16( NS_sprm::sprmCIss );

1385

1386 m_rWW8Export.pO->push_back( b );

1387 }

1388

1389 if ( 0 == b || 0xFF == b )

1390 {

1391 long nHeight = m_rWW8Export.GetItem( RES_CHRATR_FONTSIZE ).GetHeight();

1392 m_rWW8Export.InsUInt16( NS_sprm::sprmCHpsPos );

1393

1394 m_rWW8Export.InsUInt16( static_cast(( nHeight * nEsc + 500 ) / 1000 ));

1395

1396 if( 100 != nProp || !b )

1397 {

1398 m_rWW8Export.InsUInt16( NS_sprm::sprmCHps );

1399

1400 m_rWW8Export.InsUInt16(

1401 msword_cast((nHeight * nProp + 500 ) / 1000));

1402 }

1403 }

1404}

1405

1406void WW8AttributeOutput::CharFontSize( const SvxFontHeightItem& rHeight )

1407{

1408 sal_uInt16 nId = 0;

1409 switch ( rHeight.Which() )

1410 {

1411 case RES_CHRATR_FONTSIZE:

1412 case RES_CHRATR_CJK_FONTSIZE:

1413 nId = NS_sprm::sprmCHps;

1414 break;

1415 case RES_CHRATR_CTL_FONTSIZE:

1416 nId = NS_sprm::sprmCHpsBi;

1417 break;

1418 }

1419

1420 if ( nId )

1421 {

1422 m_rWW8Export.InsUInt16( nId );

1423

1424 m_rWW8Export.InsUInt16( static_cast(( rHeight.GetHeight() + 5 ) / 10 ) );

1425 }

1426}

1427

1428void WW8AttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )

1429{

1430 m_rWW8Export.InsUInt16( NS_sprm::sprmCCharScale );

1431 m_rWW8Export.InsUInt16( rScaleWidth.GetValue() );

1432}

1433

1434void WW8AttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )

1435{

1436 sal_uInt16 nId;

1437 switch ( rRelief.GetValue() )

1438 {

1439 case FontRelief::Embossed: nId = NS_sprm::sprmCFEmboss; break;

1440 case FontRelief::Engraved: nId = NS_sprm::sprmCFImprint; break;

1441 default: nId = 0; break;

1442 }

1443

1444 if( nId )

1445 {

1446 m_rWW8Export.InsUInt16( nId );

1447 m_rWW8Export.pO->push_back( sal_uInt8(0x81) );

1448 }

1449 else

1450 {

1451 // switch both flags off

1452 m_rWW8Export.InsUInt16( NS_sprm::sprmCFEmboss );

1453 m_rWW8Export.pO->push_back( sal_uInt8(0x0) );

1454 m_rWW8Export.InsUInt16( NS_sprm::sprmCFImprint );

1455 m_rWW8Export.pO->push_back( sal_uInt8(0x0) );

1456 }

1457}

1458

1459void WW8AttributeOutput::CharBidiRTL( const SfxPoolItem& rHt )

1460{

1461 const SfxInt16Item& rAttr = static_cast(rHt);

1462 if( rAttr.GetValue() == 1 )

1463 {

1464 m_rWW8Export.InsUInt16(0x85a);

1465 m_rWW8Export.pO->push_back(sal_uInt8(1));

1466 }

1467}

1468

1469void WW8AttributeOutput::CharIdctHint( const SfxPoolItem& rHt )

1470{

1471 const SfxInt16Item& rAttr = static_cast(rHt);

1472 m_rWW8Export.InsUInt16(0x286F);

1473 m_rWW8Export.pO->push_back(static_cast(rAttr.GetValue()));

1474}

1475

1476void WW8AttributeOutput::CharRotate( const SvxCharRotateItem& rRotate )

1477{

1478 // #i28331# - check that a Value is set

1479 if ( !rRotate.GetValue() )

1480 return;

1481

1482 if (!m_rWW8Export.IsInTable())

1483 {

1484 // #i36867 In word the text in a table is rotated via the TC or NS_sprm::sprmTTextFlow

1485 // This means you can only rotate all or none of the text adding NS_sprm::sprmCFELayout

1486 // here corrupts the table, hence !m_rWW8Export.bIsInTable

1487

1488 m_rWW8Export.InsUInt16( NS_sprm::sprmCFELayout );

1489 m_rWW8Export.pO->push_back( sal_uInt8(0x06) ); //len 6

1490 m_rWW8Export.pO->push_back( sal_uInt8(0x01) );

1491

1492 m_rWW8Export.InsUInt16( rRotate.IsFitToLine() ? 1 : 0 );

1493 static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 };

1494 m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), aZeroArr, aZeroArr+3);

1495 }

1496}

1497

1498void WW8AttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )

1499{

1500 sal_uInt8 nVal;

1501 const FontEmphasisMark v = rEmphasisMark.GetEmphasisMark();

1502 if (v == FontEmphasisMark::NONE)

1503 nVal = 0;

1504 else if (v == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove))

1505 nVal = 2;

1506 else if (v == (FontEmphasisMark::Circle | FontEmphasisMark::PosAbove))

1507 nVal = 3;

1508 else if (v == (FontEmphasisMark::Dot | FontEmphasisMark::PosBelow))

1509 nVal = 4;

1510 else

1511 // case 1:

1512 nVal = 1;

1513

1514 m_rWW8Export.InsUInt16( NS_sprm::sprmCKcd );

1515 m_rWW8Export.pO->push_back( nVal );

1516}

1517

1526bool WW8Export::TransBrush(const Color& rCol, WW8_SHD& rShd)

1527{

1528 if( rCol.GetTransparency() )

1529 rShd = WW8_SHD(); // all zeros: transparent

1530 else

1531 {

1532 rShd.SetFore( 0);

1533 rShd.SetBack( msfilter::util::TransColToIco( rCol ) );

1534 rShd.SetStyle( 0 );

1535 }

1536 return !rCol.GetTransparency();

1537}

1538

1539sal_uInt32 SuitableBGColor(Color nIn)

1540{

1541 if (nIn == COL_AUTO)

1542 return 0xFF000000;

1543 return wwUtility::RGBToBGR(nIn);

1544}

1545

1546void WW8AttributeOutput::CharColor( const SvxColorItem& rColor )

1547{

1548 m_rWW8Export.InsUInt16( NS_sprm::sprmCIco );

1549

1550 sal_uInt8 nColor = msfilter::util::TransColToIco( rColor.GetValue() );

1551 m_rWW8Export.pO->push_back( nColor );

1552

1553 if (nColor)

1554 {

1555 m_rWW8Export.InsUInt16( NS_sprm::sprmCCv );

1556 m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( rColor.GetValue() ) );

1557 }

1558}

1559

1560void WW8AttributeOutput::CharBackground( const SvxBrushItem& rBrush )

1561{

1562 WW8_SHD aSHD;

1563

1564 WW8Export::TransBrush( rBrush.GetColor(), aSHD );

1565 // sprmCShd80

1566 m_rWW8Export.InsUInt16( NS_sprm::sprmCShd80 );

1567 m_rWW8Export.InsUInt16( aSHD.GetValue() );

1568

1569 //Quite a few unknowns, some might be transparency or something

1570 //of that nature...

1571 m_rWW8Export.InsUInt16( NS_sprm::sprmCShd );

1572 m_rWW8Export.pO->push_back( 10 );

1573 m_rWW8Export.InsUInt32( 0xFF000000 );

1574 m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor() ) );

1575 m_rWW8Export.InsUInt16( 0x0000);

1576}

1577

1578void WW8AttributeOutput::TextINetFormat( const SwFormatINetFormat& rINet )

1579{

1580 if ( !rINet.GetValue().isEmpty() )

1581 {

1582 const sal_uInt16 nId = rINet.GetINetFormatId();

1583 const OUString& rStr = rINet.GetINetFormat();

1584 if (rStr.isEmpty())

1585 {

1586 OSL_ENSURE( false, "WW8AttributeOutput::TextINetFormat(..) - missing unvisited character format at hyperlink attribute" );

1587 }

1588

1589 const SwCharFormat* pFormat = IsPoolUserFormat( nId )

1590 ? m_rWW8Export.m_pDoc->FindCharFormatByName( rStr )

1591 : m_rWW8Export.m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( nId );

1592

1593 m_rWW8Export.InsUInt16( NS_sprm::sprmCIstd );

1594

1595 m_rWW8Export.InsUInt16( m_rWW8Export.GetId( pFormat ) );

1596 }

1597}

1598

1599// #i43956# - add optional parameter

1600// It's needed to write the hyperlink data for a certain cross-reference

1601// - it contains the name of the link target, which is a bookmark.

1602// add optional parameter

1603// It is needed to write an empty picture location for page number field separators

1604static void InsertSpecialChar( WW8Export& rWrt, sal_uInt8 c,

1605 OUString const * pLinkStr,

1606 bool bIncludeEmptyPicLocation = false )

1607{

1608 ww::bytes aItems;

1609 rWrt.GetCurrentItems(aItems);

1610

1611 if (c == 0x13)

1612 rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell());

1613 else

1614 rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.size(), aItems.data());

1615

1616 rWrt.WriteChar(c);

1617

1618 // store empty sprmCPicLocation for field separator

1619 if ( bIncludeEmptyPicLocation &&

1620 ( c == 0x13 || c == 0x14 || c == 0x15 ) )

1621 {

1622 SwWW8Writer::InsUInt16( aItems, NS_sprm::sprmCPicLocation );

1623 SwWW8Writer::InsUInt32( aItems, 0x00000000 );

1624 }

1625

1626 // #i43956# - write hyperlink data and attributes

1627 if ( c == 0x01 && pLinkStr)

1628 {

1629 // write hyperlink data to data stream

1630 SvStream& rStrm = *rWrt.pDataStrm;

1631 // position of hyperlink data

1632 const sal_uInt32 nLinkPosInDataStrm = rStrm.Tell();

1633 // write empty header

1634 const sal_uInt16 nEmptyHdrLen = 0x44;

1635 sal_uInt8 aEmptyHeader[ nEmptyHdrLen ] = { 0 };

1636 aEmptyHeader[ 4 ] = 0x44;

1637 rStrm.WriteBytes( aEmptyHeader, nEmptyHdrLen );

1638 // writer fixed header

1639 const sal_uInt16 nFixHdrLen = 0x19;

1640 sal_uInt8 const aFixHeader[ nFixHdrLen ] =

1641 {

1642 0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE,

1643 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9,

1644 0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,

1645 0x00,

1646 };

1647 rStrm.WriteBytes( aFixHeader, nFixHdrLen );

1648 // write reference string including length+1

1649 sal_uInt32 nStrLen( pLinkStr->getLength() + 1 );

1650 SwWW8Writer::WriteLong( rStrm, nStrLen );

1651 SwWW8Writer::WriteString16( rStrm, *pLinkStr, false );

1652 // write additional two NULL Bytes

1653 SwWW8Writer::WriteLong( rStrm, 0 );

1654 // write length of hyperlink data

1655 const sal_uInt32 nCurrPos = rStrm.Tell();

1656 rStrm.Seek( nLinkPosInDataStrm );

1657 rStrm.WriteUInt32(nCurrPos - nLinkPosInDataStrm);

1658 rStrm.Seek( nCurrPos );

1659

1660 // write attributes of hyperlink character 0x01

1661 SwWW8Writer::InsUInt16( aItems, NS_sprm::sprmCFFldVanish );

1662 aItems.push_back( sal_uInt8(0x81) );

1663 SwWW8Writer::InsUInt16( aItems, NS_sprm::sprmCPicLocation );

1664 SwWW8Writer::InsUInt32( aItems, nLinkPosInDataStrm );

1665 SwWW8Writer::InsUInt16( aItems, NS_sprm::sprmCFData );

1666 aItems.push_back( sal_uInt8(0x01) );

1667 }

1668

1669 //Technically we should probably Remove all attribs

1670 //here for the 0x13, 0x14, 0x15, but our import

1671 //is slightly lacking

1672 //aItems.Remove(0, aItems.Count());

1673 // fSpec-Attribute true

1674 SwWW8Writer::InsUInt16( aItems, NS_sprm::sprmCFSpec );

1675 aItems.push_back( 1 );

1676

1677 rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.size(), aItems.data());

1678}

1679

1680static OUString lcl_GetExpandedField(const SwField &rField)

1681{

1682 OUString sRet(rField.ExpandField(true));

1683

1684 //replace LF 0x0A with VT 0x0B

1685 return sRet.replace(0x0A, 0x0B);

1686}

1687

1688WW8_WrPlcField* WW8Export::CurrentFieldPlc() const

1689{

1690 WW8_WrPlcField* pFieldP = nullptr;

1691 switch (m_nTextTyp)

1692 {

1693 case TXT_MAINTEXT:

1694 pFieldP = m_pFieldMain;

1695 break;

1696 case TXT_HDFT:

1697 pFieldP = m_pFieldHdFt;

1698 break;

1699 case TXT_FTN:

1700 pFieldP = m_pFieldFootnote;

1701 break;

1702 case TXT_EDN:

1703 pFieldP = m_pFieldEdn;

1704 break;

1705 case TXT_ATN:

1706 pFieldP = m_pFieldAtn;

1707 break;

1708 case TXT_TXTBOX:

1709 pFieldP = m_pFieldTextBxs;

1710 break;

1711 case TXT_HFTXTBOX:

1712 pFieldP = m_pFieldHFTextBxs;

1713 break;

1714 default:

1715 OSL_ENSURE( false, "what type of SubDoc is that?" );

1716 }

1717 return pFieldP;

1718}

1719

1720void WW8Export::OutputField( const SwField* pField, ww::eField eFieldType,

1721 const OUString& rFieldCmd, FieldFlags nMode )

1722{

1723 OUString sFieldCmd(rFieldCmd);

1724 switch (eFieldType)

1725 {

1726 // map fields that are not supported in WW8 as of Word 2003

1727 case ww::eBIBLIOGRPAHY:

1728 eFieldType = ww::eQUOTE;

1729 assert(rFieldCmd == FieldString(ww::eBIBLIOGRPAHY));

1730 sFieldCmd = FieldString(ww::eQUOTE);

1731 break;

1732 case ww::eCITATION:

1733 eFieldType = ww::eQUOTE;

1734 assert(rFieldCmd.trim().startsWith("CITATION"));

1735 sFieldCmd = rFieldCmd.replaceFirst(FieldString(ww::eCITATION),

1736 FieldString(ww::eQUOTE));

1737 break;

1738 default:

1739 break;

1740 }

1741

1742 assert(eFieldType (eFieldType); // add type

1754 pFieldP->Append( Fc2Cp( Strm().Tell() ), aField13 );

1755 InsertSpecialChar( *this, 0x13, nullptr, bIncludeEmptyPicLocation );

1756 }

1757 if (FieldFlags::CmdStart & nMode)

1758 {

1759 SwWW8Writer::WriteString16(Strm(), sFieldCmd, false);

1760 // #i43956# - write hyperlink character including

1761 // attributes and corresponding binary data for certain reference fields.

1762 bool bHandleBookmark = false;

1763

1764 if (pField)

1765 {

1766 if (pField->GetTyp()->Which() == SwFieldIds::GetRef &&

1767 ( eFieldType == ww::ePAGEREF || eFieldType == ww::eREF ||

1768 eFieldType == ww::eNOTEREF || eFieldType == ww::eFOOTREF ))

1769 bHandleBookmark = true;

1770 }

1771

1772 if ( bHandleBookmark )

1773 {

1774 // retrieve reference destination - the name of the bookmark

1775 OUString aLinkStr;

1776 const sal_uInt16 nSubType = pField->GetSubType();

1777 const SwGetRefField& rRField = *static_cast(pField);

1778 if ( nSubType == REF_SETREFATTR ||

1779 nSubType == REF_BOOKMARK )

1780 {

1781 const OUString& aRefName(rRField.GetSetRefName());

1782 aLinkStr = GetBookmarkName( nSubType, &aRefName, 0 );

1783 }

1784 else if ( nSubType == REF_FOOTNOTE ||

1785 nSubType == REF_ENDNOTE )

1786 {

1787 aLinkStr = GetBookmarkName( nSubType, nullptr, rRField.GetSeqNo() );

1788 }

1789 else if ( nSubType == REF_SEQUENCEFLD )

1790 {

1791 aLinkStr = pField->GetPar2();

1792 }

1793 // insert hyperlink character including attributes and data.

1794 InsertSpecialChar( *this, 0x01, &aLinkStr );

1795 }

1796 }

1797 if (FieldFlags::CmdEnd & nMode)

1798 {

1799 static const sal_uInt8 aField14[2] = { 0x14, 0xff };

1800 pFieldP->Append( Fc2Cp( Strm().Tell() ), aField14 );

1801 pFieldP->ResultAdded();

1802 InsertSpecialChar( *this, 0x14, nullptr, bIncludeEmptyPicLocation );

1803 }

1804 if (FieldFlags::End & nMode)

1805 {

1806 OUString sOut;

1807 if( pField )

1808 sOut = lcl_GetExpandedField(*pField);

1809 else

1810 sOut = sFieldCmd;

1811 if( !sOut.isEmpty() )

1812 {

1813 SwWW8Writer::WriteString16(Strm(), sOut, false);

1814

1815 if (pField)

1816 {

1817 if (pField->GetTyp()->Which() == SwFieldIds::Input &&

1818 eFieldType == ww::eFORMTEXT)

1819 {

1820 sal_uInt8 aArr[12];

1821 sal_uInt8 *pArr = aArr;

1822

1823 Set_UInt16( pArr, NS_sprm::sprmCPicLocation );

1824 Set_UInt32( pArr, 0x0 );

1825

1826 Set_UInt16( pArr, NS_sprm::sprmCFSpec );

1827 Set_UInt8( pArr, 1 );

1828

1829 Set_UInt16( pArr, NS_sprm::sprmCFNoProof );

1830 Set_UInt8( pArr, 1 );

1831

1832 m_pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );

1833 }

1834 }

1835 }

1836 }

1837 if (FieldFlags::Close & nMode)

1838 {

1839 sal_uInt8 aField15[2] = { 0x15, 0x80 };

1840

1841 if (pField)

1842 {

1843 if (pField->GetTyp()->Which() == SwFieldIds::Input &&

1844 eFieldType == ww::eFORMTEXT)

1845 {

1846 sal_uInt16 nSubType = pField->GetSubType();

1847

1848 if (nSubType == REF_SEQUENCEFLD)

1849 aField15[0] |= (0x4 Append( Fc2Cp( Strm().Tell() ), aField15 );

1854 InsertSpecialChar( *this, 0x15, nullptr, bIncludeEmptyPicLocation );

1855 }

1856}

1857

1858void WW8Export::StartCommentOutput(const OUString& rName)

1859{

1860 OUString sStr(FieldString(ww::eQUOTE));

1861 sStr += "[" + rName + "] ";

1862 OutputField(nullptr, ww::eQUOTE, sStr, FieldFlags::Start | FieldFlags::CmdStart);

1863}

1864

1865void WW8Export::EndCommentOutput(const OUString& rName)

1866{

1867 OUString sStr(" [");

1868 sStr += rName + "] ";

1869 OutputField(nullptr, ww::eQUOTE, sStr, FieldFlags::CmdEnd | FieldFlags::End |

1870 FieldFlags::Close);

1871}

1872

1873sal_uInt16 MSWordExportBase::GetId( const SwTOXType& rTOXType )

1874{

1875 std::vector::iterator it

1876 = std::find( m_aTOXArr.begin(), m_aTOXArr.end(), &rTOXType );

1877 if ( it != m_aTOXArr.end() )

1878 {

1879 return it - m_aTOXArr.begin();

1880 }

1881 m_aTOXArr.push_back( &rTOXType );

1882 return m_aTOXArr.size() - 1;

1883}

1884

1885// return values: 1 - no PageNum,

1886// 2 - TabStop before PageNum,

1887// 3 - Text before PageNum - rText hold the text

1888// 4 - no Text and no TabStop before PageNum

1889static int lcl_CheckForm( const SwForm& rForm, sal_uInt8 nLvl, OUString& rText )

1890{

1891 int nRet = 4;

1892 rText.clear();

1893

1894 // #i21237#

1895 SwFormTokens aPattern = rForm.GetPattern(nLvl);

1896 SwFormTokens::iterator aIt = aPattern.begin();

1897 FormTokenType eTType;

1898

1899 // #i61362#

1900 if (! aPattern.empty())

1901 {

1902 bool bPgNumFnd = false;

1903

1904 // #i21237#

1905 while( ++aIt != aPattern.end() && !bPgNumFnd )

1906 {

1907 eTType = aIt->eTokenType;

1908

1909 switch( eTType )

1910 {

1911 case TOKEN_PAGE_NUMS:

1912 bPgNumFnd = true;

1913 break;

1914

1915 case TOKEN_TAB_STOP:

1916 nRet = 2;

1917 break;

1918 case TOKEN_TEXT:

1919 {

1920 nRet = 3;

1921 sal_Int32 nCount = std::min(5, aIt->sText.getLength());

1922 rText = aIt->sText.copy(0, nCount); // #i21237#

1923 break;

1924 }

1925 case TOKEN_LINK_START:

1926 case TOKEN_LINK_END:

1927 break;

1928

1929 default:

1930 nRet = 4;

1931 break;

1932 }

1933 }

1934

1935 if( !bPgNumFnd )

1936 nRet = 1;

1937 }

1938

1939 return nRet;

1940}

1941

1942static bool lcl_IsHyperlinked(const SwForm& rForm, sal_uInt16 nTOXLvl)

1943{

1944 bool bRes = false;

1945 for (sal_uInt16 nI = 1; nI < nTOXLvl; ++nI)

1946 {

1947 // #i21237#

1948 SwFormTokens aPattern = rForm.GetPattern(nI);

1949

1950 if ( !aPattern.empty() )

1951 {

1952 SwFormTokens::iterator aIt = aPattern.begin();

1953

1954 FormTokenType eTType;

1955

1956 // #i21237#

1957 while ( ++aIt != aPattern.end() )

1958 {

1959 eTType = aIt->eTokenType;

1960 switch (eTType)

1961 {

1962 case TOKEN_LINK_START:

1963 case TOKEN_LINK_END:

1964 bRes = true;

1965 break;

1966 default:

1967 ;

1968 }

1969 }

1970 }

1971 }

1972 return bRes;

1973}

1974

1975void AttributeOutputBase::GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter)

1976{

1977 if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) // Not implemented for RTF

1978 return;

1979

1980 if (const SwpHints* pTextAttrs = rNode.GetpSwpHints())

1981 {

1982 for( size_t i = 0; i < pTextAttrs->Count(); ++i )

1983 {

1984 const SwTextAttr* pHt = pTextAttrs->Get(i);

1985 if (pHt->GetAttr().Which() == RES_TXTATR_FIELD)

1986 {

1987 const SwFormatField& rField = static_cast(pHt->GetAttr());

1988 const SwField* pField = rField.GetField();

1989 // Need to have bookmarks only for sequence fields

1990 if (pField && pField->GetTyp()->Which() == SwFieldIds::SetExp && pField->GetSubType() == nsSwGetSetExpType::GSE_SEQ)

1991 {

1992 const sal_uInt16 nSeqFieldNumber = static_cast(pField)->GetSeqNumber();

1993 const OUString sObjectName = static_cast(pField->GetTyp())->GetName();

1994 const SwFieldTypes* pFieldTypes = GetExport().m_pDoc->getIDocumentFieldsAccess().GetFieldTypes();

1995 bool bHaveFullBkm = false;

1996 bool bHaveLabelAndNumberBkm = false;

1997 bool bHaveCaptionOnlyBkm = false;

1998 bool bHaveNumberOnlyBkm = false;

1999 bool bRunSplittedAtSep = false;

2000 for( auto pFieldType : *pFieldTypes )

2001 {

2002 if( SwFieldIds::GetRef == pFieldType->Which() )

2003 {

2004 SwIterator aIter( *pFieldType );

2005 for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() )

2006 {

2007 SwGetRefField* pRefField = static_cast(pFormatField->GetField());

2008 // If we have a reference to the current sequence field

2009 if(pRefField->GetSeqNo() == nSeqFieldNumber && pRefField->GetSetRefName() == sObjectName)

2010 {

2011 // Need to create a separate run for separator character

2012 SwWW8AttrIter aLocalAttrIter( GetExport(), rNode ); // We need a local iterator having the right number of runs

2013 const OUString aText = rNode.GetText();

2014 const sal_Int32 nCategoryStart = aText.indexOf(pRefField->GetSetRefName());

2015 const sal_Int32 nPosBeforeSeparator = std::max(nCategoryStart, pHt->GetStart());

2016 bool bCategoryFirst = nCategoryStart < pHt->GetStart();

2017 sal_Int32 nSeparatorPos = 0;

2018 if (bCategoryFirst)

2019 {

2020 nSeparatorPos = aLocalAttrIter.WhereNext();

2021 while (nSeparatorPos GetSetRefName().getLength();

2030 }

2031 sal_Int32 nRefTextPos = 0;

2032 if(nSeparatorPos < aText.getLength())

2033 {

2034 nRefTextPos = SwGetExpField::GetReferenceTextPos(pHt->GetFormatField(), *GetExport().m_pDoc, nSeparatorPos);

2035 if(nRefTextPos != nSeparatorPos)

2036 {

2037 if(!bRunSplittedAtSep)

2038 {

2039 if(!bCategoryFirst)

2040 rAttrIter.SplitRun(nSeparatorPos);

2041 rAttrIter.SplitRun(nRefTextPos);

2042 bRunSplittedAtSep = true;

2043 }

2044 if(!bCategoryFirst)

2045 aLocalAttrIter.SplitRun(nSeparatorPos);

2046 aLocalAttrIter.SplitRun(nRefTextPos);

2047 }

2048 else if (bCategoryFirst)

2049 {

2050 if(!bRunSplittedAtSep)

2051 {

2052