LibreOffice Module sw (master)  1
writerhelper.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 <sal/config.h>
21 #include <sal/log.hxx>
22 
23 #include <com/sun/star/util/CloseVetoException.hpp>
24 
25 #include <doc.hxx>
26 #include "writerhelper.hxx"
27 #include <msfilter.hxx>
28 #include <com/sun/star/container/XChild.hpp>
29 
30 #include <algorithm>
31 #include <svl/itemiter.hxx>
32 #include <svx/svdobj.hxx>
33 #include <svx/svdoole2.hxx>
34 #include <tools/UnitConversion.hxx>
36 #include <ndtxt.hxx>
37 #include <ndnotxt.hxx>
38 #include <fmtcntnt.hxx>
39 #include <swtable.hxx>
40 #include <frmfmt.hxx>
41 #include <flypos.hxx>
42 #include <fmtanchr.hxx>
43 #include <fmtfsize.hxx>
44 #include <SwStyleNameMapper.hxx>
45 #include <docary.hxx>
46 #include <charfmt.hxx>
47 #include <fchrfmt.hxx>
48 #include <redline.hxx>
49 #include "types.hxx"
50 #include <svtools/embedhlp.hxx>
51 #include <numrule.hxx>
52 #include <vcl/svapp.hxx>
56 #include <IDocumentMarkAccess.hxx>
57 #include <IMark.hxx>
58 #include <grfatr.hxx>
59 
60 using namespace com::sun::star;
61 
62 namespace
63 {
64  // #i98791# - adjust sorting
65  // Utility to sort SwTextFormatColl's by their assigned outline style list level
66  class outlinecmp
67  {
68  public:
69  bool operator()(const SwTextFormatColl *pA, const SwTextFormatColl *pB) const
70  {
71  // #i98791#
72  bool bResult( false );
73  const bool bIsAAssignedToOutlineStyle( pA->IsAssignedToListLevelOfOutlineStyle() );
74  const bool bIsBAssignedToOutlineStyle( pB->IsAssignedToListLevelOfOutlineStyle() );
75  if ( bIsAAssignedToOutlineStyle != bIsBAssignedToOutlineStyle )
76  {
77  bResult = bIsBAssignedToOutlineStyle;
78  }
79  else if ( !bIsAAssignedToOutlineStyle )
80  {
81  // pA and pB are equal regarding the sorting criteria.
82  // Thus return value does not matter.
83  bResult = false;
84  }
85  else
86  {
88  }
89 
90  return bResult;
91  }
92  };
93 
94  bool IsValidSlotWhich(sal_uInt16 nSlotId, sal_uInt16 nWhichId)
95  {
96  return (nSlotId != 0 && nWhichId != 0 && nSlotId != nWhichId);
97  }
98 
99  /*
100  Utility to convert a SwPosFlyFrames into a simple vector of ww8::Frames
101 
102  The crucial thing is that a ww8::Frame always has an anchor which
103  points to some content in the document. This is a requirement of exporting
104  to Word
105  */
106  ww8::Frames SwPosFlyFramesToFrames(const SwPosFlyFrames &rFlys)
107  {
108  ww8::Frames aRet;
109 
110  for(const auto& rpFly : rFlys)
111  {
112  const SwFrameFormat &rEntry = rpFly->GetFormat();
113 
114  if (const SwPosition* pAnchor = rEntry.GetAnchor().GetContentAnchor())
115  {
116  // the anchor position will be invalidated by SetRedlineFlags
117  // so set a dummy position and fix it in UpdateFramePositions
118  SwPosition const dummy(SwNodeIndex(
119  const_cast<SwNodes&>(pAnchor->nNode.GetNodes())));
120  aRet.emplace_back(rEntry, dummy);
121  }
122  else
123  {
124  SwPosition aPos(rpFly->GetNdIndex());
125 
126  if (SwTextNode* pTextNd = aPos.nNode.GetNode().GetTextNode())
127  {
128  aPos.nContent.Assign(pTextNd, 0);
129  }
130 
131  aRet.emplace_back(rEntry, aPos);
132  }
133  }
134  return aRet;
135  }
136 
137  //Utility to test if a frame is anchored at a given node index
138  class anchoredto
139  {
140  private:
141  sal_uLong mnNode;
142  public:
143  explicit anchoredto(sal_uLong nNode) : mnNode(nNode) {}
144  bool operator()(const ww8::Frame &rFrame) const
145  {
146  return (mnNode == rFrame.GetPosition().nNode.GetNode().GetIndex());
147  }
148  };
149 }
150 
151 namespace ww8
152 {
153  //For i120928,size conversion before exporting graphic of bullet
154  Frame::Frame(const Graphic &rGrf, const SwPosition &rPos)
155  : mpFlyFrame(nullptr)
156  , maPos(rPos)
157  , maSize()
158  , maLayoutSize()
159  , meWriterType(eBulletGrf)
160  , mpStartFrameContent(nullptr)
161  , mbIsInline(true)
162  , mbForBullet(true)
163  , maGrf(rGrf)
164  {
165  const MapMode aMap100mm( MapUnit::Map100thMM );
166  Size aSize( rGrf.GetPrefSize() );
167  if ( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
168  {
169  aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
170  }
171  else
172  {
173  aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
174  }
175  maSize = aSize;
177  }
178 
179  Frame::Frame(const SwFrameFormat &rFormat, const SwPosition &rPos)
180  : mpFlyFrame(&rFormat)
181  , maPos(rPos)
182  , maSize()
183  , maLayoutSize() // #i43447#
184  , meWriterType(eTextBox)
185  , mpStartFrameContent(nullptr)
186  // #i43447# - move to initialization list
187  , mbIsInline( (rFormat.GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) )
188  // #i120928# - handle graphic of bullet within existing implementation
189  , mbForBullet(false)
190  , maGrf()
191  {
192  switch (rFormat.Which())
193  {
194  case RES_FLYFRMFMT:
195  if (const SwNodeIndex* pIdx = rFormat.GetContent().GetContentIdx())
196  {
197  SwNodeIndex aIdx(*pIdx, 1);
198  const SwNode &rNd = aIdx.GetNode();
199  // #i43447# - determine layout size
200  {
201  SwRect aLayRect( rFormat.FindLayoutRect() );
202  tools::Rectangle aRect( aLayRect.SVRect() );
203  // The Object is not rendered (e.g. something in unused
204  // header/footer) - thus, get the values from the format.
205  if ( aLayRect.IsEmpty() )
206  {
207  aRect.SetSize( rFormat.GetFrameSize().GetSize() );
208  }
209  maLayoutSize = aRect.GetSize();
210  }
211  switch (rNd.GetNodeType())
212  {
213  case SwNodeType::Grf:
215  maSize = rNd.GetNoTextNode()->GetTwipSize();
216  break;
217  case SwNodeType::Ole:
218  meWriterType = eOle;
219  maSize = rNd.GetNoTextNode()->GetTwipSize();
220  break;
221  default:
223  // #i43447# - Size equals layout size for text boxes
225  break;
226  }
227  mpStartFrameContent = &rNd;
228  }
229  else
230  {
231  OSL_ENSURE(false, "Impossible");
233  }
234  break;
235  default:
236  if (const SdrObject* pObj = rFormat.FindRealSdrObject())
237  {
238  if (pObj->GetObjInventor() == SdrInventor::FmForm)
240  else
242  maSize = pObj->GetSnapRect().GetSize();
244  }
245  else
246  {
247  OSL_ENSURE(false, "Impossible");
249  }
250  break;
251  }
252  }
253 
254 
256  {
257  mbIsInline = true;
258  }
259 }
260 
261 namespace sw
262 {
263  namespace hack
264  {
265 
266  sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool,
267  const SfxItemPool &rSrcPool, sal_uInt16 nWhich)
268  {
269  sal_uInt16 nSlotId = rSrcPool.GetSlotId(nWhich);
270  if (IsValidSlotWhich(nSlotId, nWhich))
271  nWhich = rDestPool.GetWhich(nSlotId);
272  else
273  nWhich = 0;
274  return nWhich;
275  }
276 
277  sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet,
278  const SwDoc &rDoc, sal_uInt16 nWhich)
279  {
280  if (RES_WHICHHINT_END < *(rSet.GetRanges()))
281  {
282  nWhich = TransformWhichBetweenPools(*rSet.GetPool(),
283  rDoc.GetAttrPool(), nWhich);
284  }
285  return nWhich;
286  }
287 
289  SfxObjectShell &rPers)
290  : mxIPRef(rObj.GetObjRef()), mrPers(rPers),
291  mpGraphic( rObj.GetGraphic() )
292  {
293  rObj.AbandonObject();
294  }
295 
296  bool DrawingOLEAdaptor::TransferToDoc( OUString &rName )
297  {
298  OSL_ENSURE(mxIPRef.is(), "Transferring invalid object to doc");
299  if (!mxIPRef.is())
300  return false;
301 
302  uno::Reference < container::XChild > xChild( mxIPRef, uno::UNO_QUERY );
303  if ( xChild.is() )
304  xChild->setParent( mrPers.GetModel() );
305 
307  if (bSuccess)
308  {
309  if ( mpGraphic )
312  rName,
313  OUString() );
314 
315  mxIPRef = nullptr;
316  }
317 
318  return bSuccess;
319  }
320 
322  {
323  if (!mxIPRef.is())
324  return;
325 
326  OSL_ENSURE( !mrPers.GetEmbeddedObjectContainer().HasEmbeddedObject( mxIPRef ), "Object in adaptor is inserted?!" );
327  try
328  {
329  mxIPRef->close(true);
330  }
331  catch ( const css::util::CloseVetoException& )
332  {
333  }
334 
335  mxIPRef = nullptr;
336  }
337  }
338 
339  namespace util
340  {
342  {
343  if (nIn > SHRT_MAX)
344  nIn = SHRT_MAX;
345  else if (nIn < SHRT_MIN)
346  nIn = SHRT_MIN;
347  return nIn;
348  }
349 
351  {
352  SetObjectLayer(rObject, eHell);
353  }
354 
356  {
357  SetObjectLayer(rObject, eHeaven);
358  }
359 
360  void SetLayer::SetObjectLayer(SdrObject &rObject, Layer eLayer) const
361  {
362  if (SdrInventor::FmForm == rObject.GetObjInventor())
363  rObject.SetLayer(mnFormLayer);
364  else
365  {
366  switch (eLayer)
367  {
368  case eHeaven:
369  rObject.SetLayer(mnHeavenLayer);
370  break;
371  case eHell:
372  rObject.SetLayer(mnHellLayer);
373  break;
374  }
375  }
376  }
377 
378  //SetLayer boilerplate begin
379 
380  // #i38889# - by default put objects into the invisible layers.
382  : mnHeavenLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId()),
383  mnHellLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId()),
384  mnFormLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleControlsId())
385  {
386  }
387  //SetLayer boilerplate end
388 
389  void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet )
390  {
391  if( bExportParentItemSet )
392  {
393  sal_uInt16 nTotal = rSet.TotalCount();
394  for( sal_uInt16 nItem =0; nItem < nTotal; ++nItem )
395  {
396  const SfxPoolItem* pItem = nullptr;
397  if( SfxItemState::SET == rSet.GetItemState( rSet.GetWhichByPos( nItem ), true, &pItem ) )
398  {
399  rItems[pItem->Which()] = pItem;
400  }
401  }
402  }
403  else if( rSet.Count())
404  {
405  SfxItemIter aIter(rSet);
406  if (const SfxPoolItem *pItem = aIter.GetCurItem())
407  {
408  do
409  rItems[pItem->Which()] = pItem;
410  while ((pItem = aIter.NextItem()));
411  }
412  }
413  }
414 
416  sal_uInt16 eType)
417  {
418  auto aIter = rItems.find(eType);
419  if (aIter != rItems.end())
420  return aIter->second;
421  return nullptr;
422  }
423 
425  {
426  if (const SwCharFormat* pCharFormat = rFormat.GetCharFormat())
427  {
428  if (pCharFormat->GetAttrSet().Count())
429  {
430  SfxItemIter aIter(pCharFormat->GetAttrSet());
431  const SfxPoolItem *pItem = aIter.GetCurItem();
432  do
433  rSet.ClearItem(pItem->Which());
434  while ((pItem = aIter.NextItem()));
435  }
436  }
437  }
438 
440  {
441  ww8::ParaStyles aStyles;
442  typedef ww8::ParaStyles::size_type mysizet;
443 
444  const SwTextFormatColls *pColls = rDoc.GetTextFormatColls();
445  mysizet nCount = pColls ? pColls->size() : 0;
446  aStyles.reserve(nCount);
447  for (mysizet nI = 0; nI < nCount; ++nI)
448  aStyles.push_back((*pColls)[ static_cast< sal_uInt16 >(nI) ]);
449  return aStyles;
450  }
451 
452  SwTextFormatColl* GetParaStyle(SwDoc &rDoc, const OUString& rName)
453  {
454  // Search first in the Doc-Styles
455  SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName(rName);
456  if (!pColl)
457  {
458  // Collection not found, try in Pool ?
459  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
461  if (n != SAL_MAX_UINT16) // found or standard
462  pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(n, false);
463  }
464  return pColl;
465  }
466 
467  SwCharFormat* GetCharStyle(SwDoc &rDoc, const OUString& rName)
468  {
469  SwCharFormat *pFormat = rDoc.FindCharFormatByName(rName);
470  if (!pFormat)
471  {
472  // Collection not found, try in Pool ?
473  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
475  if (n != SAL_MAX_UINT16) // found or standard
477  }
478  return pFormat;
479  }
480 
481  // #i98791# - adjust sorting algorithm
483  {
484  std::sort(rStyles.begin(), rStyles.end(), outlinecmp());
485  }
486 
487  /*
488  Utility to extract FlyFormats from a document, potentially from a
489  selection.
490  */
491  ww8::Frames GetFrames(const SwDoc &rDoc, SwPaM const *pPaM /*, bool bAll*/)
492  {
493  SwPosFlyFrames aFlys(rDoc.GetAllFlyFormats(pPaM, true));
494  ww8::Frames aRet(SwPosFlyFramesToFrames(aFlys));
495  return aRet;
496  }
497 
499  {
500  for (ww8::Frame & rFrame : rFrames)
501  {
502  SwFormatAnchor const& rAnchor = rFrame.GetFrameFormat().GetAnchor();
503  if (SwPosition const*const pAnchor = rAnchor.GetContentAnchor())
504  {
505  rFrame.SetPosition(*pAnchor);
506  }
507  else
508  { // these don't need to be corrected, they're not in redlines
509  assert(RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId());
510  }
511  }
512  }
513 
514  ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
515  {
516  ww8::Frames aRet;
517  std::copy_if(rFrames.begin(), rFrames.end(),
518  std::back_inserter(aRet), anchoredto(rNode.GetIndex()));
519  return aRet;
520  }
521 
523  int nLevel)
524  {
525  if (nLevel < 0 || nLevel >= MAXLEVEL)
526  {
527  OSL_FAIL("Invalid level");
528  return nullptr;
529  }
530  return &(rRule.Get( static_cast< sal_uInt16 >(nLevel) ));
531  }
532 
534  {
535  const SwNumRule *pRule = nullptr;
536  if (
537  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
538  nullptr != (pRule = rTextNode.GetNumRule())
539  )
540  {
541  return GetNumFormatFromSwNumRuleLevel(*pRule,
542  rTextNode.GetActualListLevel());
543  }
544 
545  OSL_ENSURE(rTextNode.GetDoc(), "No document for node?, suspicious");
546  if (!rTextNode.GetDoc())
547  return nullptr;
548 
549  if (
550  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
551  nullptr != (pRule = rTextNode.GetDoc()->GetOutlineNumRule())
552  )
553  {
554  return GetNumFormatFromSwNumRuleLevel(*pRule,
555  rTextNode.GetActualListLevel());
556  }
557 
558  return nullptr;
559  }
560 
561  const SwNumRule* GetNumRuleFromTextNode(const SwTextNode &rTextNode)
562  {
563  return GetNormalNumRuleFromTextNode(rTextNode);
564  }
565 
567  {
568  const SwNumRule *pRule = nullptr;
569 
570  if (
571  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
572  nullptr != (pRule = rTextNode.GetNumRule())
573  )
574  {
575  return pRule;
576  }
577  return nullptr;
578  }
579 
581  {
582  const SwNodeIndex *pIndex = rFormat.GetContent().GetContentIdx();
583  OSL_ENSURE(pIndex, "No NodeIndex in SwFrameFormat ?, suspicious");
584  if (!pIndex)
585  return nullptr;
586  SwNodeIndex aIdx(*pIndex, 1);
587  return aIdx.GetNode().GetNoTextNode();
588  }
589 
590  bool HasPageBreak(const SwNode &rNd)
591  {
592  const SvxFormatBreakItem *pBreak = nullptr;
593  if (rNd.IsTableNode() && rNd.GetTableNode())
594  {
595  const SwTable& rTable = rNd.GetTableNode()->GetTable();
596  const SwFrameFormat* pApply = rTable.GetFrameFormat();
597  OSL_ENSURE(pApply, "impossible");
598  if (pApply)
599  pBreak = &(ItemGet<SvxFormatBreakItem>(*pApply, RES_BREAK));
600  }
601  else if (const SwContentNode *pNd = rNd.GetContentNode())
602  pBreak = &(ItemGet<SvxFormatBreakItem>(*pNd, RES_BREAK));
603 
604  return pBreak && pBreak->GetBreak() == SvxBreak::PageBefore;
605  }
606 
608  {
609  if(1 == rPolyPoly.Count())
610  {
611  return rPolyPoly[0];
612  }
613  else
614  {
615  // This method will now just concatenate the polygons contained
616  // in the given PolyPolygon. Anything else which might be thought of
617  // for reducing to a single polygon will just need more power and
618  // cannot create more correct results.
619  sal_uInt32 nPointCount(0);
620  sal_uInt16 a;
621 
622  for(a = 0; a < rPolyPoly.Count(); a++)
623  {
624  nPointCount += static_cast<sal_uInt32>(rPolyPoly[a].GetSize());
625  }
626 
627  if(nPointCount > 0x0000ffff)
628  {
629  OSL_FAIL("PolygonFromPolyPolygon: too many points for a single polygon (!)");
630  nPointCount = 0x0000ffff;
631  }
632 
633  tools::Polygon aRetval(static_cast<sal_uInt16>(nPointCount));
634  sal_uInt32 nAppendIndex(0);
635 
636  for(a = 0; a < rPolyPoly.Count(); a++)
637  {
638  const tools::Polygon& rCandidate = rPolyPoly[a];
639 
640  for(sal_uInt16 b(0); nAppendIndex <= nPointCount && b < rCandidate.GetSize(); b++)
641  {
642  aRetval[static_cast<sal_uInt16>(nAppendIndex++)] = rCandidate[b];
643  }
644  }
645 
646  return aRetval;
647  }
648  }
649 
650  tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon& rPolyPoly, const SwNoTextNode* pNd, bool bCorrectCrop)
651  {
652  tools::Polygon aPoly(PolygonFromPolyPolygon(rPolyPoly));
653  const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
654 
655  const SwAttrSet* pAttrSet = pNd->GetpSwAttrSet();
656  if (bCorrectCrop && pAttrSet)
657  {
658  if (pAttrSet->HasItem(RES_GRFATR_CROPGRF))
659  {
660  // Word's wrap polygon deals with a canvas which has the size of the already
661  // cropped graphic, do the opposite of correctCrop() in writerfilter/.
662  const SwCropGrf& rCrop = pAttrSet->GetCropGrf();
663  sal_Int32 nCropLeft = convertTwipToMm100(rCrop.GetLeft());
664  sal_Int32 nCropRight = convertTwipToMm100(rCrop.GetRight());
665  sal_Int32 nCropTop = convertTwipToMm100(rCrop.GetTop());
666  sal_Int32 nCropBottom = convertTwipToMm100(rCrop.GetBottom());
667  aPoly.Move(-nCropLeft, -nCropTop);
668 
669  Fraction aScaleX(rOrigSize.getWidth(), rOrigSize.getWidth() - nCropLeft - nCropRight);
670  Fraction aScaleY(rOrigSize.getHeight(), rOrigSize.getHeight() - nCropTop - nCropBottom);
671  aPoly.Scale(double(aScaleX), double(aScaleY));
672  }
673  }
674 
675  Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
676  Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
677  aPoly.Scale(double(aMapPolyX), double(aMapPolyY));
678 
679  /*
680  a) stretch right bound by 15twips
681  b) shrink bottom bound to where it would have been in word
682  c) Move it to the left by 15twips
683 
684  See the import for details
685  */
686  const Size &rSize = pNd->GetTwipSize();
687  Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
688  aMoveHack *= Fraction(15, 1);
689  long nMove(aMoveHack);
690 
691  Fraction aHackX(ww::nWrap100Percent + nMove,
693  Fraction aHackY(ww::nWrap100Percent - nMove,
695  aPoly.Scale(double(aHackX), double(aHackY));
696 
697  aPoly.Move(-nMove, 0);
698  return aPoly;
699  }
700 
701  void RedlineStack::open(const SwPosition& rPos, const SfxPoolItem& rAttr)
702  {
703  OSL_ENSURE(rAttr.Which() == RES_FLTR_REDLINE, "not a redline");
704  maStack.emplace_back(new SwFltStackEntry(rPos, std::unique_ptr<SfxPoolItem>(rAttr.Clone())));
705  }
706 
707  namespace {
708 
709  class SameOpenRedlineType
710  {
711  private:
713  public:
714  explicit SameOpenRedlineType(RedlineType eType) : meType(eType) {}
715  bool operator()(const std::unique_ptr<SwFltStackEntry> & pEntry) const
716  {
717  const SwFltRedline *pTest = static_cast<const SwFltRedline *>
718  (pEntry->pAttr.get());
719  return (pEntry->bOpen && (pTest->eType == meType));
720  }
721  };
722 
723  }
724 
725  bool RedlineStack::close(const SwPosition& rPos, RedlineType eType)
726  {
727  //Search from end for same type
728  auto aResult = std::find_if(maStack.rbegin(), maStack.rend(),
729  SameOpenRedlineType(eType));
730  if (aResult != maStack.rend())
731  {
732  SwTextNode *const pNode(rPos.nNode.GetNode().GetTextNode());
733  sal_Int32 const nIndex(rPos.nContent.GetIndex());
734  // HACK to prevent overlap of field-mark and redline,
735  // which would destroy field-mark invariants when the redline
736  // is hidden: move the redline end one to the left
737  if (pNode && nIndex > 0
738  && pNode->GetText()[nIndex - 1] == CH_TXT_ATR_FIELDEND)
739  {
740  SwPosition const end(*rPos.nNode.GetNode().GetTextNode(),
741  nIndex - 1);
742  sw::mark::IFieldmark *const pFieldMark(
744  SAL_WARN_IF(!pFieldMark, "sw.ww8", "expected a field mark");
745  if (pFieldMark && pFieldMark->GetMarkPos().nNode.GetIndex() == (*aResult)->m_aMkPos.m_nNode.GetIndex()+1
746  && pFieldMark->GetMarkPos().nContent.GetIndex() < (*aResult)->m_aMkPos.m_nContent)
747  {
748  (*aResult)->SetEndPos(end);
749  return true;
750  }
751  }
752  (*aResult)->SetEndPos(rPos);
753  return true;
754  }
755  return false;
756  }
757 
759  {
760  std::for_each(maStack.begin(), maStack.end(), SetEndIfOpen(rPos));
761  }
762 
764  {
765  size_t nCnt = maStack.size();
766  sal_Int32 const nInserted = 2; // CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDSEP
767  sal_uLong nPosNd = rPos.nNode.GetIndex();
768  sal_Int32 nPosCt = rPos.nContent.GetIndex() - nInserted;
769 
770  for (size_t i=0; i < nCnt; ++i)
771  {
772  SwFltStackEntry& rEntry = *maStack[i];
773  bool const isPoint(rEntry.m_aMkPos == rEntry.m_aPtPos);
774  if ((rEntry.m_aMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
775  (nPosCt <= rEntry.m_aMkPos.m_nContent))
776  {
777  rEntry.m_aMkPos.m_nContent += nInserted;
778  SAL_WARN_IF(rEntry.m_aMkPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
779  "sw.ww8", "redline ends after end of line");
780  if (isPoint) // sigh ... important special case...
781  {
782  rEntry.m_aPtPos.m_nContent += nInserted;
783  continue;
784  }
785  }
786  // for the end position, leave it alone if it's *on* the dummy
787  // char position, that should remain *before*
788  if ((rEntry.m_aPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
789  (nPosCt < rEntry.m_aPtPos.m_nContent))
790  {
791  rEntry.m_aPtPos.m_nContent += nInserted;
792  SAL_WARN_IF(rEntry.m_aPtPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
793  "sw.ww8", "redline ends after end of line");
794  }
795  }
796  }
797 
798  void SetInDocAndDelete::operator()(std::unique_ptr<SwFltStackEntry>& pEntry)
799  {
800  SwPaM aRegion(pEntry->m_aMkPos.m_nNode);
801  if (pEntry->MakeRegion(&mrDoc, aRegion,
803  (*aRegion.GetPoint() != *aRegion.GetMark())
804  )
805  {
808  const SwFltRedline *pFltRedline = static_cast<const SwFltRedline*>
809  (pEntry->pAttr.get());
810 
811  SwRedlineData aData(pFltRedline->eType, pFltRedline->nAutorNo,
812  pFltRedline->aStamp, OUString(), nullptr);
813 
814  SwRangeRedline *const pNewRedline(new SwRangeRedline(aData, aRegion));
815  // the point node may be deleted in AppendRedline, so park
816  // the PaM somewhere safe
817  aRegion.DeleteMark();
818  *aRegion.GetPoint() = SwPosition(SwNodeIndex(mrDoc.GetNodes()));
819  mrDoc.getIDocumentRedlineAccess().AppendRedline(pNewRedline, true);
822  }
823  pEntry.reset();
824  }
825 
826  bool CompareRedlines::operator()(const std::unique_ptr<SwFltStackEntry> & pOneE,
827  const std::unique_ptr<SwFltStackEntry> & pTwoE) const
828  {
829  const SwFltRedline *pOne= static_cast<const SwFltRedline*>
830  (pOneE->pAttr.get());
831  const SwFltRedline *pTwo= static_cast<const SwFltRedline*>
832  (pTwoE->pAttr.get());
833 
834  //Return the earlier time, if two have the same time, prioritize
835  //inserts over deletes
836  if (pOne->aStamp == pTwo->aStamp)
837  return (pOne->eType == RedlineType::Insert && pTwo->eType != RedlineType::Insert);
838  else
839  return (pOne->aStamp < pTwo->aStamp);
840  }
841 
843  {
844  std::sort(maStack.begin(), maStack.end(), CompareRedlines());
845  std::for_each(maStack.begin(), maStack.end(), SetInDocAndDelete(mrDoc));
846  }
847 
848  sal_uInt16 WrtRedlineAuthor::AddName( const OUString& rNm )
849  {
850  sal_uInt16 nRet;
851  auto aIter = std::find(maAuthors.begin(), maAuthors.end(), rNm);
852  if (aIter != maAuthors.end())
853  nRet = static_cast< sal_uInt16 >(aIter - maAuthors.begin());
854  else
855  {
856  nRet = static_cast< sal_uInt16 >(maAuthors.size());
857  maAuthors.push_back(rNm);
858  }
859  return nRet;
860  }
861  }
862 
863  namespace util
864  {
866  : m_pTableNode(&rNode)
867  {
868  StartListening(rNode.GetNotifier());
869  }
870 
872  { return m_pTableNode; }
873 
875  {
876  if(rHint.GetId() == SfxHintId::Dying)
877  m_pTableNode = nullptr;
878  }
879 
881  : mbHasRoot(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
882  { }
883 
885  {
886  if (!mbHasRoot)
887  return;
888  for (auto& aTable : maTables)
889  {
890  // If already a layout exists, then the BoxFrames must recreated at this table
891  SwTableNode *pTable = aTable.first->GetTableNode();
892  OSL_ENSURE(pTable, "Why no expected table");
893  if (pTable)
894  {
895  SwFrameFormat * pFrameFormat = pTable->GetTable().GetFrameFormat();
896 
897  if (pFrameFormat != nullptr)
898  {
899  SwNodeIndex *pIndex = aTable.second;
900  pTable->DelFrames();
901  pTable->MakeOwnFrames(pIndex);
902  }
903  }
904  }
905  }
906 
908  {
909  if (!mbHasRoot)
910  return;
911  //Associate this tablenode with this after position, replace an //old
912  //node association if necessary
913  maTables.emplace(
914  std::unique_ptr<InsertedTableListener>(new InsertedTableListener(rTableNode)),
915  &(rPaM.GetPoint()->nNode));
916  }
917  }
918 
919 }
920 
921 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool TransferToDoc(OUString &rName)
Transfer ownership of the OLE object to a document's SvPersist.
virtual SwCharFormat * GetCharFormatFromPool(sal_uInt16 nId)=0
sal_uInt16 Count() const
constexpr TypedWhichId< SwCropGrf > RES_GRFATR_CROPGRF(132)
Graphic GetGraphic() const
Definition: ndnotxt.cxx:228
long Width() const
std::set< SwPosFlyFramePtr, SwPosFlyFrameCmp > SwPosFlyFrames
Definition: flypos.hxx:51
void DeleteMark()
Definition: pam.hxx:177
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNoTextNode * GetNoTextNodeFromSwFrameFormat(const SwFrameFormat &rFormat)
Get the SwNoTextNode associated with a SwFrameFormat if here is one.
sal_Int32 nIndex
std::map< std::unique_ptr< InsertedTableListener >, SwNodeIndex * > maTables
Definition: msfilter.hxx:287
int GetAssignedOutlineStyleLevel() const
Definition: fmtcol.cxx:587
InsertedTablesManager(const SwDoc &rDoc)
virtual ::sw::mark::IFieldmark * getFieldmarkAt(const SwPosition &rPos) const =0
get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
Marks a position in the document model.
Definition: pam.hxx:35
sal_Int32 GetLeft() const
ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
Get the Frames anchored to a given node.
const SfxPoolItem * SearchPoolItems(const ww8::PoolItems &rItems, sal_uInt16 eType)
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2436
const char aData[]
Definition: ww8scan.hxx:47
void closeall(const SwPosition &rPos)
Frame(const SwFrameFormat &rFlyFrame, const SwPosition &rPos)
constexpr sal_uInt16 RES_WHICHHINT_END(HINT_END)
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
SwNodeIndex m_nNode
Definition: fltshell.hxx:51
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
bool operator()(const std::unique_ptr< SwFltStackEntry > &pOneE, const std::unique_ptr< SwFltStackEntry > &pTwoE) const
long Height() const
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const =0
SwNodeIndex nNode
Definition: pam.hxx:37
SvxBreak GetBreak() const
SwTextFormatColl * FindTextFormatCollByName(const OUString &rName) const
Definition: doc.hxx:796
virtual Size GetTwipSize() const =0
sal_uIntPtr sal_uLong
bool close(const SwPosition &rPos, RedlineType eType)
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2686
const SwPosition * GetMark() const
Definition: pam.hxx:209
sal_Int64 n
Definition: doc.hxx:184
bool HasEmbeddedObject(const OUString &)
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
sal_uInt16 AddName(const OUString &rNm)
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
void MoveAttrsFieldmarkInserted(const SwPosition &rPos)
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1682
Dialog to specify the properties of date form field.
css::uno::Reference< css::frame::XModel > GetModel() const
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
std::vector< OUString > maAuthors
Definition: msfilter.hxx:346
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4109
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
SfxHintId GetId() const
tools::Polygon PolygonFromPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Make a best fit Polygon from a PolyPolygon.
SwPosFlyFrames GetAllFlyFormats(const SwPaM *, bool bDrawAlso, bool bAsCharAlso=false) const
Returns positions of all FlyFrames in the document.
Definition: doclay.cxx:502
void Scale(double fScaleX, double fScaleY)
const int nWrap100Percent
For custom wrapping.
Definition: types.hxx:40
show all inserts
void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet)
Get the SfxPoolItems of a SfxItemSet.
~DrawingOLEAdaptor()
Destructor will destroy the owned OLE object if not transferred.
SdrLayerID mnFormLayer
static OutputDevice * GetDefaultDevice()
const SfxPoolItem * NextItem()
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:109
RedlineType eType
Definition: fltshell.hxx:216
SwTableNode * GetTableNode()
Definition: node.hxx:599
SwNodeType GetNodeType() const
Definition: node.hxx:144
SwIndex nContent
Definition: pam.hxx:38
SwDoc * GetDoc() const
Returns the document this position is in.
Definition: pam.cxx:178
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
SetLayer(const SwDoc &rDoc)
Normal constructor.
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:425
void open(const SwPosition &rPos, const SfxPoolItem &rAttr)
int nCount
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
static SW_DLLPUBLIC sal_uInt16 GetPoolIdFromUIName(const OUString &rName, SwGetPoolIdFromName)
void InsertTable(SwTableNode &rTableNode, SwPaM &rPaM)
constexpr TypedWhichId< SwFltRedline > RES_FLTR_REDLINE(192)
const SwTable & GetTable() const
Definition: node.hxx:497
const SwNumRule * GetNumRuleFromTextNode(const SwTextNode &rTextNode)
const SwCropGrf & GetCropGrf(bool=true) const
Definition: grfatr.hxx:282
RedlineFlags on.
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
void SendObjectToHeaven(SdrObject &rObject) const
Make Object lives in the top layer.
SdrLayerID mnHellLayer
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:443
void Move(long nHorzMove, long nVertMove)
virtual void SetLayer(SdrLayerID nLayer)
tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon &rPolyPoly, const SwNoTextNode *pNd, bool bCorrectCrop)
Undo all scaling / move tricks of the wrap polygon done during import.
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
bool HasPageBreak(const SwNode &rNd)
Does a node have a "page break before" applied.
Style of a layout element.
Definition: frmfmt.hxx:57
void UpdateFramePositions(ww8::Frames &rFrames)
fix up frame positions, must be called after SetRedlineFlags
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
std::map< sal_uInt16, const SfxPoolItem *, sw::util::ItemSort > PoolItems
STL container of SfxPoolItems (Attributes)
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
int i
uno_Any a
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwTwips MakeSafePositioningValue(SwTwips nIn)
Clips a value to MAX/MIN 16bit value to make it safe for use as a position value to give to writer...
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
void SortByAssignedOutlineStyleListLevel(ww8::ParaStyles &rStyles)
Sort sequence of Paragraph Styles by assigned outline style list level.
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
static void SetGraphicToContainer(const Graphic &rGraphic, comphelper::EmbeddedObjectContainer &aContainer, const OUString &aName, const OUString &aMediaType)
void SetSize(const Size &rSize)
SwContentNode * GetContentNode()
Definition: node.hxx:615
FlyAnchors.
Definition: fmtanchr.hxx:34
sal_uInt16 Count() const
SwNoTextNode * GetNoTextNode()
Definition: ndnotxt.hxx:96
std::vector< std::unique_ptr< SwFltStackEntry > > maStack
Definition: msfilter.hxx:293
css::ui::LayoutSize maLayoutSize
SwDoc * GetDoc()
Definition: node.hxx:702
size_t size() const
Definition: docary.hxx:84
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2806
void MakeOwnFrames(SwNodeIndex *pIdxBehind)
Creates the frms for the table node (i.e. the TabFrames).
Definition: ndtbl.cxx:2397
sal_uInt16 GetSize() const
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNumRule * GetNormalNumRuleFromTextNode(const SwTextNode &rTextNode)
void ForceTreatAsInline()
Even if the frame isn't an inline frame, force it to behave as one.
void SetPosition(SwPosition const &rPos)
void SetObjectLayer(SdrObject &rObject, Layer eLayer) const
MapUnit GetMapUnit() const
sal_uInt16 GetSlotId(sal_uInt16 nWhich) const
sal_uInt16 GetWhichByPos(sal_uInt16 nPos) const
sal_Int32 m_nContent
Definition: fltshell.hxx:52
bool StartListening(SvtBroadcaster &rBroadcaster)
std::size_t nAutorNo
Definition: fltshell.hxx:217
InsertedTableListener(SwTableNode &rNode)
sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool, const SfxItemPool &rSrcPool, sal_uInt16 nWhich)
Map an ID valid in one SfxItemPool to its equivalent in another.
SfxItemPool * GetPool() const
show all deletes
SwFltPosition m_aMkPos
Definition: fltshell.hxx:86
enumrange< T >::Iterator end(enumrange< T >)
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
virtual SdrInventor GetObjInventor() const
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
Point PixelToLogic(const Point &rDevicePt) const
Size GetPrefSize() const
sal_Int32 GetBottom() const
SwTextFormatColl * GetParaStyle(SwDoc &rDoc, const OUString &rName)
Get a Paragraph Style which fits a given name.
SvtBroadcaster & GetNotifier()
Definition: calbck.hxx:93
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:78
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:78
SwCharFormat * FindCharFormatByName(const OUString &rName) const
Definition: doc.hxx:768
sal_Int32 GetTop() const
Size maLayoutSize
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
SwFltPosition m_aPtPos
Definition: fltshell.hxx:87
comphelper::EmbeddedObjectContainer & GetEmbeddedObjectContainer() const
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:334
SwCharFormat * GetCharFormat() const
Definition: fchrfmt.hxx:70
constexpr sal_Int64 convertTwipToMm100(sal_Int64 n)
sal_uInt16 GetWhich(sal_uInt16 nSlot, bool bDeep=true) const
#define SAL_WARN_IF(condition, area, stream)
const SwTextFormatColls * GetTextFormatColls() const
Definition: doc.hxx:775
MapMode GetPrefMapMode() const
const SwNodes & GetNodes() const
Definition: ndindex.hxx:156
Make exporting a Writer Frame easy.
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2881
DrawingOLEAdaptor(SdrOle2Obj &rObj, SfxObjectShell &rPers)
Take ownership of a SdrOle2Objs OLE object.
virtual void SetRedlineFlags(RedlineFlags eMode)=0
Set a new redline mode.
sal_Int32 GetIndex() const
Definition: index.hxx:91
bool IsCountedInList() const
Definition: ndtxt.cxx:4252
ww8::ParaStyles GetParaStyles(const SwDoc &rDoc)
Get the Paragraph Styles of a SwDoc.
sal_uInt16 TotalCount() const
SwNodes & GetNodes()
Definition: doc.hxx:403
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
bool HasItem(sal_uInt16 nWhich, const SfxPoolItem **ppItem=nullptr) const
css::uno::Reference< css::embed::XEmbeddedObject > mxIPRef
WriterSource meWriterType
void AbandonObject()
virtual void Notify(const SfxHint &) override
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:181
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(154)
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
bool InsertEmbeddedObject(const css::uno::Reference< css::embed::XEmbeddedObject > &, OUString &)
const SwNode * mpStartFrameContent
ww8::Frames GetFrames(const SwDoc &rDoc, SwPaM const *pPaM)
Get the Floating elements in a SwDoc.
sal_Int32 GetRight() const
const SwNumFormat * GetNumFormatFromTextNode(const SwTextNode &rTextNode)
Get the Numbering Format used on a paragraph.
void operator()(std::unique_ptr< SwFltStackEntry > &pEntry)
const sal_uInt16 * GetRanges() const
RndStdIds
bool IsTableNode() const
Definition: node.hxx:640
void SendObjectToHell(SdrObject &rObject) const
Make Object live in the bottom drawing layer.
DateTime aStamp
Definition: fltshell.hxx:215
RedlineType
SdrLayerID mnHeavenLayer
long getHeight() const
const SwNumFormat * GetNumFormatFromSwNumRuleLevel(const SwNumRule &rRule, int nLevel)
Get the Numbering Format for a given level from a numbering rule.
sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet, const SwDoc &rDoc, sal_uInt16 nWhich)
Map a SwDoc WhichId to the equivalent Id for a given SfxItemSet.
std::vector< SwTextFormatColl * > ParaStyles
STL container of Paragraph Styles (SwTextFormatColl)
void ClearOverridesFromSet(const SwFormatCharFormat &rFormat, SfxItemSet &rSet)
Remove properties from an SfxItemSet which a SwFormatCharFormat overrides.
long getWidth() const
SwCharFormat * GetCharStyle(SwDoc &rDoc, const OUString &rName)
Get a Character Style which fits a given name.
const SwPosition & GetPosition() const
Get the position this frame is anchored at.
RedlineType meType
sal_uInt16 Which() const
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2739
no RedlineFlags
const Size & GetSize() const
const SfxPoolItem * GetCurItem() const
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1315
std::vector< Frame > Frames
STL container of Frames.
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:844
::basegfx::B2IVector maSize
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1021
Base class of the Writer document model elements.
Definition: node.hxx:79