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