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__anonffb1c5bf0111::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__anonffb1c5bf0111::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 ()__anonffb1c5bf0111::BookmarkCompareStruct116 bool operator () ( const SwXBookmarkPortion_ImplSharedPtr &r1,
117 const SwXBookmarkPortion_ImplSharedPtr &r2 )
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__anonffb1c5bf0111::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__anonffb1c5bf0111::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 ()__anonffb1c5bf0111::AnnotationStartCompareStruct225 bool operator () ( const SwAnnotationStartPortion_ImplSharedPtr &r1,
226 const SwAnnotationStartPortion_ImplSharedPtr &r2 )
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 throw(uno::RuntimeException)
302 {
303 if( rId.getLength() == 16
304 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
305 rId.getConstArray(), 16 ) )
306 {
307 return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
308 }
309 return 0;
310 }
311 /* -----------------------------06.04.00 16:39--------------------------------
312
313 ---------------------------------------------------------------------------*/
getImplementationName()314 OUString SwXTextPortionEnumeration::getImplementationName()
315 throw( RuntimeException )
316 {
317 return C2U("SwXTextPortionEnumeration");
318 }
319 /* -----------------------------06.04.00 16:39--------------------------------
320
321 ---------------------------------------------------------------------------*/
322 sal_Bool
supportsService(const OUString & rServiceName)323 SwXTextPortionEnumeration::supportsService(const OUString& rServiceName)
324 throw( RuntimeException )
325 {
326 return C2U("com.sun.star.text.TextPortionEnumeration") == rServiceName;
327 }
328 /* -----------------------------06.04.00 16:39--------------------------------
329
330 ---------------------------------------------------------------------------*/
getSupportedServiceNames()331 Sequence< OUString > SwXTextPortionEnumeration::getSupportedServiceNames()
332 throw( RuntimeException )
333 {
334 Sequence< OUString > aRet(1);
335 OUString* pArray = aRet.getArray();
336 pArray[0] = C2U("com.sun.star.text.TextPortionEnumeration");
337 return aRet;
338 }
339
340 /*-- 27.01.99 10:44:43---------------------------------------------------
341
342 -----------------------------------------------------------------------*/
SwXTextPortionEnumeration(SwPaM & rParaCrsr,uno::Reference<XText> const & xParentText,const sal_Int32 nStart,const sal_Int32 nEnd)343 SwXTextPortionEnumeration::SwXTextPortionEnumeration(
344 SwPaM& rParaCrsr,
345 uno::Reference< XText > const & xParentText,
346 const sal_Int32 nStart,
347 const sal_Int32 nEnd )
348 : m_Portions()
349 {
350 SwUnoCrsr* pUnoCrsr =
351 rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), sal_False);
352 pUnoCrsr->Add(this);
353
354 DBG_ASSERT(nEnd == -1 || (nStart <= nEnd &&
355 nEnd <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->GetTxt().Len()),
356 "start or end value invalid!");
357
358 // find all frames, graphics and OLEs that are bound AT character in para
359 FrameDependSortList_t frames;
360 ::CollectFrameAtNode(*this, pUnoCrsr->GetPoint()->nNode, frames, true);
361 lcl_CreatePortions(m_Portions, xParentText, pUnoCrsr, frames, nStart, nEnd);
362 }
363
SwXTextPortionEnumeration(SwPaM & rParaCrsr,TextRangeList_t const & rPortions)364 SwXTextPortionEnumeration::SwXTextPortionEnumeration(
365 SwPaM& rParaCrsr,
366 TextRangeList_t const & rPortions )
367 : m_Portions( rPortions )
368 {
369 SwUnoCrsr* const pUnoCrsr =
370 rParaCrsr.GetDoc()->CreateUnoCrsr(*rParaCrsr.GetPoint(), sal_False);
371 pUnoCrsr->Add(this);
372 }
373
374 /*-- 27.01.99 10:44:44---------------------------------------------------
375
376 -----------------------------------------------------------------------*/
~SwXTextPortionEnumeration()377 SwXTextPortionEnumeration::~SwXTextPortionEnumeration()
378 {
379 vos::OGuard aGuard(Application::GetSolarMutex());
380
381 SwUnoCrsr* pUnoCrsr = GetCursor();
382 delete pUnoCrsr;
383 }
384 /*-- 27.01.99 10:44:44---------------------------------------------------
385
386 -----------------------------------------------------------------------*/
hasMoreElements()387 sal_Bool SwXTextPortionEnumeration::hasMoreElements()
388 throw( uno::RuntimeException )
389 {
390 vos::OGuard aGuard(Application::GetSolarMutex());
391
392 return (m_Portions.size() > 0) ? sal_True : sal_False;
393 }
394 /*-- 27.01.99 10:44:45---------------------------------------------------
395
396 -----------------------------------------------------------------------*/
nextElement()397 uno::Any SwXTextPortionEnumeration::nextElement()
398 throw( container::NoSuchElementException, lang::WrappedTargetException,
399 uno::RuntimeException )
400 {
401 vos::OGuard aGuard(Application::GetSolarMutex());
402
403 if (!m_Portions.size())
404 throw container::NoSuchElementException();
405
406 Any any;
407 any <<= m_Portions.front();
408 m_Portions.pop_front();
409 return any;
410 }
411
412 //======================================================================
413
414 typedef ::std::deque< xub_StrLen > FieldMarks_t;
415
lcl_FillFieldMarkArray(FieldMarks_t & rFieldMarks,SwUnoCrsr const & rUnoCrsr,const sal_Int32 i_nStartPos)416 static void lcl_FillFieldMarkArray(
417 FieldMarks_t & rFieldMarks,
418 SwUnoCrsr const & rUnoCrsr,
419 const sal_Int32 i_nStartPos)
420 {
421 const SwTxtNode * const pTxtNode =
422 rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
423 if (!pTxtNode) return;
424
425 const sal_Unicode fld[] = {
426 CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, CH_TXT_ATR_FORMELEMENT, 0 };
427 xub_StrLen pos = ::std::max(static_cast<const sal_Int32>(0), i_nStartPos);
428 while ((pos = pTxtNode->GetTxt().SearchChar(fld, pos)) != STRING_NOTFOUND)
429 {
430 rFieldMarks.push_back(pos);
431 ++pos;
432 }
433 }
434
435 static uno::Reference<text::XTextRange>
lcl_ExportFieldMark(uno::Reference<text::XText> const & i_xParentText,SwUnoCrsr * const pUnoCrsr,const SwTxtNode * const pTxtNode)436 lcl_ExportFieldMark(
437 uno::Reference< text::XText > const & i_xParentText,
438 SwUnoCrsr * const pUnoCrsr,
439 const SwTxtNode * const pTxtNode )
440 {
441 uno::Reference<text::XTextRange> xRef;
442 SwDoc* pDoc = pUnoCrsr->GetDoc();
443 //flr: maybe its a good idea to add a special hint to the hints array and rely on the hint segmentation....
444 const xub_StrLen start = pUnoCrsr->Start()->nContent.GetIndex();
445 ASSERT(pUnoCrsr->End()->nContent.GetIndex() == start,
446 "hmm --- why is this different");
447
448 pUnoCrsr->Right(1, CRSR_SKIP_CHARS, sal_False, sal_False);
449 if ( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
450 {
451 ASSERT(false, "cannot move cursor?");
452 return 0;
453 }
454
455 const sal_Unicode Char = pTxtNode->GetTxt().GetChar(start);
456 if (CH_TXT_ATR_FIELDSTART == Char)
457 {
458 ::sw::mark::IFieldmark* pFieldmark = NULL;
459 if ( pDoc != NULL )
460 {
461 pFieldmark =
462 pDoc->getIDocumentMarkAccess()->getFieldmarkFor(*pUnoCrsr->GetMark());
463 }
464 SwXTextPortion* pPortion =
465 new SwXTextPortion( pUnoCrsr, i_xParentText, PORTION_FIELD_START );
466 xRef = pPortion;
467 if ( pPortion != NULL
468 && pFieldmark != NULL
469 && pDoc != NULL )
470 {
471 pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
472 }
473 }
474 else if (CH_TXT_ATR_FIELDEND == Char)
475 {
476 ::sw::mark::IFieldmark* pFieldmark = NULL;
477 if ( pDoc != NULL )
478 {
479 pFieldmark =
480 pDoc->getIDocumentMarkAccess()->getFieldmarkFor(*pUnoCrsr->GetMark());
481 }
482 SwXTextPortion* pPortion =
483 new SwXTextPortion( pUnoCrsr, i_xParentText, PORTION_FIELD_END );
484 xRef = pPortion;
485 if ( pPortion != NULL
486 && pFieldmark != NULL
487 && pDoc != NULL )
488 {
489 pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
490 }
491 }
492 else if (CH_TXT_ATR_FORMELEMENT == Char)
493 {
494 ::sw::mark::IFieldmark* pFieldmark = NULL;
495 if ( pDoc != NULL )
496 {
497 pFieldmark = pDoc->getIDocumentMarkAccess()->getFieldmarkFor(*pUnoCrsr->GetMark());
498 }
499 SwXTextPortion* pPortion =
500 new SwXTextPortion( pUnoCrsr, i_xParentText, PORTION_FIELD_START_END );
501 xRef = pPortion;
502 if ( pPortion != NULL
503 && pFieldmark != NULL
504 && pDoc != NULL )
505 {
506 pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
507 }
508 }
509 else
510 {
511 ASSERT(false, "no fieldmark found?");
512 }
513 return xRef;
514 }
515
516 /* -----------------------------31.08.00 14:28--------------------------------
517
518 ---------------------------------------------------------------------------*/
519 static Reference<XTextRange>
lcl_CreateRefMarkPortion(Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,const SwTxtAttr & rAttr,const bool bEnd)520 lcl_CreateRefMarkPortion(
521 Reference<XText> const& xParent,
522 const SwUnoCrsr * const pUnoCrsr,
523 const SwTxtAttr & rAttr, const bool bEnd)
524 {
525 SwDoc* pDoc = pUnoCrsr->GetDoc();
526 const SwFmtRefMark& rRefMark =
527 static_cast<const SwFmtRefMark&>(rAttr.GetAttr());
528 Reference<XTextContent> xContent;
529 if (!xContent.is())
530 {
531 xContent = new SwXReferenceMark(pDoc, &rRefMark);
532 }
533
534 SwXTextPortion* pPortion = 0;
535 if (!bEnd)
536 {
537 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_START);
538 pPortion->SetRefMark(xContent);
539 pPortion->SetCollapsed(rAttr.End() ? false : true);
540 }
541 else
542 {
543 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_REFMARK_END);
544 pPortion->SetRefMark(xContent);
545 }
546 return pPortion;
547 }
548
549 //-----------------------------------------------------------------------------
550 static void
lcl_InsertRubyPortion(TextRangeList_t & rPortions,Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,const SwTxtAttr & rAttr,const sal_Bool bEnd)551 lcl_InsertRubyPortion(
552 TextRangeList_t & rPortions,
553 Reference<XText> const& xParent,
554 const SwUnoCrsr * const pUnoCrsr,
555 const SwTxtAttr & rAttr, const sal_Bool bEnd)
556 {
557 SwXTextPortion* pPortion = new SwXTextPortion(pUnoCrsr,
558 static_cast<const SwTxtRuby&>(rAttr), xParent, bEnd);
559 rPortions.push_back(pPortion);
560 pPortion->SetCollapsed(rAttr.End() ? false : true);
561 }
562
563 //-----------------------------------------------------------------------------
564 static Reference<XTextRange>
lcl_CreateTOXMarkPortion(Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,SwTxtAttr & rAttr,const bool bEnd)565 lcl_CreateTOXMarkPortion(
566 Reference<XText> const& xParent,
567 const SwUnoCrsr * const pUnoCrsr,
568 SwTxtAttr & rAttr, const bool bEnd)
569 {
570 SwDoc* pDoc = pUnoCrsr->GetDoc();
571 SwTOXMark & rTOXMark = static_cast<SwTOXMark&>(rAttr.GetAttr());
572
573 const Reference<XTextContent> xContent(
574 SwXDocumentIndexMark::CreateXDocumentIndexMark(*pDoc,
575 *const_cast<SwTOXType*>(rTOXMark.GetTOXType()), rTOXMark),
576 uno::UNO_QUERY);
577
578 SwXTextPortion* pPortion = 0;
579 if (!bEnd)
580 {
581 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_START);
582 pPortion->SetTOXMark(xContent);
583 pPortion->SetCollapsed(rAttr.GetEnd() ? false : true);
584 }
585 else
586 {
587 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_TOXMARK_END);
588 pPortion->SetTOXMark(xContent);
589 }
590 return pPortion;
591 }
592
593 //-----------------------------------------------------------------------------
594 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)595 lcl_CreateMetaPortion(
596 uno::Reference<text::XText> const& xParent,
597 const SwUnoCrsr * const pUnoCrsr,
598 SwTxtAttr & rAttr, ::std::auto_ptr<TextRangeList_t const> & pPortions)
599 {
600 const uno::Reference<rdf::XMetadatable> xMeta( SwXMeta::CreateXMeta(
601 *static_cast<SwFmtMeta &>(rAttr.GetAttr()).GetMeta(),
602 xParent, pPortions));
603 SwXTextPortion * pPortion(0);
604 if (RES_TXTATR_META == rAttr.Which())
605 {
606 const uno::Reference<text::XTextContent> xContent(xMeta,
607 uno::UNO_QUERY);
608 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_META);
609 pPortion->SetMeta(xContent);
610 }
611 else
612 {
613 const uno::Reference<text::XTextField> xField(xMeta, uno::UNO_QUERY);
614 pPortion = new SwXTextPortion(pUnoCrsr, xParent, PORTION_FIELD);
615 pPortion->SetTextField(xField);
616 }
617 return pPortion;
618 }
619
620 //-----------------------------------------------------------------------------
lcl_ExportBookmark(TextRangeList_t & rPortions,Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,SwXBookmarkPortion_ImplList & rBkmArr,const xub_StrLen nIndex)621 static void lcl_ExportBookmark(
622 TextRangeList_t & rPortions,
623 Reference<XText> const& xParent,
624 const SwUnoCrsr * const pUnoCrsr,
625 SwXBookmarkPortion_ImplList& rBkmArr,
626 const xub_StrLen nIndex)
627 {
628 for ( SwXBookmarkPortion_ImplList::iterator aIter = rBkmArr.begin(), aEnd = rBkmArr.end(); aIter != aEnd; )
629 {
630 SwXBookmarkPortion_ImplSharedPtr pPtr = (*aIter);
631 if ( nIndex > pPtr->getIndex() )
632 {
633 rBkmArr.erase( aIter++ );
634 continue;
635 }
636 if ( nIndex < pPtr->getIndex() )
637 break;
638
639 SwXTextPortion* pPortion = 0;
640 if ((BKM_TYPE_START == pPtr->nBkmType) ||
641 (BKM_TYPE_START_END == pPtr->nBkmType))
642 {
643 pPortion =
644 new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_START);
645 rPortions.push_back(pPortion);
646 pPortion->SetBookmark(pPtr->xBookmark);
647 pPortion->SetCollapsed( (BKM_TYPE_START_END == pPtr->nBkmType)
648 ? true : false);
649
650 }
651 if (BKM_TYPE_END == pPtr->nBkmType)
652 {
653 pPortion =
654 new SwXTextPortion(pUnoCrsr, xParent, PORTION_BOOKMARK_END);
655 rPortions.push_back(pPortion);
656 pPortion->SetBookmark(pPtr->xBookmark);
657 }
658 rBkmArr.erase( aIter++ );
659 }
660 }
661
662 static void
lcl_ExportSoftPageBreak(TextRangeList_t & rPortions,Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,SwSoftPageBreakList & rBreakArr,const xub_StrLen nIndex)663 lcl_ExportSoftPageBreak(
664 TextRangeList_t & rPortions,
665 Reference<XText> const& xParent,
666 const SwUnoCrsr * const pUnoCrsr,
667 SwSoftPageBreakList& rBreakArr,
668 const xub_StrLen nIndex)
669 {
670 for ( SwSoftPageBreakList::iterator aIter = rBreakArr.begin(),
671 aEnd = rBreakArr.end();
672 aIter != aEnd; )
673 {
674 if ( nIndex > *aIter )
675 {
676 rBreakArr.erase( aIter++ );
677 continue;
678 }
679 if ( nIndex < *aIter )
680 break;
681
682 rPortions.push_back(
683 new SwXTextPortion(pUnoCrsr, xParent, PORTION_SOFT_PAGEBREAK) );
684 rBreakArr.erase( aIter++ );
685 }
686 }
687
688
689 /* -----------------------------18.12.00 14:51--------------------------------
690
691 ---------------------------------------------------------------------------*/
692 //-----------------------------------------------------------------------------
693 #define REDLINE_PORTION_START_REMOVE 0//removed redlines are visible
694 #define REDLINE_PORTION_END_REMOVE 1//removed redlines are visible
695 #define REDLINE_PORTION_REMOVE 2//removed redlines are NOT visible
696 #define REDLINE_PORTION_INSERT_START 3
697 #define REDLINE_PORTION_INSERT_END 4
698
699 struct SwXRedlinePortion_Impl
700 {
701 const SwRedline* m_pRedline;
702 const bool m_bStart;
703
SwXRedlinePortion_ImplSwXRedlinePortion_Impl704 SwXRedlinePortion_Impl ( const SwRedline* pRed, const bool bIsStart )
705 : m_pRedline(pRed)
706 , m_bStart(bIsStart)
707 {
708 }
709
getRealIndexSwXRedlinePortion_Impl710 xub_StrLen getRealIndex ()
711 {
712 return m_bStart ? m_pRedline->Start()->nContent.GetIndex()
713 : m_pRedline->End() ->nContent.GetIndex();
714 }
715 };
716
717 typedef boost::shared_ptr < SwXRedlinePortion_Impl >
718 SwXRedlinePortion_ImplSharedPtr;
719
720 struct RedlineCompareStruct
721 {
getPositionRedlineCompareStruct722 const SwPosition& getPosition ( const SwXRedlinePortion_ImplSharedPtr &r )
723 {
724 return *(r->m_bStart ? r->m_pRedline->Start() : r->m_pRedline->End());
725 }
726
operator ()RedlineCompareStruct727 bool operator () ( const SwXRedlinePortion_ImplSharedPtr &r1,
728 const SwXRedlinePortion_ImplSharedPtr &r2 )
729 {
730 return getPosition ( r1 ) < getPosition ( r2 );
731 }
732 };
733
734 typedef std::multiset < SwXRedlinePortion_ImplSharedPtr, RedlineCompareStruct >
735 SwXRedlinePortion_ImplList;
736
737 //-----------------------------------------------------------------------------
738 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)739 lcl_ExportHints(
740 PortionStack_t & rPortionStack,
741 const Reference<XText> & xParent,
742 SwUnoCrsr * const pUnoCrsr,
743 SwpHints * const pHints,
744 const sal_Int32 i_nStartPos,
745 const sal_Int32 i_nEndPos,
746 const xub_StrLen nCurrentIndex,
747 const bool bRightMoveForbidden,
748 bool & o_rbCursorMoved,
749 sal_Int32 & o_rNextAttrPosition )
750 {
751 // if the attribute has a dummy character, then xRef is set (except META)
752 // otherwise, the portion for the attribute is inserted into rPortions!
753 Reference<XTextRange> xRef;
754 SwDoc* pDoc = pUnoCrsr->GetDoc();
755 //search for special text attributes - first some ends
756 sal_uInt16 nEndIndex = 0;
757 sal_uInt16 nNextEnd = 0;
758 while(nEndIndex < pHints->GetEndCount() &&
759 (!pHints->GetEnd(nEndIndex)->GetEnd() ||
760 nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetEnd()))))
761 {
762 if(pHints->GetEnd(nEndIndex)->GetEnd())
763 {
764 SwTxtAttr * const pAttr = pHints->GetEnd(nEndIndex);
765 if (nNextEnd == nCurrentIndex)
766 {
767 const sal_uInt16 nWhich( pAttr->Which() );
768 switch (nWhich)
769 {
770 case RES_TXTATR_TOXMARK:
771 {
772 Reference<XTextRange> xTmp = lcl_CreateTOXMarkPortion(
773 xParent, pUnoCrsr, *pAttr, true);
774 rPortionStack.top().first->push_back(xTmp);
775 }
776 break;
777 case RES_TXTATR_REFMARK:
778 {
779 Reference<XTextRange> xTmp = lcl_CreateRefMarkPortion(
780 xParent, pUnoCrsr, *pAttr, true);
781 rPortionStack.top().first->push_back(xTmp);
782 }
783 break;
784 case RES_TXTATR_CJK_RUBY:
785 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
786 if( *pAttr->GetEnd() == *pAttr->GetStart())
787 {
788 lcl_InsertRubyPortion( *rPortionStack.top().first,
789 xParent, pUnoCrsr, *pAttr, sal_False);
790 }
791 lcl_InsertRubyPortion( *rPortionStack.top().first,
792 xParent, pUnoCrsr, *pAttr, sal_True);
793 break;
794 case RES_TXTATR_META:
795 case RES_TXTATR_METAFIELD:
796 {
797 ASSERT(*pAttr->GetStart() != *pAttr->GetEnd(),
798 "empty meta?");
799 if ((i_nStartPos > 0) &&
800 (*pAttr->GetStart() < i_nStartPos))
801 {
802 // force skip pAttr and rest of attribute ends
803 // at nCurrentIndex
804 // because they are not contained in the meta pAttr
805 // and the meta pAttr itself is outside selection!
806 // (necessary for SwXMeta::createEnumeration)
807 if (*pAttr->GetStart() + 1 == i_nStartPos)
808 {
809 nEndIndex = pHints->GetEndCount() - 1;
810 }
811 break;
812 }
813 PortionList_t Top = rPortionStack.top();
814 if (Top.second != pAttr)
815 {
816 ASSERT(false, "ExportHints: stack error" );
817 }
818 else
819 {
820 ::std::auto_ptr<const TextRangeList_t>
821 pCurrentPortions(Top.first);
822 rPortionStack.pop();
823 const uno::Reference<text::XTextRange> xPortion(
824 lcl_CreateMetaPortion(xParent, pUnoCrsr,
825 *pAttr, pCurrentPortions));
826 rPortionStack.top().first->push_back(xPortion);
827 }
828 }
829 break;
830 }
831 }
832 }
833 nEndIndex++;
834 }
835
836 // then some starts
837 sal_uInt16 nStartIndex = 0;
838 sal_uInt16 nNextStart = 0;
839 while(nStartIndex < pHints->GetStartCount() &&
840 nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
841 {
842 SwTxtAttr * const pAttr = pHints->GetStart(nStartIndex);
843 sal_uInt16 nAttrWhich = pAttr->Which();
844 if (nNextStart == nCurrentIndex)
845 {
846 switch( nAttrWhich )
847 {
848 case RES_TXTATR_FIELD:
849 if(!bRightMoveForbidden)
850 {
851 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
852 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
853 break;
854 SwXTextPortion* pPortion;
855 xRef = pPortion =
856 new SwXTextPortion(
857 pUnoCrsr, xParent, PORTION_FIELD);
858 Reference<XTextField> xField =
859 SwXTextField::CreateSwXTextField(*pDoc, pAttr->GetFmtFld());
860 pPortion->SetTextField(xField);
861 }
862 break;
863
864 case RES_TXTATR_ANNOTATION:
865 if(!bRightMoveForbidden)
866 {
867 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
868 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
869 break;
870
871 const SwTxtAnnotationFld* pTxtAnnotationFld = dynamic_cast<const SwTxtAnnotationFld*>( pAttr );
872 ::sw::mark::IMark* pAnnotationMark = pTxtAnnotationFld->GetAnnotationMark();
873 if ( pAnnotationMark != NULL )
874 {
875 SwXTextPortion* pPortion = new SwXTextPortion( pUnoCrsr, xParent, PORTION_ANNOTATION_END );
876 pPortion->SetBookmark( SwXBookmark::CreateXBookmark( *pDoc, *pAnnotationMark ) );
877 xRef = pPortion;
878 }
879 else
880 {
881 SwXTextPortion* pPortion = new SwXTextPortion( pUnoCrsr, xParent, PORTION_ANNOTATION );
882 Reference<XTextField> xField =
883 SwXTextField::CreateSwXTextField(*pDoc, pAttr->GetFmtFld());
884 pPortion->SetTextField(xField);
885 xRef = pPortion;
886 }
887 }
888 break;
889
890 case RES_TXTATR_INPUTFIELD:
891 if(!bRightMoveForbidden)
892 {
893
894 pUnoCrsr->Right(
895 pAttr->GetFmtFld().GetField()->ExpandField( true ).Len() + 2,
896 CRSR_SKIP_CHARS,
897 sal_False,
898 sal_False );
899 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
900 break;
901 SwXTextPortion* pPortion =
902 new SwXTextPortion( pUnoCrsr, xParent, PORTION_FIELD);
903 xRef = pPortion;
904 Reference<XTextField> xField =
905 SwXTextField::CreateSwXTextField(*pDoc, pAttr->GetFmtFld());
906 pPortion->SetTextField(xField);
907 }
908 break;
909
910 case RES_TXTATR_FLYCNT:
911 if(!bRightMoveForbidden)
912 {
913 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
914 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
915 break; // Robust #i81708 content in covered cells
916 pUnoCrsr->Exchange();
917 xRef = new SwXTextPortion( pUnoCrsr, xParent, PORTION_FRAME);
918 }
919 break;
920
921 case RES_TXTATR_FTN:
922 {
923 if(!bRightMoveForbidden)
924 {
925 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
926 if( *pUnoCrsr->GetMark() == *pUnoCrsr->GetPoint() )
927 break;
928 SwXTextPortion* pPortion;
929 xRef = pPortion = new SwXTextPortion(
930 pUnoCrsr, xParent, PORTION_FOOTNOTE);
931 Reference<XFootnote> xContent =
932 SwXFootnotes::GetObject(*pDoc, pAttr->GetFtn());
933 pPortion->SetFootnote(xContent);
934 }
935 }
936 break;
937
938 case RES_TXTATR_TOXMARK:
939 case RES_TXTATR_REFMARK:
940 {
941 bool bIsPoint = !(pAttr->GetEnd());
942 if (!bRightMoveForbidden || !bIsPoint)
943 {
944 if (bIsPoint)
945 {
946 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
947 }
948 Reference<XTextRange> xTmp =
949 (RES_TXTATR_REFMARK == nAttrWhich)
950 ? lcl_CreateRefMarkPortion(
951 xParent, pUnoCrsr, *pAttr, false)
952 : lcl_CreateTOXMarkPortion(
953 xParent, pUnoCrsr, *pAttr, false);
954 if (bIsPoint) // consume CH_TXTATR!
955 {
956 pUnoCrsr->Normalize(sal_False);
957 pUnoCrsr->DeleteMark();
958 xRef = xTmp;
959 }
960 else // just insert it
961 {
962 rPortionStack.top().first->push_back(xTmp);
963 }
964 }
965 }
966 break;
967 case RES_TXTATR_CJK_RUBY:
968 //#i91534# GetEnd() == 0 mixes the order of ruby start/end
969 if(pAttr->GetEnd() && (*pAttr->GetEnd() != *pAttr->GetStart()))
970 {
971 lcl_InsertRubyPortion( *rPortionStack.top().first,
972 xParent, pUnoCrsr, *pAttr, sal_False);
973 }
974 break;
975 case RES_TXTATR_META:
976 case RES_TXTATR_METAFIELD:
977 if (*pAttr->GetStart() != *pAttr->GetEnd())
978 {
979 if (!bRightMoveForbidden)
980 {
981 pUnoCrsr->Right(1,CRSR_SKIP_CHARS,sal_False,sal_False);
982 o_rbCursorMoved = true;
983 // only if the end is included in selection!
984 if ((i_nEndPos < 0) ||
985 (*pAttr->GetEnd() <= i_nEndPos))
986 {
987 rPortionStack.push( ::std::make_pair(
988 new TextRangeList_t, pAttr ));
989 }
990 }
991 }
992 break;
993 case RES_TXTATR_AUTOFMT:
994 case RES_TXTATR_INETFMT:
995 case RES_TXTATR_CHARFMT:
996 break; // these are handled as properties of a "Text" portion
997 default:
998 DBG_ERROR("unknown attribute");
999 break;
1000 }
1001 }
1002 nStartIndex++;
1003 }
1004
1005 if (xRef.is()) // implies that we have moved the cursor
1006 {
1007 o_rbCursorMoved = true;
1008 }
1009 if (!o_rbCursorMoved)
1010 {
1011 // search for attribute changes behind the current cursor position
1012 // break up at frames, bookmarks, redlines
1013
1014 nStartIndex = 0;
1015 nNextStart = 0;
1016 while(nStartIndex < pHints->GetStartCount() &&
1017 nCurrentIndex >= (nNextStart = (*pHints->GetStart(nStartIndex)->GetStart())))
1018 nStartIndex++;
1019
1020 nEndIndex = 0;
1021 nNextEnd = 0;
1022 while(nEndIndex < pHints->GetEndCount() &&
1023 nCurrentIndex >= (nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd())))
1024 nEndIndex++;
1025
1026 sal_Int32 nNextPos =
1027 ((nNextStart > nCurrentIndex) && (nNextStart < nNextEnd))
1028 ? nNextStart : nNextEnd;
1029 if (nNextPos > nCurrentIndex)
1030 {
1031 o_rNextAttrPosition = nNextPos;
1032 }
1033 }
1034 return xRef;
1035 }
1036
1037 //-----------------------------------------------------------------------------
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)1038 void lcl_MoveCursor( SwUnoCrsr * const pUnoCrsr,
1039 const xub_StrLen nCurrentIndex,
1040 const sal_Int32 nNextFrameIndex,
1041 const sal_Int32 nNextPortionIndex,
1042 const sal_Int32 nNextAttrIndex,
1043 const sal_Int32 nNextMarkIndex,
1044 const sal_Int32 nEndPos )
1045 {
1046 sal_Int32 nMovePos = pUnoCrsr->GetCntntNode()->Len();
1047
1048 if ((nEndPos >= 0) && (nEndPos < nMovePos))
1049 {
1050 nMovePos = nEndPos;
1051 }
1052
1053 if ((nNextFrameIndex >= 0) && (nNextFrameIndex < nMovePos))
1054 {
1055 nMovePos = nNextFrameIndex;
1056 }
1057
1058 if ((nNextPortionIndex >= 0) && (nNextPortionIndex < nMovePos))
1059 {
1060 nMovePos = nNextPortionIndex;
1061 }
1062
1063 if ((nNextAttrIndex >= 0) && (nNextAttrIndex < nMovePos))
1064 {
1065 nMovePos = nNextAttrIndex;
1066 }
1067
1068 if ((nNextMarkIndex >= 0) && (nNextMarkIndex < nMovePos))
1069 {
1070 nMovePos = nNextMarkIndex;
1071 }
1072
1073 if (nMovePos > nCurrentIndex)
1074 {
1075 pUnoCrsr->GetPoint()->nContent = static_cast<sal_uInt16>(nMovePos);
1076 }
1077 }
1078
1079 //-----------------------------------------------------------------------------
lcl_FillRedlineArray(SwDoc const & rDoc,SwUnoCrsr const & rUnoCrsr,SwXRedlinePortion_ImplList & rRedArr)1080 static void lcl_FillRedlineArray(
1081 SwDoc const & rDoc,
1082 SwUnoCrsr const & rUnoCrsr,
1083 SwXRedlinePortion_ImplList& rRedArr )
1084 {
1085 const SwRedlineTbl& rRedTbl = rDoc.GetRedlineTbl();
1086 sal_uInt16 nRedTblCount = rRedTbl.Count();
1087
1088 if ( nRedTblCount > 0 )
1089 {
1090 const SwPosition* pStart = rUnoCrsr.GetPoint();
1091 const SwNodeIndex nOwnNode = pStart->nNode;
1092
1093 for(sal_uInt16 nRed = 0; nRed < nRedTblCount; nRed++)
1094 {
1095 const SwRedline* pRedline = rRedTbl[nRed];
1096 const SwPosition* pRedStart = pRedline->Start();
1097 const SwNodeIndex nRedNode = pRedStart->nNode;
1098 if ( nOwnNode == nRedNode )
1099 rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
1100 new SwXRedlinePortion_Impl ( pRedline, true ) ) );
1101 if( pRedline->HasMark() && pRedline->End()->nNode == nOwnNode )
1102 rRedArr.insert( SwXRedlinePortion_ImplSharedPtr (
1103 new SwXRedlinePortion_Impl ( pRedline, false) ) );
1104 }
1105 }
1106 }
1107
1108 //-----------------------------------------------------------------------------
lcl_FillSoftPageBreakArray(SwUnoCrsr const & rUnoCrsr,SwSoftPageBreakList & rBreakArr)1109 static void lcl_FillSoftPageBreakArray(
1110 SwUnoCrsr const & rUnoCrsr,
1111 SwSoftPageBreakList& rBreakArr )
1112 {
1113 const SwTxtNode *pTxtNode =
1114 rUnoCrsr.GetPoint()->nNode.GetNode().GetTxtNode();
1115 if( pTxtNode )
1116 pTxtNode->fillSoftPageBreakList( rBreakArr );
1117 }
1118
1119 /* -----------------------------19.12.00 12:25--------------------------------
1120
1121 ---------------------------------------------------------------------------*/
lcl_ExportRedline(TextRangeList_t & rPortions,Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,SwXRedlinePortion_ImplList & rRedlineArr,const xub_StrLen nIndex)1122 static void lcl_ExportRedline(
1123 TextRangeList_t & rPortions,
1124 Reference<XText> const& xParent,
1125 const SwUnoCrsr * const pUnoCrsr,
1126 SwXRedlinePortion_ImplList& rRedlineArr,
1127 const xub_StrLen nIndex)
1128 {
1129
1130 // MTG: 23/11/05: We want this loop to iterate over all red lines in this
1131 // array. We will only insert the ones with index matches
1132 for ( SwXRedlinePortion_ImplList::iterator aIter = rRedlineArr.begin(), aEnd = rRedlineArr.end();
1133 aIter != aEnd; )
1134 {
1135 SwXRedlinePortion_ImplSharedPtr pPtr = (*aIter );
1136 sal_uLong nRealIndex = pPtr->getRealIndex();
1137 // MTG: 23/11/05: If there are elements before nIndex, remove them
1138 if ( nIndex > nRealIndex )
1139 rRedlineArr.erase ( aIter++ );
1140 // MTG: 23/11/05: If the elements match, and them to the list
1141 else if ( nIndex == nRealIndex )
1142 {
1143 rPortions.push_back( new SwXRedlinePortion(
1144 pPtr->m_pRedline, pUnoCrsr, xParent, pPtr->m_bStart) );
1145 rRedlineArr.erase ( aIter++ );
1146 }
1147 // MTG: 23/11/05: If we've iterated past nIndex, exit the loop
1148 else
1149 break;
1150 }
1151 }
1152
1153 /* -----------------------------19.12.00 13:09--------------------------------
1154
1155 ---------------------------------------------------------------------------*/
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)1156 static void lcl_ExportBkmAndRedline(
1157 TextRangeList_t & rPortions,
1158 Reference<XText> const & xParent,
1159 const SwUnoCrsr * const pUnoCrsr,
1160 SwXBookmarkPortion_ImplList& rBkmArr,
1161 SwXRedlinePortion_ImplList& rRedlineArr,
1162 SwSoftPageBreakList& rBreakArr,
1163 const xub_StrLen nIndex )
1164 {
1165 if (rBkmArr.size())
1166 lcl_ExportBookmark(rPortions, xParent, pUnoCrsr, rBkmArr, nIndex);
1167
1168 if (rRedlineArr.size())
1169 lcl_ExportRedline(rPortions, xParent, pUnoCrsr, rRedlineArr, nIndex);
1170
1171 if (rBreakArr.size())
1172 lcl_ExportSoftPageBreak(rPortions, xParent, pUnoCrsr, rBreakArr, nIndex);
1173 }
1174
lcl_ExportAnnotationStarts(TextRangeList_t & rPortions,Reference<XText> const & xParent,const SwUnoCrsr * const pUnoCrsr,SwAnnotationStartPortion_ImplList & rAnnotationStartArr,const xub_StrLen nIndex)1175 static void lcl_ExportAnnotationStarts(
1176 TextRangeList_t & rPortions,
1177 Reference<XText> const & xParent,
1178 const SwUnoCrsr * const pUnoCrsr,
1179 SwAnnotationStartPortion_ImplList& rAnnotationStartArr,
1180 const xub_StrLen nIndex)
1181 {
1182 if ( rAnnotationStartArr.size() > 0 )
1183 {
1184 for ( SwAnnotationStartPortion_ImplList::iterator aIter = rAnnotationStartArr.begin(), aEnd = rAnnotationStartArr.end();
1185 aIter != aEnd; )
1186 {
1187 SwAnnotationStartPortion_ImplSharedPtr pPtr = (*aIter);
1188 if ( nIndex > pPtr->getIndex() )
1189 {
1190 rAnnotationStartArr.erase( aIter++ );
1191 continue;
1192 }
1193 if ( pPtr->getIndex() > nIndex )
1194 {
1195 break;
1196 }
1197
1198 SwXTextPortion* pPortion =
1199 new SwXTextPortion( pUnoCrsr, xParent, PORTION_ANNOTATION );
1200 pPortion->SetTextField( pPtr->mxAnnotationField );
1201 rPortions.push_back(pPortion);
1202
1203 rAnnotationStartArr.erase( aIter++ );
1204 }
1205 }
1206 }
1207
1208 //-----------------------------------------------------------------------------
lcl_ExportFrames(TextRangeList_t & rPortions,Reference<XText> const & i_xParent,SwUnoCrsr * const i_pUnoCrsr,FrameDependSortList_t & i_rFrames,xub_StrLen const i_nCurrentIndex)1209 static sal_Int32 lcl_ExportFrames(
1210 TextRangeList_t & rPortions,
1211 Reference<XText> const & i_xParent,
1212 SwUnoCrsr * const i_pUnoCrsr,
1213 FrameDependSortList_t & i_rFrames,
1214 xub_StrLen const i_nCurrentIndex)
1215 {
1216 // find first Frame in (sorted) i_rFrames at current position
1217 while (i_rFrames.size() && (i_rFrames.front().nIndex == i_nCurrentIndex))
1218 // do not check for i_nEnd here; this is done implicity by lcl_MoveCursor
1219 {
1220 const SwModify * const pFrame =
1221 i_rFrames.front().pFrameDepend->GetRegisteredIn();
1222 if (pFrame) // Frame could be disposed
1223 {
1224 SwXTextPortion* pPortion = new SwXTextPortion(i_pUnoCrsr, i_xParent,
1225 *static_cast<SwFrmFmt*>( const_cast<SwModify*>( pFrame ) ) );
1226 rPortions.push_back(pPortion);
1227 }
1228 i_rFrames.pop_front();
1229 }
1230
1231 return i_rFrames.size() ? i_rFrames.front().nIndex : -1;
1232 }
1233
1234 //-----------------------------------------------------------------------------
lcl_GetNextIndex(SwXBookmarkPortion_ImplList const & rBkmArr,SwXRedlinePortion_ImplList const & rRedlineArr,SwSoftPageBreakList const & rBreakArr)1235 static sal_Int32 lcl_GetNextIndex(
1236 SwXBookmarkPortion_ImplList const & rBkmArr,
1237 SwXRedlinePortion_ImplList const & rRedlineArr,
1238 SwSoftPageBreakList const & rBreakArr )
1239 {
1240 sal_Int32 nRet = -1;
1241 if(rBkmArr.size())
1242 {
1243 SwXBookmarkPortion_ImplSharedPtr pPtr = (*rBkmArr.begin());
1244 nRet = pPtr->getIndex();
1245 }
1246 if(rRedlineArr.size())
1247 {
1248 SwXRedlinePortion_ImplSharedPtr pPtr = (*rRedlineArr.begin());
1249 sal_Int32 nTmp = pPtr->getRealIndex();
1250 if(nRet < 0 || nTmp < nRet)
1251 nRet = nTmp;
1252 }
1253 if(rBreakArr.size())
1254 {
1255 if(nRet < 0 || *rBreakArr.begin() < static_cast<sal_uInt32>(nRet))
1256 nRet = *rBreakArr.begin();
1257 }
1258 return nRet;
1259 };
1260
1261 //-----------------------------------------------------------------------------
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)1262 static void lcl_CreatePortions(
1263 TextRangeList_t & i_rPortions,
1264 uno::Reference< text::XText > const & i_xParentText,
1265 SwUnoCrsr * const pUnoCrsr,
1266 FrameDependSortList_t & i_rFrames,
1267 const sal_Int32 i_nStartPos,
1268 const sal_Int32 i_nEndPos )
1269 {
1270 if (!pUnoCrsr)
1271 return;
1272
1273 // set the start if a selection should be exported
1274 if ((i_nStartPos > 0) &&
1275 (pUnoCrsr->Start()->nContent.GetIndex() != i_nStartPos))
1276 {
1277 pUnoCrsr->DeleteMark();
1278 DBG_ASSERT(pUnoCrsr->Start()->nNode.GetNode().GetTxtNode() &&
1279 (i_nStartPos <= pUnoCrsr->Start()->nNode.GetNode().GetTxtNode()->
1280 GetTxt().Len()), "Incorrect start position" );
1281 // ??? should this be i_nStartPos - current position ?
1282 pUnoCrsr->Right(static_cast<xub_StrLen>(i_nStartPos),
1283 CRSR_SKIP_CHARS, sal_False, sal_False);
1284 }
1285
1286 SwDoc * const pDoc = pUnoCrsr->GetDoc();
1287
1288 FieldMarks_t FieldMarks;
1289 lcl_FillFieldMarkArray(FieldMarks, *pUnoCrsr, i_nStartPos);
1290
1291 SwXBookmarkPortion_ImplList Bookmarks;
1292 lcl_FillBookmarkArray(*pDoc, *pUnoCrsr, Bookmarks);
1293
1294 SwXRedlinePortion_ImplList Redlines;
1295 lcl_FillRedlineArray(*pDoc, *pUnoCrsr, Redlines);
1296
1297 SwSoftPageBreakList SoftPageBreaks;
1298 lcl_FillSoftPageBreakArray(*pUnoCrsr, SoftPageBreaks);
1299
1300 SwAnnotationStartPortion_ImplList AnnotationStarts;
1301 lcl_FillAnnotationStartArray( *pDoc, *pUnoCrsr, AnnotationStarts );
1302
1303 PortionStack_t PortionStack;
1304 PortionStack.push( PortionList_t(&i_rPortions, 0) );
1305
1306 bool bAtEnd( false );
1307 while (!bAtEnd) // every iteration consumes at least current character!
1308 {
1309 if (pUnoCrsr->HasMark())
1310 {
1311 pUnoCrsr->Normalize(sal_False);
1312 pUnoCrsr->DeleteMark();
1313 }
1314
1315 SwTxtNode * const pTxtNode = pUnoCrsr->GetNode()->GetTxtNode();
1316 if (!pTxtNode)
1317 {
1318 DBG_ERROR("lcl_CreatePortions: no TextNode - what now ?");
1319 return;
1320 }
1321
1322 SwpHints * const pHints = pTxtNode->GetpSwpHints();
1323 const xub_StrLen nCurrentIndex =
1324 pUnoCrsr->GetPoint()->nContent.GetIndex();
1325 // this contains the portion which consumes the character in the
1326 // text at nCurrentIndex; i.e. it must be set _once_ per iteration
1327 uno::Reference< XTextRange > xRef;
1328
1329 SwUnoCursorHelper::SelectPam(*pUnoCrsr, true); // set mark
1330
1331 const sal_Int32 nFirstFrameIndex =
1332 lcl_ExportFrames( *PortionStack.top().first,
1333 i_xParentText, pUnoCrsr, i_rFrames, nCurrentIndex);
1334
1335 lcl_ExportBkmAndRedline( *PortionStack.top().first, i_xParentText,
1336 pUnoCrsr, Bookmarks, Redlines, SoftPageBreaks, nCurrentIndex );
1337
1338 lcl_ExportAnnotationStarts(
1339 *PortionStack.top().first,
1340 i_xParentText,
1341 pUnoCrsr,
1342 AnnotationStarts,
1343 nCurrentIndex );
1344
1345 bool bCursorMoved( false );
1346 sal_Int32 nNextAttrIndex = -1;
1347 // #111716# the cursor must not move right at the
1348 // end position of a selection!
1349 bAtEnd = ((i_nEndPos >= 0) && (nCurrentIndex >= i_nEndPos))
1350 || (nCurrentIndex >= pTxtNode->Len());
1351 if (pHints)
1352 {
1353 // N.B.: side-effects nNextAttrIndex, bCursorMoved; may move cursor
1354 xRef = lcl_ExportHints(PortionStack, i_xParentText, pUnoCrsr,
1355 pHints, i_nStartPos, i_nEndPos, nCurrentIndex, bAtEnd,
1356 bCursorMoved, nNextAttrIndex);
1357 if (PortionStack.empty())
1358 {
1359 ASSERT(false, "CreatePortions: stack underflow");
1360 return;
1361 }
1362 }
1363
1364 if (!xRef.is() && !bCursorMoved)
1365 {
1366 if (!bAtEnd &&
1367 FieldMarks.size() && (FieldMarks.front() == nCurrentIndex))
1368 {
1369 // moves cursor
1370 xRef = lcl_ExportFieldMark(i_xParentText, pUnoCrsr, pTxtNode);
1371 FieldMarks.pop_front();
1372 }
1373 }
1374 else
1375 {
1376 ASSERT(!FieldMarks.size() ||
1377 (FieldMarks.front() != nCurrentIndex),
1378 "fieldmark and hint with CH_TXTATR at same pos?");
1379 }
1380
1381 if (!bAtEnd && !xRef.is() && !bCursorMoved)
1382 {
1383 const sal_Int32 nNextPortionIndex =
1384 lcl_GetNextIndex(Bookmarks, Redlines, SoftPageBreaks);
1385
1386 sal_Int32 nNextMarkIndex = ( FieldMarks.size() ? FieldMarks.front() : -1 );
1387 if ( AnnotationStarts.size() > 0
1388 && ( nNextMarkIndex == -1
1389 || (*AnnotationStarts.begin())->getIndex() < nNextMarkIndex ) )
1390 {
1391 nNextMarkIndex = (*AnnotationStarts.begin())->getIndex();
1392 }
1393
1394 lcl_MoveCursor(
1395 pUnoCrsr,
1396 nCurrentIndex,
1397 nFirstFrameIndex,
1398 nNextPortionIndex,
1399 nNextAttrIndex,
1400 nNextMarkIndex,
1401 i_nEndPos );
1402
1403 xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
1404 }
1405 else if (bAtEnd && !xRef.is() && !pTxtNode->Len())
1406 {
1407 // special case: for an empty paragraph, we better put out a
1408 // text portion because there may be a hyperlink attribute
1409 xRef = new SwXTextPortion(pUnoCrsr, i_xParentText, PORTION_TEXT);
1410 }
1411
1412 if (xRef.is())
1413 {
1414 PortionStack.top().first->push_back(xRef);
1415 }
1416 }
1417
1418 ASSERT((PortionStack.size() == 1) && !PortionStack.top().second,
1419 "CreatePortions: stack error" );
1420 }
1421
1422 /*-- 27.01.99 10:44:45---------------------------------------------------
1423
1424 -----------------------------------------------------------------------*/
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)1425 void SwXTextPortionEnumeration::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew)
1426 {
1427 ClientModify(this, pOld, pNew);
1428 }
1429
1430