1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoportenum.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 // --> OD 2007-10-23 #i81002#
37 #include <crossrefbookmark.hxx>
40 #include <txatbase.hxx>
41 #include <ndhints.hxx>
43 #include <unocrsr.hxx>
45 #include <fmthbsh.hxx>
47 #include <unoclbck.hxx>
49 #include <unoredline.hxx>
50 #include <fmtanchr.hxx>
52 #include <redline.hxx>
53 #include <crsskip.hxx>
54 #include <vos/mutex.hxx>
55 #include <vcl/svapp.hxx>
57 #include <boost/shared_ptr.hpp>
58 #include <boost/bind.hpp>
61 using namespace ::com::sun::star
;
62 using namespace ::com::sun::star::uno
;
63 using namespace ::com::sun::star::text
;
64 using ::rtl::OUString
;
65 using namespace ::std
;
70 static const BYTE BKM_TYPE_START
= 0;
71 static const BYTE BKM_TYPE_END
= 1;
72 static const BYTE BKM_TYPE_START_END
= 2;
74 struct SwXBookmarkPortion_Impl
76 Reference
<XTextContent
> xBookmark
;
78 const SwPosition aPosition
;
80 SwXBookmarkPortion_Impl( SwXBookmark
* pXMark
, BYTE nType
, const SwPosition
&rPosition
)
81 : xBookmark ( pXMark
)
83 , aPosition ( rPosition
)
88 return aPosition
.nContent
.GetIndex();
91 typedef boost::shared_ptr
< SwXBookmarkPortion_Impl
> SwXBookmarkPortion_ImplSharedPtr
;
92 struct BookmarkCompareStruct
94 bool operator () ( const SwXBookmarkPortion_ImplSharedPtr
&r1
,
95 const SwXBookmarkPortion_ImplSharedPtr
&r2
)
97 // #i16896# for bookmark portions at the same position, the start should
98 // always precede the end. Hence compare positions, and use bookmark type
99 // as tie-breaker for same position.
100 // return ( r1->nIndex == r2->nIndex )
101 // ? ( r1->nBkmType < r2->nBkmType )
102 // : ( r1->nIndex < r2->nIndex );
104 // MTG: 25/11/05: Note that the above code does not correctly handle
105 // the case when one bookmark ends, and another begins in the same
106 // position. When this occurs, the above code will return the
107 // the start of the 2nd bookmark BEFORE the end of the first bookmark
108 // See bug #i58438# for more details. The below code is correct and
109 // fixes both #i58438 and #i16896#
110 return r1
->aPosition
< r2
->aPosition
;
113 typedef std::multiset
< SwXBookmarkPortion_ImplSharedPtr
, BookmarkCompareStruct
> SwXBookmarkPortion_ImplList
;
116 static void lcl_FillBookmarkArray(SwDoc
& rDoc
, SwUnoCrsr
& rUnoCrsr
, SwXBookmarkPortion_ImplList
& rBkmArr
)
118 IDocumentMarkAccess
* const pMarkAccess
= rDoc
.getIDocumentMarkAccess();
119 if(!pMarkAccess
->getBookmarksCount())
122 // no need to consider marks starting after aEndOfPara
123 SwPosition
aEndOfPara(*rUnoCrsr
.GetPoint());
124 aEndOfPara
.nContent
= aEndOfPara
.nNode
.GetNode().GetTxtNode()->Len();
125 const IDocumentMarkAccess::const_iterator_t pCandidatesEnd
= upper_bound(
126 pMarkAccess
->getBookmarksBegin(),
127 pMarkAccess
->getBookmarksEnd(),
129 bind(&::sw::mark::IMark::StartsAfter
, _2
, _1
)); // finds the first that starts after
131 // search for all bookmarks that start or end in this paragraph
132 const SwNodeIndex nOwnNode
= rUnoCrsr
.GetPoint()->nNode
;
133 for(IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->getBookmarksBegin();
134 ppMark
!= pCandidatesEnd
;
137 ::sw::mark::IMark
* const pBkmk
= ppMark
->get();
138 bool hasOther
= pBkmk
->IsExpanded();
140 const SwPosition
& rStartPos
= pBkmk
->GetMarkStart();
141 if(rStartPos
.nNode
== nOwnNode
)
143 const BYTE nType
= hasOther
? BKM_TYPE_START
: BKM_TYPE_START_END
;
144 rBkmArr
.insert(SwXBookmarkPortion_ImplSharedPtr(
145 new SwXBookmarkPortion_Impl ( SwXBookmarks::GetObject(*pBkmk
, &rDoc
), nType
, rStartPos
)));
148 const SwPosition
& rEndPos
= pBkmk
->GetMarkEnd();
149 if(rEndPos
.nNode
== nOwnNode
)
151 auto_ptr
<SwPosition
> pCrossRefEndPos
;
152 const SwPosition
* pEndPos
= NULL
;
155 else if(dynamic_cast< ::sw::mark::CrossRefBookmark
*>(pBkmk
))
157 // Crossrefbookmarks only remember the start position but have to span the whole paragraph
158 pCrossRefEndPos
= auto_ptr
<SwPosition
>(new SwPosition(rEndPos
));
159 pCrossRefEndPos
->nContent
= pCrossRefEndPos
->nNode
.GetNode().GetTxtNode()->Len();
160 pEndPos
= pCrossRefEndPos
.get();
163 rBkmArr
.insert(SwXBookmarkPortion_ImplSharedPtr(
164 new SwXBookmarkPortion_Impl ( SwXBookmarks::GetObject(*pBkmk
, &rDoc
), BKM_TYPE_END
, *pEndPos
)));
171 /******************************************************************
172 * SwXTextPortionEnumeration
173 ******************************************************************/
174 /* -----------------------------13.03.00 12:15--------------------------------
176 ---------------------------------------------------------------------------*/
177 const uno::Sequence
< sal_Int8
> & SwXTextPortionEnumeration::getUnoTunnelId()
179 static uno::Sequence
< sal_Int8
> aSeq
= ::CreateUnoTunnelId();
182 /* -----------------------------10.03.00 18:04--------------------------------
184 ---------------------------------------------------------------------------*/
185 sal_Int64 SAL_CALL
SwXTextPortionEnumeration::getSomething( const uno::Sequence
< sal_Int8
>& rId
)
186 throw(uno::RuntimeException
)
188 if( rId
.getLength() == 16
189 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
190 rId
.getConstArray(), 16 ) )
192 return sal::static_int_cast
< sal_Int64
>( reinterpret_cast< sal_IntPtr
>( this ) );
196 /* -----------------------------06.04.00 16:39--------------------------------
198 ---------------------------------------------------------------------------*/
199 OUString
SwXTextPortionEnumeration::getImplementationName(void) throw( RuntimeException
)
201 return C2U("SwXTextPortionEnumeration");
203 /* -----------------------------06.04.00 16:39--------------------------------
205 ---------------------------------------------------------------------------*/
206 BOOL
SwXTextPortionEnumeration::supportsService(const OUString
& rServiceName
) throw( RuntimeException
)
208 return C2U("com.sun.star.text.TextPortionEnumeration") == rServiceName
;
210 /* -----------------------------06.04.00 16:39--------------------------------
212 ---------------------------------------------------------------------------*/
213 Sequence
< OUString
> SwXTextPortionEnumeration::getSupportedServiceNames(void) throw( RuntimeException
)
215 Sequence
< OUString
> aRet(1);
216 OUString
* pArray
= aRet
.getArray();
217 pArray
[0] = C2U("com.sun.star.text.TextPortionEnumeration");
220 /*-- 27.01.99 10:44:43---------------------------------------------------
222 -----------------------------------------------------------------------*/
223 SwXTextPortionEnumeration::SwXTextPortionEnumeration(
225 uno::Reference
< XText
> xParentText
,
229 xParent(xParentText
),
231 bFirstPortion(sal_True
),
235 SwUnoCrsr
* pUnoCrsr
= rParaCrsr
.GetDoc()->CreateUnoCrsr(*rParaCrsr
.GetPoint(), sal_False
);
238 DBG_ASSERT(nEnd
== -1 || (nStart
<= nEnd
&&
239 nEnd
<= pUnoCrsr
->Start()->nNode
.GetNode().GetTxtNode()->GetTxt().Len()),
240 "start or end value invalid!");
241 //alle Rahmen, Grafiken und OLEs suchen, die an diesem Absatz
242 // AM ZEICHEN gebunden sind
243 ::CollectFrameAtNode( *this, pUnoCrsr
->GetPoint()->nNode
,
247 /*-- 27.01.99 10:44:44---------------------------------------------------
249 -----------------------------------------------------------------------*/
250 SwXTextPortionEnumeration::~SwXTextPortionEnumeration()
252 vos::OGuard
aGuard(Application::GetSolarMutex());
253 for(sal_uInt16 nFrame
= aFrameArr
.Count(); nFrame
; )
254 delete aFrameArr
.GetObject( --nFrame
);
255 aFrameArr
.Remove(0, aFrameArr
.Count());
257 if( aPortionArr
.Count() )
258 aPortionArr
.DeleteAndDestroy(0, aPortionArr
.Count() );
260 SwUnoCrsr
* pUnoCrsr
= GetCrsr();
263 /*-- 27.01.99 10:44:44---------------------------------------------------
265 -----------------------------------------------------------------------*/
266 sal_Bool
SwXTextPortionEnumeration::hasMoreElements(void) throw( uno::RuntimeException
)
268 vos::OGuard
aGuard(Application::GetSolarMutex());
269 return aPortionArr
.Count() > 0;
271 /*-- 27.01.99 10:44:45---------------------------------------------------
273 -----------------------------------------------------------------------*/
274 uno::Any
SwXTextPortionEnumeration::nextElement(void)
275 throw( container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
277 vos::OGuard
aGuard(Application::GetSolarMutex());
278 if(!aPortionArr
.Count())
279 throw container::NoSuchElementException();
280 XTextRangeRefPtr pPortion
= aPortionArr
.GetObject(0);
281 Any
aRet(pPortion
, ::getCppuType((uno::Reference
<XTextRange
>*)0));
282 aPortionArr
.Remove(0);
286 /* -----------------------------31.08.00 14:28--------------------------------
288 ---------------------------------------------------------------------------*/
289 void lcl_InsertRefMarkPortion(
290 XTextRangeArr
& rArr
, SwUnoCrsr
* pUnoCrsr
,
291 Reference
<XText
> const& rParent
, SwTxtAttr
* pAttr
, BOOL bEnd
)
293 SwDoc
* pDoc
= pUnoCrsr
->GetDoc();
294 SwFmtRefMark
& rRefMark
= ((SwFmtRefMark
&)pAttr
->GetAttr());
295 Reference
<XTextContent
> xContent
= ((SwUnoCallBack
*)pDoc
->GetUnoCallBack())->GetRefMark(rRefMark
);
297 xContent
= new SwXReferenceMark(pDoc
, &rRefMark
);
299 SwXTextPortion
* pPortion
= 0;
303 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_REFMARK_START
)),
305 pPortion
->SetRefMark(xContent
);
306 pPortion
->SetCollapsed(pAttr
->GetEnd() ? FALSE
: TRUE
);
311 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_REFMARK_END
)),
313 pPortion
->SetRefMark(xContent
);
316 //-----------------------------------------------------------------------------
317 void lcl_InsertRubyPortion( XTextRangeArr
& rArr
, SwUnoCrsr
* pUnoCrsr
,
318 Reference
<XText
> const& rParent
, SwTxtAttr
* pAttr
, BOOL bEnd
)
320 SwXRubyPortion
* pPortion
=
321 new SwXRubyPortion(pUnoCrsr
, *(SwTxtRuby
*)pAttr
, rParent
, bEnd
);
322 rArr
.Insert( new Reference
< XTextRange
>(pPortion
), rArr
.Count() );
323 pPortion
->SetCollapsed(pAttr
->GetEnd() ? FALSE
: TRUE
);
325 //-----------------------------------------------------------------------------
326 void lcl_InsertTOXMarkPortion(
327 XTextRangeArr
& rArr
, SwUnoCrsr
* pUnoCrsr
, Reference
<XText
> const& rParent
,
328 SwTxtAttr
* pAttr
, BOOL bEnd
)
330 SwDoc
* pDoc
= pUnoCrsr
->GetDoc();
331 SwTOXMark
& rTOXMark
= ((SwTOXMark
&)pAttr
->GetAttr());
333 Reference
<XTextContent
> xContent
=
334 ((SwUnoCallBack
*)pDoc
->GetUnoCallBack())->GetTOXMark(rTOXMark
);
336 xContent
= new SwXDocumentIndexMark(rTOXMark
.GetTOXType(), &rTOXMark
, pDoc
);
338 SwXTextPortion
* pPortion
= 0;
342 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_TOXMARK_START
)),
344 pPortion
->SetTOXMark(xContent
);
345 pPortion
->SetCollapsed(pAttr
->GetEnd() ? FALSE
: TRUE
);
350 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_TOXMARK_END
)),
352 pPortion
->SetTOXMark(xContent
);
356 //-----------------------------------------------------------------------------
357 void lcl_ExportBookmark(
358 SwXBookmarkPortion_ImplList
& rBkmArr
, ULONG nIndex
,
359 SwUnoCrsr
* pUnoCrsr
, Reference
<XText
> & rParent
, XTextRangeArr
& rPortionArr
)
361 for ( SwXBookmarkPortion_ImplList::iterator aIter
= rBkmArr
.begin(), aEnd
= rBkmArr
.end();
364 SwXBookmarkPortion_ImplSharedPtr pPtr
= (*aIter
);
365 if ( nIndex
> pPtr
->getIndex() )
367 rBkmArr
.erase( aIter
++ );
370 if ( nIndex
< pPtr
->getIndex() )
373 SwXTextPortion
* pPortion
= 0;
374 if(BKM_TYPE_START
== pPtr
->nBkmType
|| BKM_TYPE_START_END
== pPtr
->nBkmType
)
377 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_BOOKMARK_START
)),
378 rPortionArr
.Count());
379 pPortion
->SetBookmark(pPtr
->xBookmark
);
380 pPortion
->SetCollapsed(BKM_TYPE_START_END
== pPtr
->nBkmType
? TRUE
: FALSE
);
383 if(BKM_TYPE_END
== pPtr
->nBkmType
)
386 new Reference
< XTextRange
>(pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_BOOKMARK_END
)),
387 rPortionArr
.Count());
388 pPortion
->SetBookmark(pPtr
->xBookmark
);
390 rBkmArr
.erase( aIter
++ );
394 void lcl_ExportSoftPageBreak(
395 SwSoftPageBreakList
& rBreakArr
, ULONG nIndex
,
396 SwUnoCrsr
* pUnoCrsr
, Reference
<XText
> & rParent
, XTextRangeArr
& rPortionArr
)
398 for ( SwSoftPageBreakList::iterator aIter
= rBreakArr
.begin(), aEnd
= rBreakArr
.end();
401 if ( nIndex
> *aIter
)
403 rBreakArr
.erase( aIter
++ );
406 if ( nIndex
< *aIter
)
410 new Reference
< XTextRange
>(new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_SOFT_PAGEBREAK
)),
411 rPortionArr
.Count());
412 rBreakArr
.erase( aIter
++ );
417 /* -----------------------------18.12.00 14:51--------------------------------
419 ---------------------------------------------------------------------------*/
420 //-----------------------------------------------------------------------------
421 #define REDLINE_PORTION_START_REMOVE 0//removed redlines are visible
422 #define REDLINE_PORTION_END_REMOVE 1//removed redlines are visible
423 #define REDLINE_PORTION_REMOVE 2//removed redlines are NOT visible
424 #define REDLINE_PORTION_INSERT_START 3
425 #define REDLINE_PORTION_INSERT_END 4
427 struct SwXRedlinePortion_Impl
429 const SwRedline
* pRedline
;
432 SwXRedlinePortion_Impl ( const SwRedline
* pRed
, sal_Bool bIsStart
)
437 ULONG
getRealIndex ()
439 return bStart
? pRedline
->Start()->nContent
.GetIndex() :
440 pRedline
->End() ->nContent
.GetIndex();
444 typedef boost::shared_ptr
< SwXRedlinePortion_Impl
> SwXRedlinePortion_ImplSharedPtr
;
445 struct RedlineCompareStruct
447 const SwPosition
& getPosition ( const SwXRedlinePortion_ImplSharedPtr
&r
)
449 return *(r
->bStart
? r
->pRedline
->Start() : r
->pRedline
->End());
451 bool operator () ( const SwXRedlinePortion_ImplSharedPtr
&r1
,
452 const SwXRedlinePortion_ImplSharedPtr
&r2
)
454 return getPosition ( r1
) < getPosition ( r2
);
457 typedef std::multiset
< SwXRedlinePortion_ImplSharedPtr
, RedlineCompareStruct
> SwXRedlinePortion_ImplList
;
459 //-----------------------------------------------------------------------------
460 Reference
<XTextRange
> lcl_ExportHints(SwpHints
* pHints
,
461 XTextRangeArr
& rPortionArr
,
463 const Reference
<XText
> & rParent
,
464 const xub_StrLen nCurrentIndex
,
465 SwTextPortionType
& rePortionType
,
466 bool & io_rbRightMoveForbidden
,
467 sal_Int32
& o_rNextAttrPosition
)
469 Reference
<XTextRange
> xRef
;
470 SwDoc
* pDoc
= pUnoCrsr
->GetDoc();
471 bool bAlreadyMoved
= false;
472 //search for special text attributes - first some ends
473 sal_uInt16 nEndIndex
= 0;
474 sal_uInt16 nNextEnd
= 0;
475 while(nEndIndex
< pHints
->GetEndCount() &&
476 (!pHints
->GetEnd(nEndIndex
)->GetEnd() ||
477 nCurrentIndex
>= (nNextEnd
= (*pHints
->GetEnd(nEndIndex
)->GetEnd()))))
479 if(pHints
->GetEnd(nEndIndex
)->GetEnd())
481 SwTxtAttr
* pAttr
= pHints
->GetEnd(nEndIndex
);
482 USHORT nAttrWhich
= pAttr
->Which();
483 if(nNextEnd
== nCurrentIndex
&&
484 ( RES_TXTATR_TOXMARK
== nAttrWhich
||
485 RES_TXTATR_REFMARK
== nAttrWhich
||
486 RES_TXTATR_CJK_RUBY
== nAttrWhich
))
490 case RES_TXTATR_TOXMARK
:
491 lcl_InsertTOXMarkPortion(
492 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, TRUE
);
493 rePortionType
= PORTION_TEXT
;
495 case RES_TXTATR_REFMARK
:
496 lcl_InsertRefMarkPortion(
497 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, TRUE
);
498 rePortionType
= PORTION_TEXT
;
500 case RES_TXTATR_CJK_RUBY
:
501 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
502 if( *pAttr
->GetEnd() == *pAttr
->GetStart())
504 lcl_InsertRubyPortion(
505 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, sal_False
);
507 lcl_InsertRubyPortion(
508 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, TRUE
);
509 rePortionType
= PORTION_TEXT
;
518 sal_uInt16 nStartIndex
= 0;
519 sal_uInt16 nNextStart
= 0;
520 while(nStartIndex
< pHints
->GetStartCount() &&
521 nCurrentIndex
>= (nNextStart
= (*pHints
->GetStart(nStartIndex
)->GetStart())))
523 SwTxtAttr
* pAttr
= pHints
->GetStart(nStartIndex
);
524 USHORT nAttrWhich
= pAttr
->Which();
525 if(nNextStart
== nCurrentIndex
&&
527 RES_TXTATR_TOXMARK
== nAttrWhich
||
528 RES_TXTATR_REFMARK
== nAttrWhich
||
529 RES_TXTATR_CJK_RUBY
== nAttrWhich
))
533 case RES_TXTATR_FIELD
:
534 if(!io_rbRightMoveForbidden
)
536 pUnoCrsr
->Right(1,CRSR_SKIP_CHARS
,FALSE
,FALSE
);
537 if( *pUnoCrsr
->GetMark() == *pUnoCrsr
->GetPoint() )
539 bAlreadyMoved
= true;
540 rePortionType
= PORTION_FIELD
;
543 case RES_TXTATR_FLYCNT
:
544 if(!io_rbRightMoveForbidden
)
546 pUnoCrsr
->Right(1,CRSR_SKIP_CHARS
,FALSE
,FALSE
);
547 if( *pUnoCrsr
->GetMark() == *pUnoCrsr
->GetPoint() )
548 break; // Robust #i81708 content in covered cells
549 pUnoCrsr
->Exchange();
550 bAlreadyMoved
= true;
551 rePortionType
= PORTION_FRAME
;
554 case RES_TXTATR_FTN
:
556 if(!io_rbRightMoveForbidden
)
558 pUnoCrsr
->Right(1,CRSR_SKIP_CHARS
,FALSE
,FALSE
);
559 if( *pUnoCrsr
->GetMark() == *pUnoCrsr
->GetPoint() )
561 SwXTextPortion
* pPortion
;
562 xRef
= pPortion
= new SwXTextPortion(pUnoCrsr
, rParent
, PORTION_FOOTNOTE
);
563 Reference
<XTextContent
> xContent
=
564 Reference
<XTextContent
>(
565 SwXFootnotes::GetObject(*pDoc
, pAttr
->SwTxtAttr::GetFtn()),
567 pPortion
->SetFootnote(xContent
);
568 bAlreadyMoved
= true;
569 rePortionType
= PORTION_TEXT
;
573 case RES_TXTATR_SOFTHYPH
:
575 SwXTextPortion
* pPortion
= 0;
577 new Reference
< XTextRange
>(
578 pPortion
= new SwXTextPortion(
579 pUnoCrsr
, rParent
, PORTION_CONTROL_CHAR
)),
580 rPortionArr
.Count());
581 pPortion
->SetControlChar(3);
582 rePortionType
= PORTION_TEXT
;
585 case RES_TXTATR_HARDBLANK
:
587 rePortionType
= PORTION_CONTROL_CHAR
;
588 SwXTextPortion
* pPortion
= 0;
590 new Reference
< XTextRange
>(
591 pPortion
= new SwXTextPortion(
592 pUnoCrsr
, rParent
, PORTION_CONTROL_CHAR
)),
593 rPortionArr
.Count());
594 const SwFmtHardBlank
& rFmt
= pAttr
->GetHardBlank();
595 if(rFmt
.GetChar() == '-')
596 pPortion
->SetControlChar(2);//HARD_HYPHEN
598 pPortion
->SetControlChar(4);//HARD_SPACE
599 rePortionType
= PORTION_TEXT
;
602 case RES_TXTATR_TOXMARK
:
603 lcl_InsertTOXMarkPortion(
604 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, FALSE
);
605 rePortionType
= PORTION_TEXT
;
607 case RES_TXTATR_REFMARK
:
609 if(!io_rbRightMoveForbidden
|| pAttr
->GetEnd())
613 pUnoCrsr
->Right(1,CRSR_SKIP_CHARS
,FALSE
,FALSE
);
614 bAlreadyMoved
= true;
616 lcl_InsertRefMarkPortion(
617 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, FALSE
);
618 rePortionType
= PORTION_TEXT
;
621 if(*pUnoCrsr
->GetPoint() < *pUnoCrsr
->GetMark())
622 pUnoCrsr
->Exchange();
623 pUnoCrsr
->DeleteMark();
627 case RES_TXTATR_CJK_RUBY
:
628 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
629 if(pAttr
->GetEnd() && (*pAttr
->GetEnd() != *pAttr
->GetStart()))
631 lcl_InsertRubyPortion(
632 rPortionArr
, pUnoCrsr
, rParent
, pAttr
, FALSE
);
633 rePortionType
= PORTION_TEXT
;
637 DBG_ERROR("was fuer ein Attribut?");
646 // search for attribute changes behind the current cursor position
647 // break up at frames, bookmarks, redlines
651 while(nStartIndex
< pHints
->GetStartCount() &&
652 nCurrentIndex
>= (nNextStart
= (*pHints
->GetStart(nStartIndex
)->GetStart())))
657 while(nEndIndex
< pHints
->GetEndCount() &&
658 nCurrentIndex
>= (nNextEnd
= (*pHints
->GetEnd(nEndIndex
)->GetAnyEnd())))
662 ((nNextStart
> nCurrentIndex
) && (nNextStart
< nNextEnd
))
663 ? nNextStart
: nNextEnd
;
664 if (nNextPos
> nCurrentIndex
)
666 o_rNextAttrPosition
= nNextPos
;
671 io_rbRightMoveForbidden
= true;
676 void lcl_MoveCursor( SwUnoCrsr
* pUnoCrsr
,
677 const xub_StrLen nCurrentIndex
,
678 const sal_Int32 nNextFrameIndex
, const sal_Int32 nNextPortionIndex
,
679 const sal_Int32 nNextAttrIndex
, const sal_Int32 nEndPos
)
681 sal_Int32 nMovePos
= pUnoCrsr
->GetCntntNode()->Len();
683 if ((nEndPos
>= 0) && (nEndPos
< nMovePos
))
688 if ((nNextFrameIndex
>= 0) && (nNextFrameIndex
< nMovePos
))
690 nMovePos
= nNextFrameIndex
;
693 if ((nNextPortionIndex
>= 0) && (nNextPortionIndex
< nMovePos
))
695 nMovePos
= nNextPortionIndex
;
698 if ((nNextAttrIndex
>= 0) && (nNextAttrIndex
< nMovePos
))
700 nMovePos
= nNextAttrIndex
;
703 if (nMovePos
> nCurrentIndex
)
705 // pUnoCrsr->Right(nMovePos - nCurrentIndex);
706 pUnoCrsr
->GetPoint()->nContent
= static_cast<USHORT
>(nMovePos
);
708 else if(nEndPos
< 0 || nCurrentIndex
< nEndPos
)
710 // ensure proper exit: move to paragraph end
711 // (this should not be necessary any more; we assert it only
712 // happens when the above would move to the end of the
714 DBG_ASSERT(nMovePos
== pUnoCrsr
->GetCntntNode()->Len()||
715 (nEndPos
> 0 && nMovePos
== nEndPos
),
716 "may only happen at paragraph end");
717 pUnoCrsr
->MovePara(fnParaCurr
, fnParaEnd
);
721 //-----------------------------------------------------------------------------
722 void lcl_FillRedlineArray(SwDoc
& rDoc
,SwUnoCrsr
& rUnoCrsr
, SwXRedlinePortion_ImplList
& rRedArr
)
724 const SwRedlineTbl
& rRedTbl
= rDoc
.GetRedlineTbl();
725 USHORT nRedTblCount
= rRedTbl
.Count();
727 if ( nRedTblCount
> 0 )
729 const SwPosition
* pStart
= rUnoCrsr
.GetPoint();
730 const SwNodeIndex nOwnNode
= pStart
->nNode
;
732 for(USHORT nRed
= 0; nRed
< nRedTblCount
; nRed
++)
734 const SwRedline
* pRedline
= rRedTbl
[nRed
];
735 const SwPosition
* pRedStart
= pRedline
->Start();
736 const SwNodeIndex nRedNode
= pRedStart
->nNode
;
737 if ( nOwnNode
== nRedNode
)
738 rRedArr
.insert( SwXRedlinePortion_ImplSharedPtr (
739 new SwXRedlinePortion_Impl ( pRedline
, TRUE
) ) );
740 if( pRedline
->HasMark() && pRedline
->End()->nNode
== nOwnNode
)
741 rRedArr
.insert( SwXRedlinePortion_ImplSharedPtr (
742 new SwXRedlinePortion_Impl ( pRedline
, FALSE
) ) );
747 //-----------------------------------------------------------------------------
748 void lcl_FillSoftPageBreakArray( SwUnoCrsr
& rUnoCrsr
, SwSoftPageBreakList
& rBreakArr
)
750 const SwTxtNode
*pTxtNode
= rUnoCrsr
.GetPoint()->nNode
.GetNode().GetTxtNode();
752 pTxtNode
->fillSoftPageBreakList( rBreakArr
);
755 /* -----------------------------19.12.00 12:25--------------------------------
757 ---------------------------------------------------------------------------*/
758 void lcl_ExportRedline(
759 SwXRedlinePortion_ImplList
& rRedlineArr
, ULONG nIndex
,
760 SwUnoCrsr
* pUnoCrsr
, Reference
<XText
> & rParent
, XTextRangeArr
& rPortionArr
)
763 // MTG: 23/11/05: We want this loop to iterate over all red lines in this
764 // array. We will only insert the ones with index matches
765 for ( SwXRedlinePortion_ImplList::iterator aIter
= rRedlineArr
.begin(), aEnd
= rRedlineArr
.end();
768 SwXRedlinePortion_ImplSharedPtr pPtr
= (*aIter
);
769 ULONG nRealIndex
= pPtr
->getRealIndex();
770 // MTG: 23/11/05: If there are elements before nIndex, remove them
771 if ( nIndex
> nRealIndex
)
772 rRedlineArr
.erase ( aIter
++ );
773 // MTG: 23/11/05: If the elements match, and them to the list
774 else if ( nIndex
== nRealIndex
)
777 new Reference
< XTextRange
>( new SwXRedlinePortion(
778 pPtr
->pRedline
, pUnoCrsr
, rParent
, pPtr
->bStart
)),
779 rPortionArr
.Count());
780 rRedlineArr
.erase ( aIter
++ );
782 // MTG: 23/11/05: If we've iterated past nIndex, exit the loop
787 /* -----------------------------19.12.00 13:09--------------------------------
789 ---------------------------------------------------------------------------*/
790 void lcl_ExportBkmAndRedline(
791 SwXBookmarkPortion_ImplList
& rBkmArr
,
792 SwXRedlinePortion_ImplList
& rRedlineArr
,
793 SwSoftPageBreakList
& rBreakArr
,
795 SwUnoCrsr
* pUnoCrsr
, Reference
<XText
> & rParent
, XTextRangeArr
& rPortionArr
)
798 lcl_ExportBookmark(rBkmArr
, nIndex
, pUnoCrsr
, rParent
, rPortionArr
);
800 if (rRedlineArr
.size())
801 lcl_ExportRedline(rRedlineArr
, nIndex
, pUnoCrsr
, rParent
, rPortionArr
);
803 if (rBreakArr
.size())
804 lcl_ExportSoftPageBreak(rBreakArr
, nIndex
, pUnoCrsr
, rParent
, rPortionArr
);
806 //-----------------------------------------------------------------------------
807 sal_Int32
lcl_GetNextIndex(SwXBookmarkPortion_ImplList
& rBkmArr
,
808 SwXRedlinePortion_ImplList
& rRedlineArr
,
809 SwSoftPageBreakList
& rBreakArr
)
814 SwXBookmarkPortion_ImplSharedPtr pPtr
= (*rBkmArr
.begin());
815 nRet
= pPtr
->getIndex();
817 if(rRedlineArr
.size())
819 SwXRedlinePortion_ImplSharedPtr pPtr
= (*rRedlineArr
.begin());
820 sal_Int32 nTmp
= pPtr
->getRealIndex();
821 if(nRet
< 0 || nTmp
< nRet
)
826 if(nRet
< 0 || *rBreakArr
.begin() < static_cast<sal_uInt32
>(nRet
))
827 nRet
= *rBreakArr
.begin();
831 //-----------------------------------------------------------------------------
832 void SwXTextPortionEnumeration::CreatePortions()
834 SwUnoCrsr
* pUnoCrsr
= GetCrsr();
835 // set the start if a selection should be exported
836 if(nStartPos
> 0 && pUnoCrsr
->Start()->nContent
.GetIndex() != nStartPos
)
838 if(pUnoCrsr
->HasMark())
839 pUnoCrsr
->DeleteMark();
840 DBG_ASSERT(pUnoCrsr
->Start()->nNode
.GetNode().GetTxtNode() &&
841 nStartPos
<= pUnoCrsr
->Start()->nNode
.GetNode().GetTxtNode()->GetTxt().Len(),
842 "Incorrect start position" );
843 // ??? should this be nStartPos - current position ?
844 pUnoCrsr
->Right((xub_StrLen
)nStartPos
,CRSR_SKIP_CHARS
,FALSE
,FALSE
);
846 if(pUnoCrsr
/*&& !bAtEnd*/)
848 SwXBookmarkPortion_ImplList aBkmArr
;
849 SwXRedlinePortion_ImplList aRedArr
;
850 SwSoftPageBreakList aBreakArr
;
852 SwDoc
* pDoc
= pUnoCrsr
->GetDoc();
853 lcl_FillRedlineArray(*pDoc
, *pUnoCrsr
, aRedArr
);
854 lcl_FillBookmarkArray(*pDoc
, *pUnoCrsr
, aBkmArr
);
855 lcl_FillSoftPageBreakArray( *pUnoCrsr
, aBreakArr
);
856 #if OSL_DEBUG_LEVEL > 1
857 for (SwXBookmarkPortion_ImplList::const_iterator aIter
= aBkmArr
.begin(), aEnd
= aBkmArr
.end();
861 SwXBookmarkPortion_ImplSharedPtr pPtr
= (*aIter
);
867 if(pUnoCrsr
->HasMark())
869 if(*pUnoCrsr
->GetPoint() < *pUnoCrsr
->GetMark())
870 pUnoCrsr
->Exchange();
871 pUnoCrsr
->DeleteMark();
873 SwNode
* pNode
= pUnoCrsr
->GetNode();
874 SwCntntNode
*pCNd
= pNode
->GetCntntNode();
875 if(!bFirstPortion
&& pCNd
&&
876 pUnoCrsr
->GetPoint()->nContent
== pCNd
->Len())
878 //hier sollte man nie ankommen!
883 if(ND_TEXTNODE
== pNode
->GetNodeType())
885 SwTxtNode
* pTxtNode
= (SwTxtNode
*)pNode
;
886 SwpHints
* pHints
= pTxtNode
->GetpSwpHints();
887 SwTextPortionType ePortionType
= PORTION_TEXT
;
888 xub_StrLen nCurrentIndex
= pUnoCrsr
->GetPoint()->nContent
.GetIndex();
889 xub_StrLen nFirstFrameIndex
= STRING_MAXLEN
;
890 uno::Reference
< XTextRange
> xRef
;
893 lcl_ExportBkmAndRedline(aBkmArr
, aRedArr
, aBreakArr
, 0, pUnoCrsr
, xParent
, aPortionArr
);
894 // the paragraph is empty
895 xRef
= new SwXTextPortion(pUnoCrsr
, xParent
, ePortionType
);
896 // are there any frames?
897 while(aFrameArr
.Count())
899 SwDepend
* pCurDepend
= aFrameArr
.GetObject(0);
900 if(pCurDepend
->GetRegisteredIn())
902 //the previously created portion has to be inserted here
903 aPortionArr
.Insert(new Reference
<XTextRange
>(xRef
), aPortionArr
.Count());
904 xRef
= new SwXTextPortion(pUnoCrsr
, xParent
,
905 *(SwFrmFmt
*)pCurDepend
->GetRegisteredIn());
913 //falls schon Rahmen entsorgt wurden, dann raus hier
914 for(sal_uInt16 nFrame
= aFrameArr
.Count(); nFrame
; nFrame
--)
916 SwDepend
* pCurDepend
= aFrameArr
.GetObject(nFrame
- 1);
917 if(!pCurDepend
->GetRegisteredIn())
920 aFrameArr
.Remove(nFrame
- 1);
924 //zunaechst den ersten Frame im aFrameArr finden (bezogen auf die Position im Absatz)
925 SwDepend
* pFirstFrameDepend
= 0;
926 //Eintraege im aFrameArr sind sortiert!
927 if(aFrameArr
.Count())
929 SwDepend
* pCurDepend
= aFrameArr
.GetObject(0);
930 SwFrmFmt
* pFormat
= (SwFrmFmt
*)pCurDepend
->GetRegisteredIn();
931 const SwFmtAnchor
& rAnchor
= pFormat
->GetAnchor();
932 const SwPosition
* pAnchorPos
= rAnchor
.GetCntntAnchor();
933 pFirstFrameDepend
= pCurDepend
;
934 nFirstFrameIndex
= pAnchorPos
->nContent
.GetIndex();
935 if(nEndPos
>= 0 && nFirstFrameIndex
>= nEndPos
)
936 nFirstFrameIndex
= USHRT_MAX
;
939 SwXTextCursor::SelectPam(*pUnoCrsr
, sal_True
);
941 //ist hier schon ein Rahmen faellig?
942 if(nCurrentIndex
== nFirstFrameIndex
)
944 xRef
= new SwXTextPortion(pUnoCrsr
, xParent
,
945 *(SwFrmFmt
*)pFirstFrameDepend
->GetRegisteredIn());
946 SwDepend
* pCurDepend
= aFrameArr
.GetObject(0);
953 lcl_ExportBkmAndRedline(aBkmArr
, aRedArr
, aBreakArr
,
954 nCurrentIndex
, pUnoCrsr
, xParent
, aPortionArr
);
955 sal_Int32 nNextAttrIndex
= -1;
956 sal_Int32 nNextPortionIndex
=
957 lcl_GetNextIndex(aBkmArr
, aRedArr
, aBreakArr
);
958 // #111716# the cursor must not move right at the
959 // end position of a selection!
960 bool bRightMoveForbidden
=
961 ((nEndPos
> 0) && (nCurrentIndex
>= nEndPos
));
964 // N.B.: side-effects bRightMoveForbidden
965 // and nNextAttrIndex
966 xRef
= lcl_ExportHints(pHints
, aPortionArr
,
967 pUnoCrsr
, xParent
, nCurrentIndex
, ePortionType
,
968 bRightMoveForbidden
, nNextAttrIndex
);
970 if (!bRightMoveForbidden
)
972 lcl_MoveCursor(pUnoCrsr
, nCurrentIndex
,
973 nFirstFrameIndex
, nNextPortionIndex
,
974 nNextAttrIndex
, nEndPos
);
977 if(!xRef
.is() && pUnoCrsr
->HasMark() ) {
978 //flr: maybe its a good idea to add a special hint to the hints array and rely on the hint segmentation....
979 xub_StrLen start
=pUnoCrsr
->Start()->nContent
.GetIndex();
980 xub_StrLen end
=pUnoCrsr
->End()->nContent
.GetIndex();
981 ASSERT(start
<=end
, "hmm --- why is this different");
982 xub_StrLen startMarkerPos
=pTxtNode
->GetTxt().Search(CH_TXT_ATR_FIELDSTART
, start
);
983 xub_StrLen endMarkerPos
=pTxtNode
->GetTxt().Search(CH_TXT_ATR_FIELDEND
, start
);
984 xub_StrLen formMarkerPos
=pTxtNode
->GetTxt().Search(CH_TXT_ATR_FORMELEMENT
, start
);
985 xub_StrLen markerPos
=STRING_LEN
;
986 if (startMarkerPos
>=start
&& startMarkerPos
<end
)
988 markerPos
=startMarkerPos
;
990 if (endMarkerPos
>=start
&& endMarkerPos
<end
)
992 if (endMarkerPos
<markerPos
)
993 markerPos
=endMarkerPos
;
995 if (formMarkerPos
>=start
&& formMarkerPos
<end
)
997 if (formMarkerPos
<markerPos
)
998 markerPos
=formMarkerPos
;
1002 if (start
==markerPos
)
1007 pUnoCrsr
->GetPoint()->nContent
= end
;
1009 if (start
+1==end
&& pTxtNode
->GetTxt().GetChar(start
)==CH_TXT_ATR_FIELDSTART
)
1011 ::sw::mark::IFieldmark
* pFieldmark
= NULL
;
1012 if (pDoc
&& pUnoCrsr
->GetPoint())
1013 pFieldmark
= pDoc
->getIDocumentMarkAccess()->getFieldmarkFor(*pUnoCrsr
->GetPoint());
1014 SwXTextPortion
* pPortion
= NULL
;
1015 xRef
= (pPortion
= new SwXTextPortion(pUnoCrsr
, xParent
, PORTION_FIELD_START
));
1016 if (pPortion
&& pFieldmark
&& pDoc
)
1017 pPortion
->SetBookmark(new SwXFieldmark(false, pFieldmark
, pDoc
));
1019 else if (start
+1==end
&& pTxtNode
->GetTxt().GetChar(start
)==CH_TXT_ATR_FIELDEND
)
1021 ::sw::mark::IFieldmark
* pFieldmark
= NULL
;
1022 if (pDoc
&& pUnoCrsr
->GetPoint())
1024 SwPosition
aPos(*pUnoCrsr
->GetPoint());
1025 aPos
.nContent
= markerPos
;
1026 pFieldmark
= pDoc
->getIDocumentMarkAccess()->getFieldmarkFor(aPos
);
1028 SwXTextPortion
* pPortion
= NULL
;
1029 xRef
= (pPortion
= new SwXTextPortion(pUnoCrsr
, xParent
, PORTION_FIELD_END
));
1030 if (pPortion
&& pFieldmark
&& pDoc
)
1031 pPortion
->SetBookmark(new SwXFieldmark(false, pFieldmark
, pDoc
));
1033 else if (start
+1==end
&& pTxtNode
->GetTxt().GetChar(start
)==CH_TXT_ATR_FORMELEMENT
)
1035 ::sw::mark::IFieldmark
* pFieldmark
= NULL
;
1036 if (pDoc
&& pUnoCrsr
->GetPoint())
1038 SwPosition
aPos(*pUnoCrsr
->GetPoint());
1039 aPos
.nContent
=markerPos
;
1040 pFieldmark
= pDoc
->getIDocumentMarkAccess()->getFieldmarkFor(aPos
);
1042 SwXTextPortion
* pPortion
=NULL
;
1043 xRef
= (pPortion
= new SwXTextPortion(pUnoCrsr
, xParent
, PORTION_FIELD_START_END
));
1044 if(pPortion
&& pFieldmark
&& pDoc
)
1045 pPortion
->SetBookmark(new SwXFieldmark(true, pFieldmark
, pDoc
));
1049 xRef
= new SwXTextPortion(pUnoCrsr
, xParent
, ePortionType
);
1053 aPortionArr
.Insert(new Reference
<XTextRange
>(xRef
), aPortionArr
.Count());
1057 DBG_ERROR("kein TextNode - was nun?");
1060 if(*pUnoCrsr
->GetPoint() < *pUnoCrsr
->GetMark())
1061 pUnoCrsr
->Exchange();
1064 pNode
= pUnoCrsr
->GetNode();
1065 pCNd
= pNode
->GetCntntNode();
1066 sal_Int32 nLocalEnd
= nEndPos
>= 0 ? nEndPos
: pCNd
->Len();
1067 if( pCNd
&& pUnoCrsr
->GetPoint()->nContent
>= (xub_StrLen
)nLocalEnd
)
1070 lcl_ExportBkmAndRedline(aBkmArr
, aRedArr
, aBreakArr
, nLocalEnd
,
1071 pUnoCrsr
, xParent
, aPortionArr
);
1072 if(ND_TEXTNODE
== pNode
->GetNodeType())
1074 SwTxtNode
* pTxtNode
= (SwTxtNode
*)pNode
;
1075 SwpHints
* pHints
= pTxtNode
->GetpSwpHints();
1078 SwTextPortionType ePortionType
= PORTION_TEXT
;
1079 bool bDummy
= false;
1080 sal_Int32 nDummy
= -1;
1081 Reference
<XTextRange
> xRef
= lcl_ExportHints(pHints
,
1085 static_cast< xub_StrLen
>(nLocalEnd
),
1089 aPortionArr
.Insert(new Reference
<XTextRange
>(xRef
), aPortionArr
.Count());
1092 while(aFrameArr
.Count())
1094 SwDepend
* pCurDepend
= aFrameArr
.GetObject(0);
1095 if(pCurDepend
->GetRegisteredIn())
1097 Reference
<XTextRange
> xRef
= new SwXTextPortion(pUnoCrsr
, xParent
,
1098 *(SwFrmFmt
*)pCurDepend
->GetRegisteredIn());
1099 aPortionArr
.Insert(new Reference
<XTextRange
>(xRef
), aPortionArr
.Count());
1102 aFrameArr
.Remove(0);
1109 /*-- 27.01.99 10:44:45---------------------------------------------------
1111 -----------------------------------------------------------------------*/
1112 void SwXTextPortionEnumeration::Modify( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
)
1114 ClientModify(this, pOld
, pNew
);