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  , maSize()
160  , maLayoutSize()
161  , meWriterType(eBulletGrf)
162  , mpStartFrameContent(nullptr)
163  , mbIsInline(true)
164  , mbForBullet(true)
165  , maGrf(rGrf)
166  {
167  const MapMode aMap100mm( MapUnit::Map100thMM );
168  Size aSize( rGrf.GetPrefSize() );
169  if ( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() )
170  {
171  aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
172  }
173  else
174  {
175  aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
176  }
177  maSize = aSize;
179  }
180 
181  Frame::Frame(const SwFrameFormat &rFormat, const SwPosition &rPos)
182  : mpFlyFrame(&rFormat)
183  , maPos(rPos)
184  , maSize()
185  , maLayoutSize() // #i43447#
186  , meWriterType(eTextBox)
187  , mpStartFrameContent(nullptr)
188  // #i43447# - move to initialization list
189  , mbIsInline( (rFormat.GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) )
190  // #i120928# - handle graphic of bullet within existing implementation
191  , mbForBullet(false)
192  , maGrf()
193  {
194  switch (rFormat.Which())
195  {
196  case RES_FLYFRMFMT:
197  if (const SwNodeIndex* pIdx = rFormat.GetContent().GetContentIdx())
198  {
199  SwNodeIndex aIdx(*pIdx, 1);
200  const SwNode &rNd = aIdx.GetNode();
201  // #i43447# - determine layout size
202  {
203  SwRect aLayRect( rFormat.FindLayoutRect() );
204  tools::Rectangle aRect( aLayRect.SVRect() );
205  // The Object is not rendered (e.g. something in unused
206  // header/footer) - thus, get the values from the format.
207  if ( aLayRect.IsEmpty() )
208  {
209  aRect.SetSize( rFormat.GetFrameSize().GetSize() );
210  }
211  maLayoutSize = aRect.GetSize();
212  }
213  switch (rNd.GetNodeType())
214  {
215  case SwNodeType::Grf:
217  maSize = rNd.GetNoTextNode()->GetTwipSize();
218  break;
219  case SwNodeType::Ole:
220  meWriterType = eOle;
221  maSize = rNd.GetNoTextNode()->GetTwipSize();
222  break;
223  default:
225  // #i43447# - Size equals layout size for text boxes
227  break;
228  }
229  mpStartFrameContent = &rNd;
230  }
231  else
232  {
233  OSL_ENSURE(false, "Impossible");
235  }
236  break;
237  default:
238  if (const SdrObject* pObj = rFormat.FindRealSdrObject())
239  {
240  if (pObj->GetObjInventor() == SdrInventor::FmForm)
242  else
244  maSize = pObj->GetSnapRect().GetSize();
246  }
247  else
248  {
249  OSL_ENSURE(false, "Impossible");
251  }
252  break;
253  }
254  }
255 
256 
258  {
259  mbIsInline = true;
260  }
261 }
262 
263 namespace sw
264 {
265  namespace hack
266  {
267 
268  sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool,
269  const SfxItemPool &rSrcPool, sal_uInt16 nWhich)
270  {
271  sal_uInt16 nSlotId = rSrcPool.GetSlotId(nWhich);
272  if (IsValidSlotWhich(nSlotId, nWhich))
273  nWhich = rDestPool.GetWhich(nSlotId);
274  else
275  nWhich = 0;
276  return nWhich;
277  }
278 
279  sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet,
280  const SwDoc &rDoc, sal_uInt16 nWhich)
281  {
282  if (RES_WHICHHINT_END < *(rSet.GetRanges()))
283  {
284  nWhich = TransformWhichBetweenPools(*rSet.GetPool(),
285  rDoc.GetAttrPool(), nWhich);
286  }
287  return nWhich;
288  }
289 
291  SfxObjectShell &rPers)
292  : mxIPRef(rObj.GetObjRef()), mrPers(rPers),
293  mpGraphic( rObj.GetGraphic() )
294  {
295  rObj.AbandonObject();
296  }
297 
298  bool DrawingOLEAdaptor::TransferToDoc( OUString &rName )
299  {
300  OSL_ENSURE(mxIPRef.is(), "Transferring invalid object to doc");
301  if (!mxIPRef.is())
302  return false;
303 
304  uno::Reference < container::XChild > xChild( mxIPRef, uno::UNO_QUERY );
305  if ( xChild.is() )
306  xChild->setParent( mrPers.GetModel() );
307 
309  if (bSuccess)
310  {
311  if ( mpGraphic )
314  rName,
315  OUString() );
316 
317  mxIPRef = nullptr;
318  }
319 
320  return bSuccess;
321  }
322 
324  {
325  if (!mxIPRef.is())
326  return;
327 
328  OSL_ENSURE( !mrPers.GetEmbeddedObjectContainer().HasEmbeddedObject( mxIPRef ), "Object in adaptor is inserted?!" );
329  try
330  {
331  mxIPRef->close(true);
332  }
333  catch ( const css::util::CloseVetoException& )
334  {
335  }
336 
337  mxIPRef = nullptr;
338  }
339  }
340 
341  namespace util
342  {
344  {
345  if (nIn > SHRT_MAX)
346  nIn = SHRT_MAX;
347  else if (nIn < SHRT_MIN)
348  nIn = SHRT_MIN;
349  return nIn;
350  }
351 
353  {
354  SetObjectLayer(rObject, eHell);
355  }
356 
358  {
359  SetObjectLayer(rObject, eHeaven);
360  }
361 
362  void SetLayer::SetObjectLayer(SdrObject &rObject, Layer eLayer) const
363  {
364  if (SdrInventor::FmForm == rObject.GetObjInventor())
365  rObject.SetLayer(mnFormLayer);
366  else
367  {
368  switch (eLayer)
369  {
370  case eHeaven:
371  rObject.SetLayer(mnHeavenLayer);
372  break;
373  case eHell:
374  rObject.SetLayer(mnHellLayer);
375  break;
376  }
377  }
378  }
379 
380  //SetLayer boilerplate begin
381 
382  // #i38889# - by default put objects into the invisible layers.
384  : mnHeavenLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId()),
385  mnHellLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId()),
386  mnFormLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleControlsId())
387  {
388  }
389  //SetLayer boilerplate end
390 
391  void GetPoolItems(const SfxItemSet &rSet, ww8::PoolItems &rItems, bool bExportParentItemSet )
392  {
393  if( bExportParentItemSet )
394  {
395  sal_uInt16 nTotal = rSet.TotalCount();
396  for( sal_uInt16 nItem =0; nItem < nTotal; ++nItem )
397  {
398  const SfxPoolItem* pItem = nullptr;
399  if( SfxItemState::SET == rSet.GetItemState( rSet.GetWhichByPos( nItem ), true, &pItem ) )
400  {
401  rItems[pItem->Which()] = pItem;
402  }
403  }
404  }
405  else if( rSet.Count())
406  {
407  SfxItemIter aIter(rSet);
408  if (const SfxPoolItem *pItem = aIter.GetCurItem())
409  {
410  do
411  rItems[pItem->Which()] = pItem;
412  while ((pItem = aIter.NextItem()));
413  }
414  }
415  }
416 
418  sal_uInt16 eType)
419  {
420  auto aIter = rItems.find(eType);
421  if (aIter != rItems.end())
422  return aIter->second;
423  return nullptr;
424  }
425 
427  {
428  if (const SwCharFormat* pCharFormat = rFormat.GetCharFormat())
429  {
430  if (pCharFormat->GetAttrSet().Count())
431  {
432  SfxItemIter aIter(pCharFormat->GetAttrSet());
433  const SfxPoolItem *pItem = aIter.GetCurItem();
434  do
435  rSet.ClearItem(pItem->Which());
436  while ((pItem = aIter.NextItem()));
437  }
438  }
439  }
440 
442  {
443  ww8::ParaStyles aStyles;
444  typedef ww8::ParaStyles::size_type mysizet;
445 
446  const SwTextFormatColls *pColls = rDoc.GetTextFormatColls();
447  mysizet nCount = pColls ? pColls->size() : 0;
448  aStyles.reserve(nCount);
449  for (mysizet nI = 0; nI < nCount; ++nI)
450  aStyles.push_back((*pColls)[ static_cast< sal_uInt16 >(nI) ]);
451  return aStyles;
452  }
453 
454  SwTextFormatColl* GetParaStyle(SwDoc &rDoc, const OUString& rName)
455  {
456  // Search first in the Doc-Styles
457  SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName(rName);
458  if (!pColl)
459  {
460  // Collection not found, try in Pool ?
461  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
463  if (n != SAL_MAX_UINT16) // found or standard
464  pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(n, false);
465  }
466  return pColl;
467  }
468 
469  SwCharFormat* GetCharStyle(SwDoc &rDoc, const OUString& rName)
470  {
471  SwCharFormat *pFormat = rDoc.FindCharFormatByName(rName);
472  if (!pFormat)
473  {
474  // Collection not found, try in Pool ?
475  sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
477  if (n != SAL_MAX_UINT16) // found or standard
479  }
480  return pFormat;
481  }
482 
483  // #i98791# - adjust sorting algorithm
485  {
486  std::sort(rStyles.begin(), rStyles.end(), outlinecmp());
487  }
488 
489  /*
490  Utility to extract FlyFormats from a document, potentially from a
491  selection.
492  */
493  ww8::Frames GetFrames(const SwDoc &rDoc, SwPaM const *pPaM /*, bool bAll*/)
494  {
495  SwPosFlyFrames aFlys(rDoc.GetAllFlyFormats(pPaM, true));
496  ww8::Frames aRet(SwPosFlyFramesToFrames(aFlys));
497  return aRet;
498  }
499 
501  {
502  for (ww8::Frame & rFrame : rFrames)
503  {
504  SwFormatAnchor const& rAnchor = rFrame.GetFrameFormat().GetAnchor();
505  if (SwPosition const*const pAnchor = rAnchor.GetContentAnchor())
506  {
507  rFrame.SetPosition(*pAnchor);
508  }
509  else
510  { // these don't need to be corrected, they're not in redlines
511  assert(RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId());
512  }
513  }
514  }
515 
516  ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
517  {
518  ww8::Frames aRet;
519  std::copy_if(rFrames.begin(), rFrames.end(),
520  std::back_inserter(aRet), anchoredto(rNode.GetIndex()));
521  return aRet;
522  }
523 
525  int nLevel)
526  {
527  if (nLevel < 0 || nLevel >= MAXLEVEL)
528  {
529  OSL_FAIL("Invalid level");
530  return nullptr;
531  }
532  return &(rRule.Get( static_cast< sal_uInt16 >(nLevel) ));
533  }
534 
536  {
537  const SwNumRule *pRule = nullptr;
538  if (
539  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
540  nullptr != (pRule = rTextNode.GetNumRule())
541  )
542  {
543  return GetNumFormatFromSwNumRuleLevel(*pRule,
544  rTextNode.GetActualListLevel());
545  }
546 
547  if (
548  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
549  nullptr != (pRule = rTextNode.GetDoc().GetOutlineNumRule())
550  )
551  {
552  return GetNumFormatFromSwNumRuleLevel(*pRule,
553  rTextNode.GetActualListLevel());
554  }
555 
556  return nullptr;
557  }
558 
559  const SwNumRule* GetNumRuleFromTextNode(const SwTextNode &rTextNode)
560  {
561  return GetNormalNumRuleFromTextNode(rTextNode);
562  }
563 
565  {
566  const SwNumRule *pRule = nullptr;
567 
568  if (
569  rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
570  nullptr != (pRule = rTextNode.GetNumRule())
571  )
572  {
573  return pRule;
574  }
575  return nullptr;
576  }
577 
579  {
580  const SwNodeIndex *pIndex = rFormat.GetContent().GetContentIdx();
581  OSL_ENSURE(pIndex, "No NodeIndex in SwFrameFormat ?, suspicious");
582  if (!pIndex)
583  return nullptr;
584  SwNodeIndex aIdx(*pIndex, 1);
585  return aIdx.GetNode().GetNoTextNode();
586  }
587 
588  bool HasPageBreak(const SwNode &rNd)
589  {
590  const SvxFormatBreakItem *pBreak = nullptr;
591  if (rNd.IsTableNode() && rNd.GetTableNode())
592  {
593  const SwTable& rTable = rNd.GetTableNode()->GetTable();
594  const SwFrameFormat* pApply = rTable.GetFrameFormat();
595  OSL_ENSURE(pApply, "impossible");
596  if (pApply)
597  pBreak = &(ItemGet<SvxFormatBreakItem>(*pApply, RES_BREAK));
598  }
599  else if (const SwContentNode *pNd = rNd.GetContentNode())
600  pBreak = &(ItemGet<SvxFormatBreakItem>(*pNd, RES_BREAK));
601 
602  return pBreak && pBreak->GetBreak() == SvxBreak::PageBefore;
603  }
604 
606  {
607  if(1 == rPolyPoly.Count())
608  {
609  return rPolyPoly[0];
610  }
611  else
612  {
613  // This method will now just concatenate the polygons contained
614  // in the given PolyPolygon. Anything else which might be thought of
615  // for reducing to a single polygon will just need more power and
616  // cannot create more correct results.
617  sal_uInt32 nPointCount(0);
618  sal_uInt16 a;
619 
620  for(a = 0; a < rPolyPoly.Count(); a++)
621  {
622  nPointCount += static_cast<sal_uInt32>(rPolyPoly[a].GetSize());
623  }
624 
625  if(nPointCount > 0x0000ffff)
626  {
627  OSL_FAIL("PolygonFromPolyPolygon: too many points for a single polygon (!)");
628  nPointCount = 0x0000ffff;
629  }
630 
631  tools::Polygon aRetval(static_cast<sal_uInt16>(nPointCount));
632  sal_uInt32 nAppendIndex(0);
633 
634  for(a = 0; a < rPolyPoly.Count(); a++)
635  {
636  const tools::Polygon& rCandidate = rPolyPoly[a];
637 
638  for(sal_uInt16 b(0); nAppendIndex <= nPointCount && b < rCandidate.GetSize(); b++)
639  {
640  aRetval[static_cast<sal_uInt16>(nAppendIndex++)] = rCandidate[b];
641  }
642  }
643 
644  return aRetval;
645  }
646  }
647 
648  tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon& rPolyPoly, const SwNoTextNode* pNd, bool bCorrectCrop)
649  {
650  tools::Polygon aPoly(PolygonFromPolyPolygon(rPolyPoly));
651  const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
652 
653  const SwAttrSet* pAttrSet = pNd->GetpSwAttrSet();
654  if (bCorrectCrop && pAttrSet)
655  {
656  if (pAttrSet->HasItem(RES_GRFATR_CROPGRF))
657  {
658  // Word's wrap polygon deals with a canvas which has the size of the already
659  // cropped graphic, do the opposite of correctCrop() in writerfilter/.
660  const SwCropGrf& rCrop = pAttrSet->GetCropGrf();
661  sal_Int32 nCropLeft = convertTwipToMm100(rCrop.GetLeft());
662  sal_Int32 nCropRight = convertTwipToMm100(rCrop.GetRight());
663  sal_Int32 nCropTop = convertTwipToMm100(rCrop.GetTop());
664  sal_Int32 nCropBottom = convertTwipToMm100(rCrop.GetBottom());
665  aPoly.Move(-nCropLeft, -nCropTop);
666 
667  Fraction aScaleX(rOrigSize.getWidth(), rOrigSize.getWidth() - nCropLeft - nCropRight);
668  Fraction aScaleY(rOrigSize.getHeight(), rOrigSize.getHeight() - nCropTop - nCropBottom);
669  aPoly.Scale(double(aScaleX), double(aScaleY));
670  }
671  }
672 
673  Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
674  Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
675  aPoly.Scale(double(aMapPolyX), double(aMapPolyY));
676 
677  /*
678  a) stretch right bound by 15twips
679  b) shrink bottom bound to where it would have been in word
680  c) Move it to the left by 15twips
681 
682  See the import for details
683  */
684  const Size &rSize = pNd->GetTwipSize();
685  Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
686  aMoveHack *= Fraction(15, 1);
687  tools::Long nMove(aMoveHack);
688 
689  Fraction aHackX(ww::nWrap100Percent + nMove,
691  Fraction aHackY(ww::nWrap100Percent - nMove,
693  aPoly.Scale(double(aHackX), double(aHackY));
694 
695  aPoly.Move(-nMove, 0);
696  return aPoly;
697  }
698 
699  void RedlineStack::open(const SwPosition& rPos, const SfxPoolItem& rAttr)
700  {
701  OSL_ENSURE(rAttr.Which() == RES_FLTR_REDLINE, "not a redline");
702  maStack.emplace_back(new SwFltStackEntry(rPos, std::unique_ptr<SfxPoolItem>(rAttr.Clone())));
703  }
704 
705  namespace {
706 
707  class SameOpenRedlineType
708  {
709  private:
711  public:
712  explicit SameOpenRedlineType(RedlineType eType) : meType(eType) {}
713  bool operator()(const std::unique_ptr<SwFltStackEntry> & pEntry) const
714  {
715  const SwFltRedline *pTest = static_cast<const SwFltRedline *>
716  (pEntry->pAttr.get());
717  return (pEntry->bOpen && (pTest->eType == meType));
718  }
719  };
720 
721  }
722 
723  bool RedlineStack::close(const SwPosition& rPos, RedlineType eType)
724  {
725  //Search from end for same type
726  auto aResult = std::find_if(maStack.rbegin(), maStack.rend(),
727  SameOpenRedlineType(eType));
728  if (aResult != maStack.rend())
729  {
730  SwTextNode *const pNode(rPos.nNode.GetNode().GetTextNode());
731  sal_Int32 const nIndex(rPos.nContent.GetIndex());
732  // HACK to prevent overlap of field-mark and redline,
733  // which would destroy field-mark invariants when the redline
734  // is hidden: move the redline end one to the left
735  if (pNode && nIndex > 0
736  && pNode->GetText()[nIndex - 1] == CH_TXT_ATR_FIELDEND)
737  {
738  SwPosition const end(*rPos.nNode.GetNode().GetTextNode(),
739  nIndex - 1);
740  sw::mark::IFieldmark *const pFieldMark(
742  SAL_WARN_IF(!pFieldMark, "sw.ww8", "expected a field mark");
743  if (pFieldMark && pFieldMark->GetMarkPos().nNode.GetIndex() == (*aResult)->m_aMkPos.m_nNode.GetIndex()+1
744  && pFieldMark->GetMarkPos().nContent.GetIndex() < (*aResult)->m_aMkPos.m_nContent)
745  {
746  (*aResult)->SetEndPos(end);
747  return true;
748  }
749  }
750  (*aResult)->SetEndPos(rPos);
751  return true;
752  }
753  return false;
754  }
755 
757  {
758  std::for_each(maStack.begin(), maStack.end(), SetEndIfOpen(rPos));
759  }
760 
762  {
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  bool const isPoint(rMkPos == rPtPos);
768  if ((rMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
769  (nPosCt <= rMkPos.m_nContent))
770  {
771  rMkPos.m_nContent += nInserted;
772  SAL_WARN_IF(rMkPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
773  "sw.ww8", "redline ends after end of line");
774  if (isPoint) // sigh ... important special case...
775  {
776  rPtPos.m_nContent += nInserted;
777  return;
778  }
779  }
780  // for the end position, leave it alone if it's *on* the dummy
781  // char position, that should remain *before*
782  if ((rPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
783  (nPosCt < rPtPos.m_nContent))
784  {
785  rPtPos.m_nContent += nInserted;
786  SAL_WARN_IF(rPtPos.m_nContent > rPos.nNode.GetNodes()[nPosNd]->GetContentNode()->Len(),
787  "sw.ww8", "range ends after end of line");
788  }
789  }
790 
792  {
793  for (size_t i = 0, nCnt = maStack.size(); i < nCnt; ++i)
794  {
795  SwFltStackEntry& rEntry = *maStack[i];
796  MoveAttrFieldmarkInserted(rEntry.m_aMkPos, rEntry.m_aPtPos, rPos);
797  }
798  }
799 
800  void SetInDocAndDelete::operator()(std::unique_ptr<SwFltStackEntry>& pEntry)
801  {
802  SwPaM aRegion(pEntry->m_aMkPos.m_nNode);
803  if (pEntry->MakeRegion(mrDoc, aRegion,
805  (*aRegion.GetPoint() != *aRegion.GetMark())
806  )
807  {
810  const SwFltRedline *pFltRedline = static_cast<const SwFltRedline*>
811  (pEntry->pAttr.get());
812 
813  SwRedlineData aData(pFltRedline->eType, pFltRedline->nAutorNo,
814  pFltRedline->aStamp, OUString(), nullptr);
815 
816  SwRangeRedline *const pNewRedline(new SwRangeRedline(aData, aRegion));
817  // the point node may be deleted in AppendRedline, so park
818  // the PaM somewhere safe
819  aRegion.DeleteMark();
820  *aRegion.GetPoint() = SwPosition(SwNodeIndex(mrDoc.GetNodes()));
821  mrDoc.getIDocumentRedlineAccess().AppendRedline(pNewRedline, true);
824  }
825  pEntry.reset();
826  }
827 
828  bool CompareRedlines::operator()(const std::unique_ptr<SwFltStackEntry> & pOneE,
829  const std::unique_ptr<SwFltStackEntry> & pTwoE) const
830  {
831  const SwFltRedline *pOne= static_cast<const SwFltRedline*>
832  (pOneE->pAttr.get());
833  const SwFltRedline *pTwo= static_cast<const SwFltRedline*>
834  (pTwoE->pAttr.get());
835 
836  //Return the earlier time, if two have the same time, prioritize
837  //inserts over deletes
838  if (pOne->aStamp == pTwo->aStamp)
839  return (pOne->eType == RedlineType::Insert && pTwo->eType != RedlineType::Insert);
840  else
841  return (pOne->aStamp < pTwo->aStamp);
842  }
843 
845  {
846  std::sort(maStack.begin(), maStack.end(), CompareRedlines());
847  std::for_each(maStack.begin(), maStack.end(), SetInDocAndDelete(mrDoc));
848  }
849 
850  sal_uInt16 WrtRedlineAuthor::AddName( const OUString& rNm )
851  {
852  sal_uInt16 nRet;
853  auto aIter = std::find(maAuthors.begin(), maAuthors.end(), rNm);
854  if (aIter != maAuthors.end())
855  nRet = static_cast< sal_uInt16 >(aIter - maAuthors.begin());
856  else
857  {
858  nRet = static_cast< sal_uInt16 >(maAuthors.size());
859  maAuthors.push_back(rNm);
860  }
861  return nRet;
862  }
863  }
864 
865  namespace util
866  {
868  : m_pTableNode(&rNode)
869  {
870  StartListening(rNode.GetNotifier());
871  }
872 
874  { return m_pTableNode; }
875 
877  {
878  if(rHint.GetId() == SfxHintId::Dying)
879  m_pTableNode = nullptr;
880  }
881 
883  : mbHasRoot(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
884  { }
885 
887  {
888  if (!mbHasRoot)
889  return;
890  for (auto& aTable : maTables)
891  {
892  // If already a layout exists, then the BoxFrames must recreated at this table
893  SwTableNode *pTable = aTable.first->GetTableNode();
894  OSL_ENSURE(pTable, "Why no expected table");
895  if (pTable)
896  {
897  SwFrameFormat * pFrameFormat = pTable->GetTable().GetFrameFormat();
898 
899  if (pFrameFormat != nullptr)
900  {
901  SwNodeIndex *pIndex = aTable.second;
902  pTable->DelFrames();
903  pTable->MakeOwnFrames(pIndex);
904  }
905  }
906  }
907  }
908 
910  {
911  if (!mbHasRoot)
912  return;
913  //Associate this tablenode with this after position, replace an //old
914  //node association if necessary
915  maTables.emplace(
916  std::unique_ptr<InsertedTableListener>(new InsertedTableListener(rTableNode)),
917  &(rPaM.GetPoint()->nNode));
918  }
919  }
920 
921 }
922 
923 /* 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:287
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.
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:2443
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)
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
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:2660
const SwPosition * GetMark() const
Definition: pam.hxx:209
sal_Int64 n
Definition: doc.hxx:187
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:1794
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:348
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4106
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: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
RedlineType eType
Definition: fltshell.hxx:217
SwTableNode * GetTableNode()
Definition: node.hxx:603
SwNodeType GetNodeType() const
Definition: node.hxx:145
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)
const SwTable & GetTable() const
Definition: node.hxx:501
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.
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:47
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:452
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: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:619
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:295
css::ui::LayoutSize maLayoutSize
size_t size() const
Definition: docary.hxx:84
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2813
void MakeOwnFrames(SwNodeIndex *pIdxBehind)
Creates the frms for the table node (i.e. the TabFrames).
Definition: ndtbl.cxx:2404
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:218
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:87
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:82
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: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:779
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: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:4244
ww8::ParaStyles GetParaStyles(const SwDoc &rDoc)
Get the Paragraph Styles of a SwDoc.
sal_uInt16 TotalCount() const
SwNodes & GetNodes()
Definition: doc.hxx:408
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:180
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)
const sal_uInt16 * GetRanges() const
RndStdIds
bool IsTableNode() const
Definition: node.hxx:644
void SendObjectToHell(SdrObject &rObject) const
Make Object live in the bottom drawing layer.
constexpr tools::Long getWidth() const
DateTime aStamp
Definition: fltshell.hxx:216
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:2713
no RedlineFlags
const Size & GetSize() const
const SfxPoolItem * GetCurItem() const
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1320
std::vector< Frame > Frames
STL container of Frames.
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:845
::basegfx::B2IVector maSize
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1025
Base class of the Writer document model elements.
Definition: node.hxx:80