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