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