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