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 SwNode* pAnchor = rEntry.GetAnchor().GetAnchorNode())
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// DeduplicateItems(rItems);
405 }
406
408 {
409 if (rItems.find(RES_CHRATR_WEIGHT) != rItems.end()
410 && rItems.find(RES_CHRATR_CJK_WEIGHT) != rItems.end())
411 {
412 // avoid duplicate w:b element (DOC and DOCX map Western and
413 // CJK the same - inconsistently RTF maps CJK and CTL the same?)
414 rItems.erase(rItems.find(RES_CHRATR_CJK_WEIGHT));
415 }
416 }
417
419 sal_uInt16 eType)
420 {
421 auto aIter = rItems.find(eType);
422 if (aIter != rItems.end())
423 return aIter->second;
424 return nullptr;
425 }
426
428 {
429 if (const SwCharFormat* pCharFormat = rFormat.GetCharFormat())
430 {
431 if (pCharFormat->GetAttrSet().Count())
432 {
433 SfxItemIter aIter(pCharFormat->GetAttrSet());
434 const SfxPoolItem *pItem = aIter.GetCurItem();
435 do
436 rSet.ClearItem(pItem->Which());
437 while ((pItem = aIter.NextItem()));
438 }
439 }
440 }
441
443 {
444 ww8::ParaStyles aStyles;
445 typedef ww8::ParaStyles::size_type mysizet;
446
447 const SwTextFormatColls *pColls = rDoc.GetTextFormatColls();
448 mysizet nCount = pColls ? pColls->size() : 0;
449 aStyles.reserve(nCount);
450 for (mysizet nI = 0; nI < nCount; ++nI)
451 aStyles.push_back((*pColls)[ static_cast< sal_uInt16 >(nI) ]);
452 return aStyles;
453 }
454
455 SwTextFormatColl* GetParaStyle(SwDoc &rDoc, const OUString& rName)
456 {
457 // Search first in the Doc-Styles
458 SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName(rName);
459 if (!pColl)
460 {
461 // Collection not found, try in Pool ?
462 sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
464 if (n != SAL_MAX_UINT16) // found or standard
466 }
467 return pColl;
468 }
469
470 SwCharFormat* GetCharStyle(SwDoc &rDoc, const OUString& rName)
471 {
472 SwCharFormat *pFormat = rDoc.FindCharFormatByName(rName);
473 if (!pFormat)
474 {
475 // Collection not found, try in Pool ?
476 sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
478 if (n != SAL_MAX_UINT16) // found or standard
480 }
481 return pFormat;
482 }
483
484 // #i98791# - adjust sorting algorithm
486 {
487 std::sort(rStyles.begin(), rStyles.end(), outlinecmp());
488 }
489
490 /*
491 Utility to extract FlyFormats from a document, potentially from a
492 selection.
493 */
494 ww8::Frames GetFrames(const SwDoc &rDoc, SwPaM const *pPaM /*, bool bAll*/)
495 {
496 SwPosFlyFrames aFlys(rDoc.GetAllFlyFormats(pPaM, true));
497 ww8::Frames aRet(SwPosFlyFramesToFrames(aFlys));
498 return aRet;
499 }
500
502 {
503 for (ww8::Frame & rFrame : rFrames)
504 {
505 SwFormatAnchor const& rAnchor = rFrame.GetFrameFormat().GetAnchor();
506 if (SwPosition const*const pAnchor = rAnchor.GetContentAnchor())
507 {
508 rFrame.SetPosition(*pAnchor);
509 }
510 else
511 { // these don't need to be corrected, they're not in redlines
512 assert(RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId());
513 }
514 }
515 }
516
517 ww8::Frames GetFramesInNode(const ww8::Frames &rFrames, const SwNode &rNode)
518 {
519 ww8::Frames aRet;
520 std::copy_if(rFrames.begin(), rFrames.end(),
521 std::back_inserter(aRet), anchoredto(rNode));
522 return aRet;
523 }
524
526 int nLevel)
527 {
528 if (nLevel < 0 || nLevel >= MAXLEVEL)
529 {
530 OSL_FAIL("Invalid level");
531 return nullptr;
532 }
533 return &(rRule.Get( static_cast< sal_uInt16 >(nLevel) ));
534 }
535
537 {
538 const SwNumRule *pRule = nullptr;
539 if (
540 rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
541 nullptr != (pRule = rTextNode.GetNumRule())
542 )
543 {
544 return GetNumFormatFromSwNumRuleLevel(*pRule,
545 rTextNode.GetActualListLevel());
546 }
547
548 if (
549 rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
550 nullptr != (pRule = rTextNode.GetDoc().GetOutlineNumRule())
551 )
552 {
553 return GetNumFormatFromSwNumRuleLevel(*pRule,
554 rTextNode.GetActualListLevel());
555 }
556
557 return nullptr;
558 }
559
561 {
562 return GetNormalNumRuleFromTextNode(rTextNode);
563 }
564
566 {
567 const SwNumRule *pRule = nullptr;
568
569 if (
570 rTextNode.IsNumbered() && rTextNode.IsCountedInList() &&
571 nullptr != (pRule = rTextNode.GetNumRule())
572 )
573 {
574 return pRule;
575 }
576 return nullptr;
577 }
578
580 {
581 const SwNodeIndex *pIndex = rFormat.GetContent().GetContentIdx();
582 OSL_ENSURE(pIndex, "No NodeIndex in SwFrameFormat ?, suspicious");
583 if (!pIndex)
584 return nullptr;
585 SwNodeIndex aIdx(*pIndex, 1);
586 return aIdx.GetNode().GetNoTextNode();
587 }
588
589 bool HasPageBreak(const SwNode &rNd)
590 {
591 const SvxFormatBreakItem *pBreak = nullptr;
592 if (rNd.IsTableNode() && rNd.GetTableNode())
593 {
594 const SwTable& rTable = rNd.GetTableNode()->GetTable();
595 const SwFrameFormat* pApply = rTable.GetFrameFormat();
596 OSL_ENSURE(pApply, "impossible");
597 if (pApply)
598 pBreak = &pApply->GetFormatAttr(RES_BREAK);
599 }
600 else if (const SwContentNode *pNd = rNd.GetContentNode())
601 pBreak = &pNd->GetAttr(RES_BREAK);
602
603 return pBreak && pBreak->GetBreak() == SvxBreak::PageBefore;
604 }
605
607 {
608 if(1 == rPolyPoly.Count())
609 {
610 return rPolyPoly[0];
611 }
612 else
613 {
614 // This method will now just concatenate the polygons contained
615 // in the given PolyPolygon. Anything else which might be thought of
616 // for reducing to a single polygon will just need more power and
617 // cannot create more correct results.
618 sal_uInt32 nPointCount(0);
619 sal_uInt16 a;
620
621 for(a = 0; a < rPolyPoly.Count(); a++)
622 {
623 nPointCount += static_cast<sal_uInt32>(rPolyPoly[a].GetSize());
624 }
625
626 if(nPointCount > 0x0000ffff)
627 {
628 OSL_FAIL("PolygonFromPolyPolygon: too many points for a single polygon (!)");
629 nPointCount = 0x0000ffff;
630 }
631
632 tools::Polygon aRetval(o3tl::narrowing<sal_uInt16>(nPointCount));
633 sal_uInt32 nAppendIndex(0);
634
635 for(a = 0; a < rPolyPoly.Count(); a++)
636 {
637 const tools::Polygon& rCandidate = rPolyPoly[a];
638
639 for(sal_uInt16 b(0); nAppendIndex <= nPointCount && b < rCandidate.GetSize(); b++)
640 {
641 aRetval[o3tl::narrowing<sal_uInt16>(nAppendIndex++)] = rCandidate[b];
642 }
643 }
644
645 return aRetval;
646 }
647 }
648
649 tools::Polygon CorrectWordWrapPolygonForExport(const tools::PolyPolygon& rPolyPoly, const SwNoTextNode* pNd, bool bCorrectCrop)
650 {
651 tools::Polygon aPoly(PolygonFromPolyPolygon(rPolyPoly));
652 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
653
654 const SwAttrSet* pAttrSet = pNd->GetpSwAttrSet();
655 if (bCorrectCrop && pAttrSet)
656 {
657 if (pAttrSet->HasItem(RES_GRFATR_CROPGRF))
658 {
659 // Word's wrap polygon deals with a canvas which has the size of the already
660 // cropped graphic, do the opposite of correctCrop() in writerfilter/.
661 const SwCropGrf& rCrop = pAttrSet->GetCropGrf();
662 sal_Int32 nCropLeft = convertTwipToMm100(rCrop.GetLeft());
663 sal_Int32 nCropRight = convertTwipToMm100(rCrop.GetRight());
664 sal_Int32 nCropTop = convertTwipToMm100(rCrop.GetTop());
665 sal_Int32 nCropBottom = convertTwipToMm100(rCrop.GetBottom());
666 aPoly.Move(-nCropLeft, -nCropTop);
667
668 Fraction aScaleX(rOrigSize.getWidth(), rOrigSize.getWidth() - nCropLeft - nCropRight);
669 Fraction aScaleY(rOrigSize.getHeight(), rOrigSize.getHeight() - nCropTop - nCropBottom);
670 aPoly.Scale(double(aScaleX), double(aScaleY));
671 }
672 }
673
674 Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
675 Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
676 aPoly.Scale(double(aMapPolyX), double(aMapPolyY));
677
678 /*
679 a) stretch right bound by 15twips
680 b) shrink bottom bound to where it would have been in word
681 c) Move it to the left by 15twips
682
683 See the import for details
684 */
685 const Size &rSize = pNd->GetTwipSize();
686 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
687 aMoveHack *= Fraction(15, 1);
688 tools::Long nMove(aMoveHack);
689
690 Fraction aHackX(ww::nWrap100Percent + nMove,
692 Fraction aHackY(ww::nWrap100Percent - nMove,
694 aPoly.Scale(double(aHackX), double(aHackY));
695
696 aPoly.Move(-nMove, 0);
697 return aPoly;
698 }
699
700 void RedlineStack::open(const SwPosition& rPos, const SfxPoolItem& rAttr)
701 {
702 OSL_ENSURE(rAttr.Which() == RES_FLTR_REDLINE, "not a redline");
703 maStack.emplace_back(new SwFltStackEntry(rPos, std::unique_ptr<SfxPoolItem>(rAttr.Clone())));
704 }
705
706 namespace {
707
708 class SameOpenRedlineType
709 {
710 private:
712 public:
713 explicit SameOpenRedlineType(RedlineType eType) : meType(eType) {}
714 bool operator()(const std::unique_ptr<SwFltStackEntry> & pEntry) const
715 {
716 const SwFltRedline *pTest = static_cast<const SwFltRedline *>
717 (pEntry->m_pAttr.get());
718 return (pEntry->m_bOpen && (pTest->m_eType == meType));
719 }
720 };
721
722 }
723
725 {
726 //Search from end for same type
727 auto aResult = std::find_if(maStack.rbegin(), maStack.rend(),
728 SameOpenRedlineType(eType));
729 if (aResult != maStack.rend())
730 {
731 SwTextNode *const pNode(rPos.GetNode().GetTextNode());
732 sal_Int32 const nIndex(rPos.GetContentIndex());
733 // HACK to prevent overlap of field-mark and redline,
734 // which would destroy field-mark invariants when the redline
735 // is hidden: move the redline end one to the left
736 if (pNode && nIndex > 0
737 && pNode->GetText()[nIndex - 1] == CH_TXT_ATR_FIELDEND)
738 {
739 SwPosition const end(*rPos.GetNode().GetTextNode(),
740 nIndex - 1);
741 sw::mark::IFieldmark *const pFieldMark(
743 SAL_WARN_IF(!pFieldMark, "sw.ww8", "expected a field mark");
744 if (pFieldMark && pFieldMark->GetMarkPos().GetNodeIndex() == (*aResult)->m_aMkPos.m_nNode.GetIndex()+1
745 && pFieldMark->GetMarkPos().GetContentIndex() < (*aResult)->m_aMkPos.m_nContent)
746 {
747 (*aResult)->SetEndPos(end);
748 return true;
749 }
750 }
751 (*aResult)->SetEndPos(rPos);
752 return true;
753 }
754 return false;
755 }
756
758 {
759 std::for_each(maStack.begin(), maStack.end(), SetEndIfOpen(rPos));
760 }
761
763 {
764 sal_Int32 const nInserted = 2; // CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDSEP
765 SwNodeOffset nPosNd = rPos.GetNodeIndex();
766 sal_Int32 nPosCt = rPos.GetContentIndex() - nInserted;
767
768 bool const isPoint(rMkPos == rPtPos);
769 if ((rMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
770 (nPosCt <= rMkPos.m_nContent))
771 {
772 rMkPos.m_nContent += nInserted;
773 SAL_WARN_IF(rMkPos.m_nContent > rPos.GetNodes()[nPosNd]->GetContentNode()->Len(),
774 "sw.ww8", "redline ends after end of line");
775 if (isPoint) // sigh ... important special case...
776 {
777 rPtPos.m_nContent += nInserted;
778 return;
779 }
780 }
781 // for the end position, leave it alone if it's *on* the dummy
782 // char position, that should remain *before*
783 if ((rPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
784 (nPosCt < rPtPos.m_nContent))
785 {
786 rPtPos.m_nContent += nInserted;
787 SAL_WARN_IF(rPtPos.m_nContent > rPos.GetNodes()[nPosNd]->GetContentNode()->Len(),
788 "sw.ww8", "range ends after end of line");
789 }
790 }
791
793 {
794 for (size_t i = 0, nCnt = maStack.size(); i < nCnt; ++i)
795 {
796 SwFltStackEntry& rEntry = *maStack[i];
797 MoveAttrFieldmarkInserted(rEntry.m_aMkPos, rEntry.m_aPtPos, rPos);
798 }
799 }
800
801 void SetInDocAndDelete::operator()(std::unique_ptr<SwFltStackEntry>& pEntry)
802 {
803 SwPaM aRegion(pEntry->m_aMkPos.m_nNode);
804 if (pEntry->MakeRegion(mrDoc, aRegion,
806 (*aRegion.GetPoint() != *aRegion.GetMark())
807 )
808 {
811 const SwFltRedline *pFltRedline = static_cast<const SwFltRedline*>
812 (pEntry->m_pAttr.get());
813
814 SwRedlineData aData(pFltRedline->m_eType, pFltRedline->m_nAutorNo,
815 pFltRedline->m_aStamp, OUString(), nullptr);
816
817 SwRangeRedline *const pNewRedline(new SwRangeRedline(aData, aRegion));
818 // the point node may be deleted in AppendRedline, so park
819 // the PaM somewhere safe
820 aRegion.DeleteMark();
821 aRegion.GetPoint()->Assign(*mrDoc.GetNodes()[SwNodeOffset(0)]);
822 mrDoc.getIDocumentRedlineAccess().AppendRedline(pNewRedline, true);
825 }
826 pEntry.reset();
827 }
828
829 bool CompareRedlines::operator()(const std::unique_ptr<SwFltStackEntry> & pOneE,
830 const std::unique_ptr<SwFltStackEntry> & pTwoE) const
831 {
832 const SwFltRedline *pOne= static_cast<const SwFltRedline*>
833 (pOneE->m_pAttr.get());
834 const SwFltRedline *pTwo= static_cast<const SwFltRedline*>
835 (pTwoE->m_pAttr.get());
836
837 //Return the earlier time, if two have the same time, prioritize
838 //inserts over deletes
839 if (pOne->m_aStamp == pTwo->m_aStamp)
840 return (pOne->m_eType == RedlineType::Insert && pTwo->m_eType != RedlineType::Insert);
841 else
842 return (pOne->m_aStamp < pTwo->m_aStamp);
843 }
844
846 {
847 std::stable_sort(maStack.begin(), maStack.end(), CompareRedlines());
848 std::for_each(maStack.begin(), maStack.end(), SetInDocAndDelete(mrDoc));
849 }
850
851 sal_uInt16 WrtRedlineAuthor::AddName( const OUString& rNm )
852 {
853 sal_uInt16 nRet;
854 auto aIter = std::find(maAuthors.begin(), maAuthors.end(), rNm);
855 if (aIter != maAuthors.end())
856 nRet = static_cast< sal_uInt16 >(aIter - maAuthors.begin());
857 else
858 {
859 nRet = static_cast< sal_uInt16 >(maAuthors.size());
860 maAuthors.push_back(rNm);
861 }
862 return nRet;
863 }
864 }
865
866 namespace util
867 {
869 : m_pTableNode(&rNode)
870 {
871 StartListening(rNode.GetNotifier());
872 }
873
875 { return m_pTableNode; }
876
878 {
879 if(rHint.GetId() == SfxHintId::Dying)
880 m_pTableNode = nullptr;
881 }
882
884 : mbHasRoot(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
885 { }
886
888 {
889 if (!mbHasRoot)
890 return;
891 for (auto& aTable : maTables)
892 {
893 // If already a layout exists, then the BoxFrames must recreated at this table
894 SwTableNode *pTable = aTable.first->GetTableNode();
895 OSL_ENSURE(pTable, "Why no expected table");
896 if (pTable)
897 {
898 SwFrameFormat * pFrameFormat = pTable->GetTable().GetFrameFormat();
899
900 if (pFrameFormat != nullptr)
901 {
902 SwPosition *pIndex = aTable.second;
903 pTable->DelFrames();
904 pTable->MakeOwnFrames(pIndex);
905 }
906 }
907 }
908 }
909
911 {
912 if (!mbHasRoot)
913 return;
914 //Associate this tablenode with this after position, replace an old
915 //node association if necessary
916 maTables.emplace(
917 std::unique_ptr<InsertedTableListener>(new InsertedTableListener(rTableNode)),
918 rPaM.GetPoint());
919 }
920 }
921
922}
923
924/* 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:493
Definition: doc.hxx:195
SwNumRule * GetOutlineNumRule() const
Definition: doc.hxx:1033
SwCharFormat * FindCharFormatByName(const OUString &rName) const
Definition: doc.hxx:780
SwNodes & GetNodes()
Definition: doc.hxx:418
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:343
const SwTextFormatColls * GetTextFormatColls() const
Definition: doc.hxx:787
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1874
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:434
SwPosFlyFrames GetAllFlyFormats(const SwPaM *, bool bDrawAlso, bool bAsCharAlso=false) const
Returns positions of all FlyFrames in the document.
Definition: doclay.cxx:498
SwTextFormatColl * FindTextFormatCollByName(const OUString &rName) const
Definition: doc.hxx:808
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1329
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:74
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1606
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:88
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:2742
SdrObject * FindRealSdrObject()
Definition: atrfrm.cxx:2795
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:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:897
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsTableNode() const
Definition: node.hxx:691
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwNoTextNode * GetNoTextNode()
Definition: ndnotxt.hxx:95
SwTableNode * GetTableNode()
Definition: node.hxx:650
SwNodeType GetNodeType() const
Definition: node.hxx:166
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:542
void MakeOwnFrames(SwPosition *pIdxBehind=nullptr)
Creates the frms for the table node (i.e.
Definition: ndtbl.cxx:2373
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2420
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:207
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:122
int GetAssignedOutlineStyleLevel() const
Definition: fmtcol.cxx:614
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:111
bool IsCountedInList() const
Definition: ndtxt.cxx:4385
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2919
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:4240
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2987
const OUString & GetText() const
Definition: ndtxt.hxx:242
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)
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.
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 >, SwPosition * > 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 TypedWhichId< SvxWeightItem > RES_CHRATR_WEIGHT(15)
constexpr sal_uInt16 RES_WHICHHINT_END(HINT_END)
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_CJK_WEIGHT(26)
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:182
constexpr TypedWhichId< SwCropGrf > RES_GRFATR_CROPGRF(136)
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 DeduplicateItems(ww8::PoolItems &rItems)
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
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