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