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>
57 #include <IDocumentMarkAccess.hxx>
58 #include <IMark.hxx>
59 #include <grfatr.hxx>
60 
61 using namespace com::sun::star;
62 
63 namespace
64 {
65  // #i98791# - adjust sorting
66  // Utility to sort SwTextFormatColl's by their assigned outline style list level
67  class outlinecmp
68  {
69  public:
70  bool operator()(const SwTextFormatColl *pA, const SwTextFormatColl *pB) const
71  {
72  // #i98791#
73  bool bResult( false );
74  const bool bIsAAssignedToOutlineStyle( pA->IsAssignedToListLevelOfOutlineStyle() );
75  const bool bIsBAssignedToOutlineStyle( pB->IsAssignedToListLevelOfOutlineStyle() );
76  if ( bIsAAssignedToOutlineStyle != bIsBAssignedToOutlineStyle )
77  {
78  bResult = bIsBAssignedToOutlineStyle;
79  }
80  else if ( !bIsAAssignedToOutlineStyle )
81  {
82  // pA and pB are equal regarding the sorting criteria.
83  // Thus return value does not matter.
84  bResult = false;
85  }
86  else
87  {
89  }
90 
91  return bResult;
92  }
93  };
94 
95  bool IsValidSlotWhich(sal_uInt16 nSlotId, sal_uInt16 nWhichId)
96  {
97  return (nSlotId != 0 && nWhichId != 0 && nSlotId != nWhichId);
98  }
99 
100  /*
101  Utility to convert a SwPosFlyFrames into a simple vector of ww8::Frames
102 
103  The crucial thing is that a ww8::Frame always has an anchor which
104  points to some content in the document. This is a requirement of exporting
105  to Word
106  */
107  ww8::Frames SwPosFlyFramesToFrames(const SwPosFlyFrames &rFlys)
108  {
109  ww8::Frames aRet;
110 
111  for(const auto& rpFly : rFlys)
112  {
113  const SwFrameFormat &rEntry = rpFly->GetFormat();
114 
115  if (const SwPosition* pAnchor = rEntry.GetAnchor().GetContentAnchor())
116  {
117  // the anchor position will be invalidated by SetRedlineFlags
118  // so set a dummy position and fix it in UpdateFramePositions
119  SwPosition const dummy(SwNodeIndex(
120  const_cast<SwNodes&>(pAnchor->nNode.GetNodes())));
121  aRet.emplace_back(rEntry, dummy);
122  }
123  else
124  {
125  SwPosition aPos(rpFly->GetNdIndex());
126 
127  if (SwTextNode* pTextNd = aPos.nNode.GetNode().GetTextNode())
128  {
129  aPos.nContent.Assign(pTextNd, 0);
130  }
131 
132  aRet.emplace_back(rEntry, aPos);
133  }
134  }
135  return aRet;
136  }
137 
138  //Utility to test if a frame is anchored at a given node index
139  class anchoredto
140  {
141  private:
142  sal_uLong mnNode;
143  public:
144  explicit anchoredto(sal_uLong nNode) : mnNode(nNode) {}
145  bool operator()(const ww8::Frame &rFrame) const
146  {
147  return (mnNode == rFrame.GetPosition().nNode.GetNode().GetIndex());
148  }
149  };
150 }
151 
152 namespace ww8
153 {
154  //For i120928,size conversion before exporting graphic of bullet
155  Frame::Frame(const Graphic &rGrf, const SwPosition &rPos)
156  : mpFlyFrame(nullptr)
157  , maPos(rPos)
158  , maSize()
159  , maLayoutSize()
160  , meWriterType(eBulletGrf)
161  , mpStartFrameContent(nullptr)
162  , mbIsInline(true)
163  , mbForBullet(true)
164  , maGrf(rGrf)
165  {
166  const MapMode aMap100mm( MapUnit::Map100thMM );
167  Size aSize( rGrf.GetPrefSize() );
168  if ( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
169  {
170  aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
171  }
172  else
173  {
174  aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
175  }
176  maSize = aSize;
178  }
179 
180  Frame::Frame(const SwFrameFormat &rFormat, const SwPosition &rPos)
181  : mpFlyFrame(&rFormat)
182  , maPos(rPos)
183  , maSize()
184  , maLayoutSize() // #i43447#
185  , meWriterType(eTextBox)
186  , mpStartFrameContent(nullptr)
187  // #i43447# - move to initialization list
188  , mbIsInline( (rFormat.GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) )
189  // #i120928# - handle graphic of bullet within existing implementation
190  , mbForBullet(false)
191  , maGrf()
192  {
193  switch (rFormat.Which())
194  {
195  case RES_FLYFRMFMT:
196  if (const SwNodeIndex* pIdx = rFormat.GetContent().GetContentIdx())
197  {
198  SwNodeIndex aIdx(*pIdx, 1);
199  const SwNode &rNd = aIdx.GetNode();
200  // #i43447# - determine layout size
201  {
202  SwRect aLayRect( rFormat.FindLayoutRect() );
203  tools::Rectangle aRect( aLayRect.SVRect() );
204  // The Object is not rendered (e.g. something in unused
205  // header/footer) - thus, get the values from the format.
206  if ( aLayRect.IsEmpty() )
207  {
208  aRect.SetSize( rFormat.GetFrameSize().GetSize() );
209  }
210  maLayoutSize = aRect.GetSize();
211  }
212  switch (rNd.GetNodeType())
213  {
214  case SwNodeType::Grf:
216  maSize = rNd.GetNoTextNode()->GetTwipSize();
217  break;
218  case SwNodeType::Ole:
219  meWriterType = eOle;
220  maSize = rNd.GetNoTextNode()->GetTwipSize();
221  break;
222  default:
224  // #i43447# - Size equals layout size for text boxes
226  break;
227  }
228  mpStartFrameContent = &rNd;
229  }
230  else
231  {
232  OSL_ENSURE(false, "Impossible");
234  }
235  break;
236  default:
237  if (const SdrObject* pObj = rFormat.FindRealSdrObject())
238  {
239  if (pObj->GetObjInventor() == SdrInventor::FmForm)
241  else
243  maSize = pObj->GetSnapRect().GetSize();
245  }
246  else
247  {
248  OSL_ENSURE(false, "Impossible");
250  }
251  break;
252  }
253  }
254 
255 
257  {
258  mbIsInline = true;
259  }
260 }
261 
262 namespace sw
263 {
264  namespace hack
265  {
266 
267  sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool,
268  const SfxItemPool &rSrcPool, sal_uInt16 nWhich)
269  {
270  sal_uInt16 nSlotId = rSrcPool.GetSlotId(nWhich);
271  if (IsValidSlotWhich(nSlotId, nWhich))
272  nWhich = rDestPool.GetWhich(nSlotId);
273  else
274  nWhich = 0;
275  return nWhich;
276  }
277 
278  sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet,
279  const SwDoc &rDoc, sal_uInt16 nWhich)
280  {
281  if (RES_WHICHHINT_END < *(rSet.GetRanges()))
282  {
283  nWhich = TransformWhichBetweenPools(*rSet.GetPool(),
284  rDoc.GetAttrPool(), nWhich);
285  }
286  return nWhich;
287  }
288 
290  SfxObjectShell &rPers)
291  : mxIPRef(rObj.GetObjRef()), mrPers(rPers),
292  mpGraphic( rObj.GetGraphic() )
293  {
294  rObj.AbandonObject();
295  }
296 
297  bool DrawingOLEAdaptor::TransferToDoc( OUString &rName )
298  {
299  OSL_ENSURE(mxIPRef.is(), "Transferring invalid object to doc");
300  if (!mxIPRef.is())
301  return false;
302 
303  uno::Reference < container::XChild > xChild( mxIPRef, uno::UNO_QUERY );
304  if ( xChild.is() )
305  xChild->setParent( mrPers.GetModel() );
306 
308  if (bSuccess)
309  {
310  if ( mpGraphic )
313  rName,
314  OUString() );
315 
316  mxIPRef = nullptr;
317  }
318 
319  return bSuccess;
320  }
321 
323  {
324  if (!mxIPRef.is())
325  return;
326 
327  OSL_ENSURE( !mrPers.GetEmbeddedObjectContainer().HasEmbeddedObject( mxIPRef ), "Object in adaptor is inserted?!" );
328  try
329  {
330  mxIPRef->close(true);
331  }
332  catch ( const css::util::CloseVetoException& )
333  {
334  }
335 
336  mxIPRef = nullptr;
337  }
338  }
339 
340  namespace util
341  {
343  {
344  if (nIn > SHRT_MAX)
345  nIn = SHRT_MAX;
346  else if (nIn < SHRT_MIN)
347  nIn = SHRT_MIN;
348  return nIn;
349  }
350 
352  {
353  SetObjectLayer(rObject, eHell);
354  }
355 
357  {
358  SetObjectLayer(rObject, eHeaven);
359  }
360 
361  void SetLayer::SetObjectLayer(SdrObject &rObject, Layer eLayer) const
362  {
363  if (SdrInventor::FmForm == rObject.GetObjInventor())
364  rObject.SetLayer(mnFormLayer);
365  else
366  {
367  switch (eLayer)
368  {
369  case eHeaven:
370  rObject.SetLayer(mnHeavenLayer);
371  break;
372  case eHell:
373  rObject.SetLayer(mnHellLayer);
374  break;
375  }
376  }
377  }
378 
379  //SetLayer boilerplate begin
380 
381  // #i38889# - by default put objects into the invisible layers.
383  : mnHeavenLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId()),
384  mnHellLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId()),
385  mnFormLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleControlsId())
386  {
387  }
388  //SetLayer boilerplate end
389 
390  void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet )
391  {
392  if( bExportParentItemSet )
393  {
394  sal_uInt16 nTotal = rSet.TotalCount();
395  for( sal_uInt16 nItem =0; nItem < nTotal; ++nItem )
396  {
397  const SfxPoolItem* pItem = nullptr;
398  if( SfxItemState::SET == rSet.GetItemState( rSet.GetWhichByPos( nItem ), true, &pItem ) )
399  {
400  rItems[pItem->Which()] = pItem;
401  }
402  }
403  }
404  else if( rSet.Count())
405  {
406  SfxItemIter aIter(rSet);
407  if (const SfxPoolItem *pItem = aIter.GetCurItem())
408  {
409  do
410  rItems[pItem->Which()] = pItem;
411  while ((pItem = aIter.NextItem()));
412  }
413  }
414  }
415 
417  sal_uInt16 eType)
418  {
419  auto aIter = rItems.find(eType);
420  if (aIter != rItems.end())
421  return aIter->second;
422  return nullptr;
423  }
424 
426  {
427  if (const SwCharFormat* pCharFormat = rFormat.GetCharFormat())
428  {
429  if (pCharFormat->GetAttrSet().Count())
430  {
431  SfxItemIter aIter(pCharFormat->GetAttrSet());
432  const SfxPoolItem *pItem = aIter.GetCurItem();
433  do
434  rSet.ClearItem(pItem->Which());
435  while ((pItem = aIter.NextItem()));
436  }
437  }
438  }
439 
441  {
442  ww8::ParaStyles aStyles;
443  typedef ww8::ParaStyles::size_type mysizet;
444 
445  const SwTextFormatColls *pColls = rDoc.GetTextFormatColls();
446  mysizet nCount = pColls ? pColls->size() : 0;
447  aStyles.reserve(nCount);
448  for (mysizet nI = 0; nI < nCount; ++nI)
449  aStyles.push_back((*pColls)[ static_cast< sal_uInt16 >(nI) ]);
450  return aStyles;
451  }
452 
453  SwTextFormatColl* GetParaStyle(SwDoc &rDoc, const OUString& rName)
454  {
455  // Search first in the Doc-Styles
456  SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName(rName);
457  if (!pColl)
458  {
459  // Collection not found, try in Pool ?
460  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
462  if (n != SAL_MAX_UINT16) // found or standard
463  pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(n, false);
464  }
465  return pColl;
466  }
467 
468  SwCharFormat* GetCharStyle(SwDoc &rDoc, const OUString& rName)
469  {
470  SwCharFormat *pFormat = rDoc.FindCharFormatByName(rName);
471  if (!pFormat)
472  {
473  // Collection not found, try in Pool ?
474  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
476  if (n != SAL_MAX_UINT16) // found or standard
478  }
479  return pFormat;
480  }
481 
482  // #i98791# - adjust sorting algorithm
484  {
485  std::sort(rStyles.begin(), rStyles.end(), outlinecmp());
486  }
487 
488  /*
489  Utility to extract FlyFormats from a document, potentially from a
490  selection.
491  */
492  ww8::Frames GetFrames(const SwDoc &rDoc, SwPaM const *pPaM /*, bool bAll*/)
493  {
494  SwPosFlyFrames aFlys(rDoc.GetAllFlyFormats(pPaM, true));
495  ww8::Frames aRet(SwPosFlyFramesToFrames(aFlys));
496  return aRet;
497  }
498 
500  {
501  for (ww8::Frame & rFrame : rFrames)
502  {
503  SwFormatAnchor const& rAnchor = rFrame.GetFrameFormat().GetAnchor();
504  if (SwPosition const*const pAnchor = rAnchor.GetContentAnchor())
505  {
506  rFrame.SetPosition(*pAnchor);
507  }
508  else
509  { // these don't need to be corrected, they're not in redlines
510  assert(RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId());
511  }
512  }
513  }
514 
515  ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
516  {
517  ww8::Frames aRet;
518  std::copy_if(rFrames.begin(), rFrames.end(),
519  std::back_inserter(aRet), anchoredto(rNode.GetIndex()));
520  return aRet;
521  }
522 
524  int nLevel)
525  {
526  if (nLevel < 0 || nLevel >= MAXLEVEL)
527  {
528  OSL_FAIL("Invalid level");
529  return nullptr;
530  }
531  return &(rRule.Get( static_cast< sal_uInt16 >(nLevel) ));
532  }
533 
535  {
536  const SwNumRule *pRule = nullptr;
537  if (
538  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
539  nullptr != (pRule = rTextNode.GetNumRule())
540  )
541  {
542  return GetNumFormatFromSwNumRuleLevel(*pRule,
543  rTextNode.GetActualListLevel());
544  }
545 
546  if (
547  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
548  nullptr != (pRule = rTextNode.GetDoc().GetOutlineNumRule())
549  )
550  {
551  return GetNumFormatFromSwNumRuleLevel(*pRule,
552  rTextNode.GetActualListLevel());
553  }
554 
555  return nullptr;
556  }
557 
558  const SwNumRule* GetNumRuleFromTextNode(const SwTextNode &rTextNode)
559  {
560  return GetNormalNumRuleFromTextNode(rTextNode);
561  }
562 
564  {
565  const SwNumRule *pRule = nullptr;
566 
567  if (
568  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
569  nullptr != (pRule = rTextNode.GetNumRule())
570  )
571  {
572  return pRule;
573  }
574  return nullptr;
575  }
576 
578  {
579  const SwNodeIndex *pIndex = rFormat.GetContent().GetContentIdx();
580  OSL_ENSURE(pIndex, "No NodeIndex in SwFrameFormat ?, suspicious");
581  if (!pIndex)
582  return nullptr;
583  SwNodeIndex aIdx(*pIndex, 1);
584  return aIdx.GetNode().GetNoTextNode();
585  }
586 
587  bool HasPageBreak(const SwNode &rNd)
588  {
589  const SvxFormatBreakItem *pBreak = nullptr;
590  if (rNd.IsTableNode() && rNd.GetTableNode())
591  {
592  const SwTable& rTable = rNd.GetTableNode()->GetTable();
593  const SwFrameFormat* pApply = rTable.GetFrameFormat();
594  OSL_ENSURE(pApply, "impossible");
595  if (pApply)
596  pBreak = &(ItemGet<SvxFormatBreakItem>(*pApply, RES_BREAK));
597  }
598  else if (const SwContentNode *pNd = rNd.GetContentNode())
599  pBreak = &(ItemGet<SvxFormatBreakItem>(*pNd, RES_BREAK));
600 
601  return pBreak && pBreak->GetBreak() == SvxBreak::PageBefore;
602  }
603 
605  {
606  if(1 == rPolyPoly.Count())
607  {
608  return rPolyPoly[0];
609  }
610  else
611  {
612  // This method will now just concatenate the polygons contained
613  // in the given PolyPolygon. Anything else which might be thought of
614  // for reducing to a single polygon will just need more power and
615  // cannot create more correct results.
616  sal_uInt32 nPointCount(0);
617  sal_uInt16 a;
618 
619  for(a = 0; a < rPolyPoly.Count(); a++)
620  {
621  nPointCount += static_cast<sal_uInt32>(rPolyPoly[a].GetSize());
622  }
623 
624  if(nPointCount > 0x0000ffff)
625  {
626  OSL_FAIL("PolygonFromPolyPolygon: too many points for a single polygon (!)");
627  nPointCount = 0x0000ffff;
628  }
629 
630  tools::Polygon aRetval(static_cast<sal_uInt16>(nPointCount));
631  sal_uInt32 nAppendIndex(0);
632 
633  for(a = 0; a < rPolyPoly.Count(); a++)
634  {
635  const tools::Polygon& rCandidate = rPolyPoly[a];
636 
637  for(sal_uInt16 b(0); nAppendIndex <= nPointCount && b < rCandidate.GetSize(); b++)
638  {
639  aRetval[static_cast<sal_uInt16>(nAppendIndex++)] = rCandidate[b];
640  }
641  }
642 
643  return aRetval;
644  }
645  }
646 
647  tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon& rPolyPoly, const SwNoTextNode* pNd, bool bCorrectCrop)
648  {
649  tools::Polygon aPoly(PolygonFromPolyPolygon(rPolyPoly));
650  const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
651 
652  const SwAttrSet* pAttrSet = pNd->GetpSwAttrSet();
653  if (bCorrectCrop && pAttrSet)
654  {
655  if (pAttrSet->HasItem(RES_GRFATR_CROPGRF))
656  {
657  // Word's wrap polygon deals with a canvas which has the size of the already
658  // cropped graphic, do the opposite of correctCrop() in writerfilter/.
659  const SwCropGrf& rCrop = pAttrSet->GetCropGrf();
660  sal_Int32 nCropLeft = convertTwipToMm100(rCrop.GetLeft());
661  sal_Int32 nCropRight = convertTwipToMm100(rCrop.GetRight());
662  sal_Int32 nCropTop = convertTwipToMm100(rCrop.GetTop());
663  sal_Int32 nCropBottom = convertTwipToMm100(rCrop.GetBottom());
664  aPoly.Move(-nCropLeft, -nCropTop);
665 
666  Fraction aScaleX(rOrigSize.getWidth(), rOrigSize.getWidth() - nCropLeft - nCropRight);
667  Fraction aScaleY(rOrigSize.getHeight(), rOrigSize.getHeight() - nCropTop - nCropBottom);
668  aPoly.Scale(double(aScaleX), double(aScaleY));
669  }
670  }
671 
672  Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
673  Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
674  aPoly.Scale(double(aMapPolyX), double(aMapPolyY));
675 
676  /*
677  a) stretch right bound by 15twips
678  b) shrink bottom bound to where it would have been in word
679  c) Move it to the left by 15twips
680 
681  See the import for details
682  */
683  const Size &rSize = pNd->GetTwipSize();
684  Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
685  aMoveHack *= Fraction(15, 1);
686  tools::Long nMove(aMoveHack);
687 
688  Fraction aHackX(ww::nWrap100Percent + nMove,
690  Fraction aHackY(ww::nWrap100Percent - nMove,
692  aPoly.Scale(double(aHackX), double(aHackY));
693 
694  aPoly.Move(-nMove, 0);
695  return aPoly;
696  }
697 
698  void RedlineStack::open(const SwPosition& rPos, const SfxPoolItem& rAttr)
699  {
700  OSL_ENSURE(rAttr.Which() == RES_FLTR_REDLINE, "not a redline");
701  maStack.emplace_back(new SwFltStackEntry(rPos, std::unique_ptr<SfxPoolItem>(rAttr.Clone())));
702  }
703 
704  namespace {
705 
706  class SameOpenRedlineType
707  {
708  private:
710  public:
711  explicit SameOpenRedlineType(RedlineType eType) : meType(eType) {}
712  bool operator()(const std::unique_ptr<SwFltStackEntry> & pEntry) const
713  {
714  const SwFltRedline *pTest = static_cast<const SwFltRedline *>
715  (pEntry->pAttr.get());
716  return (pEntry->bOpen && (pTest->eType == meType));
717  }
718  };
719 
720  }
721 
722  bool RedlineStack::close(const SwPosition& rPos, RedlineType eType)
723  {
724  //Search from end for same type
725  auto aResult = std::find_if(maStack.rbegin(), maStack.rend(),
726  SameOpenRedlineType(eType));
727  if (aResult != maStack.rend())
728  {
729  SwTextNode *const pNode(rPos.nNode.GetNode().GetTextNode());
730  sal_Int32 const nIndex(rPos.nContent.GetIndex());
731  // HACK to prevent overlap of field-mark and redline,
732  // which would destroy field-mark invariants when the redline
733  // is hidden: move the redline end one to the left
734  if (pNode && nIndex > 0
735  && pNode->GetText()[nIndex - 1] == CH_TXT_ATR_FIELDEND)
736  {
737  SwPosition const end(*rPos.nNode.GetNode().GetTextNode(),
738  nIndex - 1);
739  sw::mark::IFieldmark *const pFieldMark(
741  SAL_WARN_IF(!pFieldMark, "sw.ww8", "expected a field mark");
742  if (pFieldMark && pFieldMark->GetMarkPos().nNode.GetIndex() == (*aResult)->m_aMkPos.m_nNode.GetIndex()+1
743  && pFieldMark->GetMarkPos().nContent.GetIndex() < (*aResult)->m_aMkPos.m_nContent)
744  {
745  (*aResult)->SetEndPos(end);
746  return true;
747  }
748  }
749  (*aResult)->SetEndPos(rPos);
750  return true;
751  }
752  return false;
753  }
754 
756  {
757  std::for_each(maStack.begin(), maStack.end(), SetEndIfOpen(rPos));
758  }
759 
761  {
762  size_t nCnt = maStack.size();
763  sal_Int32 const nInserted = 2; // CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDSEP
764  sal_uLong nPosNd = rPos.nNode.GetIndex();
765  sal_Int32 nPosCt = rPos.nContent.GetIndex() - nInserted;
766 
767  for (size_t i=0; i < nCnt; ++i)
768  {
769  SwFltStackEntry& rEntry = *maStack[i];
770  bool const isPoint(rEntry.m_aMkPos == rEntry.m_aPtPos);
771  if ((rEntry.m_aMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
772  (nPosCt <= rEntry.m_aMkPos.m_nContent))
773  {
774  rEntry.m_aMkPos.m_nContent += nInserted;
775  SAL_WARN_IF(rEntry.m_aMkPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
776  "sw.ww8", "redline ends after end of line");
777  if (isPoint) // sigh ... important special case...
778  {
779  rEntry.m_aPtPos.m_nContent += nInserted;
780  continue;
781  }
782  }
783  // for the end position, leave it alone if it's *on* the dummy
784  // char position, that should remain *before*
785  if ((rEntry.m_aPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
786  (nPosCt < rEntry.m_aPtPos.m_nContent))
787  {
788  rEntry.m_aPtPos.m_nContent += nInserted;
789  SAL_WARN_IF(rEntry.m_aPtPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
790  "sw.ww8", "redline ends after end of line");
791  }
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->pAttr.get());
807 
808  SwRedlineData aData(pFltRedline->eType, pFltRedline->nAutorNo,
809  pFltRedline->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->pAttr.get());
828  const SwFltRedline *pTwo= static_cast<const SwFltRedline*>
829  (pTwoE->pAttr.get());
830 
831  //Return the earlier time, if two have the same time, prioritize
832  //inserts over deletes
833  if (pOne->aStamp == pTwo->aStamp)
834  return (pOne->eType == RedlineType::Insert && pTwo->eType != RedlineType::Insert);
835  else
836  return (pOne->aStamp < pTwo->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
constexpr TypedWhichId< SwCropGrf > RES_GRFATR_CROPGRF(132)
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:290
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:590
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.
SwCharFormat * FindCharFormatByName(std::u16string_view rName) const
Definition: doc.hxx:772
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
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: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
tools::Long getWidth() const
SvxBreak GetBreak() const
virtual Size GetTwipSize() const =0
sal_uIntPtr sal_uLong
long Long
bool close(const SwPosition &rPos, RedlineType eType)
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2659
const SwPosition * GetMark() const
Definition: pam.hxx:209
sal_Int64 n
Definition: doc.hxx:186
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:1705
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:4076
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:203
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:503
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:215
SwTableNode * GetTableNode()
Definition: node.hxx:602
SwNodeType GetNodeType() const
Definition: node.hxx:144
SwIndex nContent
Definition: pam.hxx:38
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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
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:500
const SwNumRule * GetNumRuleFromTextNode(const SwTextNode &rTextNode)
const SwCropGrf & GetCropGrf(bool=true) const
Definition: grfatr.hxx:284
RedlineFlags on.
const SwFrameFormat & GetFrameFormat() const
Get the writer SwFrameFormat that this object describes.
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:47
void SendObjectToHeaven(SdrObject &rObject) const
Make Object lives in the top layer.
SdrLayerID mnHellLayer
tools::Long getHeight() const
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:451
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:58
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:211
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:618
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
tools::Long Width() const
size_t size() const
Definition: docary.hxx:84
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2775
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:51
bool StartListening(SvtBroadcaster &rBroadcaster)
std::size_t nAutorNo
Definition: fltshell.hxx:216
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:49
SwFltPosition m_aMkPos
Definition: fltshell.hxx:85
enumrange< T >::Iterator end(enumrange< T >)
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:111
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:99
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:97
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:79
sal_Int32 GetTop() const
SwTextFormatColl * FindTextFormatCollByName(std::u16string_view rName) const
Definition: doc.hxx:800
Size maLayoutSize
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
SwFltPosition m_aPtPos
Definition: fltshell.hxx:86
comphelper::EmbeddedObjectContainer & GetEmbeddedObjectContainer() const
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
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:779
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:2849
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:4214
ww8::ParaStyles GetParaStyles(const SwDoc &rDoc)
Get the Paragraph Styles of a SwDoc.
sal_uInt16 TotalCount() const
SwNodes & GetNodes()
Definition: doc.hxx:407
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
tools::Long Height() 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:180
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:643
void SendObjectToHell(SdrObject &rObject) const
Make Object live in the bottom drawing layer.
DateTime aStamp
Definition: fltshell.hxx:214
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:2712
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:846
::basegfx::B2IVector maSize
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1025
Base class of the Writer document model elements.
Definition: node.hxx:79