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