libreoffice module sw (master): ww8par6.cxx source file * file, you can obtain one ... 260 // seem...

Download LibreOffice Module sw (master): ww8par6.cxx Source File * file, You can obtain one ... 260 // seem to not add external leading in word, ... 881 // Type of break: break codes are:

If you can't read please download the document

Upload: truongthuan

Post on 06-Feb-2018

215 views

Category:

Documents


1 download

TRANSCRIPT

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

LibreOffice Module sw (master) 1

MainPageRelatedPagesModulesNamespacesClassesFilesExamples

FileListFileMembers

swsourcefilterww8

ww8par6.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#include

21#include

22#include

23#include

24

25#include

26#include

27#include

28#include

29#include

30#include

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 "sprmids.hxx"

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 "writerhelper.hxx"

96#include "writerwordglue.hxx"

97#include "ww8scan.hxx"

98#include "ww8par2.hxx"

99#include "ww8graf.hxx"

100

101#include

102

103using namespace sw::util;

104using namespace sw::types;

105using namespace ::com::sun::star;

106using namespace nsHdFtFlags;

107

108// various

109

110#define MM_250 1417 // WW default for horizontal borders: 2.5 cm

111#define MM_200 1134 // WW default for lower border: 2.0 cm

112

113

114static sal_uInt8 lcl_ReadBorders(bool bVer67, WW8_BRCVer9* brc, WW8PLCFx_Cp_FKP* pPap,

115 const WW8RStyle* pSty = nullptr, const WW8PLCFx_SEPX* pSep = nullptr);

116

117Color SwWW8ImplReader::GetCol(sal_uInt8 nIco)

118{

119 static const Color eSwWW8ColA[] =

120 {

121 COL_AUTO, COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,

122 COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,

123 COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,

124 COL_LIGHTGRAY

125 };

126 SAL_WARN_IF(

127 nIco >= SAL_N_ELEMENTS(eSwWW8ColA), "sw.ww8",

128 "ico " HasSprm(nId); // sprm here?

143 const sal_uInt8* pS = aRes.pSprm;

144 short nVal = (pS && aRes.nRemainingData >= 2) ? SVBT16ToShort(pS) : nDefaultVal;

145 return nVal;

146}

147

148static sal_uInt16 ReadUSprm( const WW8PLCFx_SEPX* pSep, sal_uInt16 nId, short nDefaultVal )

149{

150 SprmResult aRes = pSep->HasSprm(nId); // sprm here?

151 const sal_uInt8* pS = aRes.pSprm;

152 sal_uInt16 nVal = (pS && aRes.nRemainingData >= 2) ? SVBT16ToShort(pS) : nDefaultVal;

153 return nVal;

154}

155

156static sal_uInt8 ReadBSprm( const WW8PLCFx_SEPX* pSep, sal_uInt16 nId, sal_uInt8 nDefaultVal )

157{

158 SprmResult aRes = pSep->HasSprm(nId); // sprm here?

159 const sal_uInt8* pS = aRes.pSprm;

160 sal_uInt8 nVal = (pS && aRes.nRemainingData >= 1) ? *pS : nDefaultVal;

161 return nVal;

162}

163

164void wwSection::SetDirection()

165{

166 //sprmSTextFlow

167 switch (maSep.wTextFlow)

168 {

169 default:

170 OSL_ENSURE(false, "Unknown layout type");

171 SAL_FALLTHROUGH;

172 case 0:

173 meDir=SvxFrameDirection::Horizontal_LR_TB;

174 break;

175 case 1:

176 meDir=SvxFrameDirection::Vertical_RL_TB;

177 break;

178 case 2:

179 //asian letters are not rotated, western are. We can't import

180 //bottom to top going left to right, we can't do this in

181 //pages, (in drawboxes we could partly hack it with a rotated

182 //drawing box, though not frame)

183 meDir=SvxFrameDirection::Vertical_RL_TB;

184 break;

185 case 3:

186 //asian letters are not rotated, western are. We can't import

187 meDir=SvxFrameDirection::Vertical_RL_TB;

188 break;

189 case 4:

190 //asian letters are rotated, western not. We can't import

191 meDir=SvxFrameDirection::Horizontal_LR_TB;

192 break;

193 }

194

195 sal_uInt8 bRTLPgn = maSep.fBiDi;

196 if ((meDir == SvxFrameDirection::Horizontal_LR_TB) && bRTLPgn)

197 meDir = SvxFrameDirection::Horizontal_RL_TB;

198}

199

200bool wwSection::IsVertical() const

201{

202 return meDir == SvxFrameDirection::Vertical_RL_TB || meDir == SvxFrameDirection::Vertical_LR_TB;

203}

204

205/*

206 This is something of festering mapping, I'm open to better ways of doing it,

207 but primarily the grid in writer is different to that in word. In writer the

208 grid elements are squares with ruby rows inbetween. While in word there is no

209 ruby stuff, and the elements are rectangles. By misusing the ruby row I can

210 handle distortions in one direction, but its all a bit of a mess:

211*/

212void SwWW8ImplReader::SetDocumentGrid(SwFrameFormat &rFormat, const wwSection &rSection)

213{

214 if (m_bVer67)

215 return;

216

217 rFormat.SetFormatAttr(SvxFrameDirectionItem(rSection.meDir, RES_FRAMEDIR));

218

219 SwTwips nTextareaHeight = rFormat.GetFrameSize().GetHeight();

220 const SvxULSpaceItem &rUL = ItemGet(rFormat, RES_UL_SPACE);

221 nTextareaHeight -= rUL.GetUpper();

222 nTextareaHeight -= rUL.GetLower();

223

224 SwTwips nTextareaWidth = rFormat.GetFrameSize().GetWidth();

225 const SvxLRSpaceItem &rLR = ItemGet(rFormat, RES_LR_SPACE);

226 nTextareaWidth -= rLR.GetLeft();

227 nTextareaWidth -= rLR.GetRight();

228

229 if (rSection.IsVertical())

230 std::swap(nTextareaHeight, nTextareaWidth);

231

232 SwTextGridItem aGrid;

233 aGrid.SetDisplayGrid(false);

234 aGrid.SetPrintGrid(false);

235 SwTextGrid eType=GRID_NONE;

236

237 switch (rSection.maSep.clm)

238 {

239 case 0:

240 eType = GRID_NONE;

241 break;

242 default:

243 OSL_ENSURE(false, "Unknown grid type");

244 SAL_FALLTHROUGH;

245 case 3:

246 eType = GRID_LINES_CHARS;

247 aGrid.SetSnapToChars(true);

248 break;

249 case 1:

250 eType = GRID_LINES_CHARS;

251 aGrid.SetSnapToChars(false);

252 break;

253 case 2:

254 eType = GRID_LINES_ONLY;

255 break;

256 }

257

258 aGrid.SetGridType(eType);

259

260 // seem to not add external leading in word, or the character would run across

261 // two line in some cases.

262 if (eType != GRID_NONE)

263 m_rDoc.getIDocumentSettingAccess().set(DocumentSettingId::ADD_EXT_LEADING, false);

264

265 //force to set document as standard page mode

266 bool bSquaredMode = false;

267 m_rDoc.SetDefaultPageMode( bSquaredMode );

268 aGrid.SetSquaredMode( bSquaredMode );

269

270 //Get the size of word's default styles font

271 sal_uInt32 nCharWidth=240;

272 for (sal_uInt16 nI = 0; nI < m_xStyles->GetCount(); ++nI)

273 {

274 if (m_vColl[nI].m_bValid && m_vColl[nI].m_pFormat &&

275 m_vColl[nI].IsWW8BuiltInDefaultStyle())

276 {

277 nCharWidth = ItemGet(*(m_vColl[nI].m_pFormat),

278 RES_CHRATR_CJK_FONTSIZE).GetHeight();

279 break;

280 }

281 }

282

283 //dxtCharSpace

284 if (rSection.maSep.dxtCharSpace)

285 {

286 sal_uInt32 nCharSpace = rSection.maSep.dxtCharSpace;

287 //main lives in top 20 bits, and is signed.

288 sal_Int32 nMain = (nCharSpace & 0xFFFFF000);

289 nMain/=0x1000;

290 nCharWidth += nMain*20;

291

292 int nFraction = (nCharSpace & 0x00000FFF);

293 nFraction = (nFraction*20)/0xFFF;

294 nCharWidth += nFraction;

295 }

296

297 aGrid.SetBaseWidth( writer_cast(nCharWidth));

298

299 //sep.dyaLinePitch

300 sal_Int32 nLinePitch = rSection.maSep.dyaLinePitch;

301 if (nLinePitch >= 1 && nLinePitch SetAttr(*m_pPaM->GetPoint(), RES_FRAMEDIR);

316 else

317 {

318 SvxFrameDirection eDir =

319 *pData ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;

320 NewAttr(SvxFrameDirectionItem(eDir, RES_FRAMEDIR));

321 }

322}

323

324bool wwSectionManager::SetCols(SwFrameFormat &rFormat, const wwSection &rSection,

325 sal_uInt32 nNetWidth)

326{

327 //sprmSCcolumns - number of columns - 1

328 const sal_Int16 nCols = rSection.NoCols();

329

330 if (nCols < 2) //check for no columns or other weird state

331 return false;

332

333 const sal_uInt16 nNetWriterWidth = writer_cast(nNetWidth);

334 if (nNetWriterWidth == 0)

335 return false;

336

337 SwFormatCol aCol; // Create SwFormatCol

338

339 //sprmSDxaColumns - Default distance is 1.25 cm

340 sal_Int32 nColSpace = rSection.StandardColSeparation();

341

342 const SEPr& rSep = rSection.maSep;

343

344 // sprmSLBetween

345 if (rSep.fLBetween)

346 {

347 aCol.SetLineAdj(COLADJ_TOP); // Line

348 aCol.SetLineHeight(100);

349 aCol.SetLineColor(COL_BLACK);

350 aCol.SetLineWidth(1);

351 }

352

353 aCol.Init(nCols, writer_cast(nColSpace), nNetWriterWidth);

354

355 // sprmSFEvenlySpaced

356 if (!rSep.fEvenlySpaced)

357 {

358 aCol.SetOrtho_(false);

359 const sal_uInt16 maxIdx = SAL_N_ELEMENTS(rSep.rgdxaColumnWidthSpacing);

360 for (sal_uInt16 i = 0, nIdx = 1; i < nCols && nIdx < maxIdx; i++, nIdx+=2 )

361 {

362 SwColumn* pCol = &aCol.GetColumns()[i];

363 const sal_Int32 nLeft = rSep.rgdxaColumnWidthSpacing[nIdx-1]/2;

364 const sal_Int32 nRight = rSep.rgdxaColumnWidthSpacing[nIdx+1]/2;

365 const sal_Int32 nWishWidth = rSep.rgdxaColumnWidthSpacing[nIdx]

366 + nLeft + nRight;

367 pCol->SetWishWidth(writer_cast(nWishWidth));

368 pCol->SetLeft(writer_cast(nLeft));

369 pCol->SetRight(writer_cast(nRight));

370 }

371 aCol.SetWishWidth(nNetWriterWidth);

372 }

373 rFormat.SetFormatAttr(aCol);

374 return true;

375}

376

377void wwSectionManager::SetLeftRight(wwSection &rSection)

378{

379 // 3. LR-Margin

380 sal_uInt32 nWWLe = MSRoundTweak(rSection.maSep.dxaLeft);

381 sal_uInt32 nWWRi = MSRoundTweak(rSection.maSep.dxaRight);

382 sal_uInt32 nWWGu = rSection.maSep.dzaGutter;

383

384 /*

385 fRTLGutter is set if the gutter is on the right, the gutter is otherwise

386 placed on the left unless the global dop options are to put it on top, that

387 case is handled in GetPageULData.

388 */

389 if (rSection.maSep.fRTLGutter)

390 nWWRi += nWWGu;

391 else if (!mrReader.m_xWDop->iGutterPos)

392 nWWLe += nWWGu;

393

394 // Left / Right

395 if ((rSection.nPgWidth - nWWLe - nWWRi) < MINLAY)

396 {

397 /*

398 There are some label templates which are "broken", they specify

399 margins which make no sense e.g. Left 16.10cm, Right 16.10cm. So the

400 space left between the margins is less than 0 In word the left margin

401 is honoured and if the right margin would be past the left margin is

402 left at the left margin position.

403

404 Now this will work fine for importing, layout and exporting, *but* the

405 page layout dialog has a hardcoded minimum page width of 0.5cm so it

406 will report a different value than what is actually being used. i.e.

407 it will add up the values to give a wider page than is actually being

408 used.

409 */

410 nWWRi = rSection.nPgWidth - nWWLe - MINLAY;

411 }

412

413 rSection.nPgLeft = nWWLe;

414 rSection.nPgRight = nWWRi;

415}

416

417void wwSectionManager::SetPage(SwPageDesc &rInPageDesc, SwFrameFormat &rFormat,

418 const wwSection &rSection, bool bIgnoreCols)

419{

420 // 1. orientation

421 rInPageDesc.SetLandscape(rSection.IsLandScape());

422

423 // 2. paper size

424 SwFormatFrameSize aSz( rFormat.GetFrameSize() );

425 aSz.SetWidth(rSection.GetPageWidth());

426 aSz.SetHeight(SvxPaperInfo::GetSloppyPaperDimension(rSection.GetPageHeight()));

427 rFormat.SetFormatAttr(aSz);

428

429 rFormat.SetFormatAttr(

430 SvxLRSpaceItem(rSection.GetPageLeft(), rSection.GetPageRight(), 0, 0, RES_LR_SPACE));

431

432 if (!bIgnoreCols)

433 SetCols(rFormat, rSection, rSection.GetTextAreaWidth());

434}

435

436namespace {

437// Returns corrected (ODF) margin size

438long SetBorderDistance(bool bFromEdge, SvxBoxItem& aBox, SvxBoxItemLine eLine, long nMSMargin)

439{

440 const editeng::SvxBorderLine* pLine = aBox.GetLine(eLine);

441 if (!pLine)

442 return nMSMargin;

443 sal_Int32 nNewMargin = nMSMargin;

444 sal_Int32 nNewDist = aBox.GetDistance(eLine);

445 sal_Int32 nLineWidth = pLine->GetScaledWidth();

446

447 editeng::BorderDistanceFromWord(bFromEdge, nNewMargin, nNewDist, nLineWidth);

448 aBox.SetDistance(nNewDist, eLine);

449

450 return nNewMargin;

451}

452}

453

454void SwWW8ImplReader::SetPageBorder(SwFrameFormat &rFormat, const wwSection &rSection)

455{

456 if (!IsBorder(rSection.brc))

457 return;

458

459 SfxItemSet aSet(rFormat.GetAttrSet());

460 short aSizeArray[5]={0};

461 SetFlyBordersShadow(aSet, rSection.brc, &aSizeArray[0]);

462 SvxLRSpaceItem aLR(ItemGet(aSet, RES_LR_SPACE));

463 SvxULSpaceItem aUL(ItemGet(aSet, RES_UL_SPACE));

464 SvxBoxItem aBox(ItemGet(aSet, RES_BOX));

465 bool bFromEdge = rSection.maSep.pgbOffsetFrom == 1;

466

467 aLR.SetLeft(SetBorderDistance(bFromEdge, aBox, SvxBoxItemLine::LEFT, aLR.GetLeft()));

468 aLR.SetRight(SetBorderDistance(bFromEdge, aBox, SvxBoxItemLine::RIGHT, aLR.GetRight()));

469 aUL.SetUpper(SetBorderDistance(bFromEdge, aBox, SvxBoxItemLine::TOP, aUL.GetUpper()));

470 aUL.SetLower(SetBorderDistance(bFromEdge, aBox, SvxBoxItemLine::BOTTOM, aUL.GetLower()));

471

472 aSet.Put(aBox);

473 aSet.Put(aLR);

474 aSet.Put(aUL);

475 rFormat.SetFormatAttr(aSet);

476}

477

478void wwSectionManager::GetPageULData(const wwSection &rSection,

479 wwSectionManager::wwULSpaceData& rData) const

480{

481 sal_Int32 nWWUp = rSection.maSep.dyaTop;

482 sal_Int32 nWWLo = rSection.maSep.dyaBottom;

483 sal_uInt32 nWWHTop = rSection.maSep.dyaHdrTop;

484 sal_uInt32 nWWFBot = rSection.maSep.dyaHdrBottom;

485

486 /*

487 If there is gutter in 97+ and the dop says put it on top then get the

488 gutter distance and set it to the top margin. When we are "two pages

489 in one" the gutter is put at the top of odd pages, and bottom of

490 even pages, something we cannot do. So we will put it on top of all

491 pages, that way the pages are at least the right size.

492 */

493 if (!mrReader.m_bVer67 && mrReader.m_xWDop->iGutterPos &&

494 rSection.maSep.fRTLGutter)

495 {

496 nWWUp += rSection.maSep.dzaGutter;

497 }

498

499 rData.bHasHeader = (rSection.maSep.grpfIhdt &

500 (WW8_HEADER_EVEN | WW8_HEADER_ODD | WW8_HEADER_FIRST)) != 0;

501

502 if( rData.bHasHeader )

503 {

504 rData.nSwUp = nWWHTop; // Header -> convert

505 // #i19922# - correction:

506 // consider that can be negative, compare only if it's positive

507 if ( nWWUp > 0 &&

508 static_cast(abs(nWWUp)) >= nWWHTop )

509 rData.nSwHLo = nWWUp - nWWHTop;

510 else

511 rData.nSwHLo = 0;

512

513 // #i19922# - minimum page header height is now 1mm

514 // use new constant

515 if (rData.nSwHLo < sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight))

516 rData.nSwHLo = sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight);

517 }

518 else // no header -> just use Up as-is

519 rData.nSwUp = std::abs(nWWUp);

520

521 rData.bHasFooter = (rSection.maSep.grpfIhdt &

522 (WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST)) != 0;

523

524 if( rData.bHasFooter )

525 {

526 rData.nSwLo = nWWFBot; // footer -> convert

527 // #i19922# - correction: consider that can be negative, compare only if it's positive

528 if ( nWWLo > 0 &&

529 static_cast(abs(nWWLo)) >= nWWFBot )

530 rData.nSwFUp = nWWLo - nWWFBot;

531 else

532 rData.nSwFUp = 0;

533

534 // #i19922# - minimum page header height is now 1mm

535 // use new constant

536 if (rData.nSwFUp < sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight))

537 rData.nSwFUp = sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight);

538 }

539 else // no footer -> just use Lo as-is

540 rData.nSwLo = std::abs(nWWLo);

541}

542

543void wwSectionManager::SetPageULSpaceItems(SwFrameFormat &rFormat,

544 wwSectionManager::wwULSpaceData const & rData, const wwSection &rSection)

545{

546 if (rData.bHasHeader) // ... and set Header-Lower

547 {

548 // set header height to minimum

549 if (SwFrameFormat* pHdFormat = const_cast(rFormat.GetHeader().GetHeaderFormat()))

550 {

551 SvxULSpaceItem aHdUL(pHdFormat->GetULSpace());

552 if (!rSection.IsFixedHeightHeader()) //normal

553 {

554 pHdFormat->SetFormatAttr(SwFormatFrameSize(ATT_MIN_SIZE, 0, rData.nSwHLo));

555 // #i19922# - minimum page header height is now 1mm

556 // use new constant

557 aHdUL.SetLower( writer_cast(rData.nSwHLo - cMinHdFtHeight) );

558 pHdFormat->SetFormatAttr(SwHeaderAndFooterEatSpacingItem(

559 RES_HEADER_FOOTER_EAT_SPACING, true));

560 }

561 else

562 {

563 // #i48832# - set correct spacing between header and body.

564 const sal_Int32 nHdLowerSpace( std::abs(rSection.maSep.dyaTop) - rData.nSwUp - rData.nSwHLo );

565 pHdFormat->SetFormatAttr(SwFormatFrameSize(ATT_FIX_SIZE, 0, rData.nSwHLo + nHdLowerSpace));

566 aHdUL.SetLower( static_cast< sal_uInt16 >(nHdLowerSpace) );

567 pHdFormat->SetFormatAttr(SwHeaderAndFooterEatSpacingItem(

568 RES_HEADER_FOOTER_EAT_SPACING, false));

569 }

570 pHdFormat->SetFormatAttr(aHdUL);

571 }

572 }

573

574 if (rData.bHasFooter) // ... and set footer-upper

575 {

576 if (SwFrameFormat* pFtFormat = const_cast(rFormat.GetFooter().GetFooterFormat()))

577 {

578 SvxULSpaceItem aFtUL(pFtFormat->GetULSpace());

579 if (!rSection.IsFixedHeightFooter()) //normal

580 {

581 pFtFormat->SetFormatAttr(SwFormatFrameSize(ATT_MIN_SIZE, 0, rData.nSwFUp));

582 // #i19922# - minimum page header height is now 1mm

583 // use new constant

584 aFtUL.SetUpper( writer_cast(rData.nSwFUp - cMinHdFtHeight) );

585 pFtFormat->SetFormatAttr(SwHeaderAndFooterEatSpacingItem(

586 RES_HEADER_FOOTER_EAT_SPACING, true));

587 }

588 else

589 {

590 // #i48832# - set correct spacing between footer and body.

591 const SwTwips nFtUpperSpace( std::abs(rSection.maSep.dyaBottom) - rData.nSwLo - rData.nSwFUp );

592 pFtFormat->SetFormatAttr(SwFormatFrameSize(ATT_FIX_SIZE, 0, rData.nSwFUp + nFtUpperSpace));

593 aFtUL.SetUpper( static_cast< sal_uInt16 >(nFtUpperSpace) );

594 pFtFormat->SetFormatAttr(SwHeaderAndFooterEatSpacingItem(

595 RES_HEADER_FOOTER_EAT_SPACING, false));

596 }

597 pFtFormat->SetFormatAttr(aFtUL);

598 }

599 }

600

601 SvxULSpaceItem aUL(writer_cast(rData.nSwUp),

602 writer_cast(rData.nSwLo), RES_UL_SPACE);

603 rFormat.SetFormatAttr(aUL);

604}

605

606SwSectionFormat *wwSectionManager::InsertSection(

607 SwPaM const & rMyPaM, wwSection &rSection)

608{

609 SwSectionData aSection( CONTENT_SECTION,

610 mrReader.m_rDoc.GetUniqueSectionName() );

611

612 SfxItemSet aSet( mrReader.m_rDoc.GetAttrPool(), aFrameFormatSetRange );

613

614 bool bRTLPgn = !maSegments.empty() && maSegments.back().IsBiDi();

615 aSet.Put(SvxFrameDirectionItem(

616 bRTLPgn ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));

617

618 if (2 == mrReader.m_xWDop->fpc)

619 aSet.Put( SwFormatFootnoteAtTextEnd(FTNEND_ATTXTEND));

620 if (0 == mrReader.m_xWDop->epc)

621 aSet.Put( SwFormatEndAtTextEnd(FTNEND_ATTXTEND));

622

623 aSection.SetProtectFlag(SectionIsProtected(rSection));

624

625 rSection.mpSection =

626 mrReader.m_rDoc.InsertSwSection( rMyPaM, aSection, nullptr, & aSet );

627 OSL_ENSURE(rSection.mpSection, "section not inserted!");

628 if (!rSection.mpSection)

629 return nullptr;

630

631 SwPageDesc *pPage = nullptr;

632 mySegrIter aEnd = maSegments.rend();

633 for (mySegrIter aIter = maSegments.rbegin(); aIter != aEnd; ++aIter)

634 {

635 if (nullptr != (pPage = aIter->mpPage))

636 break;

637 }

638

639 OSL_ENSURE(pPage, "no page outside this section!");

640

641 if (!pPage)

642 pPage = &mrReader.m_rDoc.GetPageDesc(0);

643

644 if (!pPage)

645 return nullptr;

646

647 SwSectionFormat *pFormat = rSection.mpSection->GetFormat();

648 OSL_ENSURE(pFormat, "impossible");

649 if (!pFormat)

650 return nullptr;

651

652 SwFrameFormat& rFormat = pPage->GetMaster();

653 const SvxLRSpaceItem& rLR = rFormat.GetLRSpace();

654 long nPageLeft = rLR.GetLeft();

655 long nPageRight = rLR.GetRight();

656 long nSectionLeft = rSection.GetPageLeft() - nPageLeft;

657 long nSectionRight = rSection.GetPageRight() - nPageRight;

658 if ((nSectionLeft != 0) || (nSectionRight != 0))

659 {

660 SvxLRSpaceItem aLR(nSectionLeft, nSectionRight, 0, 0, RES_LR_SPACE);

661 pFormat->SetFormatAttr(aLR);

662 }

663

664 SetCols(*pFormat, rSection, rSection.GetTextAreaWidth());

665 return pFormat;

666}

667

668void SwWW8ImplReader::HandleLineNumbering(const wwSection &rSection)

669{

670 // check if Line Numbering must be activated or reset

671 if (m_bNewDoc && rSection.maSep.nLnnMod)

672 {

673 // restart-numbering-mode: 0 per page, 1 per section, 2 never restart

674 bool bRestartLnNumPerSection = (1 == rSection.maSep.lnc);

675

676 if (m_bNoLnNumYet)

677 {

678 SwLineNumberInfo aInfo( m_rDoc.GetLineNumberInfo() );

679

680 aInfo.SetPaintLineNumbers(true);

681

682 aInfo.SetRestartEachPage(rSection.maSep.lnc == 0);

683

684 aInfo.SetPosFromLeft(writer_cast(rSection.maSep.dxaLnn));

685

686 //Paint only for every n line

687 aInfo.SetCountBy(rSection.maSep.nLnnMod);

688

689 // to be defaulted features ( HARDCODED in MS Word 6,7,8,9 )

690 aInfo.SetCountBlankLines(true);

691 aInfo.SetCountInFlys(false);

692 aInfo.SetPos( LINENUMBER_POS_LEFT );

693 SvxNumberType aNumType; // this sets SVX_NUM_ARABIC per default

694 aInfo.SetNumType( aNumType );

695

696 m_rDoc.SetLineNumberInfo( aInfo );

697 m_bNoLnNumYet = false;

698 }

699

700 if (

701 (0 < rSection.maSep.lnnMin) ||

702 (bRestartLnNumPerSection && !m_bNoLnNumYet)

703 )

704 {

705 SwFormatLineNumber aLN;

706 if (const SwFormatLineNumber* pLN

707 = static_cast(GetFormatAttr(RES_LINENUMBER)))

708 {

709 aLN.SetCountLines( pLN->IsCount() );

710 }

711 aLN.SetStartValue(1 + rSection.maSep.lnnMin);

712 NewAttr(aLN);

713 m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_LINENUMBER);

714 }

715 m_bNoLnNumYet = false;

716 }

717}

718

719wwSection::wwSection(const SwPosition &rPos) : maStart(rPos.nNode)

720 , mpSection(nullptr)

721 , mpPage(nullptr)

722 , meDir(SvxFrameDirection::Horizontal_LR_TB)

723 , nPgWidth(SvxPaperInfo::GetPaperSize(PAPER_A4).Width())

724 , nPgLeft(MM_250)

725 , nPgRight(MM_250)

726 , mnVerticalAdjustment(drawing::TextVerticalAdjust_TOP)

727 , mnBorders(0)

728 , mbHasFootnote(false)

729{

730}

731

732void wwSectionManager::SetNumberingType(const wwSection &rNewSection,

733 SwPageDesc &rPageDesc)

734{

735 // save page number format

736 static const SvxNumType aNumTyp[5] =

737 {

738 SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,

739 SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N

740 };

741

742 SvxNumberType aType;

743 aType.SetNumberingType( aNumTyp[rNewSection.maSep.nfcPgn] );

744 rPageDesc.SetNumType(aType);

745}

746

747// CreateSep is called for every section change (even at the start of

748// the document. CreateSep also creates the pagedesc(s) and

749// fills it/them with attributes and KF texts.

750// This has become necessary because the translation of the various

751// page attributes is interconnected too much.

752void wwSectionManager::CreateSep(const long nTextPos)

753{

754 /*

755 #i1909# section/page breaks should not occur in tables or subpage

756 elements like frames. Word itself ignores them in this case. The bug is

757 more likely that this filter created such documents in the past!

758 */

759 if (mrReader.m_nInTable || mrReader.m_bTxbxFlySection || mrReader.InLocalApo())

760 return;

761

762 WW8PLCFx_SEPX* pSep = mrReader.m_xPlcxMan->GetSepPLCF();

763 OSL_ENSURE(pSep, "impossible!");

764 if (!pSep)

765 return;

766

767 if (!maSegments.empty() && mrReader.m_pLastAnchorPos.get() && *mrReader.m_pLastAnchorPos == *mrReader.m_pPaM->GetPoint())

768 {

769 bool insert = true;

770 SwPaM pam( *mrReader.m_pLastAnchorPos );

771 if( pam.Move(fnMoveBackward, GoInNode))

772 if( SwTextNode* txtNode = pam.GetPoint()->nNode.GetNode().GetTextNode())

773 if( txtNode->Len() == 0 )

774 insert = false;

775 if( insert )

776 mrReader.AppendTextNode(*mrReader.m_pPaM->GetPoint());

777 }

778

779 ww::WordVersion eVer = mrReader.GetFib().GetFIBVersion();

780

781 // M.M. Create a linked section if the WkbPLCF

782 // has an entry for one at this cp

783 WW8PLCFspecial* pWkb = mrReader.m_xPlcxMan->GetWkbPLCF();

784 if (pWkb && pWkb->SeekPosExact(nTextPos) &&

785 pWkb->Where() == nTextPos)

786 {

787 void* pData;

788 WW8_CP nTest;

789 bool bSuccess = pWkb->Get(nTest, pData);

790 if (!bSuccess)

791 return;

792 OUString sSectionName = mrReader.m_aLinkStringMap[SVBT16ToShort( static_cast(pData)->nLinkId) ];

793 sSectionName = mrReader.ConvertFFileName(sSectionName);

794 SwSectionData aSection(FILE_LINK_SECTION, sSectionName);

795 aSection.SetLinkFileName( sSectionName );

796 aSection.SetProtectFlag(true);

797 // #i19922# - improvement: return value of method not used.

798 mrReader.m_rDoc.InsertSwSection(*mrReader.m_pPaM, aSection, nullptr, nullptr, false);

799 }

800

801 wwSection aLastSection(*mrReader.m_pPaM->GetPoint());

802 if (!maSegments.empty())

803 aLastSection = maSegments.back();

804

805 //Here

806 sal_uInt16 nLIdx = ( ( static_cast(mrReader.m_xWwFib->m_lid) & 0xff ) == 0x9 ) ? 1 : 0;

807

808 //BEGIN read section values

809 wwSection aNewSection(*mrReader.m_pPaM->GetPoint());

810

811 static const sal_uInt16 aVer2Ids0[] =

812 {

813 /*sprmSBkc*/ 117,

814 /*sprmSFTitlePage*/ 118,

815 /*sprmSNfcPgn*/ 122,

816 /*sprmSCcolumns*/ 119,

817 /*sprmSDxaColumns*/ 120,

818 /*sprmSLBetween*/ 133

819 };

820

821 static const sal_uInt16 aVer67Ids0[] =

822 {

823 NS_sprm::v6::sprmSBkc,

824 NS_sprm::v6::sprmSFTitlePage,

825 NS_sprm::v6::sprmSNfcPgn,

826 NS_sprm::v6::sprmSCcolumns,

827 NS_sprm::v6::sprmSDxaColumns,

828 NS_sprm::v6::sprmSLBetween

829 };

830

831 static const sal_uInt16 aVer8Ids0[] =

832 {

833 NS_sprm::sprmSBkc,

834 NS_sprm::sprmSFTitlePage,

835 NS_sprm::sprmSNfcPgn,

836 NS_sprm::sprmSCcolumns,

837 NS_sprm::sprmSDxaColumns,

838 NS_sprm::sprmSLBetween

839 };

840

841 const sal_uInt16* pIds = eVer = 1)

854 aNewSection.maSep.bkc = *pSprmBkc;

855 }

856

857 // Has a table page

858 aNewSection.maSep.fTitlePage =

859 sal_uInt8(0 != ReadBSprm( pSep, pIds[1], 0 ));

860

861 // sprmSNfcPgn

862 aNewSection.maSep.nfcPgn = ReadBSprm( pSep, pIds[2], 0 );

863 if (aNewSection.maSep.nfcPgn > 4)

864 aNewSection.maSep.nfcPgn = 0;

865

866 aNewSection.maSep.fUnlocked = eVer > ww::eWW2 ? ReadBSprm(pSep, (eVer = ww::eWW8 ? ReadBSprm(pSep, NS_sprm::sprmSFBiDi, 0) : 0;

870

871 // Reading section property sprmSCcolumns - one less than the number of columns in the section.

872 // It must be less than MAX_NO_OF_SEP_COLUMNS according the WW8 specification.

873 aNewSection.maSep.ccolM1 = ReadSprm(pSep, pIds[3], 0 );

874 if ( aNewSection.maSep.ccolM1 >= MAX_NO_OF_SEP_COLUMNS )

875 {

876 // clip to max

877 aNewSection.maSep.ccolM1 = MAX_NO_OF_SEP_COLUMNS-1;

878 }

879

880 //sprmSDxaColumns - default distance 1.25 cm

881 aNewSection.maSep.dxaColumns = ReadUSprm( pSep, pIds[4], 708 );

882

883 // sprmSLBetween

884 aNewSection.maSep.fLBetween = ReadBSprm(pSep, pIds[5], 0 );

885

886 if (eVer >= ww::eWW6)

887 {

888 // sprmSFEvenlySpaced

889 aNewSection.maSep.fEvenlySpaced =

890 sal_uInt8(ReadBSprm(pSep, (eVer 0 && !aNewSection.maSep.fEvenlySpaced)

893 {

894 int nColumnDataIdx = 0;

895 aNewSection.maSep.rgdxaColumnWidthSpacing[nColumnDataIdx] = 0;

896

897 const sal_uInt16 nColumnWidthSprmId = ( eVer HasSprm(nColumnWidthSprmId, nColumn);

904 const sal_uInt8* pSW = aSWRes.pSprm;

905

906 OSL_ENSURE( pSW, "+Sprm 136 (resp. 0xF203) (ColWidth) missing" );

907 sal_uInt16 nWidth = (pSW && aSWRes.nRemainingData >= 3) ? SVBT16ToShort(pSW + 1) : 1440;

908

909 aNewSection.maSep.rgdxaColumnWidthSpacing[++nColumnDataIdx] = nWidth;

910

911 if ( nColumn < nColumnCount - 1 )

912 {

913 //sprmSDxaColSpacing

914 SprmResult aSDRes = pSep->HasSprm(nColumnSpacingSprmId, nColumn);

915 const sal_uInt8* pSD = aSDRes.pSprm;

916

917 OSL_ENSURE( pSD, "+Sprm 137 (resp. 0xF204) (Colspacing) missing" );

918 if (pSD && aSDRes.nRemainingData >= 3)

919 {

920 nWidth = SVBT16ToShort(pSD + 1);

921 aNewSection.maSep.rgdxaColumnWidthSpacing[++nColumnDataIdx] = nWidth;

922 }

923 }

924 }

925 }

926 }

927

928 static const sal_uInt16 aVer2Ids1[] =

929 {

930 /*sprmSBOrientation*/ 137,

931 /*sprmSXaPage*/ 139,

932 /*sprmSYaPage*/ 140,

933 /*sprmSDxaLeft*/ 141,

934 /*sprmSDxaRight*/ 142,

935 /*sprmSDzaGutter*/ 145,

936 /*sprmSFPgnRestart*/ 125,

937 /*sprmSPgnStart*/ 136,

938 /*sprmSDmBinFirst*/ 115,

939 /*sprmSDmBinOther*/ 116

940 };

941

942 static const sal_uInt16 aVer67Ids1[] =

943 {

944 NS_sprm::v6::sprmSBOrientation,

945 NS_sprm::v6::sprmSXaPage,

946 NS_sprm::v6::sprmSYaPage,

947 NS_sprm::v6::sprmSDxaLeft,

948 NS_sprm::v6::sprmSDxaRight,

949 NS_sprm::v6::sprmSDzaGutter,

950 NS_sprm::v6::sprmSFPgnRestart,

951 NS_sprm::v6::sprmSPgnStart,

952 NS_sprm::v6::sprmSDmBinFirst,

953 NS_sprm::v6::sprmSDmBinOther

954 };

955

956 static const sal_uInt16 aVer8Ids1[] =

957 {

958 NS_sprm::sprmSBOrientation,

959 NS_sprm::sprmSXaPage,

960 NS_sprm::sprmSYaPage,

961 NS_sprm::sprmSDxaLeft,

962 NS_sprm::sprmSDxaRight,

963 NS_sprm::sprmSDzaGutter,

964 NS_sprm::sprmSFPgnRestart,

965 NS_sprm::sprmSPgnStart97,

966 NS_sprm::sprmSDmBinFirst,

967 NS_sprm::sprmSDmBinOther

968 };

969

970 pIds = eVer HasSprm(nId);

1508 if (aS.pSprm && aS.nRemainingData >= 2)

1509 *pVar = static_cast(SVBT16ToShort(aS.pSprm));

1510 return aS.pSprm != nullptr;

1511}

1512

1513inline bool SetValSprm( sal_Int16* pVar, const WW8RStyle* pStyle, sal_uInt16 nId )

1514{

1515 SprmResult aS = pStyle->HasParaSprm(nId);

1516 if (aS.pSprm && aS.nRemainingData >= 2)

1517 *pVar = static_cast(SVBT16ToShort(aS.pSprm));

1518 return aS.pSprm != nullptr;

1519}

1520

1521/*

1522#i1930 revealed that sprm 0x360D (sprmTPc) as used in tables can affect the frame

1523around the table. Its full structure is not fully understood as yet.

1524*/

1525void WW8FlyPara::ApplyTabPos(const WW8_TablePos *pTabPos)

1526{

1527 if (pTabPos)

1528 {

1529 nSp26 = pTabPos->nSp26;

1530 nSp27 = pTabPos->nSp27;

1531 nSp29 = pTabPos->nSp29;

1532 nLeMgn = pTabPos->nLeMgn;

1533 nRiMgn = pTabPos->nRiMgn;

1534 nUpMgn = pTabPos->nUpMgn;

1535 nLoMgn = pTabPos->nLoMgn;

1536 nSp37 = pTabPos->nSp37;

1537 }

1538}

1539

1540WW8FlyPara::WW8FlyPara(bool bIsVer67, const WW8FlyPara* pSrc /* = 0 */)

1541{

1542 if ( pSrc )

1543 memcpy( this, pSrc, sizeof( WW8FlyPara ) ); // Copy-Ctor

1544 else

1545 {

1546 memset( this, 0, sizeof( WW8FlyPara ) ); // Default-Ctor

1547 nSp37 = 2; // Default: wrapping

1548 }

1549 bVer67 = bIsVer67;

1550}

1551

1552bool WW8FlyPara::operator==(const WW8FlyPara& rSrc) const

1553{

1554 /*

1555 Compare the parts that word seems to compare for equivalence.

1556 Interestingly being autoheight or absolute height (the & 0x7fff) doesn't

1557 matter to word

1558 */

1559 return

1560 (

1561 (nSp26 == rSrc.nSp26) &&

1562 (nSp27 == rSrc.nSp27) &&

1563 ((nSp45 & 0x7fff) == (rSrc.nSp45 & 0x7fff)) &&

1564 (nSp28 == rSrc.nSp28) &&

1565 (nLeMgn == rSrc.nLeMgn) &&

1566 (nRiMgn == rSrc.nRiMgn) &&

1567 (nUpMgn == rSrc.nUpMgn) &&

1568 (nLoMgn == rSrc.nLoMgn) &&

1569 (nSp29 == rSrc.nSp29) &&

1570 (nSp37 == rSrc.nSp37)

1571 );

1572}

1573

1574// Read for normal text

1575void WW8FlyPara::Read(sal_uInt8 nOrigSp29, WW8PLCFx_Cp_FKP* pPap)

1576{

1577 if( bVer67 )

1578 {

1579 SetValSprm( &nSp26, pPap, 26 ); // X-position //sprmPDxaAbs

1580 //set in me or in parent style

1581 mbVertSet |= SetValSprm( &nSp27, pPap, 27 ); // Y-position //sprmPDyaAbs

1582 SetValSprm( &nSp45, pPap, 45 ); // height //sprmPWHeightAbs

1583 SetValSprm( &nSp28, pPap, 28 ); // width //sprmPDxaWidth

1584 SetValSprm( &nLeMgn, pPap, 49 ); // L-border //sprmPDxaFromText

1585 SetValSprm( &nRiMgn, pPap, 49 ); // R-border //sprmPDxaFromText

1586 SetValSprm( &nUpMgn, pPap, 48 ); // U-border //sprmPDyaFromText

1587 SetValSprm( &nLoMgn, pPap, 48 ); // D-border //sprmPDyaFromText

1588

1589 SprmResult aS = pPap->HasSprm(NS_sprm::v6::sprmPWr);

1590 if (aS.pSprm && aS.nRemainingData >= 1)

1591 nSp37 = *aS.pSprm;

1592 }

1593 else

1594 {

1595 SetValSprm( &nSp26, pPap, NS_sprm::sprmPDxaAbs ); // X-position

1596 //set in me or in parent style

1597 mbVertSet |= SetValSprm( &nSp27, pPap, NS_sprm::sprmPDyaAbs ); // Y-position

1598 SetValSprm( &nSp45, pPap, NS_sprm::sprmPWHeightAbs ); // height

1599 SetValSprm( &nSp28, pPap, NS_sprm::sprmPDxaWidth ); // width

1600 SetValSprm( &nLeMgn, pPap, NS_sprm::sprmPDxaFromText ); // L-border

1601 SetValSprm( &nRiMgn, pPap, NS_sprm::sprmPDxaFromText ); // R-border

1602 SetValSprm( &nUpMgn, pPap, NS_sprm::sprmPDyaFromText ); // U-border

1603 SetValSprm( &nLoMgn, pPap, NS_sprm::sprmPDyaFromText ); // D-border

1604

1605 SprmResult aS = pPap->HasSprm(NS_sprm::sprmPWr); // wrapping

1606 if (aS.pSprm && aS.nRemainingData >= 1)

1607 nSp37 = *aS.pSprm;

1608 }

1609

1610 if( ::lcl_ReadBorders( bVer67, brc, pPap )) // borders

1611 bBorderLines = ::lcl_IsBorder( brc );

1612

1613 /*

1614 #i8798#

1615 Appears that with no dyaAbs set then the actual vert anchoring set is

1616 ignored and we remain relative to text, so if that is the case we are 0

1617 from para anchor, so we update the frame to have explicitly this type of

1618 anchoring

1619 */

1620 if (!mbVertSet)

1621 nSp29 = (nOrigSp29 & 0xCF) | 0x20;

1622 else

1623 nSp29 = nOrigSp29;

1624}

1625

1626void WW8FlyPara::ReadFull(sal_uInt8 nOrigSp29, SwWW8ImplReader* pIo)

1627{

1628 std::shared_ptr xPlcxMan = pIo->m_xPlcxMan;

1629 WW8PLCFx_Cp_FKP* pPap = xPlcxMan->GetPapPLCF();

1630

1631 Read(nOrigSp29, pPap); // read Apo parameter

1632

1633 do{ // block for quick exit

1634 if( nSp45 != 0 /* || nSp28 != 0 */ )

1635 break; // bGrafApo only automatic for height

1636 if( pIo->m_xWwFib->m_fComplex )

1637 break; // (*pPap)++ does not work for FastSave

1638 // -> for FastSave, no test for graphics APO

1639 SvStream* pIoStrm = pIo->m_pStrm;

1640 sal_uLong nPos = pIoStrm->Tell();

1641 WW8PLCFxSave1 aSave;

1642 xPlcxMan->GetPap()->Save( aSave );

1643 bGrafApo = false;

1644

1645 do{ // block for quick exit

1646 sal_uInt8 nText[2];

1647

1648 if (!checkRead(*pIoStrm, nText, 2)) // read text

1649 break;

1650

1651 if( nText[0] != 0x01 || nText[1] != 0x0d )// only graphics + CR?

1652 break; // no

1653

1654 pPap->advance(); // next line

1655

1656 // in APO ?

1657 //sprmPPc

1658 SprmResult aS = pPap->HasSprm( bVer67 ? NS_sprm::v6::sprmPPc : NS_sprm::sprmPPc);

1659

1660 // no -> graphics Apo

1661 if (!aS.pSprm || aS.nRemainingData < 1)

1662 {

1663 bGrafApo = true;

1664 break; // end of APO

1665 }

1666

1667 ww::WordVersion eVer = pIo->GetFib().GetFIBVersion();

1668 WW8FlyPara *pNowStyleApo=nullptr;

1669 sal_uInt16 nColl = pPap->GetIstd();

1670 ww::sti eSti = eVer < ww::eWW6 ? ww::GetCanonicalStiFromStc( static_cast< sal_uInt8 >(nColl) ) : static_cast(nColl);

1671 while (eSti != ww::stiNil && sal::static_int_cast(nColl) < pIo->m_vColl.size() && nullptr == (pNowStyleApo = pIo->m_vColl[nColl].m_xWWFly.get()))

1672 {

1673 nColl = pIo->m_vColl[nColl].m_nBase;

1674 eSti = eVer < ww::eWW6 ? ww::GetCanonicalStiFromStc( static_cast< sal_uInt8 >(nColl) ) : static_cast(nColl);

1675 }

1676

1677 WW8FlyPara aF(bVer67, pNowStyleApo);

1678 // new FlaPara for comparison

1679 aF.Read(*aS.pSprm, pPap); // WWPara for new Para

1680 if( !( aF == *this ) ) // same APO? (or a new one?)

1681 bGrafApo = true; // no -> 1-line APO

1682 // -> graphics APO

1683 }

1684 while( false ); // block for quick exit

1685

1686 xPlcxMan->GetPap()->Restore( aSave );

1687 pIoStrm->Seek( nPos );

1688 }while( false ); // block for quick exit

1689}

1690

1691// read for Apo definitions in Styledefs

1692void WW8FlyPara::Read(sal_uInt8 nOrigSp29, WW8RStyle const * pStyle)

1693{

1694 if (bVer67)

1695 {

1696 SetValSprm( &nSp26, pStyle, NS_sprm::v6::sprmPDxaAbs ); // X-position

1697 //set in me or in parent style

1698 mbVertSet |= SetValSprm(&nSp27, pStyle, NS_sprm::v6::sprmPDyaAbs); // Y-position

1699 SetValSprm( &nSp45, pStyle, NS_sprm::v6::sprmPWHeightAbs ); // height

1700 SetValSprm( &nSp28, pStyle, NS_sprm::v6::sprmPDxaWidth ); // width

1701 SetValSprm( &nLeMgn, pStyle, NS_sprm::v6::sprmPDxaFromText ); // L-border

1702 SetValSprm( &nRiMgn, pStyle, NS_sprm::v6::sprmPDxaFromText ); // R-border

1703 SetValSprm( &nUpMgn, pStyle, NS_sprm::v6::sprmPDyaFromText ); // U-border

1704 SetValSprm( &nLoMgn, pStyle, NS_sprm::v6::sprmPDyaFromText ); // D-border

1705

1706 SprmResult aS = pStyle->HasParaSprm( NS_sprm::v6::sprmPWr ); // wrapping

1707 if (aS.pSprm && aS.nRemainingData >= 1)

1708 nSp37 = *aS.pSprm;

1709 }

1710 else

1711 {

1712 SetValSprm( &nSp26, pStyle, NS_sprm::sprmPDxaAbs ); // X-position

1713 //set in me or in parent style

1714 mbVertSet |= SetValSprm(&nSp27, pStyle, NS_sprm::sprmPDyaAbs); // Y-position

1715 SetValSprm( &nSp45, pStyle, NS_sprm::sprmPWHeightAbs ); // height

1716 SetValSprm( &nSp28, pStyle, NS_sprm::sprmPDxaWidth ); // width

1717 SetValSprm( &nLeMgn, pStyle, NS_sprm::sprmPDxaFromText ); // L-border

1718 SetValSprm( &nRiMgn, pStyle, NS_sprm::sprmPDxaFromText ); // R-border

1719 SetValSprm( &nUpMgn, pStyle, NS_sprm::sprmPDyaFromText ); // U-border

1720 SetValSprm( &nLoMgn, pStyle, NS_sprm::sprmPDyaFromText ); // D-border

1721

1722 SprmResult aS = pStyle->HasParaSprm( NS_sprm::sprmPWr ); // wrapping

1723 if (aS.pSprm && aS.nRemainingData >= 1)

1724 nSp37 = *aS.pSprm;

1725 }

1726

1727 if (::lcl_ReadBorders(bVer67, brc, nullptr, pStyle)) // border

1728 bBorderLines = ::lcl_IsBorder(brc);

1729

1730 /*

1731 #i8798#

1732 Appears that with no dyaAbs set then the actual vert anchoring set is

1733 ignored and we remain relative to text, so if that is the case we are 0

1734 from para anchor, so we update the frame to have explicitly this type of

1735 anchoring

1736 */

1737 if (!mbVertSet)

1738 nSp29 = (nOrigSp29 & 0xCF) | 0x20;

1739 else

1740 nSp29 = nOrigSp29;

1741}

1742

1743bool WW8FlyPara::IsEmpty() const

1744{

1745 WW8FlyPara aEmpty(bVer67);

1746 /*

1747 wr of 0 like 2 appears to me to be equivalent for checking here. See

1748 #107103# if wrong, so given that the empty is 2, if we are 0 then set

1749 empty to 0 to make 0 equiv to 2 for empty checking

1750 */

1751 OSL_ENSURE(aEmpty.nSp37 == 2, "this is not what we expect for nSp37");

1752 if (this->nSp37 == 0)

1753 aEmpty.nSp37 = 0;

1754 return aEmpty == *this;

1755}

1756

1757// #i18732# - changes made on behalf of CMC

1758WW8SwFlyPara::WW8SwFlyPara( SwPaM& rPaM,

1759 SwWW8ImplReader& rIo,

1760 WW8FlyPara& rWW,

1761 const sal_uInt32 nWWPgTop,

1762 const sal_uInt32 nPgWidth,

1763 const sal_Int32 nIniFlyDx,

1764 const sal_Int32 nIniFlyDy ):

1765pFlyFormat(nullptr),

1766nXPos(0),

1767nYPos(0),

1768nLeMgn(rWW.nLeMgn),

1769nRiMgn(rWW.nRiMgn),

1770nUpMgn(rWW.nUpMgn),

1771nLoMgn(rWW.nLoMgn),

1772nWidth(rWW.nSp28),

1773nHeight(rWW.nSp45),

1774nNetWidth(rWW.nSp28),

1775eHeightFix(ATT_FIX_SIZE),

1776eHRel(text::RelOrientation::PAGE_FRAME),

1777eVRel(text::RelOrientation::FRAME),

1778eVAlign(text::VertOrientation::NONE),

1779eHAlign(text::HoriOrientation::NONE),

1780eSurround(( rWW.nSp37 > 1 ) ? css::text::WrapTextMode_DYNAMIC : css::text::WrapTextMode_NONE),

1781nXBind(( rWW.nSp29 & 0xc0 ) >> 6),

1782nYBind(( rWW.nSp29 & 0x30 ) >> 4),

1783nNewNetWidth(MINFLY),

1784xMainTextPos(nullptr),

1785nLineSpace(0),

1786bAutoWidth(false),

1787bToggelPos(false)

1788{

1789 //#i119466 mapping "Around" wrap setting to "Parallel" for table

1790 const bool bIsTable = rIo.m_xPlcxMan->HasParaSprm(NS_sprm::sprmPFInTable).pSprm;

1791 if (bIsTable && rWW.nSp37 == 2)

1792 eSurround = css::text::WrapTextMode_PARALLEL;

1793

1794 /*

1795 #95905#, #83307# seems to have gone away now, so re-enable parallel

1796 wrapping support for frames in headers/footers. I don't know if we truly

1797 have an explicitly specified behaviour for these circumstances.

1798 */

1799

1800 if( nHeight & 0x8000 )

1801 {

1802 nHeight &= 0x7fff;

1803 eHeightFix = ATT_MIN_SIZE;

1804 }

1805

1806 if( nHeight ( nYPos + nWWPgTop );

2002 }

2003

2004 FlySecur1( nWidth, rWW.bBorderLines ); // Do the borders match ?

2005 FlySecur1( nHeight, rWW.bBorderLines );

2006

2007}

2008

2009// If a Fly in WW has automatic width, this has to be simulated

2010// by modifying the Fly width (fixed in SW) afterwards.

2011// This can increase or decrease the Fly width, because the default value

2012// is set without knowledge of the contents.

2013void WW8SwFlyPara::BoxUpWidth( long nInWidth )

2014{

2015 if( bAutoWidth && nInWidth > nNewNetWidth )

2016 nNewNetWidth = nInWidth;

2017};

2018

2019// The class WW8FlySet is derived from SfxItemSet and does not

2020// provide more, but is easier to handle for me.

2021// WW8FlySet-ctor for Apos and graphics Apos

2022WW8FlySet::WW8FlySet(SwWW8ImplReader& rReader, const WW8FlyPara* pFW,

2023 const WW8SwFlyPara* pFS, bool bGraf)

2024 : SfxItemSet(rReader.m_rDoc.GetAttrPool(),svl::Items{})

2025{

2026 if (!rReader.m_bNewDoc)

2027 Reader::ResetFrameFormatAttrs(*this); // remove distance/border

2028 // position

2029 Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));

2030

2031/*Below can all go when we have from left in rtl mode*/

2032 SwTwips nXPos = pFS->nXPos;

2033 sal_Int16 eHRel = pFS->eHRel;

2034 rReader.MiserableRTLGraphicsHack(nXPos, pFS->nWidth, pFS->eHAlign, eHRel);

2035/*Above can all go when we have from left in rtl mode*/

2036 Put( SwFormatHoriOrient(nXPos, pFS->eHAlign, pFS->eHRel, pFS->bToggelPos ));

2037 Put( SwFormatVertOrient( pFS->nYPos, pFS->eVAlign, pFS->eVRel ) );

2038

2039 if (pFS->nLeMgn || pFS->nRiMgn) // set borders

2040 Put(SvxLRSpaceItem(pFS->nLeMgn, pFS->nRiMgn, 0, 0, RES_LR_SPACE));

2041

2042 if (pFS->nUpMgn || pFS->nLoMgn)

2043 Put(SvxULSpaceItem(pFS->nUpMgn, pFS->nLoMgn, RES_UL_SPACE));

2044

2045 //we no longer need to hack around the header/footer problems

2046 SwFormatSurround aSurround(pFS->eSurround);

2047 if ( pFS->eSurround == css::text::WrapTextMode_DYNAMIC )

2048 aSurround.SetAnchorOnly( true );

2049 Put( aSurround );

2050

2051 short aSizeArray[5]={0};

2052 SwWW8ImplReader::SetFlyBordersShadow(*this,pFW->brc,&aSizeArray[0]);

2053

2054 // the 5th parameter is always 0, thus we lose nothing due to the cast

2055

2056 // #i27767#

2057 // #i35017# - constant name has changed

2058 Put( SwFormatWrapInfluenceOnObjPos(

2059 text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) );

2060

2061 if( !bGraf )

2062 {

2063 Put( SwFormatAnchor(WW8SwFlyPara::eAnchor) );

2064 // adjust size

2065

2066 //Ordinarily with frames, the border width and spacing is

2067 //placed outside the frame, making it larger. With these

2068 //types of frames, the left right thickness and space makes

2069 //it wider, but the top bottom spacing and border thickness

2070 //is placed inside.

2071 Put( SwFormatFrameSize( pFS->eHeightFix, pFS->nWidth +

2072 aSizeArray[WW8_LEFT] + aSizeArray[WW8_RIGHT],

2073 pFS->nHeight));

2074 }

2075}

2076

2077// WW8FlySet-ctor for character bound graphics

2078WW8FlySet::WW8FlySet( SwWW8ImplReader& rReader, const SwPaM* pPaM,

2079 const WW8_PIC& rPic, long nWidth, long nHeight )

2080 : SfxItemSet(rReader.m_rDoc.GetAttrPool(),svl::Items{})

2081{

2082 Init(rReader, pPaM);

2083

2084 Put(SvxFrameDirectionItem(SvxFrameDirection::Horizontal_LR_TB, RES_FRAMEDIR));

2085

2086 short aSizeArray[5]={0};

2087 /*

2088 If we have set borders then in word the graphic is displaced from the left

2089 and top the width of the borders of those sides, and then the shadow

2090 itself is drawn to the bottom and right of the displaced graphic. In word

2091 the total size is that of the graphic plus the borders, plus the total

2092 shadow around all edges, for this translation the top and left shadow

2093 region is translated spacing around the graphic to those sides, and the

2094 bottom and right shadow size is added to the graphic size.

2095 */

2096 WW8_BRCVer9 brcVer9[4];

2097 for (int i = 0; i < 4; i++)

2098 brcVer9[i] = WW8_BRCVer9(rPic.rgbrc[i]);

2099 if (SwWW8ImplReader::SetFlyBordersShadow( *this, brcVer9, &aSizeArray[0]))

2100 {

2101 Put(SvxLRSpaceItem( aSizeArray[WW8_LEFT], 0, 0, 0, RES_LR_SPACE ) );

2102 Put(SvxULSpaceItem( aSizeArray[WW8_TOP], 0, RES_UL_SPACE ));

2103 aSizeArray[WW8_RIGHT]*=2;

2104 aSizeArray[WW8_BOT]*=2;

2105 }

2106

2107 Put( SwFormatFrameSize( ATT_FIX_SIZE, nWidth+aSizeArray[WW8_LEFT]+

2108 aSizeArray[WW8_RIGHT], nHeight+aSizeArray[WW8_TOP]

2109 + aSizeArray[WW8_BOT]) );

2110}

2111

2112void WW8FlySet::Init(const SwWW8ImplReader& rReader, const SwPaM* pPaM)

2113{

2114 if (!rReader.m_bNewDoc)

2115 Reader::ResetFrameFormatAttrs(*this); // remove distance/borders

2116

2117 Put(SvxLRSpaceItem(RES_LR_SPACE)); //inline writer ole2 objects start with 0.2cm l/r

2118 SwFormatAnchor aAnchor(RndStdIds::FLY_AS_CHAR);

2119

2120 aAnchor.SetAnchor(pPaM->GetPoint());

2121 Put(aAnchor);

2122

2123 //The horizontal default is on the baseline, the vertical is centered

2124 //around the character center it appears

2125 if (rReader.m_aSectionManager.CurrentSectionIsVertical())

2126 Put(SwFormatVertOrient(0, text::VertOrientation::CHAR_CENTER,text::RelOrientation::CHAR));

2127 else

2128 Put(SwFormatVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));

2129}

2130

2131WW8DupProperties::WW8DupProperties(SwDoc &rDoc, SwWW8FltControlStack *pStack)

2132 : pCtrlStck(pStack),

2133 aChrSet(rDoc.GetAttrPool(), svl::Items{} ),

2134 aParSet(rDoc.GetAttrPool(), svl::Items{} )

2135{

2136 //Close any open character properties and duplicate them inside the

2137 //first table cell

2138 size_t nCnt = pCtrlStck->size();

2139 for (size_t i=0; i < nCnt; ++i)

2140 {

2141 const SwFltStackEntry& rEntry = (*pCtrlStck)[ i ];

2142 if (rEntry.bOpen)

2143 {

2144 if (isCHRATR(rEntry.pAttr->Which()))

2145 {

2146 aChrSet.Put( *rEntry.pAttr );

2147

2148 }

2149 else if (isPARATR(rEntry.pAttr->Which()))

2150 {

2151 aParSet.Put( *rEntry.pAttr );

2152 }

2153 }

2154 }

2155}

2156

2157void WW8DupProperties::Insert(const SwPosition &rPos)

2158{

2159 for (const SfxItemSet* pSet : {&aChrSet, &aParSet})

2160 {

2161 if( pSet->Count() )

2162 {

2163 SfxItemIter aIter( *pSet );

2164 const SfxPoolItem* pItem = aIter.GetCurItem();

2165 do

2166 {

2167 pCtrlStck->NewAttr(rPos, *pItem);

2168 }while( !aIter.IsAtEnd() && nullptr != ( pItem = aIter.NextItem() ) );

2169 }

2170 }

2171}

2172

2173void SwWW8ImplReader::MoveInsideFly(const SwFrameFormat *pFlyFormat)

2174{

2175 WW8DupProperties aDup(m_rDoc, m_xCtrlStck.get());

2176

2177 m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), 0, false);

2178

2179 // set Pam in FlyFrame

2180 const SwFormatContent& rContent = pFlyFormat->GetContent();

2181 OSL_ENSURE( rContent.GetContentIdx(), "No content prepared." );

2182 m_pPaM->GetPoint()->nNode = rContent.GetContentIdx()->GetIndex() + 1;

2183 m_pPaM->GetPoint()->nContent.Assign( m_pPaM->GetContentNode(), 0 );

2184

2185 aDup.Insert(*m_pPaM->GetPoint());

2186}

2187

2188SwTwips SwWW8ImplReader::MoveOutsideFly(SwFrameFormat *pFlyFormat,

2189 const SwPosition &rPos, bool bTableJoin)

2190{

2191 SwTwips nRetWidth = 0;

2192 if (!pFlyFormat)

2193 return nRetWidth;

2194 // Close all attributes, because otherwise attributes can appear

2195 // that extend out of Flys

2196 WW8DupProperties aDup(m_rDoc, m_xCtrlStck.get());

2197 m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), 0, false);

2198

2199 /*

2200 #i1291

2201 If this fly frame consists entirely of one table inside a frame

2202 followed by an empty paragraph then we want to delete the empty

2203 paragraph so as to get the frame to autoshrink to the size of the

2204 table to emulate words behaviour closer.

2205 */

2206 if (bTableJoin)

2207 {

2208 const SwNodeIndex* pNodeIndex = pFlyFormat->GetContent().

2209 GetContentIdx();

2210 if (pNodeIndex)

2211 {

2212 SwNodeIndex aIdx( *pNodeIndex, 1 ),

2213 aEnd( *pNodeIndex->GetNode().EndOfSectionNode() );

2214

2215 if (aIdx < aEnd)

2216 {

2217 if(aIdx.GetNode().IsTableNode())

2218 {

2219 SwTableNode *pTable = aIdx.GetNode().GetTableNode();

2220 aIdx = *aIdx.GetNode().EndOfSectionNode();

2221 ++aIdx;

2222 if ( (aIdx < aEnd) && aIdx.GetNode().IsTextNode() )

2223 {

2224 SwTextNode *pNd = aIdx.GetNode().GetTextNode();

2225 ++aIdx;

2226 if (aIdx == aEnd && pNd && pNd->GetText().isEmpty())

2227 {

2228 //An extra pre-created by writer unused paragraph

2229

2230 //delete after import is complete rather than now

2231 //to avoid the complication of managing uncommitted

2232 //ctrlstack properties that refer to it.

2233 m_aExtraneousParas.insert(pNd);

2234

2235 SwTable& rTable = pTable->GetTable();

2236 SwFrameFormat* pTableFormat = rTable.GetFrameFormat();

2237

2238 if (pTableFormat)

2239 {

2240 SwFormatFrameSize aSize = pTableFormat->GetFrameSize();

2241 aSize.SetHeightSizeType(ATT_MIN_SIZE);

2242 aSize.SetHeight(MINLAY);

2243 pFlyFormat->SetFormatAttr(aSize);

2244 SwFormatHoriOrient aHori = pTableFormat->GetHoriOrient();

2245 // passing the table orientation of

2246 // LEFT_AND_WIDTH to the frame seems to

2247 // work better than FULL, especially if the

2248 // table width exceeds the page width, however

2249 // I am not brave enough to set it in all

2250 // instances

2251 pTableFormat->SetFormatAttr( SwFormatHoriOrient(0, ( aHori.GetHoriOrient() == text::HoriOrientation::LEFT_AND_WIDTH ) ? ::text::HoriOrientation::LEFT_AND_WIDTH : text::HoriOrientation::FULL ) );

2252 nRetWidth = aSize.GetWidth();

2253 }

2254 }

2255 }

2256 }

2257 }

2258 }

2259 }

2260

2261 *m_pPaM->GetPoint() = rPos;

2262 aDup.Insert(*m_pPaM->GetPoint());

2263 return nRetWidth;

2264}

2265

2266WW8FlyPara *SwWW8ImplReader::ConstructApo(const ApoTestResults &rApo,

2267 const WW8_TablePos *pTabPos)

2268{

2269 WW8FlyPara *pRet = nullptr;

2270 OSL_ENSURE(rApo.HasFrame() || pTabPos,

2271 "If no frame found, *MUST* be in a table");

2272

2273 pRet = new WW8FlyPara(m_bVer67, rApo.mpStyleApo);

2274

2275 // find APO parameter and test for bGrafApo

2276 if (rApo.HasFrame())

2277 pRet->ReadFull(rApo.m_nSprm29, this);

2278

2279 pRet->ApplyTabPos(pTabPos);

2280

2281 if (pRet->IsEmpty())

2282 {

2283 delete pRet;

2284 pRet = nullptr;

2285 }

2286 return pRet;

2287}

2288

2289bool SwWW8ImplReader::IsDropCap()

2290{

2291 // Find the DCS (Drop Cap Specifier) for the paragraph

2292 // if does not exist or if the first three bits are 0

2293 // then there is no dropcap on the paragraph

2294 WW8PLCFx_Cp_FKP *pPap = m_xPlcxMan ? m_xPlcxMan->GetPapPLCF() : nullptr;

2295 if (pPap)

2296 {

2297 SprmResult aDCS;

2298 if (m_bVer67)

2299 aDCS = pPap->HasSprm(NS_sprm::v6::sprmPDcs);

2300 else

2301 aDCS = m_xPlcxMan->GetPapPLCF()->HasSprm(NS_sprm::sprmPDcs);

2302 if (aDCS.pSprm && aDCS.nRemainingData >= 2)

2303 {

2304 /*

2305 fdct short :3 0007 drop cap type

2306 0 no drop cap

2307 1 normal drop cap

2308 2 drop cap in margin

2309 */

2310 short nDCS = SVBT16ToShort(aDCS.pSprm);

2311 if (nDCS & 7)

2312 return true;

2313 }

2314 }

2315 return false;

2316}

2317

2318bool SwWW8ImplReader::StartApo(const ApoTestResults &rApo, const WW8_TablePos *pTabPos)

2319{

2320 m_xWFlyPara.reset(ConstructApo(rApo, pTabPos));

2321 if (!m_xWFlyPara)

2322 return false;

2323

2324 // constructor has changed - new 4th parameter

2325 // containing WW8 page top margin.

2326 m_xSFlyPara.reset(new WW8SwFlyPara( *m_pPaM, *this, *m_xWFlyPara,

2327 m_aSectionManager.GetWWPageTopMargin(),

2328 m_aSectionManager.GetTextAreaWidth(),

2329 m_nIniFlyDx, m_nIniFlyDy));

2330

2331 // If this paragraph is a Dropcap set the flag and we will deal with it later

2332 if (IsDropCap())

2333 {

2334 m_bDropCap = true;

2335 m_xCurrentItemSet.reset(new SfxItemSet(m_rDoc.GetAttrPool(), svl::Items{}));

2336 return false;

2337 }

2338

2339 if (!m_xWFlyPara->bGrafApo)

2340 {

2341

2342 // Within the GrafApo text attributes have to be ignored, because

2343 // they would apply to the following lines. The frame is only inserted

2344 // if it is not merely positioning a single image. If it is an image

2345 // frame, pWFlyPara and pSFlyPara are retained and the resulting

2346 // attributes applied to the image when inserting the image.

2347

2348 WW8FlySet aFlySet(*this, m_xWFlyPara.get(), m_xSFlyPara.get(), false);

2349

2350 if (pTabPos && pTabPos->bNoFly)

2351 {

2352 m_xSFlyPara->pFlyFormat = nullptr;

2353 }

2354 else

2355 {

2356 m_xSFlyPara->pFlyFormat = m_rDoc.MakeFlySection(WW8SwFlyPara::eAnchor,

2357 m_pPaM->GetPoint(), &aFlySet);

2358 OSL_ENSURE(m_xSFlyPara->pFlyFormat->GetAnchor().GetAnchorId() ==

2359 WW8SwFlyPara::eAnchor, "Not the anchor type requested!");

2360 }

2361

2362 if (m_xSFlyPara->pFlyFormat)

2363 {

2364 if (!m_pDrawModel)

2365 GrafikCtor();

2366

2367 SdrObject* pOurNewObject = CreateContactObject(m_xSFlyPara->pFlyFormat);

2368 m_xWWZOrder->InsertTextLayerObject(pOurNewObject);

2369 }

2370

2371 if (RndStdIds::FLY_AS_CHAR != WW8SwFlyPara::eAnchor && m_xSFlyPara->pFlyFormat)

2372 {

2373 m_xAnchorStck->AddAnchor(*m_pPaM->GetPoint(), m_xSFlyPara->pFlyFormat);

2374 }

2375

2376 // remember Pos in body text

2377 m_xSFlyPara->xMainTextPos.reset(new SwPosition(*m_pPaM->GetPoint()));

2378

2379 //remove fltanchors, otherwise they will be closed inside the

2380 //frame, which makes no sense, restore them after the frame is

2381 //closed

2382 m_xSFlyPara->xOldAnchorStck = std::move(m_xAnchorStck);

2383 m_xAnchorStck.reset(new SwWW8FltAnchorStack(&m_rDoc, m_nFieldFlags));

2384

2385 if (m_xSFlyPara->pFlyFormat)

2386 MoveInsideFly(m_xSFlyPara->pFlyFormat);

2387

2388 // 1) ReadText() is not called recursively because the length of

2389 // the Apo is unknown at that time, and ReadText() needs it.

2390 // 2) the CtrlStck is not re-created.

2391 // the Char attributes continue (trouble with Sw-attributes)

2392 // Para attributes must be reset at the end of every paragraph,

2393 // i.e. at the end of a paragraph there must not be para attributes

2394 // on the stack

2395 }

2396 return true;

2397}

2398

2399void wwSectionManager::JoinNode(const SwPosition &rPos, const SwNode &rNode)

2400{

2401 if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))

2402 maSegments.back().maStart.Assign(rNode);

2403}

2404

2405bool SwWW8ImplReader::JoinNode(SwPaM &rPam, bool bStealAttr)

2406{

2407 bool bRet = false;

2408 rPam.GetPoint()->nContent = 0; // go to start of paragraph

2409

2410 SwNodeIndex aPref(rPam.GetPoint()->nNode, -1);

2411

2412 if (SwTextNode* pNode = aPref.GetNode().GetTextNode())

2413 {

2414 m_aSectionManager.JoinNode(*rPam.GetPoint(), aPref.GetNode());

2415 rPam.GetPoint()->nNode = aPref;

2416 rPam.GetPoint()->nContent.Assign(pNode, pNode->GetText().getLength());

2417 if (bStealAttr)

2418 m_xCtrlStck->StealAttr(rPam.GetPoint()->nNode);

2419

2420 if (m_pLastAnchorPos || m_pPreviousNode)

2421 {

2422 SwNodeIndex aToBeJoined(aPref, 1);

2423

2424 if (m_pLastAnchorPos)

2425 {

2426 //If the last anchor pos is here, then clear the anchor pos.

2427 //This "last anchor pos" is only used for fixing up the

2428 //positions of things anchored to page breaks and here

2429 //we are removing the last paragraph of a frame, so there

2430 //cannot be a page break at this point so we can

2431 //safely reset m_pLastAnchorPos to avoid any dangling

2432 //SwIndex's pointing into the deleted paragraph

2433 SwNodeIndex aLastAnchorPos(m_pLastAnchorPos->nNode);

2434 if (aLastAnchorPos == aToBeJoined)

2435 m_pLastAnchorPos.reset();

2436 }

2437

2438 if (m_pPreviousNode)

2439 {

2440 //If the drop character start pos is here, then clear it.

2441 SwNodeIndex aDropCharPos(*m_pPreviousNode);

2442 if (aDropCharPos == aToBeJoined)

2443 m_pPreviousNode = nullptr;

2444 }

2445 }

2446

2447 pNode->JoinNext();

2448

2449 bRet = true;

2450 }

2451 return bRet;

2452}

2453

2454//In auto-width word frames negative after-indent values are ignored

2455void SwWW8ImplReader::StripNegativeAfterIndent(SwFrameFormat const *pFlyFormat)

2456{

2457 const SwNodeIndex* pSttNd = pFlyFormat->GetContent().GetContentIdx();

2458 if (!pSttNd)

2459 return;

2460

2461 SwNodeIndex aIdx(*pSttNd, 1);

2462 SwNodeIndex aEnd(*pSttNd->GetNode().EndOfSectionNode());

2463 while (aIdx < aEnd)

2464 {

2465 SwTextNode *pNd = aIdx.GetNode().GetTextNode();

2466 if (pNd)

2467 {

2468 const SvxLRSpaceItem& rLR = ItemGet(*pNd, RES_LR_SPACE);

2469 if (rLR.GetRight() < 0)

2470 {

2471 SvxLRSpaceItem aLR(rLR);

2472 aLR.SetRight(0);

2473 pNd->SetAttr(aLR);

2474 }

2475 }

2476 ++aIdx;

2477 }

2478}

2479

2480void SwWW8ImplReader::StopApo()

2481{

2482 OSL_ENSURE(m_xWFlyPara, "no pWFlyPara to close");

2483 if (!m_xWFlyPara)

2484 return;

2485 if (m_xWFlyPara->bGrafApo)

2486 {

2487 // image frame that has not been inserted: delete empty paragraph + attr

2488 JoinNode(*m_pPaM, true);

2489

2490 }

2491 else

2492 {

2493 if (!m_xSFlyPara->xMainTextPos)

2494 {

2495 OSL_ENSURE(m_xSFlyPara->xMainTextPos.get(), "StopApo: xMainTextPos is nullptr");

2496 return;

2497 }

2498

2499 /*

2500 What we are doing with this temporary nodeindex is as follows: The

2501 stack of attributes normally only places them into the document when

2502 the current insertion point has passed them by. Otherwise the end

2503 point of the attribute gets pushed along with the insertion point. The

2504 insertion point is moved and the properties committed during

2505 MoveOutsideFly. We also may want to remove the final paragraph in the

2506 frame, but we need to wait until the properties for that frame text

2507 have been committed otherwise they will be lost. So we first get a

2508 handle to the last the filter inserted. After the attributes are

2509 committed, if that paragraph exists we join it with the para after it

2510 that comes with the frame by default so that as normal we don't end up

2511 with one more paragraph than we wanted.

2512 */

2513 SwNodeIndex aPref(m_pPaM->GetPoint()->nNode, -1);

2514

2515 SwTwips nNewWidth =

2516 MoveOutsideFly(m_xSFlyPara->pFlyFormat, *m_xSFlyPara->xMainTextPos);

2517 if (nNewWidth)

2518 m_xSFlyPara->BoxUpWidth(nNewWidth);

2519

2520 Color aBg(0xFE, 0xFF, 0xFF, 0xFF); //Transparent by default

2521

2522 SwTextNode* pNd = aPref.GetNode().GetTextNode();

2523 if (pNd && m_xSFlyPara->pFlyFormat)

2524 {

2525 /*

2526 #i582#

2527 Take the last paragraph background colour and fill the frame with

2528 it. Otherwise, make it transparent, this appears to be how MSWord

2529 works

2530 */

2531 const SfxPoolItem &rItm = pNd->SwContentNode::GetAttr(RES_BACKGROUND);

2532 const SvxBrushItem &rBrush = static_cast(rItm);

2533 if (rBrush.GetColor() != COL_AUTO)

2534 aBg = rBrush.GetColor();

2535

2536 if (m_pLastAnchorPos.get())

2537 {

2538 //If the last anchor pos is here, then clear the anchor pos.

2539 //This "last anchor pos" is only used for fixing up the

2540 //positions of things anchored to page breaks and here

2541 //we are removing the last paragraph of a frame, so there

2542 //cannot be a page break at this point so we can

2543 //safely reset m_pLastAnchorPos to avoid any dangling

2544 //SwIndex's pointing into the deleted paragraph

2545 SwNodeIndex aLastAnchorPos(m_pLastAnchorPos->nNode);

2546 SwNodeIndex aToBeJoined(aPref, 1);

2547 if (aLastAnchorPos == aToBeJoined)

2548 m_pLastAnchorPos.reset();

2549 }

2550

2551 //Get rid of extra empty paragraph

2552 pNd->JoinNext();

2553 }

2554

2555 if (m_xSFlyPara->pFlyFormat)

2556 m_xSFlyPara->pFlyFormat->SetFormatAttr(SvxBrushItem(aBg, RES_BACKGROUND));

2557

2558 DeleteAnchorStack();

2559 m_xAnchorStck = std::move(m_xSFlyPara->xOldAnchorStck);

2560

2561 // When inserting a graphic into the fly frame using the auto

2562 // function, the extension of the SW-fly has to be set

2563 // manually as the SW fly has no auto function to adjust the

2564 // frames size.

2565 if (m_xSFlyPara->nNewNetWidth > MINFLY && m_xSFlyPara->pFlyFormat) // BoxUpWidth ?

2566 {

2567 long nW = m_xSFlyPara->nNewNetWidth;

2568 nW += m_xSFlyPara->nWidth - m_xSFlyPara->nNetWidth; // border for it

2569 m_xSFlyPara->pFlyFormat->SetFormatAttr(

2570 SwFormatFrameSize(m_xSFlyPara->eHeightFix, nW, m_xSFlyPara->nHeight));

2571 }

2572 /*

2573 Word set *no* width meaning it's an automatic width. The

2574 SwFlyPara reader will have already set a fallback width of the

2575 printable regions width, so we should reuse it. Despite the related

2576 problems with layout addressed with a hack in WW8FlyPara's constructor

2577 #i27204# Added AutoWidth setting. Left the old CalculateFlySize in place

2578 so that if the user unselects autowidth, the width doesn't max out

2579 */

2580 else if (!m_xWFlyPara->nSp28 && m_xSFlyPara->pFlyFormat)

2581 {

2582 using namespace sw::util;

2583 SfxItemSet aFlySet( m_xSFlyPara->pFlyFormat->GetAttrSet() );

2584

2585 SwFormatFrameSize aSize(ItemGet(aFlySet, RES_FRM_SIZE));

2586

2587 aFlySet.ClearItem(RES_FRM_SIZE);

2588

2589 CalculateFlySize(aFlySet, m_xSFlyPara->xMainTextPos->nNode,

2590 m_xSFlyPara->nWidth);

2591

2592 nNewWidth = ItemGet(aFlySet, RES_FRM_SIZE).GetWidth();

2593

2594 aSize.SetWidth(nNewWidth);

2595 aSize.SetWidthSizeType(ATT_VAR_SIZE);

2596

2597 m_xSFlyPara->pFlyFormat->SetFormatAttr(aSize);

2598 }

2599

2600 m_xSFlyPara->xMainTextPos.reset();

2601// To create the SwFrames when inserting into an existing document, fltshell.cxx

2602// will call pFlyFrame->MakeFrames() when setting the FltAnchor attribute

2603

2604 }

2605

2606 //#i8062#

2607 if (m_xSFlyPara && m_xSFlyPara->pFlyFormat)

2608 m_pFormatOfJustInsertedApo = m_xSFlyPara->pFlyFormat;

2609

2610 m_xSFlyPara.reset();

2611 m_xWFlyPara.reset();

2612}

2613

2614// TestSameApo() returns if it's the same Apo or a different one

2615bool SwWW8ImplReader::TestSameApo(const ApoTestResults &rApo,

2616 const WW8_TablePos *pTabPos)

2617{

2618 if (!m_xWFlyPara)

2619 {

2620 OSL_ENSURE(m_xWFlyPara, " Where is my pWFlyPara ? ");

2621 return true;

2622 }

2623

2624 // We need to a full comparison (excepting borders) to identify all

2625 // combinations style/hard correctly. For this reason we create a

2626 // temporary WW8FlyPara (depending on if style or not), apply the

2627 // hard attributes and then compare.

2628

2629 // For comparison

2630 WW8FlyPara aF(m_bVer67, rApo.mpStyleApo);

2631 // WWPara for current para

2632 if (rApo.HasFrame())

2633 aF.Read(rApo.m_nSprm29, m_xPlcxMan->GetPapPLCF());

2634 aF.ApplyTabPos(pTabPos);

2635

2636 return aF == *m_xWFlyPara;

2637}

2638

2639void SwWW8ImplReader::NewAttr( const SfxPoolItem& rAttr,

2640 const bool bFirstLineOfStSet,

2641 const bool bLeftIndentSet )

2642{

2643 if( !m_bNoAttrImport ) // for ignoring styles during doc inserts

2644 {

2645 if (m_pCurrentColl)

2646 {

2647 OSL_ENSURE(rAttr.Which() != RES_FLTR_REDLINE, "redline in style!");

2648 m_pCurrentColl->SetFormatAttr(rAttr);

2649 }

2650 else if (m_xCurrentItemSet)

2651 {

2652 m_xCurrentItemSet->Put(rAttr);

2653 }

2654 else if (rAttr.Which() == RES_FLTR_REDLINE)

2655 {

2656 m_xRedlineStack->open(*m_pPaM->GetPoint(), rAttr);

2657 }

2658 else

2659 {

2660 m_xCtrlStck->NewAttr(*m_pPaM->GetPoint(), rAttr);

2661 // #i103711#

2662 if ( bFirstLineOfStSet )

2663 {

2664 const SwNode* pNd = &(m_pPaM->GetPoint()->nNode.GetNode());

2665 m_aTextNodesHavingFirstLineOfstSet.insert( pNd );

2666 }

2667 // #i105414#

2668 if ( bLeftIndentSet )

2669 {

2670 const SwNode* pNd = &(m_pPaM->GetPoint()->nNode.GetNode());

2671 m