update dev300-m58
[ooovba.git] / sw / source / core / unocore / unoportenum.cxx
blob5aa9d224c4f4c7b2a2ae24aaa2ffef45a9a3f27a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoportenum.cxx,v $
10 * $Revision: 1.42 $
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"
35 #include <IMark.hxx>
36 // --> OD 2007-10-23 #i81002#
37 #include <crossrefbookmark.hxx>
38 // <--
39 #include <doc.hxx>
40 #include <txatbase.hxx>
41 #include <ndhints.hxx>
42 #include <ndtxt.hxx>
43 #include <unocrsr.hxx>
44 #include <docary.hxx>
45 #include <fmthbsh.hxx>
46 #include <tox.hxx>
47 #include <unoclbck.hxx>
48 #include <unoobj.hxx>
49 #include <unoredline.hxx>
50 #include <fmtanchr.hxx>
51 #include <unoidx.hxx>
52 #include <redline.hxx>
53 #include <crsskip.hxx>
54 #include <vos/mutex.hxx>
55 #include <vcl/svapp.hxx>
56 #include <set>
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;
68 namespace
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;
77 BYTE nBkmType;
78 const SwPosition aPosition;
80 SwXBookmarkPortion_Impl( SwXBookmark* pXMark, BYTE nType, const SwPosition &rPosition )
81 : xBookmark ( pXMark )
82 , nBkmType ( nType )
83 , aPosition ( rPosition )
86 ULONG getIndex ()
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())
120 return;
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(),
128 aEndOfPara,
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;
135 ++ppMark)
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;
153 if(hasOther)
154 pEndPos = &rEndPos;
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();
162 if(pEndPos)
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();
180 return aSeq;
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 ) );
194 return 0;
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");
218 return aRet;
220 /*-- 27.01.99 10:44:43---------------------------------------------------
222 -----------------------------------------------------------------------*/
223 SwXTextPortionEnumeration::SwXTextPortionEnumeration(
224 SwPaM& rParaCrsr,
225 uno::Reference< XText > xParentText,
226 sal_Int32 nStart,
227 sal_Int32 nEnd
229 xParent(xParentText),
230 bAtEnd(sal_False),
231 bFirstPortion(sal_True),
232 nStartPos(nStart),
233 nEndPos(nEnd)
235 SwUnoCrsr* pUnoCrsr = rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), sal_False);
236 pUnoCrsr->Add(this);
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,
244 aFrameArr, TRUE );
245 CreatePortions();
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();
261 delete pUnoCrsr;
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);
283 delete pPortion;
284 return aRet;
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);
296 if(!xContent.is())
297 xContent = new SwXReferenceMark(pDoc, &rRefMark);
299 SwXTextPortion* pPortion = 0;
300 if(!bEnd)
302 rArr.Insert(
303 new Reference< XTextRange >(pPortion = new SwXTextPortion(pUnoCrsr, rParent, PORTION_REFMARK_START)),
304 rArr.Count());
305 pPortion->SetRefMark(xContent);
306 pPortion->SetCollapsed(pAttr->GetEnd() ? FALSE : TRUE);
308 else
310 rArr.Insert(
311 new Reference< XTextRange >(pPortion = new SwXTextPortion(pUnoCrsr, rParent, PORTION_REFMARK_END)),
312 rArr.Count());
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);
335 if(!xContent.is())
336 xContent = new SwXDocumentIndexMark(rTOXMark.GetTOXType(), &rTOXMark, pDoc);
338 SwXTextPortion* pPortion = 0;
339 if(!bEnd)
341 rArr.Insert(
342 new Reference< XTextRange >(pPortion = new SwXTextPortion(pUnoCrsr, rParent, PORTION_TOXMARK_START)),
343 rArr.Count());
344 pPortion->SetTOXMark(xContent);
345 pPortion->SetCollapsed(pAttr->GetEnd() ? FALSE : TRUE);
347 if(bEnd)
349 rArr.Insert(
350 new Reference< XTextRange >(pPortion = new SwXTextPortion(pUnoCrsr, rParent, PORTION_TOXMARK_END)),
351 rArr.Count());
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();
362 aIter != aEnd; )
364 SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
365 if ( nIndex > pPtr->getIndex() )
367 rBkmArr.erase( aIter++ );
368 continue;
370 if ( nIndex < pPtr->getIndex() )
371 break;
373 SwXTextPortion* pPortion = 0;
374 if(BKM_TYPE_START == pPtr->nBkmType || BKM_TYPE_START_END == pPtr->nBkmType)
376 rPortionArr.Insert(
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)
385 rPortionArr.Insert(
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();
399 aIter != aEnd; )
401 if ( nIndex > *aIter )
403 rBreakArr.erase( aIter++ );
404 continue;
406 if ( nIndex < *aIter )
407 break;
409 rPortionArr.Insert(
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;
430 sal_Bool bStart;
432 SwXRedlinePortion_Impl ( const SwRedline* pRed, sal_Bool bIsStart )
433 : pRedline(pRed)
434 , bStart(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,
462 SwUnoCrsr* pUnoCrsr,
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))
488 switch( nAttrWhich )
490 case RES_TXTATR_TOXMARK:
491 lcl_InsertTOXMarkPortion(
492 rPortionArr, pUnoCrsr, rParent, pAttr, TRUE);
493 rePortionType = PORTION_TEXT;
494 break;
495 case RES_TXTATR_REFMARK:
496 lcl_InsertRefMarkPortion(
497 rPortionArr, pUnoCrsr, rParent, pAttr, TRUE);
498 rePortionType = PORTION_TEXT;
499 break;
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;
510 break;
514 nEndIndex++;
517 // then some starts
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 &&
526 (!pAttr->GetEnd() ||
527 RES_TXTATR_TOXMARK == nAttrWhich ||
528 RES_TXTATR_REFMARK == nAttrWhich||
529 RES_TXTATR_CJK_RUBY == nAttrWhich))
531 switch( 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() )
538 break;
539 bAlreadyMoved = true;
540 rePortionType = PORTION_FIELD;
542 break;
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;
553 break;
554 case RES_TXTATR_FTN :
556 if(!io_rbRightMoveForbidden)
558 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,FALSE,FALSE);
559 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
560 break;
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()),
566 UNO_QUERY);
567 pPortion->SetFootnote(xContent);
568 bAlreadyMoved = true;
569 rePortionType = PORTION_TEXT;
572 break;
573 case RES_TXTATR_SOFTHYPH :
575 SwXTextPortion* pPortion = 0;
576 rPortionArr.Insert(
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;
584 break;
585 case RES_TXTATR_HARDBLANK:
587 rePortionType = PORTION_CONTROL_CHAR;
588 SwXTextPortion* pPortion = 0;
589 rPortionArr.Insert(
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
597 else
598 pPortion->SetControlChar(4);//HARD_SPACE
599 rePortionType = PORTION_TEXT;
601 break;
602 case RES_TXTATR_TOXMARK:
603 lcl_InsertTOXMarkPortion(
604 rPortionArr, pUnoCrsr, rParent, pAttr, FALSE);
605 rePortionType = PORTION_TEXT;
606 break;
607 case RES_TXTATR_REFMARK:
609 if(!io_rbRightMoveForbidden || pAttr->GetEnd())
611 if(!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;
619 if(!pAttr->GetEnd())
621 if(*pUnoCrsr->GetPoint() < *pUnoCrsr->GetMark())
622 pUnoCrsr->Exchange();
623 pUnoCrsr->DeleteMark();
626 break;
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;
635 break;
636 default:
637 DBG_ERROR("was fuer ein Attribut?");
641 nStartIndex++;
644 if (!bAlreadyMoved)
646 // search for attribute changes behind the current cursor position
647 // break up at frames, bookmarks, redlines
649 nStartIndex = 0;
650 nNextStart = 0;
651 while(nStartIndex < pHints->GetStartCount() &&
652 nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
653 nStartIndex++;
655 nEndIndex = 0;
656 nNextEnd = 0;
657 while(nEndIndex < pHints->GetEndCount() &&
658 nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd())))
659 nEndIndex++;
661 sal_Int32 nNextPos =
662 ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
663 ? nNextStart : nNextEnd;
664 if (nNextPos > nCurrentIndex)
666 o_rNextAttrPosition = nNextPos;
669 else
671 io_rbRightMoveForbidden = true;
673 return xRef;
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))
685 nMovePos = nEndPos;
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
713 // paragraph anyway)
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();
751 if( pTxtNode )
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();
766 aIter != aEnd; )
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 )
776 rPortionArr.Insert(
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
783 else
784 break;
787 /* -----------------------------19.12.00 13:09--------------------------------
789 ---------------------------------------------------------------------------*/
790 void lcl_ExportBkmAndRedline(
791 SwXBookmarkPortion_ImplList& rBkmArr,
792 SwXRedlinePortion_ImplList& rRedlineArr,
793 SwSoftPageBreakList& rBreakArr,
794 ULONG nIndex,
795 SwUnoCrsr* pUnoCrsr, Reference<XText> & rParent, XTextRangeArr& rPortionArr)
797 if (rBkmArr.size())
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 )
811 sal_Int32 nRet = -1;
812 if(rBkmArr.size())
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)
822 nRet = nTmp;
824 if(rBreakArr.size())
826 if(nRet < 0 || *rBreakArr.begin() < static_cast<sal_uInt32>(nRet))
827 nRet = *rBreakArr.begin();
829 return nRet;
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();
858 aIter != aEnd;
859 ++aIter )
861 SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
864 #endif
865 while(!bAtEnd)
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!
879 bAtEnd = sal_True;
881 else
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;
891 if(!pCNd->Len())
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());
907 delete pCurDepend;
908 aFrameArr.Remove(0);
911 else
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())
919 delete pCurDepend;
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);
947 delete pCurDepend;
948 aFrameArr.Remove(0);
951 if(!xRef.is())
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));
962 if (pHints)
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;
1000 if (markerPos<end)
1002 if (start==markerPos)
1003 end = markerPos+1;
1004 else
1005 end = markerPos;
1006 bAtEnd = sal_False;
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));
1047 else
1049 xRef = new SwXTextPortion(pUnoCrsr, xParent, ePortionType);
1052 if(xRef.is())
1053 aPortionArr.Insert(new Reference<XTextRange>(xRef), aPortionArr.Count());
1055 else
1057 DBG_ERROR("kein TextNode - was nun?");
1060 if(*pUnoCrsr->GetPoint() < *pUnoCrsr->GetMark())
1061 pUnoCrsr->Exchange();
1063 // Absatzende ?
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)
1069 bAtEnd = sal_True;
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();
1076 if(pHints)
1078 SwTextPortionType ePortionType = PORTION_TEXT;
1079 bool bDummy = false;
1080 sal_Int32 nDummy = -1;
1081 Reference<XTextRange> xRef = lcl_ExportHints(pHints,
1082 aPortionArr,
1083 pUnoCrsr,
1084 xParent,
1085 static_cast< xub_StrLen >(nLocalEnd),
1086 ePortionType,
1087 bDummy, nDummy);
1088 if(xRef.is())
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());
1101 delete pCurDepend;
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);