Line data Source code
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 :
21 : #include <unoport.hxx>
22 : #include <IMark.hxx>
23 : // #i81002#
24 : #include <crossrefbookmark.hxx>
25 : #include <doc.hxx>
26 : #include <txatbase.hxx>
27 : #include <txtatr.hxx>
28 : #include <ndhints.hxx>
29 : #include <ndtxt.hxx>
30 : #include <unocrsr.hxx>
31 : #include <docary.hxx>
32 : #include <tox.hxx>
33 : #include <unomid.h>
34 : #include <unoparaframeenum.hxx>
35 : #include <unocrsrhelper.hxx>
36 : #include <unorefmark.hxx>
37 : #include <unobookmark.hxx>
38 : #include <unoredline.hxx>
39 : #include <unofield.hxx>
40 : #include <unometa.hxx>
41 : #include <fmtmeta.hxx>
42 : #include <fmtanchr.hxx>
43 : #include <fmtrfmrk.hxx>
44 : #include <frmfmt.hxx>
45 : #include <unoidx.hxx>
46 : #include <unocoll.hxx>
47 : #include <redline.hxx>
48 : #include <crsskip.hxx>
49 : #include <switerator.hxx>
50 : #include <docufld.hxx>
51 : #include <fmtfld.hxx>
52 : #include <osl/mutex.hxx>
53 : #include <vcl/svapp.hxx>
54 : #include <comphelper/string.hxx>
55 : #include <comphelper/servicehelper.hxx>
56 : #include <cppuhelper/supportsservice.hxx>
57 : #include <set>
58 : #include <boost/shared_ptr.hpp>
59 : #include <algorithm>
60 : #include <stack>
61 :
62 :
63 : using namespace ::com::sun::star;
64 : using namespace ::com::sun::star::uno;
65 : using namespace ::com::sun::star::text;
66 : using namespace ::std;
67 :
68 : typedef ::std::pair< TextRangeList_t * const, SwTxtAttr const * const > PortionList_t;
69 : typedef ::std::stack< PortionList_t > PortionStack_t;
70 :
71 : static void lcl_CreatePortions(
72 : TextRangeList_t & i_rPortions,
73 : uno::Reference< text::XText > const& i_xParentText,
74 : SwUnoCrsr* pUnoCrsr,
75 : FrameDependSortList_t & i_rFrames,
76 : const sal_Int32 i_nStartPos, const sal_Int32 i_nEndPos );
77 :
78 : namespace
79 : {
80 : static const sal_uInt8 BKM_TYPE_START = 0;
81 : static const sal_uInt8 BKM_TYPE_END = 1;
82 : static const sal_uInt8 BKM_TYPE_START_END = 2;
83 :
84 1947 : struct SwXBookmarkPortion_Impl
85 : {
86 : Reference<XTextContent> xBookmark;
87 : sal_uInt8 nBkmType;
88 : const SwPosition aPosition;
89 :
90 1947 : SwXBookmarkPortion_Impl(uno::Reference<text::XTextContent> const& xMark,
91 : const sal_uInt8 nType, SwPosition const& rPosition)
92 : : xBookmark ( xMark )
93 : , nBkmType ( nType )
94 1947 : , aPosition ( rPosition )
95 : {
96 1947 : }
97 9430 : sal_uLong getIndex ()
98 : {
99 9430 : return aPosition.nContent.GetIndex();
100 : }
101 : };
102 : typedef boost::shared_ptr < SwXBookmarkPortion_Impl > SwXBookmarkPortion_ImplSharedPtr;
103 : struct BookmarkCompareStruct
104 : {
105 18924 : bool operator () ( const SwXBookmarkPortion_ImplSharedPtr &r1,
106 : const SwXBookmarkPortion_ImplSharedPtr &r2 ) const
107 : {
108 : // #i16896# for bookmark portions at the same position, the start should
109 : // always precede the end. Hence compare positions, and use bookmark type
110 : // as tie-breaker for same position.
111 : // return ( r1->nIndex == r2->nIndex )
112 : // ? ( r1->nBkmType < r2->nBkmType )
113 : // : ( r1->nIndex < r2->nIndex );
114 :
115 : // MTG: 25/11/05: Note that the above code does not correctly handle
116 : // the case when one bookmark ends, and another begins in the same
117 : // position. When this occurs, the above code will return the
118 : // the start of the 2nd bookmark BEFORE the end of the first bookmark
119 : // See bug #i58438# for more details. The below code is correct and
120 : // fixes both #i58438 and #i16896#
121 18924 : return r1->aPosition < r2->aPosition;
122 : }
123 : };
124 : typedef std::multiset < SwXBookmarkPortion_ImplSharedPtr, BookmarkCompareStruct > SwXBookmarkPortion_ImplList;
125 :
126 509 : static void lcl_FillBookmarkArray(SwDoc& rDoc, SwUnoCrsr& rUnoCrsr, SwXBookmarkPortion_ImplList& rBkmArr)
127 : {
128 509 : IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
129 509 : if(!pMarkAccess->getBookmarksCount())
130 898 : return;
131 :
132 : // no need to consider marks starting after aEndOfPara
133 120 : SwPosition aEndOfPara(*rUnoCrsr.GetPoint());
134 120 : aEndOfPara.nContent = aEndOfPara.nNode.GetNode().GetTxtNode()->Len();
135 : const IDocumentMarkAccess::const_iterator_t pCandidatesEnd = upper_bound(
136 120 : pMarkAccess->getBookmarksBegin(),
137 120 : pMarkAccess->getBookmarksEnd(),
138 : aEndOfPara,
139 240 : sw::mark::CompareIMarkStartsAfter()); // finds the first that starts after
140 :
141 : // search for all bookmarks that start or end in this paragraph
142 240 : const SwNodeIndex nOwnNode = rUnoCrsr.GetPoint()->nNode;
143 10489 : for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
144 : ppMark != pCandidatesEnd;
145 : ++ppMark)
146 : {
147 10369 : ::sw::mark::IMark* const pBkmk = ppMark->get();
148 : ::sw::mark::CrossRefBookmark *const pCrossRefMark(
149 10369 : dynamic_cast< ::sw::mark::CrossRefBookmark*>(pBkmk));
150 10369 : bool const hasOther = pBkmk->IsExpanded();
151 :
152 10369 : const SwPosition& rStartPos = pBkmk->GetMarkStart();
153 10369 : if(rStartPos.nNode == nOwnNode)
154 : {
155 : // #i109272#: cross reference marks: need special handling!
156 29 : sal_uInt8 const nType = (hasOther || pCrossRefMark)
157 1947 : ? BKM_TYPE_START : BKM_TYPE_START_END;
158 : rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
159 : new SwXBookmarkPortion_Impl(
160 : SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
161 987 : nType, rStartPos)));
162 : }
163 :
164 10369 : const SwPosition& rEndPos = pBkmk->GetMarkEnd();
165 10369 : if(rEndPos.nNode == nOwnNode)
166 : {
167 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
168 987 : auto_ptr<SwPosition> pCrossRefEndPos;
169 : SAL_WNODEPRECATED_DECLARATIONS_POP
170 987 : const SwPosition* pEndPos = NULL;
171 987 : if(hasOther)
172 : {
173 958 : pEndPos = &rEndPos;
174 : }
175 29 : else if (pCrossRefMark)
176 : {
177 : // Crossrefbookmarks only remember the start position but have to span the whole paragraph
178 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
179 2 : pCrossRefEndPos = auto_ptr<SwPosition>(new SwPosition(rEndPos));
180 : SAL_WNODEPRECATED_DECLARATIONS_POP
181 2 : pCrossRefEndPos->nContent = pCrossRefEndPos->nNode.GetNode().GetTxtNode()->Len();
182 2 : pEndPos = pCrossRefEndPos.get();
183 : }
184 987 : if(pEndPos)
185 : {
186 : rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
187 : new SwXBookmarkPortion_Impl(
188 : SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
189 960 : BKM_TYPE_END, *pEndPos)));
190 987 : }
191 : }
192 120 : }
193 : }
194 : }
195 :
196 : namespace
197 : {
198 : class theSwXTextPortionEnumerationUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextPortionEnumerationUnoTunnelId > {};
199 : }
200 :
201 0 : const uno::Sequence< sal_Int8 > & SwXTextPortionEnumeration::getUnoTunnelId()
202 : {
203 0 : return theSwXTextPortionEnumerationUnoTunnelId::get().getSeq();
204 : }
205 :
206 0 : sal_Int64 SAL_CALL SwXTextPortionEnumeration::getSomething(
207 : const uno::Sequence< sal_Int8 >& rId )
208 : throw(uno::RuntimeException)
209 : {
210 0 : if( rId.getLength() == 16
211 0 : && 0 == memcmp( getUnoTunnelId().getConstArray(),
212 0 : rId.getConstArray(), 16 ) )
213 : {
214 0 : return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
215 : }
216 0 : return 0;
217 : }
218 :
219 0 : OUString SwXTextPortionEnumeration::getImplementationName()
220 : throw( RuntimeException )
221 : {
222 0 : return OUString("SwXTextPortionEnumeration");
223 : }
224 :
225 : sal_Bool
226 0 : SwXTextPortionEnumeration::supportsService(const OUString& rServiceName)
227 : throw( RuntimeException )
228 : {
229 0 : return cppu::supportsService(this, rServiceName);
230 : }
231 :
232 0 : Sequence< OUString > SwXTextPortionEnumeration::getSupportedServiceNames()
233 : throw( RuntimeException )
234 : {
235 0 : Sequence< OUString > aRet(1);
236 0 : OUString* pArray = aRet.getArray();
237 0 : pArray[0] = "com.sun.star.text.TextPortionEnumeration";
238 0 : return aRet;
239 : }
240 :
241 509 : SwXTextPortionEnumeration::SwXTextPortionEnumeration(
242 : SwPaM& rParaCrsr,
243 : uno::Reference< XText > const & xParentText,
244 : const sal_Int32 nStart,
245 : const sal_Int32 nEnd )
246 509 : : m_Portions()
247 : {
248 : SwUnoCrsr* pUnoCrsr =
249 509 : rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), false);
250 509 : pUnoCrsr->Add(this);
251 :
252 : OSL_ENSURE(nEnd == -1 || (nStart <= nEnd &&
253 : nEnd <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->GetTxt().getLength()),
254 : "start or end value invalid!");
255 :
256 : // find all frames, graphics and OLEs that are bound AT character in para
257 509 : FrameDependSortList_t frames;
258 509 : ::CollectFrameAtNode(*this, pUnoCrsr->GetPoint()->nNode, frames, true);
259 509 : lcl_CreatePortions(m_Portions, xParentText, pUnoCrsr, frames, nStart, nEnd);
260 509 : }
261 :
262 175 : SwXTextPortionEnumeration::SwXTextPortionEnumeration(
263 : SwPaM& rParaCrsr,
264 : TextRangeList_t const & rPortions )
265 175 : : m_Portions( rPortions )
266 : {
267 : SwUnoCrsr* const pUnoCrsr =
268 175 : rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), false);
269 175 : pUnoCrsr->Add(this);
270 175 : }
271 :
272 2052 : SwXTextPortionEnumeration::~SwXTextPortionEnumeration()
273 : {
274 684 : SolarMutexGuard aGuard;
275 :
276 684 : SwUnoCrsr* pUnoCrsr = GetCursor();
277 684 : delete pUnoCrsr;
278 1368 : }
279 :
280 5533 : sal_Bool SwXTextPortionEnumeration::hasMoreElements()
281 : throw( uno::RuntimeException )
282 : {
283 5533 : SolarMutexGuard aGuard;
284 :
285 5533 : return (m_Portions.size() > 0) ? sal_True : sal_False;
286 : }
287 :
288 5428 : uno::Any SwXTextPortionEnumeration::nextElement()
289 : throw( container::NoSuchElementException, lang::WrappedTargetException,
290 : uno::RuntimeException )
291 : {
292 5428 : SolarMutexGuard aGuard;
293 :
294 5428 : if (!m_Portions.size())
295 1 : throw container::NoSuchElementException();
296 :
297 5427 : Any any;
298 5427 : any <<= m_Portions.front();
299 5427 : m_Portions.pop_front();
300 5428 : return any;
301 : }
302 :
303 : typedef ::std::deque< xub_StrLen > FieldMarks_t;
304 :
305 : static void
306 509 : lcl_FillFieldMarkArray(FieldMarks_t & rFieldMarks, SwUnoCrsr const & rUnoCrsr,
307 : const sal_Int32 i_nStartPos)
308 : {
309 : const SwTxtNode * const pTxtNode =
310 509 : rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
311 1018 : if (!pTxtNode) return;
312 :
313 : const sal_Unicode fld[] = {
314 509 : CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, CH_TXT_ATR_FORMELEMENT, 0 };
315 509 : sal_Int32 pos = ::std::max(static_cast<const sal_Int32>(0), i_nStartPos);
316 1039 : while ((pos = ::comphelper::string::indexOfAny(pTxtNode->GetTxt(), fld, pos)) != -1)
317 : {
318 21 : rFieldMarks.push_back(pos);
319 21 : ++pos;
320 : }
321 : }
322 :
323 : static uno::Reference<text::XTextRange>
324 21 : lcl_ExportFieldMark(
325 : uno::Reference< text::XText > const & i_xParentText,
326 : SwUnoCrsr * const pUnoCrsr,
327 : const SwTxtNode * const pTxtNode )
328 : {
329 21 : uno::Reference<text::XTextRange> xRef;
330 21 : SwDoc* pDoc = pUnoCrsr->GetDoc();
331 : //flr: maybe its a good idea to add a special hint to the hints array and rely on the hint segmentation....
332 21 : const xub_StrLen start = pUnoCrsr->Start()->nContent.GetIndex();
333 : OSL_ENSURE(pUnoCrsr->End()->nContent.GetIndex() == start,
334 : "hmm --- why is this different");
335 :
336 21 : pUnoCrsr->Right(1, CRSR_SKIP_CHARS, sal_False, sal_False);
337 21 : if ( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
338 : {
339 : OSL_FAIL("cannot move cursor?");
340 0 : return 0;
341 : }
342 :
343 21 : const sal_Unicode Char = pTxtNode->GetTxt()[start];
344 21 : if (CH_TXT_ATR_FIELDSTART == Char)
345 : {
346 11 : ::sw::mark::IFieldmark* pFieldmark = NULL;
347 11 : if (pDoc)
348 : {
349 11 : pFieldmark = pDoc->getIDocumentMarkAccess()->
350 11 : getFieldmarkFor(*pUnoCrsr->GetMark());
351 : }
352 : SwXTextPortion* pPortion = new SwXTextPortion(
353 11 : pUnoCrsr, i_xParentText, PORTION_FIELD_START);
354 11 : xRef = pPortion;
355 11 : if (pPortion && pFieldmark && pDoc)
356 : {
357 11 : pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
358 11 : Reference<XTextField> xField;
359 11 : const SwFmtFld* pField = SwPostItField::GetByName(pDoc, pFieldmark->GetName());
360 11 : if (pField)
361 10 : xField = SwXTextField::CreateXTextField(*pDoc, *pField);
362 11 : pPortion->SetTextField(xField);
363 : }
364 : }
365 10 : else if (CH_TXT_ATR_FIELDEND == Char)
366 : {
367 9 : ::sw::mark::IFieldmark* pFieldmark = NULL;
368 9 : if (pDoc)
369 : {
370 9 : pFieldmark = pDoc->getIDocumentMarkAccess()->
371 9 : getFieldmarkFor(*pUnoCrsr->GetMark());
372 : }
373 : SwXTextPortion* pPortion = new SwXTextPortion(
374 9 : pUnoCrsr, i_xParentText, PORTION_FIELD_END);
375 9 : xRef = pPortion;
376 9 : if (pPortion && pFieldmark && pDoc)
377 9 : pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
378 : }
379 1 : else if (CH_TXT_ATR_FORMELEMENT == Char)
380 : {
381 1 : ::sw::mark::IFieldmark* pFieldmark = NULL;
382 1 : if (pDoc)
383 : {
384 1 : pFieldmark = pDoc->getIDocumentMarkAccess()->
385 1 : getFieldmarkFor(*pUnoCrsr->GetMark());
386 : }
387 : SwXTextPortion* pPortion = new SwXTextPortion(
388 1 : pUnoCrsr, i_xParentText, PORTION_FIELD_START_END);
389 1 : xRef = pPortion;
390 1 : if (pPortion && pFieldmark && pDoc)
391 1 : pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
392 : }
393 : else
394 : {
395 : OSL_FAIL("no fieldmark found?");
396 : }
397 21 : return xRef;
398 : }
399 :
400 : static Reference<XTextRange>
401 46 : lcl_CreateRefMarkPortion(
402 : Reference<XText> const& xParent,
403 : const SwUnoCrsr * const pUnoCrsr,
404 : const SwTxtAttr & rAttr, const bool bEnd)
405 : {
406 46 : SwDoc* pDoc = pUnoCrsr->GetDoc();
407 : const SwFmtRefMark& rRefMark =
408 46 : static_cast<const SwFmtRefMark&>(rAttr.GetAttr());
409 46 : Reference<XTextContent> xContent;
410 46 : if (!xContent.is())
411 : {
412 46 : xContent = new SwXReferenceMark(pDoc, &rRefMark);
413 : }
414 :
415 46 : SwXTextPortion* pPortion = 0;
416 46 : if (!bEnd)
417 : {
418 32 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_START);
419 32 : pPortion->SetRefMark(xContent);
420 32 : pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
421 : }
422 : else
423 : {
424 14 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_END);
425 14 : pPortion->SetRefMark(xContent);
426 : }
427 46 : return pPortion;
428 : }
429 :
430 : static void
431 244 : lcl_InsertRubyPortion(
432 : TextRangeList_t & rPortions,
433 : Reference<XText> const& xParent,
434 : const SwUnoCrsr * const pUnoCrsr,
435 : const SwTxtAttr & rAttr, const sal_Bool bEnd)
436 : {
437 : SwXTextPortion* pPortion = new SwXTextPortion(pUnoCrsr,
438 244 : static_cast<const SwTxtRuby&>(rAttr), xParent, bEnd);
439 244 : rPortions.push_back(pPortion);
440 244 : pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
441 244 : }
442 :
443 : static Reference<XTextRange>
444 45 : lcl_CreateTOXMarkPortion(
445 : Reference<XText> const& xParent,
446 : const SwUnoCrsr * const pUnoCrsr,
447 : SwTxtAttr & rAttr, const bool bEnd)
448 : {
449 45 : SwDoc* pDoc = pUnoCrsr->GetDoc();
450 45 : SwTOXMark & rTOXMark = static_cast<SwTOXMark&>(rAttr.GetAttr());
451 :
452 : const Reference<XTextContent> xContent(
453 : SwXDocumentIndexMark::CreateXDocumentIndexMark(*pDoc,
454 45 : *const_cast<SwTOXType*>(rTOXMark.GetTOXType()), rTOXMark),
455 45 : uno::UNO_QUERY);
456 :
457 45 : SwXTextPortion* pPortion = 0;
458 45 : if (!bEnd)
459 : {
460 32 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_START);
461 32 : pPortion->SetTOXMark(xContent);
462 32 : pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
463 : }
464 : else
465 : {
466 13 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_END);
467 13 : pPortion->SetTOXMark(xContent);
468 : }
469 45 : return pPortion;
470 : }
471 :
472 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
473 : static uno::Reference<text::XTextRange>
474 175 : lcl_CreateMetaPortion(
475 : uno::Reference<text::XText> const& xParent,
476 : const SwUnoCrsr * const pUnoCrsr,
477 : SwTxtAttr & rAttr, ::std::auto_ptr<TextRangeList_t const> & pPortions)
478 : {
479 : const uno::Reference<rdf::XMetadatable> xMeta( SwXMeta::CreateXMeta(
480 175 : *static_cast<SwFmtMeta &>(rAttr.GetAttr()).GetMeta(),
481 350 : xParent, pPortions));
482 175 : SwXTextPortion * pPortion(0);
483 175 : if (RES_TXTATR_META == rAttr.Which())
484 : {
485 : const uno::Reference<text::XTextContent> xContent(xMeta,
486 145 : uno::UNO_QUERY);
487 145 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_META);
488 145 : pPortion->SetMeta(xContent);
489 : }
490 : else
491 : {
492 30 : const uno::Reference<text::XTextField> xField(xMeta, uno::UNO_QUERY);
493 30 : pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_FIELD);
494 30 : pPortion->SetTextField(xField);
495 : }
496 175 : return pPortion;
497 : }
498 : SAL_WNODEPRECATED_DECLARATIONS_POP
499 :
500 : static void
501 1918 : lcl_ExportBookmark(
502 : TextRangeList_t & rPortions,
503 : Reference<XText> const& xParent,
504 : const SwUnoCrsr * const pUnoCrsr,
505 : SwXBookmarkPortion_ImplList& rBkmArr, const sal_uLong nIndex)
506 : {
507 5783 : for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end();
508 : aIter != aEnd; )
509 : {
510 3797 : SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
511 3797 : if ( nIndex > pPtr->getIndex() )
512 : {
513 0 : rBkmArr.erase( aIter++ );
514 0 : continue;
515 : }
516 3797 : if ( nIndex < pPtr->getIndex() )
517 1850 : break;
518 :
519 1947 : SwXTextPortion* pPortion = 0;
520 2934 : if ((BKM_TYPE_START == pPtr->nBkmType) ||
521 987 : (BKM_TYPE_START_END == pPtr->nBkmType))
522 : {
523 : pPortion =
524 987 : new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_START);
525 987 : rPortions.push_back(pPortion);
526 987 : pPortion->SetBookmark(pPtr->xBookmark);
527 987 : pPortion->SetCollapsed( (BKM_TYPE_START_END == pPtr->nBkmType)
528 987 : ? true : false);
529 :
530 : }
531 1947 : if (BKM_TYPE_END == pPtr->nBkmType)
532 : {
533 : pPortion =
534 960 : new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_END);
535 960 : rPortions.push_back(pPortion);
536 960 : pPortion->SetBookmark(pPtr->xBookmark);
537 : }
538 1947 : rBkmArr.erase( aIter++ );
539 1947 : }
540 1918 : }
541 :
542 : static void
543 537 : lcl_ExportSoftPageBreak(
544 : TextRangeList_t & rPortions,
545 : Reference<XText> const& xParent,
546 : const SwUnoCrsr * const pUnoCrsr,
547 : SwSoftPageBreakList& rBreakArr, const sal_uLong nIndex)
548 : {
549 1618 : for ( SwSoftPageBreakList::iterator aIter = rBreakArr.begin(),
550 537 : aEnd = rBreakArr.end();
551 : aIter != aEnd; )
552 : {
553 538 : if ( nIndex > *aIter )
554 : {
555 0 : rBreakArr.erase( aIter++ );
556 0 : continue;
557 : }
558 538 : if ( nIndex < *aIter )
559 531 : break;
560 :
561 : rPortions.push_back(
562 7 : new SwXTextPortion(pUnoCrsr, xParent, PORTION_SOFT_PAGEBREAK) );
563 7 : rBreakArr.erase( aIter++ );
564 : }
565 537 : }
566 :
567 : struct SwXRedlinePortion_Impl
568 : {
569 : const SwRedline* m_pRedline;
570 : const bool m_bStart;
571 :
572 40 : SwXRedlinePortion_Impl ( const SwRedline* pRed, const bool bIsStart )
573 : : m_pRedline(pRed)
574 40 : , m_bStart(bIsStart)
575 : {
576 40 : }
577 :
578 120 : sal_uLong getRealIndex ()
579 : {
580 60 : return m_bStart ? m_pRedline->Start()->nContent.GetIndex()
581 180 : : m_pRedline->End() ->nContent.GetIndex();
582 : }
583 : };
584 :
585 : typedef boost::shared_ptr < SwXRedlinePortion_Impl >
586 : SwXRedlinePortion_ImplSharedPtr;
587 :
588 : struct RedlineCompareStruct
589 : {
590 80 : const SwPosition& getPosition ( const SwXRedlinePortion_ImplSharedPtr &r )
591 : {
592 80 : return *(r->m_bStart ? r->m_pRedline->Start() : r->m_pRedline->End());
593 : }
594 :
595 40 : bool operator () ( const SwXRedlinePortion_ImplSharedPtr &r1,
596 : const SwXRedlinePortion_ImplSharedPtr &r2 )
597 : {
598 40 : return getPosition ( r1 ) < getPosition ( r2 );
599 : }
600 : };
601 :
602 : typedef std::multiset < SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct >
603 : SwXRedlinePortion_ImplList;
604 :
605 : static Reference<XTextRange>
606 1685 : lcl_ExportHints(
607 : PortionStack_t & rPortionStack,
608 : const Reference<XText> & xParent,
609 : SwUnoCrsr * const pUnoCrsr,
610 : SwpHints * const pHints,
611 : const sal_Int32 i_nStartPos,
612 : const sal_Int32 i_nEndPos,
613 : const xub_StrLen nCurrentIndex,
614 : const bool bRightMoveForbidden,
615 : bool & o_rbCursorMoved,
616 : sal_Int32 & o_rNextAttrPosition )
617 : {
618 : // if the attribute has a dummy character, then xRef is set (except META)
619 : // otherwise, the portion for the attribute is inserted into rPortions!
620 1685 : Reference<XTextRange> xRef;
621 1685 : SwDoc* pDoc = pUnoCrsr->GetDoc();
622 : //search for special text attributes - first some ends
623 1685 : sal_uInt16 nEndIndex = 0;
624 1685 : sal_uInt16 nNextEnd = 0;
625 20799 : while(nEndIndex < pHints->GetEndCount() &&
626 9676 : (!pHints->GetEnd(nEndIndex)->GetEnd() ||
627 3349 : nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetEnd()))))
628 : {
629 5551 : if(pHints->GetEnd(nEndIndex)->GetEnd())
630 : {
631 2573 : SwTxtAttr * const pAttr = pHints->GetEnd(nEndIndex);
632 2573 : if (nNextEnd == nCurrentIndex)
633 : {
634 543 : const sal_uInt16 nWhich( pAttr->Which() );
635 543 : switch (nWhich)
636 : {
637 : case RES_TXTATR_TOXMARK:
638 : {
639 : Reference<XTextRange> xTmp = lcl_CreateTOXMarkPortion(
640 13 : xParent, pUnoCrsr, *pAttr, true);
641 13 : rPortionStack.top().first->push_back(xTmp);
642 : }
643 13 : break;
644 : case RES_TXTATR_REFMARK:
645 : {
646 : Reference<XTextRange> xTmp = lcl_CreateRefMarkPortion(
647 14 : xParent, pUnoCrsr, *pAttr, true);
648 14 : rPortionStack.top().first->push_back(xTmp);
649 : }
650 14 : break;
651 : case RES_TXTATR_CJK_RUBY:
652 : //#i91534# GetEnd() == 0 mixes the order of ruby start/end
653 122 : if( *pAttr->GetEnd() == *pAttr->GetStart())
654 : {
655 2 : lcl_InsertRubyPortion( *rPortionStack.top().first,
656 2 : xParent, pUnoCrsr, *pAttr, sal_False);
657 : }
658 122 : lcl_InsertRubyPortion( *rPortionStack.top().first,
659 122 : xParent, pUnoCrsr, *pAttr, sal_True);
660 122 : break;
661 : case RES_TXTATR_META:
662 : case RES_TXTATR_METAFIELD:
663 : {
664 : OSL_ENSURE(*pAttr->GetStart() != *pAttr->GetEnd(),
665 : "empty meta?");
666 177 : if ((i_nStartPos > 0) &&
667 1 : (*pAttr->GetStart() < i_nStartPos))
668 : {
669 : // force skip pAttr and rest of attribute ends
670 : // at nCurrentIndex
671 : // because they are not contained in the meta pAttr
672 : // and the meta pAttr itself is outside selection!
673 : // (necessary for SwXMeta::createEnumeration)
674 1 : if (*pAttr->GetStart() + 1 == i_nStartPos)
675 : {
676 1 : nEndIndex = pHints->GetEndCount() - 1;
677 : }
678 1 : break;
679 : }
680 175 : PortionList_t Top = rPortionStack.top();
681 175 : if (Top.second != pAttr)
682 : {
683 : OSL_FAIL("ExportHints: stack error" );
684 : }
685 : else
686 : {
687 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
688 : ::std::auto_ptr<const TextRangeList_t>
689 175 : pCurrentPortions(Top.first);
690 : SAL_WNODEPRECATED_DECLARATIONS_POP
691 175 : rPortionStack.pop();
692 : const uno::Reference<text::XTextRange> xPortion(
693 : lcl_CreateMetaPortion(xParent, pUnoCrsr,
694 350 : *pAttr, pCurrentPortions));
695 350 : rPortionStack.top().first->push_back(xPortion);
696 : }
697 : }
698 175 : break;
699 : }
700 : }
701 : }
702 5551 : nEndIndex++;
703 : }
704 :
705 : // then some starts
706 1685 : sal_uInt16 nStartIndex = 0;
707 1685 : sal_uInt16 nNextStart = 0;
708 15091 : while(nStartIndex < pHints->GetStartCount() &&
709 6276 : nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
710 : {
711 5445 : SwTxtAttr * const pAttr = pHints->GetStart(nStartIndex);
712 5445 : sal_uInt16 nAttrWhich = pAttr->Which();
713 5445 : if (nNextStart == nCurrentIndex)
714 : {
715 996 : switch( nAttrWhich )
716 : {
717 : case RES_TXTATR_FIELD:
718 43 : if(!bRightMoveForbidden)
719 : {
720 43 : pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
721 43 : if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
722 0 : break;
723 : SwXTextPortion* pPortion;
724 86 : xRef = pPortion = new SwXTextPortion(
725 86 : pUnoCrsr, xParent, PORTION_FIELD);
726 : Reference<XTextField> const xField =
727 43 : SwXTextField::CreateXTextField(*pDoc, pAttr->GetFld());
728 43 : pPortion->SetTextField(xField);
729 :
730 : // If this is a postit field and it has a fieldmark
731 : // associated, set the fieldmark as a bookmark.
732 43 : const SwField* pField = pAttr->GetFld().GetFld();
733 43 : if (pField->Which() == RES_POSTITFLD)
734 : {
735 9 : const SwPostItField* pPostItField = dynamic_cast<const SwPostItField*>(pField);
736 9 : IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
737 9 : IDocumentMarkAccess::const_iterator_t it = pMarkAccess->findMark(pPostItField->GetName());
738 9 : if (it != pMarkAccess->getMarksEnd())
739 8 : pPortion->SetBookmark(SwXFieldmark::CreateXFieldmark(*pDoc, *it->get()));
740 43 : }
741 : }
742 43 : break;
743 : case RES_TXTATR_FLYCNT :
744 354 : if(!bRightMoveForbidden)
745 : {
746 354 : pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
747 354 : if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
748 0 : break; // Robust #i81708 content in covered cells
749 354 : pUnoCrsr->Exchange();
750 708 : xRef = new SwXTextPortion(
751 708 : pUnoCrsr, xParent, PORTION_FRAME);
752 : }
753 354 : break;
754 : case RES_TXTATR_FTN :
755 : {
756 20 : if(!bRightMoveForbidden)
757 : {
758 20 : pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
759 20 : if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
760 0 : break;
761 : SwXTextPortion* pPortion;
762 40 : xRef = pPortion = new SwXTextPortion(
763 40 : pUnoCrsr, xParent, PORTION_FOOTNOTE);
764 : Reference<XFootnote> xContent =
765 20 : SwXFootnotes::GetObject(*pDoc, pAttr->GetFtn());
766 20 : pPortion->SetFootnote(xContent);
767 : }
768 : }
769 20 : break;
770 : case RES_TXTATR_TOXMARK:
771 : case RES_TXTATR_REFMARK:
772 : {
773 64 : bool bIsPoint = !(pAttr->GetEnd());
774 64 : if (!bRightMoveForbidden || !bIsPoint)
775 : {
776 64 : if (bIsPoint)
777 : {
778 37 : pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
779 : }
780 : Reference<XTextRange> xTmp =
781 : (RES_TXTATR_REFMARK == nAttrWhich)
782 : ? lcl_CreateRefMarkPortion(
783 : xParent, pUnoCrsr, *pAttr, false)
784 : : lcl_CreateTOXMarkPortion(
785 64 : xParent, pUnoCrsr, *pAttr, false);
786 64 : if (bIsPoint) // consume CH_TXTATR!
787 : {
788 37 : pUnoCrsr->Normalize(false);
789 37 : pUnoCrsr->DeleteMark();
790 37 : xRef = xTmp;
791 : }
792 : else // just insert it
793 : {
794 27 : rPortionStack.top().first->push_back(xTmp);
795 64 : }
796 : }
797 : }
798 64 : break;
799 : case RES_TXTATR_CJK_RUBY:
800 : //#i91534# GetEnd() == 0 mixes the order of ruby start/end
801 122 : if(pAttr->GetEnd() && (*pAttr->GetEnd() != *pAttr->GetStart()))
802 : {
803 120 : lcl_InsertRubyPortion( *rPortionStack.top().first,
804 240 : xParent, pUnoCrsr, *pAttr, sal_False);
805 : }
806 122 : break;
807 : case RES_TXTATR_META:
808 : case RES_TXTATR_METAFIELD:
809 175 : if (*pAttr->GetStart() != *pAttr->GetEnd())
810 : {
811 175 : if (!bRightMoveForbidden)
812 : {
813 175 : pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
814 175 : o_rbCursorMoved = true;
815 : // only if the end is included in selection!
816 175 : if ((i_nEndPos < 0) ||
817 0 : (*pAttr->GetEnd() <= i_nEndPos))
818 : {
819 : rPortionStack.push( ::std::make_pair(
820 175 : new TextRangeList_t, pAttr ));
821 : }
822 : }
823 : }
824 175 : break;
825 : case RES_TXTATR_AUTOFMT:
826 : case RES_TXTATR_INETFMT:
827 : case RES_TXTATR_CHARFMT:
828 218 : break; // these are handled as properties of a "Text" portion
829 : default:
830 : OSL_FAIL("unknown attribute");
831 0 : break;
832 : }
833 : }
834 5445 : nStartIndex++;
835 : }
836 :
837 1685 : if (xRef.is()) // implies that we have moved the cursor
838 : {
839 454 : o_rbCursorMoved = true;
840 : }
841 1685 : if (!o_rbCursorMoved)
842 : {
843 : // search for attribute changes behind the current cursor position
844 : // break up at frames, bookmarks, redlines
845 :
846 1056 : nStartIndex = 0;
847 1056 : nNextStart = 0;
848 8664 : while(nStartIndex < pHints->GetStartCount() &&
849 3489 : nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
850 3063 : nStartIndex++;
851 :
852 1056 : nEndIndex = 0;
853 1056 : nNextEnd = 0;
854 7527 : while(nEndIndex < pHints->GetEndCount() &&
855 2998 : nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd())))
856 2417 : nEndIndex++;
857 :
858 : sal_Int32 nNextPos =
859 426 : ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
860 1198 : ? nNextStart : nNextEnd;
861 1056 : if (nNextPos > nCurrentIndex)
862 : {
863 581 : o_rNextAttrPosition = nNextPos;
864 : }
865 : }
866 1685 : return xRef;
867 : }
868 :
869 2622 : static void lcl_MoveCursor( SwUnoCrsr * const pUnoCrsr,
870 : const xub_StrLen nCurrentIndex,
871 : const sal_Int32 nNextFrameIndex, const sal_Int32 nNextPortionIndex,
872 : const sal_Int32 nNextAttrIndex, const sal_Int32 nNextFieldMarkIndex,
873 : const sal_Int32 nEndPos )
874 : {
875 2622 : sal_Int32 nMovePos = pUnoCrsr->GetCntntNode()->Len();
876 :
877 2622 : if ((nEndPos >= 0) && (nEndPos < nMovePos))
878 : {
879 1 : nMovePos = nEndPos;
880 : }
881 :
882 2622 : if ((nNextFrameIndex >= 0) && (nNextFrameIndex < nMovePos))
883 : {
884 5 : nMovePos = nNextFrameIndex;
885 : }
886 :
887 2622 : if ((nNextPortionIndex >= 0) && (nNextPortionIndex < nMovePos))
888 : {
889 1847 : nMovePos = nNextPortionIndex;
890 : }
891 :
892 2622 : if ((nNextAttrIndex >= 0) && (nNextAttrIndex < nMovePos))
893 : {
894 458 : nMovePos = nNextAttrIndex;
895 : }
896 :
897 2622 : if ((nNextFieldMarkIndex >= 0) && (nNextFieldMarkIndex < nMovePos))
898 : {
899 19 : nMovePos = nNextFieldMarkIndex;
900 : }
901 :
902 2622 : if (nMovePos > nCurrentIndex)
903 : {
904 : // pUnoCrsr->Right(nMovePos - nCurrentIndex);
905 2622 : pUnoCrsr->GetPoint()->nContent = static_cast<sal_uInt16>(nMovePos);
906 : }
907 2622 : }
908 :
909 : static void
910 509 : lcl_FillRedlineArray(SwDoc const & rDoc, SwUnoCrsr const & rUnoCrsr,
911 : SwXRedlinePortion_ImplList& rRedArr )
912 : {
913 509 : const SwRedlineTbl& rRedTbl = rDoc.GetRedlineTbl();
914 509 : sal_uInt16 nRedTblCount = rRedTbl.size();
915 :
916 509 : if ( nRedTblCount > 0 )
917 : {
918 20 : const SwPosition* pStart = rUnoCrsr.GetPoint();
919 20 : const SwNodeIndex nOwnNode = pStart->nNode;
920 :
921 48 : for(sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
922 : {
923 28 : const SwRedline* pRedline = rRedTbl[nRed];
924 28 : const SwPosition* pRedStart = pRedline->Start();
925 28 : const SwNodeIndex nRedNode = pRedStart->nNode;
926 28 : if ( nOwnNode == nRedNode )
927 : rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
928 20 : new SwXRedlinePortion_Impl ( pRedline, true ) ) );
929 28 : if( pRedline->HasMark() && pRedline->End()->nNode == nOwnNode )
930 : rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
931 20 : new SwXRedlinePortion_Impl ( pRedline, false) ) );
932 48 : }
933 : }
934 509 : }
935 :
936 : static void
937 509 : lcl_FillSoftPageBreakArray(
938 : SwUnoCrsr const & rUnoCrsr, SwSoftPageBreakList& rBreakArr )
939 : {
940 : const SwTxtNode *pTxtNode =
941 509 : rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
942 509 : if( pTxtNode )
943 509 : pTxtNode->fillSoftPageBreakList( rBreakArr );
944 509 : }
945 :
946 : static void
947 60 : lcl_ExportRedline(
948 : TextRangeList_t & rPortions,
949 : Reference<XText> const& xParent,
950 : const SwUnoCrsr * const pUnoCrsr,
951 : SwXRedlinePortion_ImplList& rRedlineArr, const sal_uLong nIndex)
952 : {
953 :
954 : // MTG: 23/11/05: We want this loop to iterate over all red lines in this
955 : // array. We will only insert the ones with index matches
956 160 : for ( SwXRedlinePortion_ImplList::iterator aIter = rRedlineArr.begin(), aEnd = rRedlineArr.end();
957 : aIter != aEnd; )
958 : {
959 80 : SwXRedlinePortion_ImplSharedPtr pPtr = (*aIter );
960 80 : sal_uLong nRealIndex = pPtr->getRealIndex();
961 : // MTG: 23/11/05: If there are elements before nIndex, remove them
962 80 : if ( nIndex > nRealIndex )
963 0 : rRedlineArr.erase ( aIter++ );
964 : // MTG: 23/11/05: If the elements match, and them to the list
965 80 : else if ( nIndex == nRealIndex )
966 : {
967 : rPortions.push_back( new SwXRedlinePortion(
968 40 : *pPtr->m_pRedline, pUnoCrsr, xParent, pPtr->m_bStart));
969 40 : rRedlineArr.erase ( aIter++ );
970 : }
971 : // MTG: 23/11/05: If we've iterated past nIndex, exit the loop
972 : else
973 40 : break;
974 40 : }
975 60 : }
976 :
977 : static void
978 3781 : lcl_ExportBkmAndRedline(
979 : TextRangeList_t & rPortions,
980 : Reference<XText> const & xParent,
981 : const SwUnoCrsr * const pUnoCrsr,
982 : SwXBookmarkPortion_ImplList& rBkmArr,
983 : SwXRedlinePortion_ImplList& rRedlineArr,
984 : SwSoftPageBreakList& rBreakArr,
985 : const sal_uLong nIndex)
986 : {
987 3781 : if (!rBkmArr.empty())
988 1918 : lcl_ExportBookmark(rPortions, xParent, pUnoCrsr, rBkmArr, nIndex);
989 :
990 3781 : if (!rRedlineArr.empty())
991 60 : lcl_ExportRedline(rPortions, xParent, pUnoCrsr, rRedlineArr, nIndex);
992 :
993 3781 : if (!rBreakArr.empty())
994 537 : lcl_ExportSoftPageBreak(rPortions, xParent, pUnoCrsr, rBreakArr, nIndex);
995 3781 : }
996 :
997 : static sal_Int32
998 3781 : lcl_ExportFrames(
999 : TextRangeList_t & rPortions,
1000 : Reference<XText> const & i_xParent,
1001 : SwUnoCrsr * const i_pUnoCrsr,
1002 : FrameDependSortList_t & i_rFrames,
1003 : xub_StrLen const i_nCurrentIndex)
1004 : {
1005 : // find first Frame in (sorted) i_rFrames at current position
1006 7587 : while (i_rFrames.size() && (i_rFrames.front().nIndex == i_nCurrentIndex))
1007 : // do not check for i_nEnd here; this is done implicity by lcl_MoveCursor
1008 : {
1009 : const SwModify * const pFrame =
1010 25 : i_rFrames.front().pFrameDepend->GetRegisteredIn();
1011 25 : if (pFrame) // Frame could be disposed
1012 : {
1013 : SwXTextPortion* pPortion = new SwXTextPortion(i_pUnoCrsr, i_xParent,
1014 25 : *static_cast<SwFrmFmt*>( const_cast<SwModify*>( pFrame ) ) );
1015 25 : rPortions.push_back(pPortion);
1016 : }
1017 25 : i_rFrames.pop_front();
1018 : }
1019 :
1020 3781 : return i_rFrames.size() ? i_rFrames.front().nIndex : -1;
1021 : }
1022 :
1023 : static sal_Int32
1024 2622 : lcl_GetNextIndex(
1025 : SwXBookmarkPortion_ImplList const & rBkmArr,
1026 : SwXRedlinePortion_ImplList const & rRedlineArr,
1027 : SwSoftPageBreakList const & rBreakArr )
1028 : {
1029 2622 : sal_Int32 nRet = -1;
1030 2622 : if(!rBkmArr.empty())
1031 : {
1032 1836 : SwXBookmarkPortion_ImplSharedPtr pPtr = (*rBkmArr.begin());
1033 1836 : nRet = pPtr->getIndex();
1034 : }
1035 2622 : if(!rRedlineArr.empty())
1036 : {
1037 40 : SwXRedlinePortion_ImplSharedPtr pPtr = (*rRedlineArr.begin());
1038 40 : sal_Int32 nTmp = pPtr->getRealIndex();
1039 40 : if(nRet < 0 || nTmp < nRet)
1040 40 : nRet = nTmp;
1041 : }
1042 2622 : if(!rBreakArr.empty())
1043 : {
1044 531 : if(nRet < 0 || *rBreakArr.begin() < static_cast<sal_uInt32>(nRet))
1045 4 : nRet = *rBreakArr.begin();
1046 : }
1047 2622 : return nRet;
1048 : };
1049 :
1050 : static void
1051 509 : lcl_CreatePortions(
1052 : TextRangeList_t & i_rPortions,
1053 : uno::Reference< text::XText > const & i_xParentText,
1054 : SwUnoCrsr * const pUnoCrsr,
1055 : FrameDependSortList_t & i_rFrames,
1056 : const sal_Int32 i_nStartPos,
1057 : const sal_Int32 i_nEndPos )
1058 : {
1059 509 : if (!pUnoCrsr)
1060 0 : return;
1061 :
1062 : // set the start if a selection should be exported
1063 510 : if ((i_nStartPos > 0) &&
1064 1 : (pUnoCrsr->Start()->nContent.GetIndex() != i_nStartPos))
1065 : {
1066 0 : pUnoCrsr->DeleteMark();
1067 : OSL_ENSURE(pUnoCrsr->Start()->nNode.GetNode().GetTxtNode() &&
1068 : (i_nStartPos <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->
1069 : GetTxt().getLength()), "Incorrect start position" );
1070 : // ??? should this be i_nStartPos - current position ?
1071 : pUnoCrsr->Right(static_cast<xub_StrLen>(i_nStartPos),
1072 0 : CRSR_SKIP_CHARS, sal_False, sal_False);
1073 : }
1074 :
1075 509 : FieldMarks_t FieldMarks;
1076 1018 : SwXBookmarkPortion_ImplList Bookmarks;
1077 1018 : SwXRedlinePortion_ImplList Redlines;
1078 1018 : SwSoftPageBreakList SoftPageBreaks;
1079 :
1080 509 : SwDoc * const pDoc = pUnoCrsr->GetDoc();
1081 509 : lcl_FillFieldMarkArray(FieldMarks, *pUnoCrsr, i_nStartPos);
1082 509 : lcl_FillBookmarkArray(*pDoc, *pUnoCrsr, Bookmarks);
1083 509 : lcl_FillRedlineArray(*pDoc, *pUnoCrsr, Redlines);
1084 509 : lcl_FillSoftPageBreakArray(*pUnoCrsr, SoftPageBreaks);
1085 :
1086 1018 : PortionStack_t PortionStack;
1087 509 : PortionStack.push( PortionList_t(&i_rPortions, (const SwTxtAttr *)0) );
1088 :
1089 509 : bool bAtEnd( false );
1090 4799 : while (!bAtEnd) // every iteration consumes at least current character!
1091 : {
1092 3781 : if (pUnoCrsr->HasMark())
1093 : {
1094 3235 : pUnoCrsr->Normalize(false);
1095 3235 : pUnoCrsr->DeleteMark();
1096 : }
1097 :
1098 3781 : SwTxtNode * const pTxtNode = pUnoCrsr->GetNode()->GetTxtNode();
1099 3781 : if (!pTxtNode)
1100 : {
1101 : OSL_FAIL("lcl_CreatePortions: no TextNode - what now ?");
1102 0 : return;
1103 : }
1104 :
1105 3781 : SwpHints * const pHints = pTxtNode->GetpSwpHints();
1106 : const xub_StrLen nCurrentIndex =
1107 3781 : pUnoCrsr->GetPoint()->nContent.GetIndex();
1108 : // this contains the portion which consumes the character in the
1109 : // text at nCurrentIndex; i.e. it must be set _once_ per iteration
1110 3781 : uno::Reference< XTextRange > xRef;
1111 :
1112 3781 : SwUnoCursorHelper::SelectPam(*pUnoCrsr, true); // set mark
1113 :
1114 : const sal_Int32 nFirstFrameIndex =
1115 3781 : lcl_ExportFrames( *PortionStack.top().first,
1116 7562 : i_xParentText, pUnoCrsr, i_rFrames, nCurrentIndex);
1117 :
1118 3781 : lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
1119 7562 : pUnoCrsr, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex );
1120 :
1121 3781 : bool bCursorMoved( false );
1122 3781 : sal_Int32 nNextAttrIndex = -1;
1123 : // #111716# the cursor must not move right at the
1124 : // end position of a selection!
1125 3 : bAtEnd = ((i_nEndPos >= 0) && (nCurrentIndex >= i_nEndPos))
1126 7561 : || (nCurrentIndex >= pTxtNode->Len());
1127 3781 : if (pHints)
1128 : {
1129 : // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
1130 3370 : xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCrsr,
1131 : pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
1132 1685 : bCursorMoved, nNextAttrIndex);
1133 1685 : if (PortionStack.empty())
1134 : {
1135 : OSL_FAIL("CreatePortions: stack underflow");
1136 0 : return;
1137 : }
1138 : }
1139 :
1140 3781 : if (!xRef.is() && !bCursorMoved)
1141 : {
1142 8947 : if (!bAtEnd &&
1143 3196 : FieldMarks.size() && (FieldMarks.front() == nCurrentIndex))
1144 : {
1145 : // moves cursor
1146 21 : xRef = lcl_ExportFieldMark(i_xParentText, pUnoCrsr, pTxtNode);
1147 21 : FieldMarks.pop_front();
1148 : }
1149 : }
1150 : else
1151 : {
1152 : OSL_ENSURE(!FieldMarks.size() ||
1153 : (FieldMarks.front() != nCurrentIndex),
1154 : "fieldmark and hint with CH_TXTATR at same pos?");
1155 : }
1156 :
1157 3781 : if (!bAtEnd && !xRef.is() && !bCursorMoved)
1158 : {
1159 : const sal_Int32 nNextPortionIndex =
1160 2622 : lcl_GetNextIndex(Bookmarks, Redlines, SoftPageBreaks);
1161 : const sal_Int32 nNextFieldMarkIndex(
1162 2622 : FieldMarks.size() ? FieldMarks.front() : -1);
1163 :
1164 : lcl_MoveCursor(pUnoCrsr, nCurrentIndex,
1165 : nFirstFrameIndex, nNextPortionIndex, nNextAttrIndex,
1166 : nNextFieldMarkIndex,
1167 2622 : i_nEndPos);
1168 :
1169 2622 : xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
1170 : }
1171 1159 : else if (bAtEnd && !xRef.is() && !pTxtNode->Len())
1172 : {
1173 : // special case: for an empty paragraph, we better put out a
1174 : // text portion because there may be a hyperlink attribute
1175 38 : xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
1176 : }
1177 :
1178 3781 : if (xRef.is())
1179 : {
1180 3135 : PortionStack.top().first->push_back(xRef);
1181 : }
1182 3781 : }
1183 :
1184 : OSL_ENSURE((PortionStack.size() == 1) && !PortionStack.top().second,
1185 509 : "CreatePortions: stack error" );
1186 : }
1187 :
1188 684 : void SwXTextPortionEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
1189 : {
1190 684 : ClientModify(this, pOld, pNew);
1191 783 : }
1192 :
1193 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|