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