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