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