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