LibreOffice Module sw (master) 1
unoportenum.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 <utility>
24
25#include <unoport.hxx>
26#include <IMark.hxx>
27#include <crossrefbookmark.hxx>
28#include <annotationmark.hxx>
29#include <doc.hxx>
31#include <txatbase.hxx>
32#include <txtatr.hxx>
33#include <ndhints.hxx>
34#include <ndtxt.hxx>
35#include <unocrsr.hxx>
36#include <docary.hxx>
37#include <textboxhelper.hxx>
38#include <tox.hxx>
39#include <unoparaframeenum.hxx>
40#include <unocrsrhelper.hxx>
41#include <unorefmark.hxx>
42#include <unobookmark.hxx>
43#include <unofield.hxx>
44#include <unometa.hxx>
45#include <unolinebreak.hxx>
46#include <unocontentcontrol.hxx>
47#include <fmtfld.hxx>
48#include <fldbas.hxx>
49#include <fmtmeta.hxx>
50#include <fmtanchr.hxx>
51#include <fmtrfmrk.hxx>
52#include <frmfmt.hxx>
53#include <fmtflcnt.hxx>
54#include <unoidx.hxx>
55#include <unocoll.hxx>
56#include <redline.hxx>
57#include <txtannotationfld.hxx>
58#include <vcl/svapp.hxx>
59#include <comphelper/string.hxx>
62#include <com/sun/star/container/XEnumeration.hpp>
63#include <algorithm>
64#include <memory>
65#include <set>
66#include <stack>
67
68using namespace ::com::sun::star;
69using namespace ::com::sun::star::uno;
70using namespace ::com::sun::star::text;
71
72typedef std::pair< TextRangeList_t * const, SwTextAttr const * const > PortionList_t;
73typedef std::stack< PortionList_t > PortionStack_t;
74
75static void lcl_CreatePortions(
76 TextRangeList_t & i_rPortions,
77 uno::Reference< text::XText > const& i_xParentText,
78 SwUnoCursor* pUnoCursor,
79 FrameClientSortList_t & i_rFrames,
80 const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos, bool bOnlyTextFields );
81
82namespace
83{
84 enum class BkmType {
85 Start, End, StartEnd
86 };
87
88 struct SwXBookmarkPortion_Impl
89 {
90 Reference<XTextContent> xBookmark;
91 BkmType nBkmType;
92 const SwPosition aPosition;
93
94 SwXBookmarkPortion_Impl(uno::Reference<text::XTextContent> xMark,
95 const BkmType nType, SwPosition _aPosition)
96 : xBookmark (std::move( xMark ))
97 , nBkmType ( nType )
98 , aPosition (std::move( _aPosition ))
99 {
100 }
101 sal_Int32 getIndex () const
102 {
103 return aPosition.GetContentIndex();
104 }
105 };
106 typedef std::shared_ptr < SwXBookmarkPortion_Impl > SwXBookmarkPortion_ImplSharedPtr;
107 struct BookmarkCompareStruct
108 {
109 bool operator () ( const SwXBookmarkPortion_ImplSharedPtr &r1,
110 const SwXBookmarkPortion_ImplSharedPtr &r2 ) const
111 {
112 // #i16896# for bookmark portions at the same position, the start should
113 // always precede the end. Hence compare positions, and use bookmark type
114 // as tie-breaker for same position.
115 // return ( r1->nIndex == r2->nIndex )
116 // ? ( r1->nBkmType < r2->nBkmType )
117 // : ( r1->nIndex < r2->nIndex );
118
119 // Note that the above code does not correctly handle
120 // the case when one bookmark ends, and another begins in the same
121 // position. When this occurs, the above code will return the
122 // start of the 2nd bookmark BEFORE the end of the first bookmark
123 // See bug #i58438# for more details. The below code is correct and
124 // fixes both #i58438 and #i16896#
125 return r1->aPosition < r2->aPosition;
126 }
127 };
128 typedef std::multiset < SwXBookmarkPortion_ImplSharedPtr, BookmarkCompareStruct > SwXBookmarkPortion_ImplList;
129
131 void lcl_FillBookmark(sw::mark::IMark* const pBkmk, const SwNode& rOwnNode, SwDoc& rDoc, SwXBookmarkPortion_ImplList& rBkmArr)
132 {
133 bool const hasOther = pBkmk->IsExpanded();
134
135 const SwPosition& rStartPos = pBkmk->GetMarkStart();
136 if(rStartPos.GetNode() == rOwnNode)
137 {
138 // #i109272#: cross reference marks: need special handling!
139 ::sw::mark::CrossRefBookmark *const pCrossRefMark(dynamic_cast< ::sw::mark::CrossRefBookmark*>(pBkmk));
140 BkmType const nType = (hasOther || pCrossRefMark)
141 ? BkmType::Start : BkmType::StartEnd;
142 rBkmArr.insert(std::make_shared<SwXBookmarkPortion_Impl>(
143 SwXBookmark::CreateXBookmark(rDoc, pBkmk),
144 nType, rStartPos));
145 }
146
147 const SwPosition& rEndPos = pBkmk->GetMarkEnd();
148 if(rEndPos.GetNode() != rOwnNode)
149 return;
150
151 std::optional<SwPosition> oCrossRefEndPos;
152 const SwPosition* pEndPos = nullptr;
153 ::sw::mark::CrossRefBookmark *const pCrossRefMark(dynamic_cast< ::sw::mark::CrossRefBookmark*>(pBkmk));
154 if(hasOther)
155 {
156 pEndPos = &rEndPos;
157 }
158 else if (pCrossRefMark)
159 {
160 // Crossrefbookmarks only remember the start position but have to span the whole paragraph
161 SwTextNode& rEndNd = *rEndPos.GetNode().GetTextNode();
162 oCrossRefEndPos.emplace(rEndNd, rEndNd.Len());
163 pEndPos = &*oCrossRefEndPos;
164 }
165 if(pEndPos)
166 {
167 rBkmArr.insert(std::make_shared<SwXBookmarkPortion_Impl>(
168 SwXBookmark::CreateXBookmark(rDoc, pBkmk),
169 BkmType::End, *pEndPos));
170 }
171 }
172
173 void lcl_FillBookmarkArray(SwDoc& rDoc, SwUnoCursor& rUnoCursor, SwXBookmarkPortion_ImplList& rBkmArr)
174 {
175 IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
176 if(!pMarkAccess->getBookmarksCount())
177 return;
178
179 SwTextNode* pTextNode = rUnoCursor.GetPoint()->GetNode().GetTextNode();
180 assert(pTextNode);
181 // A text node already knows its marks via its SwIndexes.
183 for (const SwContentIndex* pIndex = pTextNode->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext())
184 {
185 // Need a non-cost mark here, as we'll create a UNO wrapper around it.
186 sw::mark::IMark* pBkmk = const_cast<sw::mark::IMark*>(pIndex->GetMark());
187 if (!pBkmk)
188 continue;
190 // These are the types stored in the container otherwise accessible via getBookmarks*()
193 continue;
194 // Only handle bookmarks once, if they start and end at this node as well.
195 if (!aSeenMarks.insert(pBkmk).second)
196 continue;
197 lcl_FillBookmark(pBkmk, *pTextNode, rDoc, rBkmArr);
198 }
199 }
200
201 struct SwAnnotationStartPortion_Impl
202 {
203
204 uno::Reference< text::XTextField > mxAnnotationField;
206
207 SwAnnotationStartPortion_Impl(
208 uno::Reference< text::XTextField > xAnnotationField,
209 SwPosition aPosition)
210 : mxAnnotationField (std::move( xAnnotationField ))
211 , maPosition (std::move( aPosition ))
212 {
213 }
214
215 sal_Int32 getIndex () const
216 {
217 return maPosition.GetContentIndex();
218 }
219 };
220 typedef std::shared_ptr < SwAnnotationStartPortion_Impl > SwAnnotationStartPortion_ImplSharedPtr;
221 struct AnnotationStartCompareStruct
222 {
223 bool operator () ( const SwAnnotationStartPortion_ImplSharedPtr &r1,
224 const SwAnnotationStartPortion_ImplSharedPtr &r2 )
225 const
226 {
227 return r1->maPosition < r2->maPosition;
228 }
229 };
230 typedef std::multiset < SwAnnotationStartPortion_ImplSharedPtr, AnnotationStartCompareStruct > SwAnnotationStartPortion_ImplList;
231
232 void lcl_FillAnnotationStartArray(
233 SwDoc& rDoc,
234 SwUnoCursor& rUnoCursor,
235 SwAnnotationStartPortion_ImplList& rAnnotationStartArr )
236 {
237 IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
238 if ( pMarkAccess->getAnnotationMarksCount() == 0 )
239 {
240 return;
241 }
242
243 // no need to consider annotation marks starting after aEndOfPara
244 SwContentNode& rPtNd = *rUnoCursor.GetPoint()->GetNode().GetContentNode();
245 SwPosition aEndOfPara( rPtNd, rPtNd.Len() );
246 const IDocumentMarkAccess::const_iterator_t pCandidatesEnd =
247 pMarkAccess->findFirstAnnotationStartsAfter(aEndOfPara);
248
249 // search for all annotation marks that have its start position in this paragraph
250 const SwNode& rOwnNode = rUnoCursor.GetPoint()->GetNode();
252 ppMark != pCandidatesEnd;
253 ++ppMark )
254 {
255 ::sw::mark::AnnotationMark* const pAnnotationMark =
256 dynamic_cast< ::sw::mark::AnnotationMark* >(*ppMark);
257
258 if (!pAnnotationMark)
259 continue;
260
261 const SwPosition& rStartPos = pAnnotationMark->GetMarkStart();
262 if (rStartPos.GetNode() != rOwnNode)
263 continue;
264
265 const SwFormatField* pAnnotationFormatField = pAnnotationMark->GetAnnotationFormatField();
266 if (!pAnnotationFormatField)
267 {
268 SAL_WARN("sw.core", "missing annotation format field");
269 continue;
270 }
271
272 rAnnotationStartArr.insert(
273 std::make_shared<SwAnnotationStartPortion_Impl>(
275 pAnnotationFormatField),
276 rStartPos));
277 }
278 }
279}
280
282{
283 return "SwXTextPortionEnumeration";
284}
285
288{
289 return cppu::supportsService(this, rServiceName);
290}
291
293{
294 return { "com.sun.star.text.TextPortionEnumeration" };
295}
296
298 SwPaM& rParaCursor,
299 uno::Reference< XText > const & xParentText,
300 const sal_Int32 nStart,
301 const sal_Int32 nEnd,
302 bool bOnlyTextFields)
303{
304 m_pUnoCursor = rParaCursor.GetDoc().CreateUnoCursor(*rParaCursor.GetPoint());
305
306 OSL_ENSURE(nEnd == -1 || (nStart <= nEnd &&
307 nEnd <= m_pUnoCursor->Start()->GetNode().GetTextNode()->GetText().getLength()),
308 "start or end value invalid!");
309
310 // find all frames, graphics and OLEs that are bound AT character in para
313 lcl_CreatePortions(m_Portions, xParentText, &*m_pUnoCursor, frames, nStart, nEnd, bOnlyTextFields);
314}
315
317 SwPaM& rParaCursor,
318 TextRangeList_t && rPortions )
319 : m_Portions( std::move(rPortions) )
320{
321 m_pUnoCursor = rParaCursor.GetDoc().CreateUnoCursor(*rParaCursor.GetPoint());
322}
323
325{
326 SolarMutexGuard aGuard;
327 if( m_pUnoCursor )
328 {
330 m_pUnoCursor.reset(nullptr);
331 }
332}
333
335{
336 SolarMutexGuard aGuard;
337
338 return !m_Portions.empty();
339}
340
342{
343 SolarMutexGuard aGuard;
344
345 if (m_Portions.empty())
346 throw container::NoSuchElementException();
347
348 Any any;
349 any <<= m_Portions.front();
350 m_Portions.pop_front();
351 return any;
352}
353
354static void
355lcl_FillFieldMarkArray(std::deque<sal_Int32> & rFieldMarks, SwUnoCursor const & rUnoCursor,
356 const sal_Int32 i_nStartPos)
357{
358 const SwTextNode * const pTextNode =
359 rUnoCursor.GetPoint()->GetNode().GetTextNode();
360 if (!pTextNode) return;
361
362 const sal_Unicode fld[] = {
364 sal_Int32 pos = std::max(static_cast<sal_Int32>(0), i_nStartPos);
365 while ((pos = ::comphelper::string::indexOfAny(pTextNode->GetText(), fld, pos)) != -1)
366 {
367 rFieldMarks.push_back(pos);
368 ++pos;
369 }
370}
371
372static uno::Reference<text::XTextRange>
374 uno::Reference< text::XText > const & i_xParentText,
375 SwUnoCursor * const pUnoCursor,
376 const SwTextNode * const pTextNode )
377{
378 uno::Reference<text::XTextRange> xRef;
379 SwDoc& rDoc = pUnoCursor->GetDoc();
380 // maybe it's a good idea to add a special hint to the hints array and rely on the hint segmentation...
381 const sal_Int32 start = pUnoCursor->Start()->GetContentIndex();
382 OSL_ENSURE(pUnoCursor->End()->GetContentIndex() == start,
383 "hmm --- why is this different");
384
385 pUnoCursor->Right(1);
386 if ( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
387 {
388 OSL_FAIL("cannot move cursor?");
389 return nullptr;
390 }
391
392 const sal_Unicode Char = pTextNode->GetText()[start];
394 {
395 ::sw::mark::IFieldmark* pFieldmark = nullptr;
396 pFieldmark = rDoc.getIDocumentMarkAccess()->
397 getFieldmarkAt(*pUnoCursor->GetMark());
399 pUnoCursor, i_xParentText, PORTION_FIELD_START);
400 xRef = pPortion;
401 if (pFieldmark)
402 {
403 pPortion->SetBookmark(
404 SwXFieldmark::CreateXFieldmark(rDoc, pFieldmark));
405 }
406 }
407 else if (CH_TXT_ATR_FIELDSEP == Char)
408 {
409 // TODO how to get the field?
410 xRef = new SwXTextPortion(
411 pUnoCursor, i_xParentText, PORTION_FIELD_SEP);
412 }
413 else if (CH_TXT_ATR_FIELDEND == Char)
414 {
415 ::sw::mark::IFieldmark* pFieldmark = nullptr;
416 pFieldmark = rDoc.getIDocumentMarkAccess()->
417 getFieldmarkAt(*pUnoCursor->GetMark());
419 pUnoCursor, i_xParentText, PORTION_FIELD_END);
420 xRef = pPortion;
421 if (pFieldmark)
422 {
423 pPortion->SetBookmark(
424 SwXFieldmark::CreateXFieldmark(rDoc, pFieldmark));
425 }
426 }
427 else if (CH_TXT_ATR_FORMELEMENT == Char)
428 {
429 ::sw::mark::IFieldmark* pFieldmark =
430 rDoc.getIDocumentMarkAccess()->getFieldmarkAt(*pUnoCursor->GetMark());
432 pUnoCursor, i_xParentText, PORTION_FIELD_START_END);
433 xRef = pPortion;
434 if (pFieldmark)
435 {
436 pPortion->SetBookmark(
437 SwXFieldmark::CreateXFieldmark(rDoc, pFieldmark));
438 }
439 }
440 else
441 {
442 OSL_FAIL("no fieldmark found?");
443 }
444 return xRef;
445}
446
447static Reference<XTextRange>
449 Reference<XText> const& xParent,
450 const SwUnoCursor * const pUnoCursor,
451 const SwTextAttr & rAttr, const bool bEnd)
452{
453 SwDoc& rDoc = pUnoCursor->GetDoc();
454 SwFormatRefMark& rRefMark = const_cast<SwFormatRefMark&>(
455 static_cast<const SwFormatRefMark&>(rAttr.GetAttr()));
456 Reference<XTextContent> xContent;
457 if (!xContent.is())
458 {
459 xContent = SwXReferenceMark::CreateXReferenceMark(rDoc, &rRefMark);
460 }
461
463 if (!bEnd)
464 {
465 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_REFMARK_START);
466 pPortion->SetRefMark(xContent);
467 pPortion->SetCollapsed(rAttr.End() == nullptr);
468 }
469 else
470 {
471 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_REFMARK_END);
472 pPortion->SetRefMark(xContent);
473 }
474 return pPortion;
475}
476
477static void
479 TextRangeList_t & rPortions,
480 Reference<XText> const& xParent,
481 const SwUnoCursor * const pUnoCursor,
482 const SwTextAttr & rAttr, const bool bEnd)
483{
484 rtl::Reference<SwXTextPortion> pPortion = new SwXTextPortion(pUnoCursor,
485 static_txtattr_cast<const SwTextRuby&>(rAttr), xParent, bEnd);
486 rPortions.emplace_back(pPortion);
487 pPortion->SetCollapsed(rAttr.End() == nullptr);
488}
489
490static Reference<XTextRange>
492 Reference<XText> const& xParent,
493 const SwUnoCursor * const pUnoCursor,
494 SwTextAttr & rAttr, const bool bEnd)
495{
496 SwDoc& rDoc = pUnoCursor->GetDoc();
497 SwTOXMark & rTOXMark = static_cast<SwTOXMark&>(rAttr.GetAttr());
498
499 const Reference<XTextContent> xContent =
501
503 if (!bEnd)
504 {
505 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_TOXMARK_START);
506 pPortion->SetTOXMark(xContent);
507 pPortion->SetCollapsed(rAttr.GetEnd() == nullptr);
508 }
509 else
510 {
511 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_TOXMARK_END);
512 pPortion->SetTOXMark(xContent);
513 }
514 return pPortion;
515}
516
517static uno::Reference<text::XTextRange>
519 uno::Reference<text::XText> const& xParent,
520 const SwUnoCursor * const pUnoCursor,
521 SwTextAttr & rAttr, std::unique_ptr<TextRangeList_t const> && pPortions)
522{
523 const uno::Reference<rdf::XMetadatable> xMeta( SwXMeta::CreateXMeta(
524 *static_cast<SwFormatMeta &>(rAttr.GetAttr()).GetMeta(),
525 xParent, std::move(pPortions)));
527 if (RES_TXTATR_META == rAttr.Which())
528 {
529 const uno::Reference<text::XTextContent> xContent(xMeta,
530 uno::UNO_QUERY);
531 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_META);
532 pPortion->SetMeta(xContent);
533 }
534 else
535 {
536 const uno::Reference<text::XTextField> xField(xMeta, uno::UNO_QUERY);
537 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_FIELD);
538 pPortion->SetTextField(xField);
539 }
540 return pPortion;
541}
542
544static uno::Reference<text::XTextRange>
545lcl_CreateContentControlPortion(const uno::Reference<text::XText>& xParent,
546 const SwUnoCursor* pUnoCursor, SwTextAttr& rAttr,
547 std::unique_ptr<const TextRangeList_t>&& pPortions)
548{
549 uno::Reference<text::XTextContent> xContentControl = SwXContentControl::CreateXContentControl(
550 *static_cast<SwFormatContentControl&>(rAttr.GetAttr()).GetContentControl(), xParent,
551 std::move(pPortions));
553 pPortion = new SwXTextPortion(pUnoCursor, xParent, PORTION_CONTENT_CONTROL);
554 pPortion->SetContentControl(xContentControl);
555 return pPortion;
556}
557
573 TextRangeList_t & rPortions,
574 Reference<XText> const& xParent,
575 const SwUnoCursor * const pUnoCursor,
576 SwXBookmarkPortion_ImplList& rBkmArr,
577 const sal_Int32 nIndex,
578 const o3tl::sorted_vector<sal_Int32>& rFramePositions,
579 bool bOnlyFrameStarts)
580{
581 for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end(); aIter != aEnd; )
582 {
583 const SwXBookmarkPortion_ImplSharedPtr& pPtr = *aIter;
584 if ( nIndex > pPtr->getIndex() )
585 {
586 if (bOnlyFrameStarts)
587 ++aIter;
588 else
589 aIter = rBkmArr.erase(aIter);
590 continue;
591 }
592 if ( nIndex < pPtr->getIndex() )
593 break;
594
595 if ((BkmType::Start == pPtr->nBkmType && bOnlyFrameStarts) ||
596 (BkmType::StartEnd == pPtr->nBkmType))
597 {
598 bool bFrameStart = rFramePositions.find(nIndex) != rFramePositions.end();
599 bool bEnd = pPtr->nBkmType == BkmType::StartEnd && bFrameStart && !bOnlyFrameStarts;
600 if (pPtr->nBkmType == BkmType::Start || bFrameStart || !bOnlyFrameStarts)
601 {
602 // At this we create a text portion, due to one of these
603 // reasons:
604 // - this is the real start of a non-collapsed bookmark
605 // - this is the real position of a collapsed bookmark
606 // - this is the start or end (depending on bOnlyFrameStarts)
607 // of a collapsed bookmark at the same position as an at-char
608 // anchored frame
610 new SwXTextPortion(pUnoCursor, xParent, bEnd ? PORTION_BOOKMARK_END : PORTION_BOOKMARK_START);
611 rPortions.emplace_back(pPortion);
612 pPortion->SetBookmark(pPtr->xBookmark);
613 pPortion->SetCollapsed( BkmType::StartEnd == pPtr->nBkmType && !bFrameStart );
614 }
615 }
616 else if (BkmType::End == pPtr->nBkmType && !bOnlyFrameStarts)
617 {
619 new SwXTextPortion(pUnoCursor, xParent, PORTION_BOOKMARK_END);
620 rPortions.emplace_back(pPortion);
621 pPortion->SetBookmark(pPtr->xBookmark);
622 }
623
624 // next bookmark
625 if (bOnlyFrameStarts)
626 ++aIter;
627 else
628 aIter = rBkmArr.erase(aIter);
629 }
630}
631
633 TextRangeList_t & rPortions,
634 Reference<XText> const& xParent,
635 const SwUnoCursor * const pUnoCursor,
636 SwSoftPageBreakList& rBreakArr,
637 const sal_Int32 nIndex)
638{
639 for ( auto aIter = rBreakArr.begin(); aIter != rBreakArr.end(); )
640 {
641 if ( nIndex > *aIter )
642 {
643 aIter = rBreakArr.erase(aIter);
644 continue;
645 }
646 if ( nIndex < *aIter )
647 break;
648
649 rPortions.push_back(
650 new SwXTextPortion(pUnoCursor, xParent, PORTION_SOFT_PAGEBREAK) );
651 aIter = rBreakArr.erase(aIter);
652 }
653}
654
655namespace {
656
657struct SwXRedlinePortion_Impl
658{
659 const SwRangeRedline* m_pRedline;
660 const bool m_bStart;
661
662 SwXRedlinePortion_Impl ( const SwRangeRedline* pRed, const bool bIsStart )
663 : m_pRedline(pRed)
664 , m_bStart(bIsStart)
665 {
666 }
667
668 sal_Int32 getRealIndex () const
669 {
670 return m_bStart ? m_pRedline->Start()->GetContentIndex()
671 : m_pRedline->End() ->GetContentIndex();
672 }
673};
674
675}
676
677typedef std::shared_ptr < SwXRedlinePortion_Impl >
679
680namespace {
681
682struct RedlineCompareStruct
683{
684 static const SwPosition& getPosition ( const SwXRedlinePortion_ImplSharedPtr &r )
685 {
686 return *(r->m_bStart ? r->m_pRedline->Start() : r->m_pRedline->End());
687 }
688
689 bool operator () ( const SwXRedlinePortion_ImplSharedPtr &r1,
690 const SwXRedlinePortion_ImplSharedPtr &r2 ) const
691 {
692 return getPosition ( r1 ) < getPosition ( r2 );
693 }
694};
695
696}
697
698typedef std::multiset < SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct >
700
701static Reference<XTextRange>
703 PortionStack_t & rPortionStack,
704 const Reference<XText> & xParent,
705 SwUnoCursor * const pUnoCursor,
706 SwpHints const * const pHints,
707 const sal_Int32 i_nStartPos,
708 const sal_Int32 i_nEndPos,
709 const sal_Int32 nCurrentIndex,
710 const bool bRightMoveForbidden,
711 bool & o_rbCursorMoved,
712 sal_Int32 & o_rNextAttrPosition)
713{
714 // if the attribute has a dummy character, then xRef is set (except META and CONTENT_CONTROL)
715 // otherwise, the portion for the attribute is inserted into rPortions!
716 Reference<XTextRange> xRef;
717 SwDoc& rDoc = pUnoCursor->GetDoc();
718 //search for special text attributes - first some ends
719 size_t nEndIndex = 0;
720 const auto nHintsCount = pHints->Count();
721 for (;;)
722 {
723 if (nEndIndex >= nHintsCount)
724 break;
725 SwTextAttr * const pAttr = pHints->GetSortedByEnd(nEndIndex);
726 const sal_Int32* pAttrEnd = pAttr->GetEnd();
727 sal_Int32 nNextEnd = 0;
728 if (pAttrEnd &&
729 nCurrentIndex < (nNextEnd = (*pAttrEnd)))
730 break;
731 if(pAttrEnd)
732 {
733 if (nNextEnd == nCurrentIndex)
734 {
735 const sal_uInt16 nWhich( pAttr->Which() );
736 switch (nWhich)
737 {
739 {
740 Reference<XTextRange> xTmp = lcl_CreateTOXMarkPortion(
741 xParent, pUnoCursor, *pAttr, true);
742 rPortionStack.top().first->push_back(xTmp);
743 }
744 break;
746 {
747 Reference<XTextRange> xTmp = lcl_CreateRefMarkPortion(
748 xParent, pUnoCursor, *pAttr, true);
749 rPortionStack.top().first->push_back(xTmp);
750 }
751 break;
753 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
754 if( *pAttr->GetEnd() == pAttr->GetStart())
755 {
756 lcl_InsertRubyPortion( *rPortionStack.top().first,
757 xParent, pUnoCursor, *pAttr, false);
758 }
759 lcl_InsertRubyPortion( *rPortionStack.top().first,
760 xParent, pUnoCursor, *pAttr, true);
761 break;
762 case RES_TXTATR_META:
764 {
765 OSL_ENSURE(pAttr->GetStart() != *pAttr->GetEnd(),
766 "empty meta?");
767 if ((i_nStartPos > 0) &&
768 (pAttr->GetStart() < i_nStartPos))
769 {
770 // force skip pAttr and rest of attribute ends
771 // at nCurrentIndex
772 // because they are not contained in the meta pAttr
773 // and the meta pAttr itself is outside selection!
774 // (necessary for SwXMeta::createEnumeration)
775 if (pAttr->GetStart() + 1 == i_nStartPos)
776 {
777 nEndIndex = pHints->Count() - 1;
778 }
779 break;
780 }
781 PortionList_t Top = rPortionStack.top();
782 if (Top.second != pAttr)
783 {
784 OSL_FAIL("ExportHints: stack error" );
785 }
786 else
787 {
788 std::unique_ptr<const TextRangeList_t>
789 pCurrentPortions(Top.first);
790 rPortionStack.pop();
791 const uno::Reference<text::XTextRange> xPortion(
792 lcl_CreateMetaPortion(xParent, pUnoCursor,
793 *pAttr, std::move(pCurrentPortions)));
794 rPortionStack.top().first->push_back(xPortion);
795 }
796 }
797 break;
799 {
800 if (pAttr->GetStart() == *pAttr->GetEnd())
801 {
802 SAL_WARN("sw.core", "lcl_ExportHints: empty content control");
803 }
804 if ((i_nStartPos > 0) && (pAttr->GetStart() < i_nStartPos))
805 {
806 // If the start pos is the start of the content of the content control,
807 // skip it: it'll be handled in SwXContentControl::createEnumeration().
808 if (pAttr->GetStart() + 1 == i_nStartPos)
809 {
810 nEndIndex = pHints->Count() - 1;
811 }
812 break;
813 }
814 PortionList_t Top = rPortionStack.top();
815 if (Top.second != pAttr)
816 {
817 SAL_WARN("sw.core", "lcl_ExportHints: content control is not at the "
818 "top of the portion stack");
819 }
820 else
821 {
822 std::unique_ptr<const TextRangeList_t> pCurrentPortions(Top.first);
823 rPortionStack.pop();
824 uno::Reference<text::XTextRange> xPortion(
825 lcl_CreateContentControlPortion(xParent, pUnoCursor, *pAttr,
826 std::move(pCurrentPortions)));
827 rPortionStack.top().first->push_back(xPortion);
828 }
829 }
830 break;
831 }
832 }
833 }
834 nEndIndex++;
835 }
836
837 // then some starts
838 size_t nStartIndex = 0;
839 sal_Int32 nNextStart = 0;
840 while(nStartIndex < nHintsCount &&
841 nCurrentIndex >= (nNextStart = pHints->Get(nStartIndex)->GetStart()))
842 {
843 SwTextAttr * const pAttr = pHints->Get(nStartIndex);
844 sal_uInt16 nAttrWhich = pAttr->Which();
845 if (nNextStart == nCurrentIndex)
846 {
847 switch( nAttrWhich )
848 {
849 case RES_TXTATR_FIELD:
850 if(!bRightMoveForbidden)
851 {
852 pUnoCursor->Right(1);
853 if( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
854 break;
856 new SwXTextPortion(
857 pUnoCursor, xParent, PORTION_FIELD);
858 xRef = pPortion;
859 Reference<XTextField> const xField =
861 &pAttr->GetFormatField());
862 pPortion->SetTextField(xField);
863 }
864 break;
865
867 if(!bRightMoveForbidden)
868 {
869 pUnoCursor->Right(1);
870 if( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
871 break;
872
873 const SwTextAnnotationField* pTextAnnotationField = dynamic_cast<const SwTextAnnotationField*>( pAttr );
874 ::sw::mark::IMark* pAnnotationMark = pTextAnnotationField ? pTextAnnotationField->GetAnnotationMark() : nullptr;
875 if ( pAnnotationMark != nullptr )
876 {
877 rtl::Reference<SwXTextPortion> pPortion = new SwXTextPortion( pUnoCursor, xParent, PORTION_ANNOTATION_END );
878 pPortion->SetBookmark(SwXBookmark::CreateXBookmark(
879 rDoc, pAnnotationMark));
880 xRef = pPortion;
881 }
882 else
883 {
884 rtl::Reference<SwXTextPortion> pPortion = new SwXTextPortion( pUnoCursor, xParent, PORTION_ANNOTATION );
885 Reference<XTextField> xField =
887 &pAttr->GetFormatField());
888 pPortion->SetTextField(xField);
889 xRef = pPortion;
890 }
891 }
892 break;
893
895 if(!bRightMoveForbidden)
896 {
897
898 pUnoCursor->Right(
899 pAttr->GetFormatField().GetField()->ExpandField(true, nullptr).getLength() + 2 );
900 if( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
901 break;
903 new SwXTextPortion( pUnoCursor, xParent, PORTION_FIELD);
904 xRef = pPortion;
905 Reference<XTextField> xField =
907 &pAttr->GetFormatField());
908 pPortion->SetTextField(xField);
909 }
910 break;
911
913 if(!bRightMoveForbidden)
914 {
915 pUnoCursor->Right(1);
916 if( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
917 break; // Robust #i81708# content in covered cells
918
919 // Do not expose inline anchored textboxes.
921 break;
922
923 pUnoCursor->Exchange();
924 xRef = new SwXTextPortion( pUnoCursor, xParent, PORTION_FRAME);
925 }
926 break;
927
928 case RES_TXTATR_FTN:
929 {
930 if(!bRightMoveForbidden)
931 {
932 pUnoCursor->Right(1);
933 if( *pUnoCursor->GetMark() == *pUnoCursor->GetPoint() )
934 break;
936 pUnoCursor, xParent, PORTION_FOOTNOTE);
937 xRef = pPortion;
938 Reference<XFootnote> xContent =
939 SwXFootnotes::GetObject(rDoc, pAttr->GetFootnote());
940 pPortion->SetFootnote(xContent);
941 }
942 }
943 break;
944
947 {
948 bool bIsPoint = !(pAttr->GetEnd());
949 if (!bRightMoveForbidden || !bIsPoint)
950 {
951 if (bIsPoint)
952 {
953 pUnoCursor->Right(1);
954 }
955 Reference<XTextRange> xTmp =
956 (RES_TXTATR_REFMARK == nAttrWhich)
958 xParent, pUnoCursor, *pAttr, false)
960 xParent, pUnoCursor, *pAttr, false);
961 if (bIsPoint) // consume CH_TXTATR!
962 {
963 pUnoCursor->Normalize(false);
964 pUnoCursor->DeleteMark();
965 xRef = xTmp;
966 }
967 else // just insert it
968 {
969 rPortionStack.top().first->push_back(xTmp);
970 }
971 }
972 }
973 break;
975 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
976 if(pAttr->GetEnd() && (*pAttr->GetEnd() != pAttr->GetStart()))
977 {
978 lcl_InsertRubyPortion( *rPortionStack.top().first,
979 xParent, pUnoCursor, *pAttr, false);
980 }
981 break;
982 case RES_TXTATR_META:
985 if (pAttr->GetStart() != *pAttr->GetEnd())
986 {
987 if (!bRightMoveForbidden)
988 {
989 pUnoCursor->Right(1);
990 o_rbCursorMoved = true;
991 // only if the end is included in selection!
992 if ((i_nEndPos < 0) ||
993 (*pAttr->GetEnd() <= i_nEndPos))
994 {
995 rPortionStack.push( std::make_pair(
996 new TextRangeList_t, pAttr ));
997 }
998 }
999 }
1000 break;
1002 if (!bRightMoveForbidden)
1003 {
1004 pUnoCursor->Right(1);
1005 if (*pUnoCursor->GetMark() == *pUnoCursor->GetPoint())
1006 break;
1008 = new SwXTextPortion(pUnoCursor, xParent, PORTION_LINEBREAK);
1009 xRef = pPortion;
1010 uno::Reference<text::XTextContent> xLineBreak
1012 &const_cast<SwFormatLineBreak&>(pAttr->GetLineBreak()));
1013 pPortion->SetLineBreak(xLineBreak);
1014 }
1015 break;
1016 case RES_TXTATR_AUTOFMT:
1017 case RES_TXTATR_INETFMT:
1018 case RES_TXTATR_CHARFMT:
1019 break; // these are handled as properties of a "Text" portion
1020 default:
1021 OSL_FAIL("unknown attribute");
1022 break;
1023 }
1024 }
1025 nStartIndex++;
1026 }
1027
1028 if (xRef.is()) // implies that we have moved the cursor
1029 {
1030 o_rbCursorMoved = true;
1031 }
1032 if (!o_rbCursorMoved)
1033 {
1034 // search for attribute changes behind the current cursor position
1035 // break up at frames, bookmarks, redlines
1036
1037 nStartIndex = 0;
1038 nNextStart = 0;
1039 while(nStartIndex < pHints->Count() &&
1040 nCurrentIndex >= (nNextStart = pHints->Get(nStartIndex)->GetStart()))
1041 nStartIndex++;
1042
1043 nEndIndex = 0;
1044 sal_Int32 nNextEnd = 0;
1045 while(nEndIndex < pHints->Count() &&
1046 nCurrentIndex >= (nNextEnd = pHints->GetSortedByEnd(nEndIndex)->GetAnyEnd()))
1047 nEndIndex++;
1048
1049 sal_Int32 nNextPos =
1050 ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
1051 ? nNextStart : nNextEnd;
1052 if (nNextPos > nCurrentIndex)
1053 {
1054 o_rNextAttrPosition = nNextPos;
1055 }
1056 }
1057 return xRef;
1058}
1059
1060static void lcl_MoveCursor( SwUnoCursor * const pUnoCursor,
1061 const sal_Int32 nCurrentIndex,
1062 const sal_Int32 nNextFrameIndex,
1063 const sal_Int32 nNextPortionIndex,
1064 const sal_Int32 nNextAttrIndex,
1065 const sal_Int32 nNextMarkIndex,
1066 const sal_Int32 nEndPos )
1067{
1068 sal_Int32 nMovePos = pUnoCursor->GetPointContentNode()->Len();
1069
1070 if ((nEndPos >= 0) && (nEndPos < nMovePos))
1071 {
1072 nMovePos = nEndPos;
1073 }
1074
1075 if ((nNextFrameIndex >= 0) && (nNextFrameIndex < nMovePos))
1076 {
1077 nMovePos = nNextFrameIndex;
1078 }
1079
1080 if ((nNextPortionIndex >= 0) && (nNextPortionIndex < nMovePos))
1081 {
1082 nMovePos = nNextPortionIndex;
1083 }
1084
1085 if ((nNextAttrIndex >= 0) && (nNextAttrIndex < nMovePos))
1086 {
1087 nMovePos = nNextAttrIndex;
1088 }
1089
1090 if ((nNextMarkIndex >= 0) && (nNextMarkIndex < nMovePos))
1091 {
1092 nMovePos = nNextMarkIndex;
1093 }
1094
1095 if (nMovePos > nCurrentIndex)
1096 {
1097 pUnoCursor->GetPoint()->SetContent( nMovePos );
1098 }
1099}
1100
1102 SwDoc const & rDoc,
1103 SwUnoCursor const & rUnoCursor,
1105{
1106 const SwRedlineTable& rRedTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
1107 const size_t nRedTableCount = rRedTable.size();
1108
1109 if ( nRedTableCount <= 0 )
1110 return;
1111
1112 const SwPosition* pStart = rUnoCursor.GetPoint();
1113 const SwNode& rOwnNode = pStart->GetNode();
1114
1115 SwRedlineTable::size_type nRed = rDoc.getIDocumentRedlineAccess().GetRedlinePos(rOwnNode, RedlineType::Any);
1116 for(; nRed < nRedTableCount; ++nRed)
1117 {
1118 const SwRangeRedline* pRedline = rRedTable[nRed];
1119 auto [pRedStart, pRedEnd]= pRedline->StartEnd();
1120 if ( rOwnNode == pRedStart->GetNode() )
1121 rRedArr.insert( std::make_shared<SwXRedlinePortion_Impl>(
1122 pRedline, true ) );
1123 if( pRedline->HasMark() && pRedEnd->GetNode() == rOwnNode )
1124 rRedArr.insert( std::make_shared<SwXRedlinePortion_Impl>(
1125 pRedline, false ) );
1126 }
1127}
1128
1130 SwUnoCursor const & rUnoCursor,
1131 SwSoftPageBreakList& rBreakArr )
1132{
1133 const SwTextNode *pTextNode =
1134 rUnoCursor.GetPoint()->GetNode().GetTextNode();
1135 if( pTextNode )
1136 pTextNode->fillSoftPageBreakList( rBreakArr );
1137}
1138
1140 TextRangeList_t & rPortions,
1141 Reference<XText> const& xParent,
1142 const SwUnoCursor * const pUnoCursor,
1143 SwXRedlinePortion_ImplList& rRedlineArr,
1144 const sal_Int32 nIndex)
1145{
1146
1147 // We want this loop to iterate over all red lines in this
1148 // array. We will only insert the ones with index matches
1149 for ( SwXRedlinePortion_ImplList::iterator aIter = rRedlineArr.begin(), aEnd = rRedlineArr.end();
1150 aIter != aEnd; )
1151 {
1152 SwXRedlinePortion_ImplSharedPtr pPtr = *aIter;
1153 sal_Int32 nRealIndex = pPtr->getRealIndex();
1154 // If there are elements before nIndex, remove them
1155 if ( nIndex > nRealIndex )
1156 aIter = rRedlineArr.erase(aIter);
1157 // If the elements match, and them to the list
1158 else if ( nIndex == nRealIndex )
1159 {
1160 rPortions.push_back( new SwXRedlinePortion(
1161 *pPtr->m_pRedline, pUnoCursor, xParent, pPtr->m_bStart));
1162 aIter = rRedlineArr.erase(aIter);
1163 }
1164 // If we've iterated past nIndex, exit the loop
1165 else
1166 break;
1167 }
1168}
1169
1171 TextRangeList_t & rPortions,
1172 Reference<XText> const & xParent,
1173 const SwUnoCursor * const pUnoCursor,
1174 SwXBookmarkPortion_ImplList& rBkmArr,
1175 SwXRedlinePortion_ImplList& rRedlineArr,
1176 SwSoftPageBreakList& rBreakArr,
1177 const sal_Int32 nIndex,
1178 const o3tl::sorted_vector<sal_Int32>& rFramePositions,
1179 bool bOnlyFrameBookmarkStarts)
1180{
1181 if (!rBkmArr.empty())
1182 lcl_ExportBookmark(rPortions, xParent, pUnoCursor, rBkmArr, nIndex, rFramePositions,
1183 bOnlyFrameBookmarkStarts);
1184
1185 if (bOnlyFrameBookmarkStarts)
1186 // Only exporting the start of some collapsed bookmarks: no export of
1187 // other arrays.
1188 return;
1189
1190 if (!rRedlineArr.empty())
1191 lcl_ExportRedline(rPortions, xParent, pUnoCursor, rRedlineArr, nIndex);
1192
1193 if (!rBreakArr.empty())
1194 lcl_ExportSoftPageBreak(rPortions, xParent, pUnoCursor, rBreakArr, nIndex);
1195}
1196
1209 TextRangeList_t & rPortions,
1210 Reference<XText> const & xParent,
1211 const SwUnoCursor * const pUnoCursor,
1212 SwAnnotationStartPortion_ImplList& rAnnotationStartArr,
1213 const sal_Int32 nIndex,
1214 const o3tl::sorted_vector<sal_Int32>& rFramePositions,
1215 bool bOnlyFrame)
1216{
1217 for ( SwAnnotationStartPortion_ImplList::iterator aIter = rAnnotationStartArr.begin(), aEnd = rAnnotationStartArr.end();
1218 aIter != aEnd; )
1219 {
1220 SwAnnotationStartPortion_ImplSharedPtr pPtr = *aIter;
1221 if ( nIndex > pPtr->getIndex() )
1222 {
1223 aIter = rAnnotationStartArr.erase(aIter);
1224 continue;
1225 }
1226 if ( pPtr->getIndex() > nIndex )
1227 {
1228 break;
1229 }
1230
1231 bool bFrameStart = rFramePositions.find(nIndex) != rFramePositions.end();
1232 if (bFrameStart || !bOnlyFrame)
1233 {
1235 new SwXTextPortion( pUnoCursor, xParent, PORTION_ANNOTATION );
1236 pPortion->SetTextField( pPtr->mxAnnotationField );
1237 rPortions.emplace_back(pPortion);
1238
1239 aIter = rAnnotationStartArr.erase(aIter);
1240 }
1241 else
1242 ++aIter;
1243 }
1244}
1245
1247static void lcl_ExtractFramePositions(FrameClientSortList_t& rFrames, sal_Int32 nCurrentIndex,
1248 o3tl::sorted_vector<sal_Int32>& rFramePositions)
1249{
1250 for (const auto& rFrame : rFrames)
1251 {
1252 if (rFrame.nIndex < nCurrentIndex)
1253 continue;
1254
1255 if (rFrame.nIndex > nCurrentIndex)
1256 break;
1257
1258 const auto pFrame = static_cast<const SwFrameFormat*>(rFrame.pFrameClient->GetRegisteredIn());
1259 if (!pFrame)
1260 continue;
1261
1262 auto& rFormat = *const_cast<SwFrameFormat*>(pFrame);
1263 const SwFormatAnchor& rAnchor = rFormat.GetAnchor();
1264 if (!rAnchor.GetAnchorNode())
1265 continue;
1266
1267 rFramePositions.insert(rAnchor.GetAnchorContentOffset());
1268 }
1269}
1270
1277static sal_Int32 lcl_ExportFrames(
1278 TextRangeList_t & rPortions,
1279 Reference<XText> const & i_xParent,
1280 SwUnoCursor const * const i_pUnoCursor,
1281 FrameClientSortList_t & i_rFrames,
1282 sal_Int32 const i_nCurrentIndex)
1283{
1284 // Ignore frames which are not exported, as we are exporting a selection
1285 // and they are anchored before the start of the selection.
1286 while (!i_rFrames.empty() && i_rFrames.front().nIndex < i_nCurrentIndex)
1287 i_rFrames.pop_front();
1288
1289 // find first Frame in (sorted) i_rFrames at current position
1290 while (!i_rFrames.empty() && (i_rFrames.front().nIndex == i_nCurrentIndex))
1291 // do not check for i_nEnd here; this is done implicitly by lcl_MoveCursor
1292 {
1293 auto pFrame = static_cast<SwFrameFormat*>(i_rFrames.front().pFrameClient->GetRegisteredIn());
1294 if (pFrame) // Frame could be disposed
1295 {
1296 rtl::Reference<SwXTextPortion> pPortion = new SwXTextPortion(i_pUnoCursor, i_xParent, *pFrame );
1297 rPortions.emplace_back(pPortion);
1298 }
1299 i_rFrames.pop_front();
1300 }
1301
1302 return !i_rFrames.empty() ? i_rFrames.front().nIndex : -1;
1303}
1304
1305static sal_Int32 lcl_GetNextIndex(
1306 SwXBookmarkPortion_ImplList const & rBkmArr,
1307 SwXRedlinePortion_ImplList const & rRedlineArr,
1308 SwSoftPageBreakList const & rBreakArr )
1309{
1310 sal_Int32 nRet = -1;
1311 if(!rBkmArr.empty())
1312 {
1313 SwXBookmarkPortion_ImplSharedPtr pPtr = *rBkmArr.begin();
1314 nRet = pPtr->getIndex();
1315 }
1316 if(!rRedlineArr.empty())
1317 {
1318 SwXRedlinePortion_ImplSharedPtr pPtr = *rRedlineArr.begin();
1319 sal_Int32 nTmp = pPtr->getRealIndex();
1320 if(nRet < 0 || nTmp < nRet)
1321 nRet = nTmp;
1322 }
1323 if(!rBreakArr.empty())
1324 {
1325 if(nRet < 0 || *rBreakArr.begin() < nRet)
1326 nRet = *rBreakArr.begin();
1327 }
1328 return nRet;
1329};
1330
1332 TextRangeList_t & i_rPortions,
1333 uno::Reference< text::XText > const & i_xParentText,
1334 SwUnoCursor * const pUnoCursor,
1335 FrameClientSortList_t & i_rFrames,
1336 const sal_Int32 i_nStartPos,
1337 const sal_Int32 i_nEndPos,
1338 bool bOnlyTextFields )
1339{
1340 if (!pUnoCursor)
1341 return;
1342
1343 // set the start if a selection should be exported
1344 if ((i_nStartPos > 0) &&
1345 (pUnoCursor->Start()->GetContentIndex() != i_nStartPos))
1346 {
1347 pUnoCursor->DeleteMark();
1348 OSL_ENSURE(pUnoCursor->Start()->GetNode().GetTextNode() &&
1349 (i_nStartPos <= pUnoCursor->Start()->GetNode().GetTextNode()->
1350 GetText().getLength()), "Incorrect start position" );
1351 // ??? should this be i_nStartPos - current position ?
1352 pUnoCursor->Right(i_nStartPos);
1353 }
1354
1355 SwDoc& rDoc = pUnoCursor->GetDoc();
1356
1357 std::deque<sal_Int32> FieldMarks;
1358 if (!bOnlyTextFields)
1359 lcl_FillFieldMarkArray(FieldMarks, *pUnoCursor, i_nStartPos);
1360
1361 SwXBookmarkPortion_ImplList Bookmarks;
1362 if (!bOnlyTextFields)
1363 lcl_FillBookmarkArray(rDoc, *pUnoCursor, Bookmarks);
1364
1366 if (!bOnlyTextFields)
1367 lcl_FillRedlineArray(rDoc, *pUnoCursor, Redlines);
1368
1369 SwSoftPageBreakList SoftPageBreaks;
1370 if (!bOnlyTextFields)
1371 lcl_FillSoftPageBreakArray(*pUnoCursor, SoftPageBreaks);
1372
1373 SwAnnotationStartPortion_ImplList AnnotationStarts;
1374 if (!bOnlyTextFields)
1375 lcl_FillAnnotationStartArray( rDoc, *pUnoCursor, AnnotationStarts );
1376
1377 PortionStack_t PortionStack;
1378 PortionStack.push( PortionList_t(&i_rPortions, nullptr) );
1379
1380 bool bAtEnd( false );
1381 while (!bAtEnd) // every iteration consumes at least current character!
1382 {
1383 if (pUnoCursor->HasMark())
1384 {
1385 pUnoCursor->Normalize(false);
1386 pUnoCursor->DeleteMark();
1387 }
1388
1389 SwTextNode * const pTextNode = pUnoCursor->GetPointNode().GetTextNode();
1390 if (!pTextNode)
1391 {
1392 OSL_FAIL("lcl_CreatePortions: no TextNode - what now ?");
1393 return;
1394 }
1395
1396 SwpHints * const pHints = pTextNode->GetpSwpHints();
1397 const sal_Int32 nCurrentIndex =
1398 pUnoCursor->GetPoint()->GetContentIndex();
1399 // this contains the portion which consumes the character in the
1400 // text at nCurrentIndex; i.e. it must be set _once_ per iteration
1401 uno::Reference< XTextRange > xRef;
1402
1403 SwUnoCursorHelper::SelectPam(*pUnoCursor, true); // set mark
1404
1405 // First remember the frame positions.
1406 o3tl::sorted_vector<sal_Int32> aFramePositions;
1407 lcl_ExtractFramePositions(i_rFrames, nCurrentIndex, aFramePositions);
1408
1409 // Then export start of collapsed bookmarks which "cover" at-char
1410 // anchored frames.
1411 lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
1412 pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, /*bOnlyFrameBookmarkStarts=*/true );
1413
1415 *PortionStack.top().first,
1416 i_xParentText,
1417 pUnoCursor,
1418 AnnotationStarts,
1419 nCurrentIndex,
1420 aFramePositions,
1421 /*bOnlyFrame=*/true );
1422
1423 const sal_Int32 nFirstFrameIndex =
1424 lcl_ExportFrames( *PortionStack.top().first,
1425 i_xParentText, pUnoCursor, i_rFrames, nCurrentIndex);
1426
1427 // Export ends of the previously started collapsed bookmarks + all
1428 // other bookmarks, redlines, etc.
1429 lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
1430 pUnoCursor, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex, aFramePositions, /*bOnlyFrameBookmarkStarts=*/false );
1431
1433 *PortionStack.top().first,
1434 i_xParentText,
1435 pUnoCursor,
1436 AnnotationStarts,
1437 nCurrentIndex,
1438 aFramePositions,
1439 /*bOnlyFrame=*/false );
1440
1441 bool bCursorMoved( false );
1442 sal_Int32 nNextAttrIndex = -1;
1443 // #111716# the cursor must not move right at the
1444 // end position of a selection!
1445 bAtEnd = ((i_nEndPos >= 0) && (nCurrentIndex >= i_nEndPos))
1446 || (nCurrentIndex >= pTextNode->Len());
1447 if (pHints)
1448 {
1449 // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
1450 xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCursor,
1451 pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
1452 bCursorMoved, nNextAttrIndex);
1453 if (PortionStack.empty())
1454 {
1455 OSL_FAIL("CreatePortions: stack underflow");
1456 return;
1457 }
1458 }
1459
1460 if (!xRef.is() && !bCursorMoved)
1461 {
1462 if (!bAtEnd &&
1463 !FieldMarks.empty() && (FieldMarks.front() == nCurrentIndex))
1464 {
1465 // moves cursor
1466 xRef = lcl_ExportFieldMark(i_xParentText, pUnoCursor, pTextNode);
1467 FieldMarks.pop_front();
1468 }
1469 }
1470 else
1471 {
1472 OSL_ENSURE(FieldMarks.empty() ||
1473 (FieldMarks.front() != nCurrentIndex),
1474 "fieldmark and hint with CH_TXTATR at same pos?");
1475 }
1476
1477 if (!bAtEnd && !xRef.is() && !bCursorMoved)
1478 {
1479 const sal_Int32 nNextPortionIndex =
1480 lcl_GetNextIndex(Bookmarks, Redlines, SoftPageBreaks);
1481
1482 sal_Int32 nNextMarkIndex = ( !FieldMarks.empty() ? FieldMarks.front() : -1 );
1483 if ( !AnnotationStarts.empty()
1484 && ( nNextMarkIndex == -1
1485 || (*AnnotationStarts.begin())->getIndex() < nNextMarkIndex ) )
1486 {
1487 nNextMarkIndex = (*AnnotationStarts.begin())->getIndex();
1488 }
1489
1491 pUnoCursor,
1492 nCurrentIndex,
1493 nFirstFrameIndex,
1494 nNextPortionIndex,
1495 nNextAttrIndex,
1496 nNextMarkIndex,
1497 i_nEndPos );
1498
1499 xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_TEXT);
1500 }
1501 else if (bAtEnd && !xRef.is() && !pTextNode->Len())
1502 {
1503 // special case: for an empty paragraph, we better put out a
1504 // text portion because there may be a hyperlink attribute
1505 xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_TEXT);
1506 }
1507 else if (bAtEnd && !xRef.is() && pHints)
1508 {
1509 // See if there is an empty autofmt at the paragraph end. If so, export it, since that
1510 // affects the formatting of number portions.
1511 for (size_t i = 0; i < pHints->Count(); ++i)
1512 {
1513 const SwTextAttr* pHint = pHints->GetSortedByEnd(i);
1514 if (pHint->GetStart() < pTextNode->Len())
1515 {
1516 break;
1517 }
1518 if (pHint->Which() == RES_TXTATR_AUTOFMT && pHint->GetEnd()
1519 && pHint->GetStart() == *pHint->GetEnd()
1520 && pHint->GetStart() == pTextNode->Len())
1521 {
1522 xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_TEXT);
1523 break;
1524 }
1525 }
1526 }
1527
1528 if (xRef.is())
1529 {
1530 PortionStack.top().first->push_back(xRef);
1531 }
1532 }
1533
1534 OSL_ENSURE((PortionStack.size() == 1) && !PortionStack.top().second,
1535 "CreatePortions: stack error" );
1536}
1537
1538/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
geometry::RealPoint2D maPosition
const Any & any
wrapper iterator: wraps iterator of implementation while hiding MarkBase class; only IMark instances ...
Provides access to the marks of a document.
virtual const_iterator_t getAnnotationMarksBegin() const =0
virtual ::sw::mark::IFieldmark * getFieldmarkAt(const SwPosition &rPos) const =0
get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos
virtual sal_Int32 getAnnotationMarksCount() const =0
virtual const_iterator_t findFirstAnnotationStartsAfter(const SwPosition &rPos) const =0
Finds the first mark that is starting after.
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:502
virtual sal_Int32 getBookmarksCount() const =0
returns the number of IBookmarks.
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
virtual const SwRedlineTable & GetRedlineTable() const =0
Marks a character position inside a document model content node (SwContentNode)
virtual sal_Int32 Len() const
Definition: node.cxx:1256
bool Right(sal_uInt16 nCnt)
Definition: swcrsr.hxx:173
Definition: doc.hxx:197
void cleanupUnoCursorTable() const
Definition: doc.hxx:1673
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1890
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1810
OUString ExpandField(bool bCached, SwRootFrame const *pLayout) const
expand the field.
Definition: fldbas.cxx:491
FlyAnchors.
Definition: fmtanchr.hxx:37
sal_Int32 GetAnchorContentOffset() const
Definition: atrfrm.cxx:1631
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
SfxPoolItem subclass that wraps an SwContentControl.
const std::shared_ptr< SwContentControl > & GetContentControl() const
const SwField * GetField() const
Definition: fmtfld.hxx:131
SwFrameFormat * GetFrameFormat() const
Definition: fmtflcnt.hxx:45
SfxPoolItem subclass that wraps an SwLineBreakClear.
SwFormatMeta is a pool item subclass that owns a Meta.
Definition: fmtmeta.hxx:93
::sw::Meta * GetMeta()
Definition: fmtmeta.hxx:123
Style of a layout element.
Definition: frmfmt.hxx:72
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwContentNode * GetContentNode()
Definition: node.hxx:666
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
SwNode & GetPointNode() const
Definition: pam.hxx:275
void Exchange()
Definition: pam.hxx:242
void Normalize(bool bPointFirst=true)
Normalizes PaM, i.e.
Definition: pam.cxx:689
std::pair< const SwPosition *, const SwPosition * > StartEnd() const
Because sometimes the cost of the operator<= can add up.
Definition: pam.hxx:269
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
const SwPosition * End() const
Definition: pam.hxx:263
SwDoc & GetDoc() const
Definition: pam.hxx:291
void DeleteMark()
Definition: pam.hxx:232
const SwPosition * GetPoint() const
Definition: pam.hxx:253
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
size_type size() const
Definition: docary.hxx:268
vector_type::size_type size_type
Definition: docary.hxx:223
::sw::mark::IMark * GetAnnotationMark() const
Definition: atrfld.cxx:784
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:167
sal_Int32 GetAnyEnd() const
end (if available), else start
Definition: txatbase.hxx:161
virtual const sal_Int32 * GetEnd() const
end position
Definition: txatbase.cxx:48
const sal_Int32 * End() const
Definition: txatbase.hxx:156
const SwFormatFlyCnt & GetFlyCnt() const
Definition: txatbase.hxx:226
const SwFormatLineBreak & GetLineBreak() const
Definition: txatbase.hxx:214
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:208
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
sal_uInt16 Which() const
Definition: txatbase.hxx:116
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
static bool isTextBox(const SwFrameFormat *pFormat, sal_uInt16 nType, const SdrObject *pObject=nullptr)
Is the frame format a text box?
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
void fillSoftPageBreakList(SwSoftPageBreakList &rBreak) const
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:252
const OUString & GetText() const
Definition: ndtxt.hxx:244
static rtl::Reference< SwXBookmark > CreateXBookmark(SwDoc &rDoc, ::sw::mark::IMark *pBookmark)
Definition: unobkm.cxx:157
static rtl::Reference< SwXContentControl > CreateXContentControl(SwContentControl &rContentControl, const css::uno::Reference< css::text::XText > &xParentText=nullptr, std::unique_ptr< const TextRangeList_t > &&pPortions=std::unique_ptr< const TextRangeList_t >())
static rtl::Reference< SwXDocumentIndexMark > CreateXDocumentIndexMark(SwDoc &rDoc, SwTOXMark *pMark, TOXTypes eType=TOX_INDEX)
Definition: unoidx.cxx:1638
static rtl::Reference< SwXBookmark > CreateXFieldmark(SwDoc &rDoc, ::sw::mark::IMark *pMark, bool isReplacementObject=false)
Definition: unobkm.cxx:674
static css::uno::Reference< css::text::XFootnote > GetObject(SwDoc &rDoc, const SwFormatFootnote &rFormat)
Definition: unocoll.cxx:1816
static rtl::Reference< SwXLineBreak > CreateXLineBreak(SwFormatLineBreak *pLineBreakFormat)
static rtl::Reference< SwXMeta > CreateXMeta(::sw::Meta &rMeta, css::uno::Reference< css::text::XText > const &xParentText=nullptr, std::unique_ptr< TextRangeList_t const > &&pPortions=std::unique_ptr< TextRangeList_t const >())
static rtl::Reference< SwXReferenceMark > CreateXReferenceMark(SwDoc &rDoc, SwFormatRefMark *pMarkFormat)
Definition: unorefmk.cxx:126
static rtl::Reference< SwXTextField > CreateXTextField(SwDoc *pDoc, SwFormatField const *pFormat, SwServiceType nServiceId=SwServiceType::Invalid)
Definition: unofield.cxx:1194
virtual OUString SAL_CALL getImplementationName() override
virtual css::uno::Any SAL_CALL nextElement() override
SwXTextPortionEnumeration(SwPaM &rParaCursor, css::uno::Reference< css::text::XText > const &xParent, const sal_Int32 nStart, const sal_Int32 nEnd, bool bOnlyTextFields=false)
TextRangeList_t m_Portions
Definition: unoport.hxx:252
virtual sal_Bool SAL_CALL hasMoreElements() override
virtual ~SwXTextPortionEnumeration() override
sw::UnoCursorPointer m_pUnoCursor
Definition: unoport.hxx:253
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
size_t Count() const
Definition: ndhints.hxx:142
SwTextAttr * GetSortedByEnd(size_t nPos) const
Definition: ndhints.hxx:158
const_iterator begin() const
const_iterator find(const Value &x) const
size_type erase(const Value &x)
bool empty() const
const_iterator end() const
std::pair< const_iterator, bool > insert(Value &&x)
void reset(std::shared_ptr< SwUnoCursor > pNew)
Definition: unocrsr.hxx:158
const SwFormatField * GetAnnotationFormatField() const
virtual bool IsExpanded() const =0
virtual const SwPosition & GetMarkEnd() const =0
virtual const SwPosition & GetMarkStart() const =0
SwPosition & GetMarkStart() const override
DocumentType eType
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:184
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:181
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(59)
constexpr TypedWhichId< SwFormatAutoFormat > RES_TXTATR_AUTOFMT(50)
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(162)
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwFormatCharFormat > RES_TXTATR_CHARFMT(52)
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
constexpr TypedWhichId< SwFormatLineBreak > RES_TXTATR_LINEBREAK(61)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
constexpr TypedWhichId< SwFormatRuby > RES_TXTATR_CJK_RUBY(53)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:185
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:183
sal_Int32 nIndex
#define SAL_WARN(area, stream)
void SelectPam(SwPaM &rPam, const bool bExpand)
Definition: unoobj.cxx:120
double getLength(const B2DPolygon &rCandidate)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:1043
QPRO_FUNC_TYPE nType
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
unsigned char sal_Bool
sal_uInt16 sal_Unicode
std::deque< css::uno::Reference< css::text::XTextRange > > TextRangeList_t
Count
std::deque< FrameClientSortListEntry > FrameClientSortList_t
void CollectFrameAtNode(const SwNode &rNd, FrameClientSortList_t &rFrames, const bool bAtCharAnchoredObjs)
Definition: unoobj2.cxx:137
@ PORTION_TOXMARK_END
Definition: unoport.hxx:62
@ PORTION_TEXT
Definition: unoport.hxx:55
@ PORTION_FIELD_SEP
Definition: unoport.hxx:72
@ PORTION_ANNOTATION
Definition: unoport.hxx:75
@ PORTION_BOOKMARK_START
Definition: unoport.hxx:63
@ PORTION_CONTENT_CONTROL
Definition: unoport.hxx:78
@ PORTION_FIELD_END
Definition: unoport.hxx:73
@ PORTION_META
Definition: unoport.hxx:70
@ PORTION_REFMARK_START
Definition: unoport.hxx:59
@ PORTION_BOOKMARK_END
Definition: unoport.hxx:64
@ PORTION_FIELD
Definition: unoport.hxx:56
@ PORTION_TOXMARK_START
Definition: unoport.hxx:61
@ PORTION_SOFT_PAGEBREAK
Definition: unoport.hxx:69
@ PORTION_FIELD_START_END
Definition: unoport.hxx:74
@ PORTION_ANNOTATION_END
Definition: unoport.hxx:76
@ PORTION_FRAME
Definition: unoport.hxx:57
@ PORTION_LINEBREAK
Definition: unoport.hxx:77
@ PORTION_FOOTNOTE
Definition: unoport.hxx:58
@ PORTION_REFMARK_END
Definition: unoport.hxx:60
@ PORTION_FIELD_START
Definition: unoport.hxx:71
static void lcl_FillSoftPageBreakArray(SwUnoCursor const &rUnoCursor, SwSoftPageBreakList &rBreakArr)
static void lcl_MoveCursor(SwUnoCursor *const pUnoCursor, const sal_Int32 nCurrentIndex, const sal_Int32 nNextFrameIndex, const sal_Int32 nNextPortionIndex, const sal_Int32 nNextAttrIndex, const sal_Int32 nNextMarkIndex, const sal_Int32 nEndPos)
std::multiset< SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct > SwXRedlinePortion_ImplList
static void lcl_FillRedlineArray(SwDoc const &rDoc, SwUnoCursor const &rUnoCursor, SwXRedlinePortion_ImplList &rRedArr)
static Reference< XTextRange > lcl_CreateTOXMarkPortion(Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwTextAttr &rAttr, const bool bEnd)
static uno::Reference< text::XTextRange > lcl_CreateContentControlPortion(const uno::Reference< text::XText > &xParent, const SwUnoCursor *pUnoCursor, SwTextAttr &rAttr, std::unique_ptr< const TextRangeList_t > &&pPortions)
Creates a text portion that has a non-empty ContentControl property.
static void lcl_ExtractFramePositions(FrameClientSortList_t &rFrames, sal_Int32 nCurrentIndex, o3tl::sorted_vector< sal_Int32 > &rFramePositions)
Fills character positions from rFrames into rFramePositions.
static void lcl_FillFieldMarkArray(std::deque< sal_Int32 > &rFieldMarks, SwUnoCursor const &rUnoCursor, const sal_Int32 i_nStartPos)
static uno::Reference< text::XTextRange > lcl_ExportFieldMark(uno::Reference< text::XText > const &i_xParentText, SwUnoCursor *const pUnoCursor, const SwTextNode *const pTextNode)
std::pair< TextRangeList_t *const, SwTextAttr const *const > PortionList_t
Definition: unoportenum.cxx:72
static void lcl_ExportAnnotationStarts(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwAnnotationStartPortion_ImplList &rAnnotationStartArr, const sal_Int32 nIndex, const o3tl::sorted_vector< sal_Int32 > &rFramePositions, bool bOnlyFrame)
Exports all start annotation marks from rAnnotationStartArr into rPortions that have the same start p...
static Reference< XTextRange > lcl_CreateRefMarkPortion(Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, const SwTextAttr &rAttr, const bool bEnd)
static Reference< XTextRange > lcl_ExportHints(PortionStack_t &rPortionStack, const Reference< XText > &xParent, SwUnoCursor *const pUnoCursor, SwpHints const *const pHints, const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos, const sal_Int32 nCurrentIndex, const bool bRightMoveForbidden, bool &o_rbCursorMoved, sal_Int32 &o_rNextAttrPosition)
static void lcl_ExportRedline(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwXRedlinePortion_ImplList &rRedlineArr, const sal_Int32 nIndex)
static void lcl_ExportSoftPageBreak(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwSoftPageBreakList &rBreakArr, const sal_Int32 nIndex)
static void lcl_ExportBookmark(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwXBookmarkPortion_ImplList &rBkmArr, const sal_Int32 nIndex, const o3tl::sorted_vector< sal_Int32 > &rFramePositions, bool bOnlyFrameStarts)
Exports all bookmarks from rBkmArr into rPortions that have the same start or end position as nIndex.
static sal_Int32 lcl_GetNextIndex(SwXBookmarkPortion_ImplList const &rBkmArr, SwXRedlinePortion_ImplList const &rRedlineArr, SwSoftPageBreakList const &rBreakArr)
static void lcl_InsertRubyPortion(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, const SwTextAttr &rAttr, const bool bEnd)
std::shared_ptr< SwXRedlinePortion_Impl > SwXRedlinePortion_ImplSharedPtr
static uno::Reference< text::XTextRange > lcl_CreateMetaPortion(uno::Reference< text::XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwTextAttr &rAttr, std::unique_ptr< TextRangeList_t const > &&pPortions)
std::stack< PortionList_t > PortionStack_t
Definition: unoportenum.cxx:73
static void lcl_ExportBkmAndRedline(TextRangeList_t &rPortions, Reference< XText > const &xParent, const SwUnoCursor *const pUnoCursor, SwXBookmarkPortion_ImplList &rBkmArr, SwXRedlinePortion_ImplList &rRedlineArr, SwSoftPageBreakList &rBreakArr, const sal_Int32 nIndex, const o3tl::sorted_vector< sal_Int32 > &rFramePositions, bool bOnlyFrameBookmarkStarts)
static sal_Int32 lcl_ExportFrames(TextRangeList_t &rPortions, Reference< XText > const &i_xParent, SwUnoCursor const *const i_pUnoCursor, FrameClientSortList_t &i_rFrames, sal_Int32 const i_nCurrentIndex)
Exports at-char anchored frames.
static void lcl_CreatePortions(TextRangeList_t &i_rPortions, uno::Reference< text::XText > const &i_xParentText, SwUnoCursor *pUnoCursor, FrameClientSortList_t &i_rFrames, const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos, bool bOnlyTextFields)
size_t pos