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